Files
TaNguyenThanhQuy fd57a35820
Release package / release (push) Successful in 1h12m42s
feat: Manage & analytics pages (#28)
Co-authored-by: Thanh Quy - wolf <524H0124@student.tdtu.edu.vn>
Reviewed-on: #28
Reviewed-by: TakahashiNguyen <takahashi.ng@icloud.com>
Co-authored-by: TaNguyenThanhQuy <tanguyenthanhquy@noreply.localhost>
Co-committed-by: TaNguyenThanhQuy <tanguyenthanhquy@noreply.localhost>
2026-04-06 14:09:45 +00:00

12 KiB
Raw Permalink Blame History

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

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

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

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

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:

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)",
};

interface SocialLinks {
  facebook: string;
  tiktok: string;
  website: string;
}

Usage: Footer component


Shop (Discovery) Type

interface Shop {
  id: number;
  name: string;
  address: string;
  image: string;
}

Usage: Feed page - list of coffee shops to discover


Financial Analytics Types

Types for the Financial Analytics module (/manager/analytics).

type AnalyticsPeriod = "day" | "week" | "month" | "year";

interface RevenueDataPoint {
  label: string; // display label (e.g. "01/04", "T3/W2")
  revenue: number; // VND
  orders: number;
}

interface ProductSalesStats {
  productId: number;
  name: string;
  category: string;
  unitsSold: number;
  revenue: number;
  costPrice: number; // giá nhập
  sellingPrice: number; // giá bán
  profit: number;
  profitMargin: number; // %
}

interface PeriodComparison {
  current: number;
  previous: number;
  change: number;
  changePercent: number;
  isPositive: boolean;
}

interface FinancialSummary {
  totalRevenue: number;
  totalOrders: number;
  totalProfit: number;
  averageOrderValue: number;
  revenueComparison: PeriodComparison;
  ordersComparison: PeriodComparison;
  profitComparison: PeriodComparison;
}

Usage: app/(manager)/manager/analytics/page.tsx


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 media links for footer component.

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.

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:

{
  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.

{
  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_REVENUE_DAILY / WEEKLY / MONTHLY / YEARLY

Revenue time-series data for different periods. Used in the Financial Analytics page.

  • MOCK_REVENUE_DAILY — 30 data points (April 2026, by day)
  • MOCK_REVENUE_WEEKLY — 12 data points (last 12 weeks)
  • MOCK_REVENUE_MONTHLY — 12 data points (last 12 months)
  • MOCK_REVENUE_YEARLY — 5 data points (20222026)

Each RevenueDataPoint: { label, revenue (VND), orders }.


MOCK_PRODUCT_SALES

Array of 18 ProductSalesStats — sales statistics for each product including cost price, selling price, profit and margin. Used in the analytics table and top-products ranking.

Usage: /manager/analytics — product table, top-5 bar, pie chart


MOCK_USERS

Pre-configured user accounts for authentication demo.

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 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 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 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

import type { MenuCategory, Product, User } from "@/lib/types";

Using Constants

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

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

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

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:

// 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")