From 5307205977ad82be6b3180672687f842b4c010cb Mon Sep 17 00:00:00 2001 From: TaNguyenThanhQuy Date: Mon, 13 Apr 2026 15:19:41 +0000 Subject: [PATCH] develop (#29) Co-authored-by: Thanh Quy - wolf <524H0124@student.tdtu.edu.vn> Co-authored-by: Thanh Quy- wolf <524H0124@student.tdtu.edu.vn> Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com> Reviewed-on: https://git.demonkernel.io.vn/FoodSurf/frontend/pulls/29 Co-authored-by: TaNguyenThanhQuy Co-committed-by: TaNguyenThanhQuy --- .blackboxcli/settings.json | 11 - .gitea/workflows/release.yaml | 45 +-- README.md | 52 ++- app/(main)/login/page.tsx | 4 +- app/(main)/page.tsx | 9 +- app/(main)/payment/page.tsx | 4 +- app/(manager)/manager/page.tsx | 10 + app/(staff)/layout.tsx | 9 + app/(staff)/staff/schedule/page.tsx | 373 ++++++++++++++++++ components/COMPONENTS.md | 67 ++-- components/atoms/ATOMS.md | 19 - components/atoms/buttons/IconButton.tsx | 46 +++ .../molecules/cards/PaymentSummaryCard.tsx | 11 +- components/molecules/cards/ShiftCard.tsx | 112 ++++++ components/molecules/cards/ShiftCard.types.ts | 7 + components/molecules/cards/index.ts | 2 + components/organisms/analytics/BarChart.tsx | 10 +- components/organisms/analytics/LineChart.tsx | 122 ++---- components/organisms/analytics/PieChart.tsx | 2 +- components/organisms/forms/LoginForm.tsx | 2 +- components/organisms/index.ts | 16 + components/organisms/manager/ProductsTab.tsx | 5 +- .../shift-schedule/MobileShiftView.tsx | 213 ++++++++++ .../shift-schedule/MonthlyCalendar.tsx | 159 ++++++++ .../shift-schedule/ShiftCreateModal.tsx | 216 ++++++++++ .../shift-schedule/ShiftDetailModal.tsx | 237 +++++++++++ .../shift-schedule/ShiftSchedule.types.ts | 28 ++ .../shift-schedule/WeeklySchedule.tsx | 249 ++++++++++++ components/organisms/shift-schedule/index.ts | 12 + components/templates/index.ts | 4 + .../templates/staff-layout/StaffLayout.tsx | 49 +++ .../staff-layout/StaffLayout.types.ts | 3 + components/templates/staff-layout/index.ts | 2 + layouts/header.tsx | 33 +- lib/constants.ts | 101 +++++ lib/shift-context.tsx | 292 ++++++++++++++ lib/types.ts | 27 ++ package-lock.json | 29 +- pnpm-lock.yaml | 45 +-- register-shift-feature-prompt.md | 135 +++++++ 40 files changed, 2442 insertions(+), 330 deletions(-) delete mode 100644 .blackboxcli/settings.json create mode 100644 app/(staff)/layout.tsx create mode 100644 app/(staff)/staff/schedule/page.tsx create mode 100644 components/atoms/buttons/IconButton.tsx create mode 100644 components/molecules/cards/ShiftCard.tsx create mode 100644 components/molecules/cards/ShiftCard.types.ts create mode 100644 components/organisms/shift-schedule/MobileShiftView.tsx create mode 100644 components/organisms/shift-schedule/MonthlyCalendar.tsx create mode 100644 components/organisms/shift-schedule/ShiftCreateModal.tsx create mode 100644 components/organisms/shift-schedule/ShiftDetailModal.tsx create mode 100644 components/organisms/shift-schedule/ShiftSchedule.types.ts create mode 100644 components/organisms/shift-schedule/WeeklySchedule.tsx create mode 100644 components/organisms/shift-schedule/index.ts create mode 100644 components/templates/staff-layout/StaffLayout.tsx create mode 100644 components/templates/staff-layout/StaffLayout.types.ts create mode 100644 components/templates/staff-layout/index.ts create mode 100644 lib/shift-context.tsx create mode 100644 register-shift-feature-prompt.md diff --git a/.blackboxcli/settings.json b/.blackboxcli/settings.json deleted file mode 100644 index 71a0cb1..0000000 --- a/.blackboxcli/settings.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "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" - } - } -} diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml index 8a7a2a4..cde1c56 100644 --- a/.gitea/workflows/release.yaml +++ b/.gitea/workflows/release.yaml @@ -4,7 +4,7 @@ on: push: branches: - main - + pull_request: branches: - main @@ -22,15 +22,6 @@ jobs: id-token: write runs-on: ubuntu-latest steps: - - name: Calculate and Export Target IP - run: | - # 1. Lấy IP hiện tại và tính toán IP đích (đổi octet cuối thành .1) - RUNNER_IP=$(hostname -I | awk '{print $1}') - CALCULATED_IP=$(echo $RUNNER_IP | cut -d'.' -f1-3).1 - - # 2. Đưa vào biến môi trường toàn cục của Job - echo "TARGET_IP=${CALCULATED_IP}" >> $GITHUB_ENV - - name: Setup SSH Key run: | mkdir -p ~/.ssh @@ -38,33 +29,17 @@ jobs: echo "${{ secrets.DEPLOY_KEY }}" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 - ssh-keyscan -p 222 -t ed25519 $TARGET_IP >> ~/.ssh/known_hosts + ssh-keyscan -t ed25519 vps.demonkernel.io.vn >> ~/.ssh/known_hosts - uses: actions/checkout@v6 with: fetch-depth: 0 - - uses: actions/setup-node@v6 - with: - node-version: latest - - uses: pnpm/action-setup@v3 with: version: latest run_install: false - - - name: Get pnpm store directory - shell: bash - run: | - echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - - - uses: actions/cache@v3 - name: Setup pnpm cache - with: - path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/package.json') }} - restore-keys: | - ${{ runner.os }}-pnpm-store- + cache: true - name: Update dependencies run: pnpm update @@ -80,7 +55,7 @@ jobs: GITEA_USER: ${{ github.actor }} GITEA_TOKEN: ${{ secrets.ACCESS_TOKEN }} run: pnpm release - + - name: Set Version Output id: set_output run: | @@ -92,7 +67,7 @@ jobs: if: gitea.ref == 'refs/heads/main' uses: docker/login-action@v3 with: - registry: git.demonkernel.io.vn + registry: vps.demonkernel.io.vn username: ${{ github.actor }} password: ${{ secrets.ACCESS_TOKEN }} @@ -102,10 +77,10 @@ jobs: run: | # Lowercase Repository REPO_LOWER=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]') - + RAW_VERSION="${{ steps.set_output.outputs.version }}" VERSION_LOWER=$(echo "$RAW_VERSION" | tr '[:upper:]' '[:lower:]') - + echo "repo=$REPO_LOWER" >> $GITHUB_OUTPUT echo "version=$VERSION_LOWER" >> $GITHUB_OUTPUT @@ -120,15 +95,14 @@ jobs: git.demonkernel.io.vn/${{ steps.meta.outputs.repo }}:${{ steps.meta.outputs.version }} - name: Commit & Push Changes - if: gitea.ref == 'refs/heads/main' run: | - if [ -n "$(git status --porcelain)" ]; then + if [ -n "$(git status --porcelain)" ]&& [ "${{ github.ref_name }}" = "main" ]; then git config --global user.name "gitea-actions" git config --global user.email "actions-user@noreply.git.demonkernel.io.vn" REPO_NAME="${{ gitea.repository }}" - git remote set-url origin ssh://git@$TARGET_IP:222/${REPO_NAME}.git + git remote set-url origin ssh://git@vps.demonkernel.io.vn/${REPO_NAME}.git git rm -r --cached . git add . @@ -136,4 +110,3 @@ jobs: git push fi - diff --git a/README.md b/README.md index c355a6e..209acc0 100644 --- a/README.md +++ b/README.md @@ -67,15 +67,13 @@ Dành cho khách hàng: Dành cho quản lý: -- Sidebar desktop: Brand, tab navigation (Thực đơn / Combo / Danh mục), link tới - Analytics +- Sidebar desktop: Brand, tab navigation (Thực đơn / Combo / Danh mục), link tới Analytics - CRUD sản phẩm, combo, danh mục qua modals - Auth guard: tự động redirect non-manager về `/` #### 9. **Trang Phân Tích Tài Chính** (`app/(manager)/manager/analytics`) -- Summary cards: Doanh thu, đơn hàng, lợi nhuận, giá trị đơn trung bình (so sánh - kỳ trước) +- Summary cards: Doanh thu, đơn hàng, lợi nhuận, giá trị đơn trung bình (so sánh kỳ trước) - Bộ chọn kỳ: Ngày / Tuần / Tháng / Năm - Biểu đồ SVG thuần: Line, Bar, Pie — hover tooltips tương tác - Bảng top 5 sản phẩm và bảng chi tiết có thể sắp xếp @@ -198,18 +196,18 @@ frondend/ ## Công Nghệ Sử Dụng -| Công nghệ | Phiên bản | Mục đích | -| ---------------- | --------- | ------------------------------------- | -| Next.js | 16.1.7 | React Framework (App Router) | -| React | 19.2.3 | Thư viện UI | -| TypeScript | ^5 | Kiểu dữ liệu tĩnh | -| Tailwind CSS | ^4.2.2 | Utility-first CSS framework | -| Geist Font | - | Font chữ (Google Fonts via next/font) | -| FontAwesome | 6.7.2 | Icon library (CDN) | -| pnpm | - | Package manager | -| ESLint | ^9 | Linting | -| Prettier | ^3 | Code formatting | -| semantic-release | ^25 | Automated versioning & release | +| Công nghệ | Phiên bản | Mục đích | +| ------------ | --------- | ------------------------------------- | +| Next.js | 16.1.7 | React Framework (App Router) | +| React | 19.2.3 | Thư viện UI | +| TypeScript | ^5 | Kiểu dữ liệu tĩnh | +| Tailwind CSS | ^4.2.2 | Utility-first CSS framework | +| Geist Font | - | Font chữ (Google Fonts via next/font) | +| FontAwesome | 6.7.2 | Icon library (CDN) | +| pnpm | - | Package manager | +| ESLint | ^9 | Linting | +| Prettier | ^3 | Code formatting | +| semantic-release | ^25 | Automated versioning & release | --- @@ -227,11 +225,11 @@ frondend/ ### Tài Khoản Demo -| Loại tài khoản | Tên đăng nhập | Mật khẩu | -| -------------- | ------------- | ------------- | -| Manager | admin | admin | -| Staff | Nguyễn Văn An | Nguyễn Văn An | -| Customer | 0987654321 | user1 | +| Loại tài khoản | Tên đăng nhập | Mật khẩu | +| -------------- | -------------- | -------------- | +| Manager | admin | admin | +| Staff | Nguyễn Văn An | Nguyễn Văn An | +| Customer | 0987654321 | user1 | ### Design & Styling @@ -245,18 +243,14 @@ frondend/ Dự án tuân theo **Atomic Design** pattern — chi tiết tại `Atomic.md`: - **Atoms** - Nguyên tố cơ bản: Button, Input, Badge, Text, Heading, Divider -- **Molecules** - Nhóm atoms: ProductCard, ShopCard, SearchBar, - PaymentSummaryCard -- **Organisms** - Phần UI phức tạp: CategorySidebar, CartFab, ProductGrid, - ShopGrid, ReviewModal, analytics charts, manager tabs/modals -- **Templates** - Bố cục trang: MainLayout, AuthLayout, FeedLayout, - ManagerLayout +- **Molecules** - Nhóm atoms: ProductCard, ShopCard, SearchBar, PaymentSummaryCard +- **Organisms** - Phần UI phức tạp: CategorySidebar, CartFab, ProductGrid, ShopGrid, ReviewModal, analytics charts, manager tabs/modals +- **Templates** - Bố cục trang: MainLayout, AuthLayout, FeedLayout, ManagerLayout ### Data & Integration - Mock data nằm trong `lib/constants.ts` -- Context providers trong `app/providers.tsx`: AuthProvider, MenuProvider, - CartProvider +- Context providers trong `app/providers.tsx`: AuthProvider, MenuProvider, CartProvider - ManagerProvider được thêm bởi `app/(manager)/layout.tsx` - Thay bằng API calls khi backend sẵn sàng - Ảnh sản phẩm: thêm vào `public/imgs/products/` diff --git a/app/(main)/login/page.tsx b/app/(main)/login/page.tsx index 9883080..b801294 100644 --- a/app/(main)/login/page.tsx +++ b/app/(main)/login/page.tsx @@ -1,7 +1,7 @@ "use client"; -import LoginForm from "@/components/organisms/forms/LoginForm"; import { SHOP_INFO } from "@/lib/constants"; +import LoginForm from "@/components/organisms/forms/LoginForm"; import Image from "next/image"; export default function LoginPage() { @@ -28,7 +28,7 @@ export default function LoginPage() { Đăng nhập vào hệ thống

- + {/* Login Form */} diff --git a/app/(main)/page.tsx b/app/(main)/page.tsx index 604f55c..705cfbc 100644 --- a/app/(main)/page.tsx +++ b/app/(main)/page.tsx @@ -1,10 +1,10 @@ "use client"; -import { SearchBar } from "@/components/molecules/search-bar"; import { CategorySidebar } from "@/components/organisms/navigation"; import { ProductGrid } from "@/components/organisms/product-grid"; -import { MENU_CATEGORIES } from "@/lib/constants"; +import { SearchBar } from "@/components/molecules/search-bar"; import { useMenu } from "@/lib/menu-context"; +import { MENU_CATEGORIES } from "@/lib/constants"; import { useEffect, useState } from "react"; /** @@ -72,7 +72,10 @@ export default function Home() { {/* ── Product grid (organism handles mobile category menu + grid) ── */} - + ); diff --git a/app/(main)/payment/page.tsx b/app/(main)/payment/page.tsx index b6d9b35..f9377f4 100644 --- a/app/(main)/payment/page.tsx +++ b/app/(main)/payment/page.tsx @@ -75,7 +75,7 @@ export default function PaymentPage() {
diff --git a/app/(staff)/layout.tsx b/app/(staff)/layout.tsx new file mode 100644 index 0000000..4f3f56a --- /dev/null +++ b/app/(staff)/layout.tsx @@ -0,0 +1,9 @@ +import { StaffLayout } from "@/components/templates/staff-layout"; + +export default function RootStaffLayout({ + children, +}: { + children: React.ReactNode; +}) { + return {children}; +} diff --git a/app/(staff)/staff/schedule/page.tsx b/app/(staff)/staff/schedule/page.tsx new file mode 100644 index 0000000..1cb09da --- /dev/null +++ b/app/(staff)/staff/schedule/page.tsx @@ -0,0 +1,373 @@ +"use client"; + +import MobileShiftView from "@/components/organisms/shift-schedule/MobileShiftView"; +import MonthlyCalendar from "@/components/organisms/shift-schedule/MonthlyCalendar"; +import ShiftCreateModal from "@/components/organisms/shift-schedule/ShiftCreateModal"; +import ShiftDetailModal from "@/components/organisms/shift-schedule/ShiftDetailModal"; +import WeeklySchedule from "@/components/organisms/shift-schedule/WeeklySchedule"; +import { useAuth } from "@/lib/auth-context"; +import { useShift } from "@/lib/shift-context"; +import type { ShiftSlot } from "@/lib/types"; +import Link from "next/link"; +import { useState } from "react"; + +const MONTH_NAMES = [ + "Tháng 1", "Tháng 2", "Tháng 3", "Tháng 4", + "Tháng 5", "Tháng 6", "Tháng 7", "Tháng 8", + "Tháng 9", "Tháng 10", "Tháng 11", "Tháng 12", +]; + +function getMonday(d: Date): Date { + const date = new Date(d); + const day = date.getDay(); + const diff = date.getDate() - day + (day === 0 ? -6 : 1); + date.setDate(diff); + return date; +} + +function formatDateShort(d: Date): string { + return `${d.getDate().toString().padStart(2, "0")}/${(d.getMonth() + 1).toString().padStart(2, "0")}`; +} + +export default function StaffSchedulePage() { + const { user, logout } = useAuth(); + const { + view, + setView, + currentDate, + goToNextWeek, + goToPrevWeek, + goToNextMonth, + goToPrevMonth, + goToToday, + getWeeklyBudget, + } = useShift(); + + const [selectedShift, setSelectedShift] = useState(null); + const [detailOpen, setDetailOpen] = useState(false); + const [createOpen, setCreateOpen] = useState(false); + const [createDate, setCreateDate] = useState(); + + const isManager = user?.role === "manager"; + + const handleShiftClick = (shift: ShiftSlot) => { + setSelectedShift(shift); + setDetailOpen(true); + }; + + const handleCreateShift = (date: string) => { + setCreateDate(date); + setCreateOpen(true); + }; + + const handleDateSelect = (date: string) => { + // In month view on desktop, clicking a date could open create modal for managers + if (isManager) { + setCreateDate(date); + setCreateOpen(true); + } + }; + + // Week range label + const monday = getMonday(currentDate); + const sunday = new Date(monday); + sunday.setDate(monday.getDate() + 6); + const weekLabel = `${formatDateShort(monday)} – ${formatDateShort(sunday)}`; + + const weeklyBudget = getWeeklyBudget(); + + return ( +
+ {/* ── Sidebar (Desktop) ── */} + + + {/* ── Main content ── */} +
+ {/* Header */} +
+
+

+ Đăng ký ca làm +

+

+ {view === "week" ? weekLabel : `${MONTH_NAMES[currentDate.getMonth()]} ${currentDate.getFullYear()}`} +

+
+ +
+ {/* View toggle (mobile) */} +
+ + +
+ + {/* Navigation arrows */} +
+ + + +
+ + {/* Create shift button (manager only) */} + {isManager && ( + + )} + + {/* Mobile nav */} +
+ + +
+
+
+ + {/* Content */} +
+ {/* Desktop views */} +
+ {view === "week" ? ( + + ) : ( + + )} +
+ + {/* Mobile view */} +
+ {view === "week" ? ( + + ) : ( + + )} +
+ + {/* Mobile FAB for manager */} + {isManager && ( + + )} +
+
+ + {/* Modals */} + { + setDetailOpen(false); + setSelectedShift(null); + }} + /> + setCreateOpen(false)} + defaultDate={createDate} + /> +
+ ); +} diff --git a/components/COMPONENTS.md b/components/COMPONENTS.md index 93b80dd..4973951 100644 --- a/components/COMPONENTS.md +++ b/components/COMPONENTS.md @@ -1,7 +1,7 @@ # Components Documentation -> This project follows **Atomic Design** pattern. See `Atomic.md` at project -> root for full structure guide. +> This project follows **Atomic Design** pattern. +> See `Atomic.md` at project root for full structure guide. ## Directory Structure @@ -19,21 +19,17 @@ components/ ### ProductCard (`molecules/cards/ProductCard.tsx`) -**Description:** Product card molecule. Displays product image, name, -description, formatted price, and a Buy button. Width is controlled by the -parent grid (w-full). +**Description:** Product card molecule. Displays product image, name, description, formatted price, and a Buy button. Width is controlled by the parent grid (w-full). **Atomic level:** Molecule (composed of Button, Caption, Text atoms) ### ShopCard (`molecules/cards/ShopCard.tsx`) -**Description:** Shop discovery card. Displays shop image, name, address, and a -link to the menu. +**Description:** Shop discovery card. Displays shop image, name, address, and a link to the menu. ### SearchBar (`molecules/search-bar/SearchBar.tsx`) -**Description:** Search input with clear button. Controlled component — value -and onChange come from parent. +**Description:** Search input with clear button. Controlled component — value and onChange come from parent. --- @@ -41,41 +37,35 @@ and onChange come from parent. ### CategorySidebar (`organisms/navigation/CategorySidebar.tsx`) -**Description:** Left sidebar with collapsible category filter. Sticky below -header, full viewport height minus header. +**Description:** Left sidebar with collapsible category filter. Sticky below header, full viewport height minus header. ### CartFab (`organisms/cart/CartFab.tsx`) -**Description:** Floating Action Button displaying cart item count. Links to -/payment page. +**Description:** Floating Action Button displaying cart item count. Links to /payment page. ### ProductGrid (`organisms/product-grid/ProductGrid.tsx`) -**Description:** Full product grid organism with mobile category tabs, -filtering, and empty state. Uses useCart and useMenu contexts. +**Description:** Full product grid organism with mobile category tabs, filtering, and empty state. Uses useCart and useMenu contexts. ### ShopGrid (`organisms/shop-grid/ShopGrid.tsx`) -**Description:** Responsive grid of ShopCard molecules for the feed/discovery -page. +**Description:** Responsive grid of ShopCard molecules for the feed/discovery page. ### ReviewModal (`organisms/modals/ReviewModal.tsx`) -**Description:** Modal for customer reviews. Shows 5-star rating and textarea. -After submission, displays thank-you message. +**Description:** Modal for customer reviews. Shows 5-star rating and textarea. After submission, displays thank-you message. ### Analytics Charts (`organisms/analytics/`) -**Description:** Pure-SVG chart and table components for the Financial Analytics -dashboard. All components are interactive with hover tooltips. +**Description:** Pure-SVG chart and table components for the Financial Analytics dashboard. All components are interactive with hover tooltips. -| Component | File | Description | -| ------------ | ---------------- | ---------------------------------------------------------- | -| LineChart | LineChart.tsx | Revenue trend line chart with area fill and hover tooltips | -| BarChart | BarChart.tsx | Grouped bar chart comparing current vs previous period | -| PieChart | PieChart.tsx | Pie chart with interactive legend for category breakdown | -| SummaryCard | SummaryCard.tsx | Metric card with period-over-period comparison indicator | -| ProductTable | ProductTable.tsx | Sortable product sales table with profit margin badges | +| Component | File | Description | +|-----------|------|-------------| +| LineChart | LineChart.tsx | Revenue trend line chart with area fill and hover tooltips | +| BarChart | BarChart.tsx | Grouped bar chart comparing current vs previous period | +| PieChart | PieChart.tsx | Pie chart with interactive legend for category breakdown | +| SummaryCard | SummaryCard.tsx | Metric card with period-over-period comparison indicator | +| ProductTable | ProductTable.tsx | Sortable product sales table with profit margin badges | **Usage:** Imported via `@/components/organisms/analytics` barrel index. @@ -85,13 +75,11 @@ dashboard. All components are interactive with hover tooltips. ### MainLayout (`templates/main-layout/MainLayout.tsx`) -**Description:** Main layout template — wraps content with Header, Footer, and -CartFab. Used by (main) route group. +**Description:** Main layout template — wraps content with Header, Footer, and CartFab. Used by (main) route group. ### AuthLayout (`templates/auth-layout/AuthLayout.tsx`) -**Description:** Auth layout template — centers content in screen. Used by -login/register pages. +**Description:** Auth layout template — centers content in screen. Used by login/register pages. ### FeedLayout (`templates/feed-layout/FeedLayout.tsx`) @@ -99,8 +87,7 @@ login/register pages. ### ManagerLayout (`templates/manager-layout/ManagerLayout.tsx`) -**Description:** Manager layout template — auth guard + ManagerProvider. Used by -the manager route group. +**Description:** Manager layout template — auth guard + ManagerProvider. Used by the manager route group. --- @@ -108,20 +95,16 @@ the manager route group. ### AuthContext (`lib/auth-context.tsx`) -Manages user authentication state including login, logout, and registration. -Uses localStorage for persistence. +Manages user authentication state including login, logout, and registration. Uses localStorage for persistence. ### CartContext (`lib/cart-context.tsx`) -Manages shopping cart state with localStorage persistence. Tracks items, -quantities, and totals. +Manages shopping cart state with localStorage persistence. Tracks items, quantities, and totals. ### MenuContext (`lib/menu-context.tsx`) -Provides shared activeCategory state across components. Synchronizes Header -mobile menu and CategorySidebar selection. +Provides shared activeCategory state across components. Synchronizes Header mobile menu and CategorySidebar selection. ### ManagerContext (`lib/manager-context.tsx`) -Manages menu CRUD state (products, combos, categories) for the manager -dashboard. +Manages menu CRUD state (products, combos, categories) for the manager dashboard. diff --git a/components/atoms/ATOMS.md b/components/atoms/ATOMS.md index e11486f..5ab88d3 100644 --- a/components/atoms/ATOMS.md +++ b/components/atoms/ATOMS.md @@ -42,7 +42,6 @@ Main interactive button component with multiple variants and sizes. - All standard HTML button attributes **Usage:** - ```tsx import { Button } from "@/components/atoms"; @@ -60,7 +59,6 @@ import { Button } from "@/components/atoms"; ``` **Styling:** - - Primary: Branded color with dark hover - Secondary: Border style with light background on hover - Danger: Red for destructive actions @@ -80,7 +78,6 @@ Button designed specifically for icon-only interactions. - All standard HTML button attributes **Usage:** - ```tsx import { IconButton } from "@/components/atoms"; @@ -105,7 +102,6 @@ General text input field with optional label, error, and icon. - All standard HTML input attributes **Usage:** - ```tsx import { TextInput } from "@/components/atoms"; @@ -139,7 +135,6 @@ Search input with built-in search icon and clear button. - All standard HTML input attributes **Usage:** - ```tsx import { SearchInput } from "@/components/atoms"; @@ -166,7 +161,6 @@ Multi-line text input with optional label and error. - All standard HTML textarea attributes **Usage:** - ```tsx import { Textarea } from "@/components/atoms"; @@ -194,7 +188,6 @@ Semantic heading component with level-based sizing. - All standard HTML heading attributes **Sizing:** - - Level 1: text-3xl font-bold - Level 2: text-2xl font-bold - Level 3: text-xl font-bold @@ -203,7 +196,6 @@ Semantic heading component with level-based sizing. - Level 6: text-sm font-semibold **Usage:** - ```tsx import { Heading } from "@/components/atoms"; @@ -225,14 +217,12 @@ Paragraph text with semantic variants. - All standard HTML paragraph attributes **Variants:** - - body1: text-base (main content) - body2: text-sm (secondary content) - caption: text-xs (smallest text) - label: text-sm font-medium (form labels) **Usage:** - ```tsx import { Text } from "@/components/atoms"; @@ -254,7 +244,6 @@ Small caption/note text component. - All standard HTML span attributes **Usage:** - ```tsx import { Caption } from "@/components/atoms"; @@ -279,7 +268,6 @@ Labeled badge component for highlighting information. - All standard HTML span attributes **Variants:** - - primary: Branded color - secondary: Light gray - success: Green @@ -287,7 +275,6 @@ Labeled badge component for highlighting information. - warning: Yellow **Usage:** - ```tsx import { Badge } from "@/components/atoms"; @@ -309,7 +296,6 @@ Specialized badge for displaying formatted prices. - All standard HTML span attributes **Usage:** - ```tsx import { PriceBadge } from "@/components/atoms"; @@ -318,7 +304,6 @@ import { PriceBadge } from "@/components/atoms"; ``` **Output:** - - VND: "50.000 ₫" - USD: "$99.99" @@ -336,7 +321,6 @@ Visual separator element. - All standard HTML hr attributes **Usage:** - ```tsx import { Divider } from "@/components/atoms"; @@ -430,7 +414,6 @@ import type { ``` ### Product Card - ```tsx
Product Name @@ -443,7 +426,6 @@ import type { ``` ### Rating Display - ```tsx
Reviews @@ -457,7 +439,6 @@ import type { ## 🧪 Testing Atoms ### Props Validation - ```tsx // ✅ Valid diff --git a/components/atoms/buttons/IconButton.tsx b/components/atoms/buttons/IconButton.tsx new file mode 100644 index 0000000..8c8c3e4 --- /dev/null +++ b/components/atoms/buttons/IconButton.tsx @@ -0,0 +1,46 @@ +"use client"; + +import type { ButtonProps } from "./Button.types"; + +export default function IconButton({ + variant = "primary", + size = "md", + icon, + disabled = false, + className = "", + children, + style: _style, + ...props +}: ButtonProps) { + const baseStyles = + "font-semibold rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed inline-flex items-center justify-center"; + + const variants: Record, string> = { + primary: + "bg-(--color-primary) text-white hover:bg-(--color-primary-dark) active:scale-95", + secondary: + "border border-(--color-border) hover:bg-(--color-border-light) active:scale-95", + danger: "bg-red-500 text-white hover:bg-red-600 active:scale-95", + ghost: "bg-transparent hover:bg-(--color-border-light) active:scale-95", + primaryNoBorder: + "bg-(--color-primary) text-white hover:bg-(--color-primary-dark) active:scale-95", + bgWhite: + "bg-white text-(--color-text-primary) hover:bg-gray-100 active:scale-95", + }; + + const sizes = { + sm: "h-8 w-8 text-sm", + md: "h-10 w-10 text-base", + lg: "h-12 w-12 text-lg", + }; + + return ( + + ); +} diff --git a/components/molecules/cards/PaymentSummaryCard.tsx b/components/molecules/cards/PaymentSummaryCard.tsx index adc8505..fb561ef 100644 --- a/components/molecules/cards/PaymentSummaryCard.tsx +++ b/components/molecules/cards/PaymentSummaryCard.tsx @@ -13,13 +13,14 @@ export default function PaymentSummaryCard({ isCustomer = false, backHref, }: PaymentSummaryCardProps) { - const [isReviewOpen, setIsReviewOpen] = useState(false); - const handlePayment = () => { + + const [isReviewOpen, setIsReviewOpen] = useState(false); + const handlePayment = () => { // UI-only: open review modal after "payment" if (isCustomer) { - setIsReviewOpen(true); - } - }; + setIsReviewOpen(true); + } +}; return (