- WiFi Miễn Phí
+ Free WiFi
- Kết nối miễn phí
+ Connect for free
{/* Stacked label + value rows — no overflow risk */}
- Tên mạng
+ Network name
{SHOP_INFO.wifi.name}
@@ -150,7 +150,7 @@ export default function Footer() {
- Mật khẩu
+ Password
{SHOP_INFO.wifi.password}
@@ -170,9 +170,9 @@ export default function Footer() {
© {new Date().getFullYear()} {SHOP_INFO.name}. All rights reserved.
- Được vận hành{" "}
+ Powered by{" "}
{" "}
- bằng Drinkool
+ Drinkool
diff --git a/layouts/header.tsx b/layouts/header.tsx
index 970fbd8..3599242 100644
--- a/layouts/header.tsx
+++ b/layouts/header.tsx
@@ -72,11 +72,11 @@ export default function Header() {
/* Guest: sign-in button */
) : user.role === "manager" ? (
/* Manager: dashboard link + logout */
@@ -90,8 +90,8 @@ export default function Header() {
diff --git a/lib/constants.ts b/lib/constants.ts
index d6c76b1..24f3f1e 100644
--- a/lib/constants.ts
+++ b/lib/constants.ts
@@ -15,9 +15,9 @@ import type {
// ===== SHOP INFORMATION =====
export const SHOP_INFO: ShopInfo = {
name: "Coffee Shop",
- tagline: "Hương vị đậm đà – Khoảnh khắc thư giãn",
+ tagline: "Rich Flavors – Moments of Relaxation",
logo: "/imgs/logo.png",
- address: "123 Đường Nguyễn Huệ, Quận 1, TP. Hồ Chí Minh",
+ address: "123 Nguyen Hue Street, District 1, Ho Chi Minh City",
phone: "0901 234 567",
managerPhone: "0912 345 678",
email: "contact@coffeeshop.vn",
@@ -25,7 +25,7 @@ export const SHOP_INFO: ShopInfo = {
name: "CoffeeShop_Free",
password: "coffee2024",
},
- openHours: "07:00 – 22:00 (Thứ 2 – Chủ nhật)",
+ openHours: "07:00 – 22:00 (Monday – Sunday)",
};
// ===== SOCIAL LINKS =====
@@ -38,15 +38,15 @@ export const SOCIAL_LINKS: SocialLinks = {
// ===== MENU CATEGORIES =====
// Each category has a unique FontAwesome icon representing the item type
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: "all", name: "All", icon: "fa-solid fa-border-all" },
+ { id: "cafe", name: "Coffee", icon: "fa-solid fa-mug-hot" },
+ { id: "tra", name: "Tea", icon: "fa-solid fa-leaf" },
+ { id: "sua-chua", name: "Yogurt", icon: "fa-solid fa-jar" },
+ { id: "nuoc-ep", name: "Juice", 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",
+ name: "Refreshments / Snacks",
icon: "fa-solid fa-ice-cream",
},
{ id: "topping", name: "Topping", icon: "fa-solid fa-layer-group" },
@@ -57,182 +57,182 @@ export const MENU_CATEGORIES: MenuCategory[] = [
export const MOCK_PRODUCTS: Product[] = [
{
id: 1,
- name: "Cà Phê Đen",
+ name: "Black Coffee",
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.",
+ "Traditional Vietnamese black coffee, rich and bold, brewed by hand with a phin filter.",
available: true,
},
{
id: 2,
- name: "Cà Phê Sữa",
+ name: "Milk Coffee",
category: "cafe",
price: 30000,
image: "/imgs/products/placeholder.jpg",
description:
- "Cà phê sữa đặc thơm ngon, béo ngậy, kết hợp hoàn hảo giữa cà phê và sữa đặc.",
+ "Aromatic condensed milk coffee, rich and creamy — a perfect blend of strong coffee and sweet condensed milk.",
available: true,
},
{
id: 3,
- name: "Bạc Xỉu",
+ name: "White Coffee",
category: "cafe",
price: 32000,
image: "/imgs/products/placeholder.jpg",
description:
- "Bạc xỉu nhẹ nhàng, ít cà phê nhiều sữa, thích hợp cho người mới uống cà phê.",
+ "Light and mild, with less coffee and more milk — perfect for those just starting to enjoy coffee.",
available: true,
},
{
id: 4,
- name: "Cà Phê Trứng",
+ name: "Egg Coffee",
category: "cafe",
price: 45000,
image: "/imgs/products/placeholder.jpg",
description:
- "Cà phê trứng đặc sản Hà Nội, lớp kem trứng mịn màng phủ trên nền cà phê đậm đà.",
+ "A Hanoi specialty — smooth, velvety egg cream layered over a bold coffee base.",
available: true,
},
{
id: 5,
- name: "Trà Đào Cam Sả",
+ name: "Peach Orange Lemongrass Tea",
category: "tra",
price: 35000,
image: "/imgs/products/placeholder.jpg",
description:
- "Trà đào thơm mát kết hợp cam tươi và sả, thanh mát và giải nhiệt tuyệt vời.",
+ "Fragrant peach tea with fresh orange and lemongrass — refreshing and wonderfully cooling.",
available: true,
},
{
id: 6,
- name: "Trà Xanh Matcha",
+ name: "Matcha Green Tea",
category: "tra",
price: 40000,
image: "/imgs/products/placeholder.jpg",
description:
- "Matcha Nhật Bản nguyên chất, vị đắng nhẹ đặc trưng, thơm mát và bổ dưỡng.",
+ "Pure Japanese matcha with a signature light bitterness — aromatic, refreshing, and nutritious.",
available: true,
},
{
id: 7,
- name: "Trà Vải Hoa Nhài",
+ name: "Lychee Jasmine Tea",
category: "tra",
price: 38000,
image: "/imgs/products/placeholder.jpg",
description:
- "Trà vải thanh ngọt kết hợp hương hoa nhài dịu dàng, thư giãn tâm hồn.",
+ "Sweet lychee tea delicately infused with jasmine blossom — a calming and soulful sip.",
available: true,
},
{
id: 8,
- name: "Sữa Chua Trân Châu",
+ name: "Yogurt with Tapioca Pearls",
category: "sua-chua",
price: 38000,
image: "/imgs/products/placeholder.jpg",
description:
- "Sữa chua mịn màng kết hợp trân châu đen dẻo dai, chua ngọt hài hòa.",
+ "Smooth, creamy yogurt paired with chewy black tapioca pearls — a perfectly balanced sweet and tangy treat.",
available: true,
},
{
id: 9,
- name: "Sữa Chua Dâu",
+ name: "Strawberry Yogurt",
category: "sua-chua",
price: 40000,
image: "/imgs/products/placeholder.jpg",
description:
- "Sữa chua mát lạnh với dâu tươi ngọt chua, giàu vitamin và khoáng chất.",
+ "Chilled yogurt with fresh sweet-tart strawberries, packed with vitamins and minerals.",
available: true,
},
{
id: 10,
- name: "Nước Ép Cam",
+ name: "Fresh Orange Juice",
category: "nuoc-ep",
price: 35000,
image: "/imgs/products/placeholder.jpg",
description:
- "Nước ép cam tươi nguyên chất, giàu vitamin C, tốt cho sức khỏe.",
+ "100% freshly squeezed orange juice, rich in vitamin C and great for your health.",
available: true,
},
{
id: 11,
- name: "Nước Ép Dưa Hấu",
+ name: "Watermelon Juice",
category: "nuoc-ep",
price: 30000,
image: "/imgs/products/placeholder.jpg",
description:
- "Nước ép dưa hấu mát lạnh, giải nhiệt tức thì trong những ngày hè oi bức.",
+ "Ice-cold watermelon juice — instantly refreshing on hot summer days.",
available: true,
},
{
id: 12,
- name: "Latte Caramel",
+ name: "Caramel Latte",
category: "latte",
price: 45000,
image: "/imgs/products/placeholder.jpg",
description:
- "Latte caramel ngọt ngào, thơm béo với lớp foam sữa mịn và sốt caramel.",
+ "Sweet and indulgent caramel latte with a velvety milk foam topping and a drizzle of caramel sauce.",
available: true,
},
{
id: 13,
- name: "Latte Vanilla",
+ name: "Vanilla Latte",
category: "latte",
price: 45000,
image: "/imgs/products/placeholder.jpg",
description:
- "Latte vanilla nhẹ nhàng, hương thơm dịu dàng từ vanilla tự nhiên.",
+ "Smooth and gentle vanilla latte with a delicate natural vanilla fragrance.",
available: true,
},
{
id: 14,
- name: "Bánh Mì Nướng Bơ",
+ name: "Toasted Butter Bread",
category: "giai-khat",
price: 20000,
image: "/imgs/products/placeholder.jpg",
description:
- "Bánh mì nướng giòn rụm, phết bơ thơm và mứt dâu, ăn kèm cà phê tuyệt vời.",
+ "Crispy toasted bread spread with fragrant butter and strawberry jam — the perfect coffee companion.",
available: true,
},
{
id: 15,
- name: "Bánh Flan",
+ name: "Caramel Flan",
category: "giai-khat",
price: 25000,
image: "/imgs/products/placeholder.jpg",
description:
- "Bánh flan mềm mịn, ngọt ngào với lớp caramel vàng óng, tan chảy trong miệng.",
+ "Silky smooth flan with a golden caramel topping that melts in your mouth.",
available: true,
},
{
id: 16,
- name: "Trân Châu Đen",
+ name: "Black Tapioca Pearls",
category: "topping",
price: 10000,
image: "/imgs/products/placeholder.jpg",
description:
- "Trân châu đen dẻo dai, thêm vào bất kỳ đồ uống nào để tăng thêm hương vị.",
+ "Chewy black tapioca pearls — add them to any drink for extra flavor and texture.",
available: true,
},
{
id: 17,
- name: "Thạch Cà Phê",
+ name: "Coffee Jelly",
category: "topping",
price: 10000,
image: "/imgs/products/placeholder.jpg",
description:
- "Thạch cà phê mát lạnh, thêm hương vị đặc biệt cho đồ uống của bạn.",
+ "Cool coffee jelly that adds a distinctive flavor boost to your drink.",
available: true,
},
{
id: 18,
- name: "Trân Châu Trắng",
+ name: "White Tapioca Pearls",
category: "topping",
price: 10000,
image: "/imgs/products/placeholder.jpg",
description:
- "Trân châu trắng dẻo dai, thêm vào bất kỳ đồ uống nào để tăng thêm hương vị.",
+ "Chewy white tapioca pearls — add them to any drink for extra flavor and texture.",
available: true,
},
];
@@ -241,8 +241,8 @@ export const MOCK_PRODUCTS: Product[] = [
export const MOCK_COMBOS: Combo[] = [
{
id: 1,
- name: "Combo Cà Phê Đôi",
- description: "2 ly cà phê đen + 2 bánh mì nướng bơ, tiết kiệm 15%.",
+ name: "Double Coffee Combo",
+ description: "2 black coffees + 2 toasted butter breads, save 15%.",
price: 75000,
image: "/imgs/products/placeholder.jpg",
items: [
@@ -253,8 +253,8 @@ export const MOCK_COMBOS: Combo[] = [
},
{
id: 2,
- name: "Combo Trà Sữa Nhóm",
- description: "2 trà đào cam sả + 2 trà xanh matcha, dành cho nhóm bạn.",
+ name: "Group Tea Combo",
+ description: "2 peach orange lemongrass teas + 2 matcha green teas, perfect for a group.",
price: 130000,
image: "/imgs/products/placeholder.jpg",
items: [
@@ -265,8 +265,8 @@ export const MOCK_COMBOS: Combo[] = [
},
{
id: 3,
- name: "Combo Buổi Sáng",
- description: "1 cà phê sữa + 1 bánh flan, khởi đầu ngày mới ngọt ngào.",
+ name: "Morning Combo",
+ description: "1 milk coffee + 1 caramel flan — start your day on a sweet note.",
price: 48000,
image: "/imgs/products/placeholder.jpg",
items: [
@@ -354,34 +354,34 @@ export const MOCK_REVENUE_DAILY: RevenueDataPoint[] = [
// Weekly revenue (last 12 weeks)
export const MOCK_REVENUE_WEEKLY: RevenueDataPoint[] = [
- { label: "T1/W1", revenue: 8200000, orders: 295 },
- { label: "T1/W2", revenue: 9450000, orders: 340 },
- { label: "T1/W3", revenue: 10100000, orders: 362 },
- { label: "T1/W4", revenue: 8750000, orders: 315 },
- { label: "T2/W1", revenue: 9200000, orders: 330 },
- { label: "T2/W2", revenue: 10500000, orders: 378 },
- { label: "T2/W3", revenue: 11200000, orders: 400 },
- { label: "T2/W4", revenue: 9800000, orders: 352 },
- { label: "T3/W1", revenue: 10400000, orders: 374 },
- { label: "T3/W2", revenue: 11800000, orders: 424 },
- { label: "T3/W3", revenue: 12500000, orders: 448 },
- { label: "T3/W4", revenue: 10900000, orders: 392 },
+ { label: "Jan/W1", revenue: 8200000, orders: 295 },
+ { label: "Jan/W2", revenue: 9450000, orders: 340 },
+ { label: "Jan/W3", revenue: 10100000, orders: 362 },
+ { label: "Jan/W4", revenue: 8750000, orders: 315 },
+ { label: "Feb/W1", revenue: 9200000, orders: 330 },
+ { label: "Feb/W2", revenue: 10500000, orders: 378 },
+ { label: "Feb/W3", revenue: 11200000, orders: 400 },
+ { label: "Feb/W4", revenue: 9800000, orders: 352 },
+ { label: "Mar/W1", revenue: 10400000, orders: 374 },
+ { label: "Mar/W2", revenue: 11800000, orders: 424 },
+ { label: "Mar/W3", revenue: 12500000, orders: 448 },
+ { label: "Mar/W4", revenue: 10900000, orders: 392 },
];
// Monthly revenue (last 12 months)
export const MOCK_REVENUE_MONTHLY: RevenueDataPoint[] = [
- { label: "T4/2025", revenue: 42000000, orders: 1512 },
- { label: "T5/2025", revenue: 45500000, orders: 1638 },
- { label: "T6/2025", revenue: 48000000, orders: 1728 },
- { label: "T7/2025", revenue: 52000000, orders: 1872 },
- { label: "T8/2025", revenue: 49500000, orders: 1782 },
- { label: "T9/2025", revenue: 46800000, orders: 1685 },
- { label: "T10/2025", revenue: 51200000, orders: 1843 },
- { label: "T11/2025", revenue: 55000000, orders: 1980 },
- { label: "T12/2025", revenue: 62000000, orders: 2232 },
- { label: "T1/2026", revenue: 44000000, orders: 1584 },
- { label: "T2/2026", revenue: 47500000, orders: 1710 },
- { label: "T3/2026", revenue: 53500000, orders: 1926 },
+ { label: "Apr/2025", revenue: 42000000, orders: 1512 },
+ { label: "May/2025", revenue: 45500000, orders: 1638 },
+ { label: "Jun/2025", revenue: 48000000, orders: 1728 },
+ { label: "Jul/2025", revenue: 52000000, orders: 1872 },
+ { label: "Aug/2025", revenue: 49500000, orders: 1782 },
+ { label: "Sep/2025", revenue: 46800000, orders: 1685 },
+ { label: "Oct/2025", revenue: 51200000, orders: 1843 },
+ { label: "Nov/2025", revenue: 55000000, orders: 1980 },
+ { label: "Dec/2025", revenue: 62000000, orders: 2232 },
+ { label: "Jan/2026", revenue: 44000000, orders: 1584 },
+ { label: "Feb/2026", revenue: 47500000, orders: 1710 },
+ { label: "Mar/2026", revenue: 53500000, orders: 1926 },
];
// Yearly revenue (last 5 years)
@@ -397,7 +397,7 @@ export const MOCK_REVENUE_YEARLY: RevenueDataPoint[] = [
export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
{
productId: 12,
- name: "Latte Caramel",
+ name: "Caramel Latte",
category: "latte",
unitsSold: 487,
revenue: 21915000,
@@ -408,7 +408,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 6,
- name: "Trà Xanh Matcha",
+ name: "Matcha Green Tea",
category: "tra",
unitsSold: 412,
revenue: 16480000,
@@ -419,7 +419,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 5,
- name: "Trà Đào Cam Sả",
+ name: "Peach Orange Lemongrass Tea",
category: "tra",
unitsSold: 398,
revenue: 13930000,
@@ -430,7 +430,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 13,
- name: "Latte Vanilla",
+ name: "Vanilla Latte",
category: "latte",
unitsSold: 356,
revenue: 16020000,
@@ -441,7 +441,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 4,
- name: "Cà Phê Trứng",
+ name: "Egg Coffee",
category: "cafe",
unitsSold: 340,
revenue: 15300000,
@@ -452,7 +452,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 2,
- name: "Cà Phê Sữa",
+ name: "Milk Coffee",
category: "cafe",
unitsSold: 325,
revenue: 9750000,
@@ -463,7 +463,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 3,
- name: "Bạc Xỉu",
+ name: "White Coffee",
category: "cafe",
unitsSold: 298,
revenue: 9536000,
@@ -474,7 +474,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 1,
- name: "Cà Phê Đen",
+ name: "Black Coffee",
category: "cafe",
unitsSold: 285,
revenue: 7125000,
@@ -485,7 +485,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 9,
- name: "Sữa Chua Dâu",
+ name: "Strawberry Yogurt",
category: "sua-chua",
unitsSold: 267,
revenue: 10680000,
@@ -496,7 +496,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 10,
- name: "Nước Ép Cam",
+ name: "Fresh Orange Juice",
category: "nuoc-ep",
unitsSold: 241,
revenue: 8435000,
@@ -507,7 +507,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 8,
- name: "Sữa Chua Trân Châu",
+ name: "Yogurt with Tapioca Pearls",
category: "sua-chua",
unitsSold: 228,
revenue: 8664000,
@@ -518,7 +518,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 7,
- name: "Trà Vải Hoa Nhài",
+ name: "Lychee Jasmine Tea",
category: "tra",
unitsSold: 215,
revenue: 8170000,
@@ -529,7 +529,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 15,
- name: "Bánh Flan",
+ name: "Caramel Flan",
category: "giai-khat",
unitsSold: 198,
revenue: 4950000,
@@ -540,7 +540,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 11,
- name: "Nước Ép Dưa Hấu",
+ name: "Watermelon Juice",
category: "nuoc-ep",
unitsSold: 182,
revenue: 5460000,
@@ -551,7 +551,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 14,
- name: "Bánh Mì Nướng Bơ",
+ name: "Toasted Butter Bread",
category: "giai-khat",
unitsSold: 175,
revenue: 3500000,
@@ -562,7 +562,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 16,
- name: "Trân Châu Đen",
+ name: "Black Tapioca Pearls",
category: "topping",
unitsSold: 456,
revenue: 4560000,
@@ -573,7 +573,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 17,
- name: "Thạch Cà Phê",
+ name: "Coffee Jelly",
category: "topping",
unitsSold: 389,
revenue: 3890000,
@@ -584,7 +584,7 @@ export const MOCK_PRODUCT_SALES: ProductSalesStats[] = [
},
{
productId: 18,
- name: "Trân Châu Trắng",
+ name: "White Tapioca Pearls",
category: "topping",
unitsSold: 342,
revenue: 3420000,
@@ -619,9 +619,9 @@ function generateMockShifts(): ShiftSlot[] {
];
const staffPool = [
- { id: 2, name: "Nguyễn Văn An" },
- { id: 3, name: "Trần Thị Bình" },
- { id: 4, name: "Lê Văn Cường" },
+ { id: 2, name: "Alex Nguyen" },
+ { id: 3, name: "Binh Tran" },
+ { id: 4, name: "Cuong Le" },
];
// Generate shifts from April 6 to April 26, 2026
diff --git a/lib/graphql.ts b/lib/graphql.ts
index 1c1bf7d..ac126dd 100644
--- a/lib/graphql.ts
+++ b/lib/graphql.ts
@@ -1,3 +1,5 @@
+import type { Eatery } from "./types";
+
export async function gqlFetch
>(
query: string,
variables?: Record,
@@ -12,3 +14,32 @@ export async function gqlFetch>(
if (!res.ok) throw new Error(`GraphQL request failed: ${res.status}`);
return res.json() as Promise;
}
+
+export async function addManagerMenuItem(
+ name: string,
+ price: number,
+): Promise<{ id: string; name: string; price: number } | null> {
+ const data = await gqlFetch<{
+ addMenuItem: { id: string; name: string; price: number } | null;
+ }>(
+ `mutation($name: String!, $price: Float!) {
+ addMenuItem(name: $name, price: $price) { id name price }
+ }`,
+ { name, price },
+ );
+ return data.addMenuItem;
+}
+
+export async function fetchManagerEatery(): Promise {
+ const data = await gqlFetch<{ eateriesByOwner: Eatery | null }>(`
+ query {
+ eateriesByOwner {
+ id
+ ownerId
+ name
+ isVerified
+ }
+ }
+ `);
+ return data.eateriesByOwner;
+}
diff --git a/lib/types.ts b/lib/types.ts
index a1f858b..7858157 100644
--- a/lib/types.ts
+++ b/lib/types.ts
@@ -52,6 +52,14 @@ export interface SocialLinks {
website: string;
}
+// ===== EATERY (GRAPHQL) TYPES =====
+export interface Eatery {
+ id: string;
+ ownerId: string;
+ name: string;
+ isVerified: boolean;
+}
+
// ===== SHOP (QUÁN NƯỚC) TYPES =====
export interface Shop {
id: number;