docs: update and create comprehensive markdown documentation

- Updated README.md with current features (Auth, Cart, Feed pages)
- Updated COMPONENTS.md with CartFab and all context providers (Auth, Cart, Menu)
- Created APP.md: detailed documentation of all routes and pages
- Created LIB.md: documentation of types, constants, and contexts
- Created LAYOUTS.md: header and footer component documentation
- Updated TODO.md: reflects completed implementations and future work

This provides agents with comprehensive documentation to understand the project structure and implementation details.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Thanh Quy - wolf
2026-03-29 20:17:55 +07:00
parent e2aeebd0e1
commit 284183098e
6 changed files with 1653 additions and 58 deletions
+92 -23
View File
@@ -8,17 +8,46 @@ Dự án Frontend cho hệ thống đặt món cà phê, xây dựng bằng Next
Giao diện người dùng (frontend) cho hệ thống đặt và bán đồ uống trực tuyến.
### Trang Người Dùng (User Page - /)
Dành cho khách hàng:
- Duyệt thực đơn theo danh mục (sidebar collapsible)
- Tìm kiếm món theo tên / mô tả
- Xem card sản phẩm với giá và nút Mua
- Lọc tự động theo trạng thái available
### Tính Năng Hiện Tại
### Trang Quản Lý (Manager Page - chưa triển khai)
Dành cho chủ quán / nhân viên:
- Quản lý thực đơn (thêm, sửa, xóa món)
- Theo dõi và xử lý đơn hàng
#### 1. **Trang Đăng Nhập & Đăng Ký** (app/(main)/login, app/(main)/register)
- Form đăng nhập với validation (username, password)
- Form đăng ký với xác thực OTP
- Lưu trữ thông tin người dùng trong localStorage
- Hỗ trợ 3 loại tài khoản: Manager, Staff, Customer
- Hiển thị thông tin shop trong form
#### 2. **Trang Khám Phá Quán Nước** (app/(feed)/feed)
- Danh sách các quán cà phê
- Tìm kiếm theo tên quán và địa chỉ
- Thẻ quán với ảnh, địa chỉ, nút "Xem menu"
- Responsive layout (grid 1/2/3 cột)
- Empty state khi không tìm thấy quán
#### 3. **Trang Chính - Duyệt Thực Đơn** (app/(main))
Dành cho khách hàng:
- Sidebar collapsible (64px/240px) - danh mục sản phẩm
- Grid sản phẩm responsive (1-5 cột tuỳ thiết bị)
- Tìm kiếm món theo tên / mô tả
- Xem card sản phẩm với giá và nút "Mua"
- Lọc tự động theo trạng thái available
- Mobile menu: scrollable category tabs (< md)
#### 4. **Hệ Thống Giỏ Hàng** (lib/cart-context.tsx)
- Lưu trữ trạng thái giỏ trong localStorage
- Thêm/xóa/tăng/giảm số lượng sản phẩm
- Tính tổng giá và số mặt hàng
- Persist dữ liệu giữa các session
#### 5. **Hệ Thống Xác Thực** (lib/auth-context.tsx)
- Quản lý trạng thái người dùng (login/logout/register)
- Lưu thông tin user trong localStorage
- Mock auth database với 3 loại tài khoản
- Hỗ trợ hoàn tất đăng ký qua OTP
#### 6. **Hệ Thống Danh Mục** (lib/menu-context.tsx)
- Chia sẻ trạng thái category giữa Header mobile và Sidebar
- Tự động clear search khi thay đổi category
---
@@ -56,23 +85,45 @@ pnpm lint
```
frondend/
+-- app/ # Next.js App Router
| +-- layout.tsx # Root layout
| +-- page.tsx # Trang chủ - sidebar + product grid
| +-- layout.tsx # Root layout + Header + Footer
| +-- globals.css # CSS design tokens + Tailwind import
| +-- providers.tsx # Context providers (Auth, Menu, Cart)
| +-- APP.md # Tài liệu chi tiết về routes
| +-- (main)/ # Main route group
| | +-- layout.tsx # Main layout
| | +-- page.tsx # Trang chính - duyệt thực đơn
| | +-- login/page.tsx # Trang đăng nhập
| | +-- register/page.tsx # Trang đăng ký
| | +-- payment/page.tsx # Trang thanh toán
| +-- (feed)/ # Feed route group
| +-- layout.tsx # Feed layout
| +-- feed/page.tsx # Trang khám phá quán nước
+-- components/ # Shared UI components
| +-- Navbar.tsx # Sidebar danh mục (collapsible)
| +-- CartProduct.tsx # Card sản phẩm
| +-- COMPONENTS.md # Tài liệu component
| +-- CartFab.tsx # FAB - nút giỏ hàng floating
| +-- COMPONENTS.md # Tài liệu chi tiết components & contexts
+-- layouts/ # Layout-level components
| +-- header.tsx # Sticky top header
| +-- footer.tsx # Footer
| +-- header.tsx # Sticky top header + auth demo
| +-- footer.tsx # Footer + shop info
| +-- LAYOUTS.md # Tài liệu chi tiết layouts
+-- lib/ # Shared logic & data
| +-- constants.ts # Mock data
| +-- constants.ts # Mock data (products, shops, users, shop info)
| +-- types.ts # TypeScript interfaces
| +-- auth-context.tsx # Authentication context & provider
| +-- cart-context.tsx # Shopping cart context & provider
| +-- menu-context.tsx # Menu/Category context & provider
| +-- LIB.md # Tài liệu chi tiết về lib
+-- types/ # Global TypeScript declarations
| +-- css.d.ts # CSS module type shim
+-- public/ # Static assets
+-- WORKFLOW.md # Tài liệu kiến trúc & quy trình
| +-- imgs/
| | +-- logo.png
| | +-- products/ # Ảnh sản phẩm
| +-- favicon/
+-- WORKFLOW.md # Tài liệu kiến trúc tổng thể & quy trình
+-- README.md # (file này) - Mô tả dự án
+-- TODO.md # Danh sách tính năng hoàn thành & chưa làm
+-- next.config.ts
+-- tsconfig.json
+-- postcss.config.mjs
@@ -100,9 +151,27 @@ frondend/
## Ghi Chú Phát Triển
- Trang chủ (app/page.tsx) là điểm vào chính của User Page
- Design tokens định nghĩa trong app/globals.css dưới dạng CSS custom properties
- Mock data nằm trong lib/constants.ts - thay bằng API calls khi backend sẵn sàng
- Dark mode: biến CSS đã chuẩn bị sẵn trong globals.css nhưng chưa kích hoạt
- Ảnh sản phẩm: thêm ảnh thực vào public/imgs/products/
- Xem WORKFLOW.md để hiểu kiến trúc tổng thể và quy trình mở rộng dự án
### Điểm Vào Chính
- **Trang Chủ (User):** `app/(main)/page.tsx` - Duyệt thực đơn
- **Trang Khám Phá:** `app/(feed)/feed/page.tsx` - Khám phá quán
- **Đăng Nhập:** `app/(main)/login/page.tsx`
- **Đăng Ký:** `app/(main)/register/page.tsx`
### Design & Styling
- Design tokens (CSS variables) định nghĩa trong `app/globals.css`
- Tailwind CSS v4 + custom properties cho consistent color/spacing
- Dark mode: biến CSS đã chuẩn bị sẵn nhưng chưa kích hoạt
- FontAwesome icons từ CDN
### Data & Integration
- Mock data nằm trong `lib/constants.ts`
- Context providers trong `app/providers.tsx` - Sử dụng: AuthProvider, MenuProvider, CartProvider
- Thay bằng API calls khi backend sẵn sàng
- Ảnh sản phẩm: thêm vào `public/imgs/products/`
### Tài Liệu Chi Tiết
- **WORKFLOW.md** - Kiến trúc tổng thể, data flow, quy trình phát triển
- **APP.md** - Chi tiết các routes, layouts, pages
- **COMPONENTS.md** - Tài liệu từng component + contexts
- **LAYOUTS.md** - Header, Footer, responsive behavior
- **LIB.md** - Constants, Types, Contexts
+102 -35
View File
@@ -1,52 +1,119 @@
# Coffee Shop Frontend - TODO
## Completed Optimizations
## Completed Features & Implementations
### A. Dead Code Removed
- [x] lib/constants.ts - Removed unused NAV_LINKS export
- [x] lib/types.ts - Removed unused NavLink interface
- [x] components/Navbar.tsx - Removed trivial handleClick wrapper; inlined onCategoryChange call
- [x] components/Navbar.tsx - Removed unused Link import
### A. Documentation
- [x] README.md - Updated with current features (Auth, Cart, Feed, etc.)
- [x] COMPONENTS.md - Added CartFab, AuthContext, CartContext, MenuContext sections
- [x] APP.md - New file: Detailed app routes, pages, layouts
- [x] LIB.md - New file: Types, Constants, Contexts documentation
- [x] LAYOUTS.md - New file: Header & Footer detailed documentation
- [x] WORKFLOW.md - Architecture and workflow documentation
### B. Bugs / Inaccuracies Fixed
- [x] layouts/header.tsx - Fixed JSDoc: 3-column -> 2-column layout (no center section exists)
- [x] app/page.tsx - Added available !== false filter to product list
- [x] app/page.tsx - Fixed setState-in-effect lint error: moved initial sidebar state to lazy useState initializer
- [x] next.config.ts - Added explanatory JSDoc comment
### B. Authentication System
- [x] lib/auth-context.tsx - Created Auth context with login/logout/register
- [x] lib/types.ts - User type with roles (manager, staff, customer)
- [x] app/(main)/login/page.tsx - Login page with form validation
- [x] app/(main)/register/page.tsx - Register page with OTP verification
- [x] localStorage integration - Persist user across sessions
- [x] Mock auth database - Pre-configured accounts for testing
### C. Documentation Updated
- [x] README.md - Fixed file structure tree, removed SCSS, fixed dark mode note, updated tech table
- [x] components/COMPONENTS.md - Fixed CartProduct styling (was outdated w-64/text-red-500/bg-blue-600); added Navbar, Header, Footer sections
### C. Shopping Cart System
- [x] lib/cart-context.tsx - Cart context with add/remove/update operations
- [x] Cart persistence - localStorage integration
- [x] CartItem interface - With id, name, description, price, quantity
- [x] Cart operations - addToCart, increaseQty, decreaseQty, removeFromCart, setQuantity
- [x] Computed totals - totalItems and totalPrice memoized
### D. New Documentation Created
- [x] WORKFLOW.md - Architecture, data flow, design token system, how-to guides, dev workflow
### D. Menu/Category System
- [x] lib/menu-context.tsx - MenuContext for shared category state
- [x] Shared state across components - Header mobile menu + Navbar sidebar sync
- [x] Category filtering - Products filtered by active category
### E. Mini-test Results
- [x] npm run lint - PASSED (0 errors, 0 warnings)
- [x] npm run build - PASSED (Compiled successfully, TypeScript clean, static pages generated)
### E. Product Pages
- [x] app/(main)/page.tsx - Main page with sidebar + product grid
- [x] Responsive product grid - 1-5 columns depending on sidebar & screen size
- [x] Product search - Search by name and description
- [x] Category filter - Sidebar collapsible navigation
- [x] Mobile category menu - Scrollable tabs on < md breakpoint
- [x] Empty states - Messaging when no products match filters
- [x] CartProduct component - Product card with image, price, buy button
### F. Feed/Discovery Page
- [x] app/(feed)/feed/page.tsx - Shop discovery page
- [x] Shop grid - Responsive 1/2/3 column layout
- [x] Search by name and address - Sticky bottom filter bar
- [x] Shop cards - Image, name, address, view menu button
- [x] Empty state - Message when no shops match filters
- [x] MOCK_SHOPS constant - 5 sample coffee shops
### G. Header & Footer
- [x] layouts/header.tsx - Sticky header with brand and auth demo
- [x] layouts/footer.tsx - Footer with shop info, social links, WiFi
- [x] Responsive layouts - Mobile/tablet/desktop optimized
- [x] Auth state display - Guest/Manager/Staff cycling demo
### H. Code Quality & Optimization
- [x] Dead code removed - Unused imports and exports cleaned
- [x] Lint passed - 0 errors, 0 warnings
- [x] Build passed - TypeScript clean, all pages compile
- [x] Type safety - Full TypeScript coverage
- [x] React best practices - Hooks, memoization, context patterns
---
## Pending Features (Future Work)
### Cart & Ordering
- [ ] Implement add-to-cart logic (onBuy callback in CartProduct)
- [ ] Cart sidebar or modal with item list and total
- [ ] Order submission flow
- [ ] Payment page
- [ ] Implement cart checkout flow (app/(main)/cart or modal)
- [ ] Cart sidebar/modal with item list and total
- [ ] Order submission API integration
- [ ] Payment page implementation (app/(main)/payment)
- [ ] Order history/tracking page
- [ ] Toast notifications for cart actions
### Authentication & User Management
- [ ] Real backend authentication (replace MOCK_AUTH_DB)
- [ ] Real OTP delivery service (SMS integration)
- [ ] User profile page with edit capability
- [ ] Password reset/recovery flow
- [ ] Session management and token refresh
### Manager Features
- [ ] Manager dashboard page (app/(manager)/page.tsx)
- [ ] Product management (add/edit/delete)
- [ ] Category management
- [ ] Order management & tracking
- [ ] Sales analytics/dashboard
- [ ] Inventory management
### Backend Integration
- [ ] Replace MOCK_PRODUCTS with real API calls (lib/api.ts)
- [ ] Replace MOCK_USERS with real authentication
- [ ] Product images: replace placeholder with real images in public/imgs/products/
### Manager Page
- [ ] Create app/manager/page.tsx
- [ ] Menu management (add/edit/delete products)
- [ ] Order tracking dashboard
- [ ] Replace MOCK_PRODUCTS with API calls (GET /api/products)
- [ ] Replace MOCK_SHOPS with API calls (GET /api/shops)
- [ ] Replace MOCK_USERS with real authentication (POST /api/auth/login)
- [ ] Real product images (replace placeholder.jpg)
- [ ] Image upload for products
### UX Improvements
- [ ] Dark mode toggle (CSS variables already prepared in globals.css)
- [ ] Loading skeleton for product grid
- [ ] Toast notifications for cart actions
- [ ] Product detail modal/page
- [ ] Dark mode toggle (CSS variables prepared, toggle UI needed)
- [ ] Loading skeletons for product grid
- [ ] Product detail modal/page with full description
- [ ] Wishlist/favorites feature
- [ ] Sort products (price, rating, etc.)
- [ ] Filter by price range
- [ ] Quantity selector in product card
- [ ] Related products suggestions
### Performance & SEO
- [ ] Dynamic route generation for products (app/(main)/product/[id]/page.tsx)
- [ ] Dynamic route generation for shops (app/(feed)/shop/[id]/page.tsx)
- [ ] Meta tags and Open Graph for SEO
- [ ] Image optimization and lazy loading
- [ ] Code splitting and dynamic imports
### Accessibility & Testing
- [ ] Keyboard navigation testing
- [ ] ARIA labels audit
- [ ] Unit tests for contexts
- [ ] E2E tests for user flows
- [ ] Accessibility audit (WCAG 2.1 AA)
+361
View File
@@ -0,0 +1,361 @@
# App Routes & Pages Documentation
> Tài liệu chi tiết về Next.js App Router structure, routes, và layouts
---
## Route Structure Overview
```
app/
├── layout.tsx # Root layout - Header + Footer wrapper
├── globals.css # CSS tokens + Tailwind imports
├── providers.tsx # Context providers (Auth, Menu, Cart)
├── (main)/
│ ├── layout.tsx # Main layout for authenticated routes
│ ├── page.tsx # Main page - Duyệt thực đơn (/)
│ ├── login/
│ │ └── page.tsx # Trang đăng nhập (/login)
│ ├── register/
│ │ └── page.tsx # Trang đăng ký (/register)
│ └── payment/
│ └── page.tsx # Trang thanh toán (/payment)
└── (feed)/
├── layout.tsx # Feed layout
└── feed/
└── page.tsx # Trang khám phá quán (/feed)
```
---
## Root Layout (app/layout.tsx)
**Description:** Root layout wrapping entire application. Loads providers, fonts, and common layouts (header/footer).
### Structure
- Imports providers (AuthProvider, MenuProvider, CartProvider)
- Renders Header component (sticky top)
- Renders page content via {children}
- Renders Footer component
### Metadata
- Title: "Coffee Shop"
- Charset: UTF-8
- Viewport: responsive
### Key Features
- Global CSS variables loaded here
- Header remains sticky across all pages
- Footer always present
---
## Providers (app/providers.tsx)
**Description:** Client component that wraps all context providers for the application.
### Providers Included
1. **AuthProvider** (lib/auth-context.tsx)
- Manages user authentication state
- Persists user in localStorage
- Enables login/logout/register flows
2. **MenuProvider** (lib/menu-context.tsx)
- Shares active category state
- Syncs Header mobile menu and Navbar sidebar
3. **CartProvider** (lib/cart-context.tsx)
- Manages shopping cart state
- Persists cart items in localStorage
- Provides add/remove/update operations
### Usage in Root Layout
```tsx
<Providers>
<Header />
{children}
<Footer />
</Providers>
```
---
## (main) Route Group
### Layout (app/(main)/layout.tsx)
**Description:** Layout for authenticated/main routes. Can include route-specific UI (e.g., sidebar navigation).
### Usage
- Wraps all pages under `(main)/` route group
- Inherits root layout above it
- Can add additional styling or structure specific to main pages
---
## Pages
### 1. Main Page - Duyệt Thực Đơn (app/(main)/page.tsx)
**Route:** `/` (default) or `/(main)`
**Type:** Client component
**Description:** Main shopping interface. Shows product grid with sidebar category filter.
#### Key Features
- **Sidebar (Navbar):**
- Collapsible (64px collapsed / 240px expanded)
- Category list with icons
- Sticky, full viewport height minus header
- Responsive: desktop (expanded) vs mobile (collapsed)
- **Product Grid:**
- Responsive columns (1/2/3/4/5 depending on sidebar state and screen size)
- Filter by: availability, active category, search query
- Search bar with clear button
- Empty state when no products match
- **Mobile Category Menu:**
- Visible only on screens < md (768px)
- Sticky scrollable tabs below search
- Allows category selection on mobile
#### Context Usage
- **useMenu()** - Get/set active category
- **useCart()** - Add products to cart
- **MenuContext** - Shares category state with Header
#### State Management
```tsx
isSidebarOpen: boolean // Sidebar expanded/collapsed
searchQuery: string // Search input value
activeCategory: string // From MenuContext
```
#### Responsive Behavior
- **Mobile (<480px):** 1 col, sidebar collapsed
- **Small phone (480px):** 2 cols, sidebar collapsed
- **Tablet (768px):** Mobile menu tabs appear
- **Desktop (1024px):** Sidebar expands, 2-4 cols depending on sidebar
- **Large screen (1280px+):** 3-5 cols
---
### 2. Login Page (app/(main)/login/page.tsx)
**Route:** `/login`
**Type:** Client component
**Description:** User authentication form. Supports login for Manager, Staff, and Customer roles.
#### Key Features
- **Form Fields:**
- Username input (with icon)
- Password input (with show/hide toggle)
- "Dang nhap" button
- "Dang ky tai khoan" link to register
- **Validation:**
- Username: required, non-empty
- Password: required, min 4 characters
- Error messages displayed inline
- **Demo Credentials:**
- Shows example accounts for testing:
- Manager: `admin / admin`
- Staff: `Nguyễn Văn An / Nguyễn Văn An`
- Customer: `0987654321 / user1`
- **UI:**
- Centered card (max-width: 448px)
- Shop logo and name at top
- Error messages with icons
- Responsive design
#### Context Usage
- **useAuth()** - Login function
#### Navigation
- Success: redirect to `/` (main page)
- Register link: go to `/register`
---
### 3. Register Page (app/(main)/register/page.tsx)
**Route:** `/register`
**Type:** Client component
**Description:** User registration flow. Two-step process: phone verification → account creation.
#### Key Features
- **Step 1: Phone Verification**
- Input phone number
- "Request OTP" button
- Mock OTP validation (no real SMS)
- **Step 2: Account Creation** (after OTP)
- Confirm phone number
- "Create Account" button
- Auto-login after registration
- **Validation:**
- Phone format validation
- OTP code validation
- **UI:**
- Centered card layout
- Step indicator
- Progress feedback
#### Context Usage
- **useAuth()** - completeRegistration()
#### Navigation
- Success: redirect to `/` (main page)
- Login link: go to `/login`
---
### 4. Payment Page (app/(main)/payment/page.tsx)
**Route:** `/payment`
**Type:** Client component (TBD)
**Description:** Payment/checkout page. Currently a placeholder; implement when cart and order system are ready.
---
## (feed) Route Group
### Layout (app/(feed)/layout.tsx)
**Description:** Layout for feed routes. Can have specific styling for discovery/exploration pages.
---
### Feed Page - Khám Phá Quán (app/(feed)/feed/page.tsx)
**Route:** `/feed`
**Type:** Client component
**Description:** Discover coffee shops. Browse and search available shops with their location and details.
#### Key Features
- **Shop Cards:**
- Shop image (responsive height)
- Name and location
- "Xem menu" button (links to `/`)
- Hover effects with shadow/lift animation
- **Search & Filter:**
- Sticky bottom filter bar
- Search by shop name
- Search by address
- Clear buttons for each field
- **Grid Layout:**
- Responsive (1/2/3 columns)
- Adjusts to screen size
- **Empty State:**
- Icon and message when no shops match
- Clear filter button
#### Context Usage
- **useAuth()** - Optional: check user role
#### State Management
```tsx
searchName: string // Shop name search
searchAddress: string // Shop address search
filteredShops: Shop[] // Filtered results
```
#### Data Source
- MOCK_SHOPS from lib/constants.ts
---
## CSS & Styling
### Global Styles (app/globals.css)
**Description:** Root CSS file. Imports Tailwind CSS, defines design tokens (CSS variables), and global styles.
### Design Tokens (CSS Variables)
Defined at `:root` for light mode, with dark mode variants:
#### Colors
- `--color-primary` - Main brand color (brown)
- `--color-primary-dark` - Darker shade for hover
- `--color-accent` - Secondary accent color
- `--color-bg-*` - Background colors (main, card, sidebar)
- `--color-border-*` - Border colors
- `--color-text-*` - Text colors (primary, secondary, muted)
- `--color-shadow-*` - Shadow colors (sm, md)
#### Spacing
- `--spacing-header-height` - Header component height
- Standard Tailwind spacing (via Tailwind)
#### Typography
- Font stack defined via Google Fonts (Geist)
### Tailwind Config Integration
- v4 with custom properties support
- Extends with CSS variables
- Dark mode: CSS variable override
---
## Key Concepts
### Route Groups
- `(main)` and `(feed)` are route groups (don't appear in URL)
- Allow different layouts/providers per route group
- Used for organization and flexibility
### SSR vs Client Components
- Most pages are "use client" (need interactivity)
- Context providers must be client components
- Layout.tsx can be server component
### Responsive Design
- Breakpoints: sm (640px), md (768px), lg (1024px), xl (1280px), 2xl (1536px)
- Sidebar width affects grid columns
- Mobile: vertical layout, collapsed sidebar
- Desktop: horizontal layout, expanded sidebar
### Navigation
- Internal links use `next/link`
- useRouter() for programmatic navigation
- Auth redirects after login/register
---
## Development Workflow
### Adding a New Page
1. Create file under appropriate route group: `app/(main)/new-feature/page.tsx`
2. Make it a client component if it needs interactivity: `"use client"`
3. Use context hooks as needed (useAuth, useCart, useMenu)
4. Export default component
5. Add to documentation
### Adding a New Route Group
1. Create directory: `app/(group-name)/`
2. Create `layout.tsx` if custom layout needed
3. Add pages under this group
4. Update codebase understanding
### Styling Pages
- Use Tailwind classes + CSS variables
- Reference design tokens for consistency
- Follow responsive patterns from existing pages
---
## Future Enhancements
- [ ] Payment page implementation
- [ ] Order history/tracking page
- [ ] Manager dashboard (menu management, order tracking)
- [ ] User profile page
- [ ] Cart checkout flow
- [ ] Real backend API integration
+151
View File
@@ -156,3 +156,154 @@ None - reads SHOP_INFO and SOCIAL_LINKS from lib/constants directly.
- next/image, next/link
- lib/constants: SHOP_INFO, SOCIAL_LINKS
- FontAwesome icons
---
## CartFab
**File:** components/CartFab.tsx
**Description:** Floating Action Button displaying cart item count. Shows badge with number of items and total price on hover.
### Props
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| onClick | () => void | no | undefined | Callback when FAB is clicked |
### Features
- Displays cart icon with item count badge
- Shows total price on hover in tooltip
- Sticky position (bottom-right)
- Uses cart context to get items and total
### Styling
| Element | Key classes |
|---------|-------------|
| FAB button | fixed bottom-6 right-6, rounded-full, shadow-lg |
| Badge | absolute top-0 right-0, red bg, small font |
| Tooltip | appears on hover, shows total price |
### Dependencies
- lib/cart-context: useCart()
- FontAwesome icons
---
# Contexts Documentation
## AuthContext (lib/auth-context.tsx)
**File:** lib/auth-context.tsx
**Description:** Manages user authentication state including login, logout, and registration. Uses localStorage for persistence.
### Provider Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| children | React.ReactNode | yes | Child components |
### Hook: useAuth()
Returns `AuthContextType` with:
| Property | Type | Description |
|----------|------|-------------|
| user | User \| null | Current logged-in user or null |
| login | (username: string, password: string) => boolean | Login function; returns success status |
| logout | () => void | Logout function; clears user and localStorage |
| registerPhone | string \| null | Phone number during registration flow |
| setRegisterPhone | (phone: string \| null) => void | Update registerPhone state |
| completeRegistration | (phone: string) => void | Complete registration and create customer account |
### Mock Database
Pre-configured accounts:
- Manager: `admin / admin`
- Staff: `Nguyễn Văn An / Nguyễn Văn An`, `Trần Thị Bình / Trần Thị Bình`, etc.
- Customer: Phone number as username, `user1` as password
### Storage
- Key: `coffee-shop-user`
- Format: JSON serialized User object
---
## CartContext (lib/cart-context.tsx)
**File:** lib/cart-context.tsx
**Description:** Manages shopping cart state with localStorage persistence. Tracks items, quantities, and totals.
### Provider Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| children | React.ReactNode | yes | Child components |
### Hook: useCart()
Returns `CartContextValue` with:
| Property | Type | Description |
|----------|------|-------------|
| items | CartItem[] | Array of items in cart |
| totalItems | number | Total quantity of items |
| totalPrice | number | Total price in VND |
| addToCart | (product: Product) => void | Add or increase product quantity |
| increaseQty | (id: number) => void | Increase product quantity by 1 |
| decreaseQty | (id: number) => void | Decrease product quantity by 1 (removes if qty reaches 0) |
| removeFromCart | (id: number) => void | Remove product from cart |
| setQuantity | (id: number, quantity: number) => void | Set exact quantity (removes if 0) |
### CartItem Interface
```typescript
interface CartItem {
id: number;
name: string;
description: string;
price: number;
quantity: number;
}
```
### Storage
- Key: `coffee-shop-cart`
- Format: JSON serialized CartItem[]
- Auto-loads on mount and auto-saves on change
---
## MenuContext (lib/menu-context.tsx)
**File:** lib/menu-context.tsx
**Description:** Provides shared category/menu state across components. Synchronizes Header mobile menu and Navbar sidebar selection.
### Provider Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| children | React.ReactNode | yes | Child components |
### Hook: useMenu()
Returns `MenuContextType` with:
| Property | Type | Description |
|----------|------|-------------|
| activeCategory | string | Currently selected category id (default: "all") |
| setActiveCategory | (id: string) => void | Update active category |
### Use Cases
- Sync Navbar sidebar and Header mobile menu category selection
- Clear search query when category changes (implemented in main page)
- Pass selected category to product filter logic
### Default Value
- `activeCategory: "all"` - Show all products by default
+486
View File
@@ -0,0 +1,486 @@
# Layouts Documentation
> Tài liệu chi tiết về layout components (Header, Footer) và responsive behavior
---
## Overview
The `layouts/` directory contains layout-level components used across all pages. These are included in the root layout and provide consistent header/footer across the application.
```
layouts/
├── header.tsx # Sticky top header with shop branding and auth
├── footer.tsx # Footer with shop info, social links, WiFi details
└── LAYOUTS.md # (this file)
```
---
## Header (layouts/header.tsx)
**File:** layouts/header.tsx
**Type:** Client component
**Description:** Sticky top navigation bar with brand info and authentication status display.
### Layout
```
┌─────────────────────────────────────────────────────┐
│ [Logo] [Shop Name] [Tagline] │ [Auth Status] │
└─────────────────────────────────────────────────────┘
height: 72px (var(--spacing-header-height))
```
**2-Column Layout:**
- **Left:** Shop branding (logo + name + tagline)
- **Right:** Auth status indicator
### Features
#### Logo & Branding
- Shop logo (40x40px)
- Shop name (bold text)
- Tagline (hidden on mobile < md, visible md+)
**Responsive:**
| Breakpoint | Logo | Name | Tagline |
|-----------|------|------|---------|
| < sm (640px) | Yes | Yes | Hidden |
| sm-md | Yes | Yes | Hidden |
| md+ (768px) | Yes | Yes | Visible |
#### Authentication Status
The header cycles through 3 auth states (for UI demo):
**State 1: Guest (Not logged in)**
```
[brown button] "Dang nhap"
```
- Guest state (user = null)
- Brown primary button
- Click: toggles to next state
**State 2: Manager**
```
[caramel/gold badge] "👔 Quản lý"
```
- Shows manager role
- Gold/caramel colored badge
- User tie icon
- Name: Nguyễn Văn An
**State 3: Staff**
```
[border button] "👤 [Name]"
```
- Shows staff role with avatar placeholder
- Bordered button style
- Name: Trần Thị Bình
- Click: toggles back to Guest state
### Responsive Behavior
| Breakpoint | Layout |
|-----------|--------|
| < sm | Stacked vertically |
| sm-md (640px) | Side-by-side, reduced spacing |
| md+ (768px) | Full width, comfortable spacing |
**Mobile (<640px):**
- Logo smaller
- Name only (no tagline)
- Auth button text hidden, icon shown
- Touch-friendly padding
**Desktop (≥640px):**
- Normal logo size
- Full layout with tagline
- Button with text and icon
- Comfortable spacing
### Styling
| Element | Classes |
|---------|---------|
| Header wrapper | `sticky top-0 z-50 bg-white shadow-md` |
| Container | `max-w-7xl mx-auto px-4 md:px-6 h-72px flex items-center` |
| Left section (brand) | `flex items-center gap-3 flex-1` |
| Right section (auth) | `flex items-center gap-3 shrink-0` |
| Logo image | `w-10 h-10 md:w-12 md:h-12` |
| Brand text | `font-bold text-sm md:text-base` |
| Tagline | `hidden md:block text-xs text-muted-foreground` |
| Auth button | `px-4 py-2 rounded-lg text-sm font-medium` |
### CSS Variables Used
```css
--spacing-header-height: 72px;
--color-primary: brown;
--color-primary-dark: darker brown;
--color-text-primary: text color;
--color-text-muted: gray text;
--color-shadow-sm: subtle shadow;
```
### Dependencies
- **next/image** - Logo image rendering
- **next/link** - Navigation links
- **lib/constants:** SHOP_INFO, MOCK_USERS
- **lib/types:** User
- **FontAwesome icons:** fa-sign-in-alt, fa-sign-out-alt, fa-user-tie, fa-user-circle
### Key Code Snippets
**Auth Demo State Machine:**
```typescript
const [user, setUser] = useState<User | null>(null);
const handleAuthClick = () => {
if (!user) {
setUser(MOCK_USERS.manager);
} else if (user.role === "manager") {
setUser(MOCK_USERS.staff);
} else {
setUser(null);
}
};
```
**Responsive Brand Text:**
```typescript
<div className="flex flex-col">
<span className="font-bold text-sm md:text-base">{SHOP_INFO.name}</span>
<span className="hidden md:block text-xs text-muted-foreground">
{SHOP_INFO.tagline}
</span>
</div>
```
---
## Footer (layouts/footer.tsx)
**File:** layouts/footer.tsx
**Type:** Client component (uses constants)
**Description:** Site footer with shop information, social links, and WiFi details.
### Layout
```
┌────────────────────────────────────────────┐
│ [Brand Info] │ [Social + WiFi] │
├────────────────────────────────────────────┤
│ © 2024 Coffee Shop. Made with ❤️ in VN │
└────────────────────────────────────────────┘
```
**12-Column Grid Layout:**
| Breakpoint | Brand Info | Social + WiFi |
|-----------|-----------|---------------|
| Mobile | col-span-12 | col-span-12 |
| md (768px) | col-span-6 | col-span-6 |
| lg+ (1024px) | col-span-6 | col-span-6 |
### Sections
#### 1. Brand Info (Left Section)
**Content:**
- Shop logo (40x40px)
- Shop name (bold)
- Tagline (gray text)
- Address with location icon
- Phone with phone icon
- Email with envelope icon
- Open hours with clock icon
**Responsive:**
```
Mobile:
└─ Logo
└─ Name & Tagline (stacked)
└─ Address
└─ Phone
└─ Email
└─ Open Hours
Desktop:
└─ Logo + Name/Tagline (flexbox, side-by-side)
└─ Address, Phone, Email, Hours (stacked below)
```
#### 2. Social Links (Top Right)
**Links:**
- Facebook icon → SHOP_INFO.facebook
- TikTok icon → SHOP_INFO.tiktok
- Website icon → SHOP_INFO.website
**Styling:**
- Icons in circle backgrounds
- Hover effect (color change)
- Flex row layout
- Centered alignment
#### 3. WiFi Card (Bottom Right)
**Content:**
- "📶 WiFi miễn phí" label
- Network name (monospace)
- Password (monospace, can be hidden/shown)
**Styling:**
- Light gray background
- Rounded borders
- Monospace font for credentials
- Eye icon toggle for password visibility
**Example:**
```
📶 WiFi miễn phí
┌────────────────────────┐
│ Network: CoffeeShop │
│ Password: •••••••• │
│ (eye icon) │
└────────────────────────┘
```
#### 4. Copyright Bar (Bottom)
**Content:**
- Copyright text: "© 2024 Coffee Shop"
- "Made with ❤️ in Vietnam"
- Centered
**Styling:**
- Small text
- Gray color
- Subtle separator line above
### Responsive Behavior
**Mobile (<768px):**
- Single column layout
- Stacked sections
- Full width
- Padding around edges
**Tablet (768px):**
- 2-column layout
- Brand info left, Social + WiFi right
- Equal width columns
**Desktop (≥768px):**
- 2-column layout with more spacing
- Brand info slightly smaller
- Comfortable padding
### Styling
| Element | Classes |
|---------|---------|
| Footer wrapper | `bg-gray-100 border-t` |
| Container | `max-w-7xl mx-auto px-4 py-8` |
| Grid | `grid grid-cols-12 gap-8` |
| Brand section | `col-span-12 md:col-span-6` |
| Social section | `col-span-12 md:col-span-6` |
| Logo | `w-10 h-10` |
| Info text | `text-sm text-gray-600` |
| Social icons | `w-10 h-10 rounded-full flex items-center justify-center` |
| WiFi card | `bg-white p-4 rounded-lg border` |
| Copyright bar | `border-t mt-8 pt-6 text-center text-xs text-gray-500` |
### CSS Variables Used
```css
--color-primary: brand color;
--color-text-secondary: secondary text color;
--color-text-muted: muted/gray text color;
--color-accent: accent color;
--color-border: border color;
--color-bg-*: background colors;
--color-shadow-sm: subtle shadow;
```
### Dependencies
- **next/image** - Shop logo
- **next/link** - Social links
- **lib/constants:** SHOP_INFO, SOCIAL_LINKS
- **FontAwesome icons:** location-dot, phone, envelope, clock, facebook, tiktok, globe, wifi, eye, eye-slash
### Key Code Snippets
**Brand Info Section:**
```typescript
<div className="flex gap-4">
<Image src={SHOP_INFO.logo} alt={SHOP_INFO.name} width={40} height={40} />
<div>
<h3 className="font-bold">{SHOP_INFO.name}</h3>
<p className="text-sm text-muted-foreground">{SHOP_INFO.tagline}</p>
<p className="text-sm mt-2">{SHOP_INFO.address}</p>
{/* etc */}
</div>
</div>
```
**Social Links:**
```typescript
<div className="flex gap-3">
<Link href={SOCIAL_LINKS.facebook} target="_blank" rel="noopener">
<i className="fab fa-facebook" />
</Link>
{/* etc */}
</div>
```
**WiFi Display:**
```typescript
<div className="bg-white p-4 rounded-lg">
<p className="font-semibold text-sm">📶 WiFi miễn phí</p>
<p className="font-mono text-xs mt-2">{SHOP_INFO.wifi.name}</p>
<p className="font-mono text-xs">
{showPassword ? SHOP_INFO.wifi.password : "••••••••"}
</p>
</div>
```
---
## Integration in Root Layout
**File:** app/layout.tsx
```typescript
export default function RootLayout({ children }) {
return (
<html>
<body>
<Header />
{children}
<Footer />
</body>
</html>
);
}
```
**Result:**
- Header: Always at top (sticky)
- Content: Takes full width between header/footer
- Footer: Always at bottom
---
## Responsive Design Patterns
### Header Responsive Pattern
```css
/* Mobile first */
.header {
flex-direction: column;
gap: 1rem;
padding: 1rem;
}
/* Tablet+ */
@media (min-width: 640px) {
.header {
flex-direction: row;
justify-content: space-between;
padding: 1.5rem;
}
}
/* Desktop+ */
@media (min-width: 768px) {
.header {
padding: 2rem;
}
.tagline {
display: block; /* Show tagline on desktop */
}
}
```
### Footer Responsive Pattern
```css
/* Mobile: stacked */
.footer-grid {
grid-template-columns: 1fr;
}
/* Tablet: 2 columns */
@media (min-width: 768px) {
.footer-grid {
grid-template-columns: 1fr 1fr;
}
}
```
---
## Dark Mode Support
CSS variables are set up for dark mode support. To enable:
1. Add dark mode CSS variable overrides:
```css
@media (prefers-color-scheme: dark) {
:root {
--color-bg-main: #1a1a1a;
--color-text-primary: #ffffff;
/* etc */
}
}
```
2. Or use Tailwind dark class:
```html
<div className="dark:bg-gray-900 dark:text-white">
Content
</div>
```
---
## Accessibility
### Header
- Logo has alt text
- Auth button has aria-label
- Icons have semantic meaning
- Good contrast ratios
### Footer
- Headings use semantic tags
- Links have descriptive text
- Icons are decorative (aria-hidden)
- Monospace font for technical info (WiFi credentials)
### General
- Touch targets ≥ 48px on mobile
- Sufficient color contrast
- Semantic HTML structure
- ARIA labels where needed
---
## Best Practices
1. **Keep layouts simple:** Avoid complex nested layouts
2. **Responsive first:** Use mobile-first CSS approach
3. **Reuse components:** Use Header/Footer across all pages
4. **Props over hardcoding:** Use lib/constants for data
5. **Type safety:** Use TypeScript for component props
6. **Performance:** Optimize images with next/image
7. **Accessibility:** Add ARIA labels and semantic HTML
+461
View File
@@ -0,0 +1,461 @@
# Lib Documentation
> Tài liệu chi tiết về utilities, contexts, types, và constants
---
## Overview
The `lib/` directory contains shared logic, data models, and context providers used throughout the application.
```
lib/
├── types.ts # TypeScript interfaces and types
├── constants.ts # Mock data (products, shops, users, info)
├── auth-context.tsx # Authentication context & provider
├── cart-context.tsx # Shopping cart context & provider
├── menu-context.tsx # Menu/category context & provider
└── LIB.md # (this file)
```
---
## Types (lib/types.ts)
**Description:** Central TypeScript definitions used throughout the application.
### User Type
```typescript
type UserRole = "manager" | "staff" | "customer";
interface User {
id: number;
name: string;
role: UserRole;
avatar: string | null;
phone?: string;
}
```
**Usage:** Authentication context, header component, role-based UI
**Roles:**
- **manager** - Shop owner, full access to menu management and orders
- **staff** - Staff member, can view/process orders
- **customer** - Regular customer, can browse and order
---
### Menu Types
```typescript
interface MenuCategory {
id: string;
name: string;
icon: string; // FontAwesome class e.g. "fa-solid fa-mug-hot"
}
```
**Usage:** Sidebar navigation, category filter, product display
**Example Categories:**
- `all` - All products
- `cafe` - Coffee
- `tra` - Tea
- `sua-chua` - Yogurt
- `nuoc-ep` - Juice
- `latte` - Latte drinks
- `giai-khat` - Snacks
- `topping` - Toppings
---
### Product Type
```typescript
interface Product {
id: number;
name: string;
category: string; // matches MenuCategory.id
price: number;
image: string;
description: string;
available?: boolean;
}
```
**Usage:** Product grid display, cart items, filtering
**Key Fields:**
- `id` - Unique product identifier
- `name` - Display name in Vietnamese
- `category` - Category ID for filtering
- `price` - Price in VND
- `image` - URL or path to product image
- `description` - Short 1-2 sentence description
- `available` - If `false`, product won't show (defaults to `true`)
---
### Shop Info Type
```typescript
interface WifiInfo {
name: string;
password: string;
}
interface ShopInfo {
name: string;
tagline: string;
logo: string;
address: string;
phone: string;
managerPhone: string;
email: string;
wifi: WifiInfo;
openHours: string;
}
```
**Usage:** Header, footer, login page display
**Example:**
```typescript
const SHOP_INFO: ShopInfo = {
name: "Coffee Shop",
tagline: "Hương vị đậm đà Khoảnh khắc thư giãn",
logo: "/imgs/logo.png",
address: "123 Đường Nguyễn Huệ, Quận 1, TP. Hồ Chí Minh",
phone: "0901 234 567",
managerPhone: "0912 345 678",
email: "contact@coffeeshop.vn",
wifi: { name: "CoffeeShop_Free", password: "coffee2024" },
openHours: "07:00 22:00 (Thứ 2 Chủ nhật)",
};
```
---
### Social Links Type
```typescript
interface SocialLinks {
facebook: string;
tiktok: string;
website: string;
}
```
**Usage:** Footer component
---
### Shop (Discovery) Type
```typescript
interface Shop {
id: number;
name: string;
address: string;
image: string;
}
```
**Usage:** Feed page - list of coffee shops to discover
---
## Constants (lib/constants.ts)
**Description:** Mock data used throughout the application. Replace with API calls when backend is ready.
### SHOP_INFO
Single instance of shop information displayed in header, footer, and login page.
**Key Info Used:**
- Header: name, logo, phone
- Footer: all fields
- Login: logo, name, email
---
### SOCIAL_LINKS
Social media links for footer component.
```typescript
export const SOCIAL_LINKS: SocialLinks = {
facebook: "https://facebook.com/coffeeshop",
tiktok: "https://tiktok.com/@coffeeshop",
website: "/",
};
```
---
### MENU_CATEGORIES
Array of 8 product categories. Used in sidebar, mobile menu, and product filtering.
```typescript
export const MENU_CATEGORIES: MenuCategory[] = [
{ id: "all", name: "Tất cả", icon: "fa-solid fa-border-all" },
{ id: "cafe", name: "Cà Phê", icon: "fa-solid fa-mug-hot" },
{ id: "tra", name: "Trà", icon: "fa-solid fa-leaf" },
{ id: "sua-chua", name: "Sữa Chua", icon: "fa-solid fa-jar" },
{ id: "nuoc-ep", name: "Nước Ép", icon: "fa-solid fa-blender" },
{ id: "latte", name: "Latte", icon: "fa-solid fa-mug-saucer" },
{ id: "giai-khat", name: "Giải Khát / Ăn Vặt", icon: "fa-solid fa-ice-cream" },
{ id: "topping", name: "Topping", icon: "fa-solid fa-layer-group" },
];
```
**Usage:**
- Navbar sidebar category buttons
- Header mobile scrollable menu
- Product grid category filter
---
### MOCK_PRODUCTS
Array of 18 mock product items across all categories.
**Example Product:**
```typescript
{
id: 1,
name: "Cà Phê Đen",
category: "cafe",
price: 25000,
image: "/imgs/products/placeholder.jpg",
description: "Cà phê đen truyền thống, đậm đà hương vị Việt Nam, pha phin thủ công.",
available: true,
}
```
**Product Distribution:**
- Café: 4 items (Đen, Sữa, Bạc Xỉu, Trứng)
- Tea: 3 items (Đào Cam Sả, Matcha, Vải Hoa Nhài)
- Yogurt: 2 items (Trân Châu, Dâu)
- Juice: 2 items (Cam, Dưa Hấu)
- Latte: 2 items (Caramel, Vanilla)
- Snacks: 2 items (Bánh Mì, Bánh Flan)
- Toppings: 3 items (Trân Châu Đen, Thạch, Trân Châu Trắng)
**Price Range:** 10,000 - 45,000 VND
---
### MOCK_SHOPS
Array of 5 coffee shops for the feed/discovery page.
```typescript
{
id: 1,
name: "The Coffee House",
address: "86 Cao Thắng, Quận 3, TP. Hồ Chí Minh",
image: "https://images.unsplash.com/...", // Unsplash URL
}
```
**Shops:**
1. The Coffee House - Quận 3
2. Highlands Coffee - Quận 1
3. Phúc Long Heritage - Quận 1
4. Katinat Saigon Kafe - Quận 1
5. Trung Nguyên E-Coffee - Quận 1
**Usage:** Feed page grid display
---
### MOCK_USERS
Pre-configured user accounts for authentication demo.
```typescript
export const MOCK_USERS: Record<string, User> = {
manager: {
id: 1,
name: "Nguyễn Văn An",
role: "manager",
avatar: null,
},
staff: {
id: 2,
name: "Trần Thị Bình",
role: "staff",
avatar: null,
},
};
```
**Usage:** AuthContext for login demo
**Note:** More accounts defined in `auth-context.tsx` MOCK_AUTH_DB
---
## Auth Context (lib/auth-context.tsx)
See [COMPONENTS.md - AuthContext](../components/COMPONENTS.md#authcontext) for detailed documentation.
**Quick Summary:**
- Manages user login/logout/register
- Persists user in localStorage
- Provides user info to components via useAuth() hook
---
## Cart Context (lib/cart-context.tsx)
See [COMPONENTS.md - CartContext](../components/COMPONENTS.md#cartcontext) for detailed documentation.
**Quick Summary:**
- Manages shopping cart items and quantities
- Persists cart in localStorage
- Provides cart operations via useCart() hook
---
## Menu Context (lib/menu-context.tsx)
See [COMPONENTS.md - MenuContext](../components/COMPONENTS.md#menucontext) for detailed documentation.
**Quick Summary:**
- Shares active category state
- Syncs sidebar and mobile menu selection
- Provides activeCategory and setActiveCategory via useMenu() hook
---
## Integration Guide
### Using Types
```typescript
import type { User, Product, MenuCategory } from "@/lib/types";
```
### Using Constants
```typescript
import { MENU_CATEGORIES, MOCK_PRODUCTS, SHOP_INFO } from "@/lib/constants";
// In a component:
const products = MOCK_PRODUCTS.filter(p => p.category === "cafe");
const shopName = SHOP_INFO.name;
```
### Using Auth Context
```typescript
import { useAuth } from "@/lib/auth-context";
export default function MyComponent() {
const { user, login, logout } = useAuth();
if (!user) return <p>Not logged in</p>;
return <p>Welcome, {user.name}!</p>;
}
```
### Using Cart Context
```typescript
import { useCart } from "@/lib/cart-context";
import type { Product } from "@/lib/types";
export default function ProductCard({ product }: { product: Product }) {
const { addToCart } = useCart();
return (
<button onClick={() => addToCart(product)}>
Add to Cart
</button>
);
}
```
### Using Menu Context
```typescript
import { useMenu } from "@/lib/menu-context";
import { MENU_CATEGORIES } from "@/lib/constants";
export default function CategoryFilter() {
const { activeCategory, setActiveCategory } = useMenu();
return (
<div>
{MENU_CATEGORIES.map(cat => (
<button
key={cat.id}
onClick={() => setActiveCategory(cat.id)}
className={activeCategory === cat.id ? "active" : ""}
>
{cat.name}
</button>
))}
</div>
);
}
```
---
## Data Flow & Updates
### When to Update Constants
1. **Product List:** When adding/removing products
- Update MOCK_PRODUCTS array
- Or replace with API call in the future
2. **Categories:** When adding new product categories
- Update MENU_CATEGORIES array
- Update product category references
3. **Shop Info:** When shop details change
- Update SHOP_INFO object
- Automatically reflects in header/footer
4. **Social Links:** When social handles change
- Update SOCIAL_LINKS object
### Future API Integration
When backend is ready:
```typescript
// Replace MOCK_PRODUCTS with:
const [products, setProducts] = useState<Product[]>([]);
useEffect(() => {
fetch("/api/products")
.then(r => r.json())
.then(setProducts);
}, []);
// Replace MOCK_USERS with:
const login = async (username: string, password: string) => {
const res = await fetch("/api/auth/login", {
method: "POST",
body: JSON.stringify({ username, password })
});
return res.ok;
};
```
---
## Best Practices
1. **Import Types:** Always use `import type` for types to avoid runtime bloat
2. **Immutability:** Contexts return functions to update state, not direct mutations
3. **localStorage:** Keys are centralized (`coffee-shop-user`, `coffee-shop-cart`)
4. **Validation:** Contexts validate/sanitize data (e.g., filter invalid cart items)
5. **Default Values:** Contexts have sensible defaults (activeCategory: "all")