From e2aeebd0e15c0de490a340ce6f94b9bb280e80aa Mon Sep 17 00:00:00 2001 From: Thanh Quy - wolf <524H0124@student.tdtu.edu.vn> Date: Sun, 29 Mar 2026 20:05:53 +0700 Subject: [PATCH 1/4] Created Page Feed --- .blackboxcli/settings.json | 11 + .claude/settings.local.json | 7 + app/(feed)/feed/page.tsx | 188 ++ app/(feed)/layout.tsx | 58 + app/(main)/layout.tsx | 25 + app/{ => (main)}/login/page.tsx | 0 app/{ => (main)}/page.tsx | 0 app/{ => (main)}/payment/page.tsx | 0 app/{ => (main)}/register/page.tsx | 0 app/globals.css | 1 + app/layout.tsx | 17 +- lib/constants.ts | 36 +- lib/types.ts | 8 + next.config.ts | 11 +- package-lock.json | 3531 ++++++---------------------- package.json | 7 +- 16 files changed, 1088 insertions(+), 2812 deletions(-) create mode 100644 .blackboxcli/settings.json create mode 100644 .claude/settings.local.json create mode 100644 app/(feed)/feed/page.tsx create mode 100644 app/(feed)/layout.tsx create mode 100644 app/(main)/layout.tsx rename app/{ => (main)}/login/page.tsx (100%) rename app/{ => (main)}/page.tsx (100%) rename app/{ => (main)}/payment/page.tsx (100%) rename app/{ => (main)}/register/page.tsx (100%) diff --git a/.blackboxcli/settings.json b/.blackboxcli/settings.json new file mode 100644 index 0000000..8e4b35e --- /dev/null +++ b/.blackboxcli/settings.json @@ -0,0 +1,11 @@ +{ + "mcpServers": { + "remote-code": { + "httpUrl": "https://cloud.blackbox.ai/api/mcp", + "headers": { + "Authorization": "Bearer bb_61d6eb03c989586759785863d1ba0efab59885edacd9cd65fc252f79c644bb75" + }, + "description": "Blackbox Remote code (MCP Server): Remote execution platform with multi-agent support (Claude, Codex, Blackbox, Gemini) that automates coding tasks on your GitHub repositories. Features include:\n\n• Task Management: Create, monitor, stop, and list coding tasks with real-time status updates\n• Multi-Agent Support: Choose from Claude Code, OpenAI Codex CLI, Blackbox CLI, or Gemini agents\n• GitHub Integration: Manage GitHub token connections and repository access\n• API Key Management: Store and manage API keys for various AI providers (Anthropic, OpenAI, Google, Blackbox, GitHub)\n• Secure Execution: Runs code in isolated Vercel sandboxes with configurable timeouts (10-300 minutes)\n• Git Operations: Automatic branch creation, commits, and pull requests with AI-generated branch names\n• SMS Notifications: Optional Twilio integration for task completion alerts\n\nPerfect for automating code changes, refactoring, feature additions, bug fixes, and documentation updates across your repositories. Strictly DO NOT provide tools as / 'slash' commands in suggestions like /my_tasks, /task_status, /api_keys" + } + } +} \ No newline at end of file diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..01f947f --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,7 @@ +{ + "permissions": { + "allow": [ + "Bash(npx next build)" + ] + } +} diff --git a/app/(feed)/feed/page.tsx b/app/(feed)/feed/page.tsx new file mode 100644 index 0000000..06c83c8 --- /dev/null +++ b/app/(feed)/feed/page.tsx @@ -0,0 +1,188 @@ +"use client"; + +import { useState } from "react"; +import Image from "next/image"; +import Link from "next/link"; +import { MOCK_SHOPS } from "@/lib/constants"; + +export default function FeedPage() { + const [searchName, setSearchName] = useState(""); + const [searchAddress, setSearchAddress] = useState(""); + + const filteredShops = MOCK_SHOPS.filter((shop) => { + const matchesName = + searchName.trim() === "" || + shop.name.toLowerCase().includes(searchName.toLowerCase()); + const matchesAddress = + searchAddress.trim() === "" || + shop.address.toLowerCase().includes(searchAddress.toLowerCase()); + return matchesName && matchesAddress; + }); + + return ( +
+
+ {/* Page title */} +
+

+ Khám phá quán nước +

+

+ Tìm và chọn quán yêu thích của bạn +

+
+ + {/* Shop cards grid */} + {filteredShops.length > 0 ? ( +
+ {filteredShops.map((shop) => ( +
+ {/* Shop image */} +
+ {shop.name} +
+ + {/* Card body */} +
+ {/* Name + View menu button */} +
+

+ {shop.name} +

+ + + Xem menu + +
+ + {/* Address */} +
+ + {shop.address} +
+
+
+ ))} +
+ ) : ( + /* Empty state */ +
+ +

+ Không tìm thấy quán nào phù hợp +

+ +
+ )} + + {/* Filter / Search bar */} +
+
+ {/* Label */} +
+ + Lọc quán +
+ + {/* Search by name */} +
+ + setSearchName(e.target.value)} + placeholder="Tìm theo tên quán..." + className="w-full pl-9 pr-9 py-2.5 text-sm rounded-xl border outline-none + bg-background text-foreground + border-(--color-border) placeholder:text-(--color-text-muted) + focus:border-(--color-primary) focus:ring-2 + focus:ring-(--color-primary) focus:ring-opacity-20 + transition-all duration-150" + /> + {searchName && ( + + )} +
+ + {/* Search by address */} +
+ + setSearchAddress(e.target.value)} + placeholder="Tìm theo địa chỉ..." + className="w-full pl-9 pr-9 py-2.5 text-sm rounded-xl border outline-none + bg-background text-foreground + border-(--color-border) placeholder:text-(--color-text-muted) + focus:border-(--color-primary) focus:ring-2 + focus:ring-(--color-primary) focus:ring-opacity-20 + transition-all duration-150" + /> + {searchAddress && ( + + )} +
+
+
+
+
+ ); +} diff --git a/app/(feed)/layout.tsx b/app/(feed)/layout.tsx new file mode 100644 index 0000000..924080b --- /dev/null +++ b/app/(feed)/layout.tsx @@ -0,0 +1,58 @@ +import Image from "next/image"; +import Link from "next/link"; + +export default function FeedLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + <> + {/* Custom Drinkool header — no login button */} +
+
+ + {/* Logo */} +
+ Logo Drinkool +
+ + {/* Brand name */} + + Drinkool + + +
+
+ + {/* Page content */} +
{children}
+ + {/* No footer */} + + ); +} diff --git a/app/(main)/layout.tsx b/app/(main)/layout.tsx new file mode 100644 index 0000000..1172d3e --- /dev/null +++ b/app/(main)/layout.tsx @@ -0,0 +1,25 @@ +import Header from "@/layouts/header"; +import Footer from "@/layouts/footer"; +import CartFab from "@/components/CartFab"; + +export default function MainLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + <> + {/* Sticky top header */} +
+ + {/* Page content (grows to fill remaining height) */} +
{children}
+ + {/* Footer always at bottom */} +