Files
frontend/lib/constants.ts
T
TakahashiNguyen ae8134fd64
Release package / release (push) Failing after 7m21s
fix: manager login and menu management (#38)
Co-authored-by: TakahashiNg <83152264+TakahashiNguyen@users.noreply.github.com>
Reviewed-on: #38
2026-05-13 06:29:14 +00:00

430 lines
13 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type {
Department,
MenuItemEntity,
ProductSalesStats,
RevenueDataPoint,
ShiftSlot,
Shop,
ShopInfo,
SocialLinks,
User,
} from "./types";
// ===== SHOP INFORMATION =====
export const SHOP_INFO: ShopInfo = {
name: "Coffee Shop",
tagline: "Rich Flavors Moments of Relaxation",
logo: "/imgs/logo.png",
address: "123 Nguyen Hue Street, District 1, Ho Chi Minh City",
phone: "0901 234 567",
managerPhone: "0912 345 678",
email: "contact@coffeeshop.vn",
wifi: {
name: "CoffeeShop_Free",
password: "coffee2024",
},
openHours: "07:00 22:00 (Monday Sunday)",
};
// ===== SOCIAL LINKS =====
export const SOCIAL_LINKS: SocialLinks = {
facebook: "https://facebook.com/coffeeshop",
tiktok: "https://tiktok.com/@coffeeshop",
website: "/",
};
// ===== MOCK PRODUCTS =====
// Placeholder data replace with real API calls when backend is ready
export const MOCK_PRODUCTS: MenuItemEntity[] = [
{
id: "1",
name: "Black Coffee",
price: 25000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Traditional Vietnamese black coffee, rich and bold, brewed by hand with a phin filter.",
available: true,
},
{
id: "2",
name: "Milk Coffee",
price: 30000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Aromatic condensed milk coffee, rich and creamy — a perfect blend of strong coffee and sweet condensed milk.",
available: true,
},
{
id: "3",
name: "White Coffee",
price: 32000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Light and mild, with less coffee and more milk — perfect for those just starting to enjoy coffee.",
available: true,
},
{
id: "4",
name: "Egg Coffee",
price: 45000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"A Hanoi specialty — smooth, velvety egg cream layered over a bold coffee base.",
available: true,
},
{
id: "5",
name: "Peach Orange Lemongrass Tea",
price: 35000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Fragrant peach tea with fresh orange and lemongrass — refreshing and wonderfully cooling.",
available: true,
},
{
id: "6",
name: "Matcha Green Tea",
price: 40000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Pure Japanese matcha with a signature light bitterness — aromatic, refreshing, and nutritious.",
available: true,
},
{
id: "7",
name: "Lychee Jasmine Tea",
price: 38000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Sweet lychee tea delicately infused with jasmine blossom — a calming and soulful sip.",
available: true,
},
{
id: "8",
name: "Yogurt with Tapioca Pearls",
price: 38000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Smooth, creamy yogurt paired with chewy black tapioca pearls — a perfectly balanced sweet and tangy treat.",
available: true,
},
{
id: "9",
name: "Strawberry Yogurt",
price: 40000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Chilled yogurt with fresh sweet-tart strawberries, packed with vitamins and minerals.",
available: true,
},
{
id: "10",
name: "Fresh Orange Juice",
price: 35000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"100% freshly squeezed orange juice, rich in vitamin C and great for your health.",
available: true,
},
{
id: "11",
name: "Watermelon Juice",
price: 30000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Ice-cold watermelon juice — instantly refreshing on hot summer days.",
available: true,
},
{
id: "12",
name: "Caramel Latte",
price: 45000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Sweet and indulgent caramel latte with a velvety milk foam topping and a drizzle of caramel sauce.",
available: true,
},
{
id: "13",
name: "Vanilla Latte",
price: 45000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Smooth and gentle vanilla latte with a delicate natural vanilla fragrance.",
available: true,
},
{
id: "14",
name: "Toasted Butter Bread",
price: 20000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Crispy toasted bread spread with fragrant butter and strawberry jam — the perfect coffee companion.",
available: true,
},
{
id: "15",
name: "Caramel Flan",
price: 25000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Silky smooth flan with a golden caramel topping that melts in your mouth.",
available: true,
},
{
id: "16",
name: "Black Tapioca Pearls",
price: 10000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Chewy black tapioca pearls — add them to any drink for extra flavor and texture.",
available: true,
},
{
id: "17",
name: "Coffee Jelly",
price: 10000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Cool coffee jelly that adds a distinctive flavor boost to your drink.",
available: true,
},
{
id: "18",
name: "White Tapioca Pearls",
price: 10000,
imageUrl: "/imgs/products/placeholder.jpg",
description:
"Chewy white tapioca pearls — add them to any drink for extra flavor and texture.",
available: true,
},
];
// ===== MOCK SHOPS (for Feed page) =====
export const MOCK_SHOPS: Shop[] = [
{
id: 1,
name: "The Coffee House",
address: "86 Cao Thắng, Quận 3, TP. Hồ Chí Minh",
image:
"https://images.unsplash.com/photo-1554118811-1e0d58224f24?w=600&h=400&fit=crop",
},
{
id: 2,
name: "Highlands Coffee",
address: "123 Nguyễn Huệ, Quận 1, TP. Hồ Chí Minh",
image:
"https://images.unsplash.com/photo-1559305616-3f99cd43e353?w=600&h=400&fit=crop",
},
{
id: 3,
name: "Phúc Long Heritage",
address: "42 Lê Lợi, Quận 1, TP. Hồ Chí Minh",
image:
"https://images.unsplash.com/photo-1501339847302-ac426a4a7cbb?w=600&h=400&fit=crop",
},
{
id: 4,
name: "Katinat Saigon Kafe",
address: "26 Lý Tự Trọng, Quận 1, TP. Hồ Chí Minh",
image:
"https://images.unsplash.com/photo-1495474472287-4d71bcdd2085?w=600&h=400&fit=crop",
},
{
id: 5,
name: "Trung Nguyên E-Coffee",
address: "15 Hai Bà Trưng, Quận 1, TP. Hồ Chí Minh",
image:
"https://images.unsplash.com/photo-1453614512568-c4024d13c247?w=600&h=400&fit=crop",
},
];
// ===== MOCK FINANCIAL DATA =====
// Daily revenue for the last 30 days (current month)
export const MOCK_REVENUE_DAILY: RevenueDataPoint[] = [
{ label: "01/04", revenue: 1250000, orders: 42 },
{ label: "02/04", revenue: 980000, orders: 35 },
{ label: "03/04", revenue: 1540000, orders: 55 },
{ label: "04/04", revenue: 1120000, orders: 40 },
{ label: "05/04", revenue: 1890000, orders: 68 },
{ label: "06/04", revenue: 2100000, orders: 74 },
{ label: "07/04", revenue: 2350000, orders: 82 },
{ label: "08/04", revenue: 1680000, orders: 60 },
{ label: "09/04", revenue: 1430000, orders: 50 },
{ label: "10/04", revenue: 1750000, orders: 63 },
{ label: "11/04", revenue: 1560000, orders: 56 },
{ label: "12/04", revenue: 1920000, orders: 70 },
{ label: "13/04", revenue: 2230000, orders: 80 },
{ label: "14/04", revenue: 2480000, orders: 90 },
{ label: "15/04", revenue: 1870000, orders: 66 },
{ label: "16/04", revenue: 1340000, orders: 48 },
{ label: "17/04", revenue: 1610000, orders: 58 },
{ label: "18/04", revenue: 1490000, orders: 53 },
{ label: "19/04", revenue: 1970000, orders: 71 },
{ label: "20/04", revenue: 2140000, orders: 77 },
{ label: "21/04", revenue: 2560000, orders: 93 },
{ label: "22/04", revenue: 1780000, orders: 64 },
{ label: "23/04", revenue: 1520000, orders: 54 },
{ label: "24/04", revenue: 1840000, orders: 66 },
{ label: "25/04", revenue: 1660000, orders: 60 },
{ label: "26/04", revenue: 2050000, orders: 74 },
{ label: "27/04", revenue: 2280000, orders: 82 },
{ label: "28/04", revenue: 2490000, orders: 89 },
{ label: "29/04", revenue: 1950000, orders: 70 },
{ label: "30/04", revenue: 1720000, orders: 62 },
];
// Weekly revenue (last 12 weeks)
export const MOCK_REVENUE_WEEKLY: RevenueDataPoint[] = [
{ 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: "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)
export const MOCK_REVENUE_YEARLY: RevenueDataPoint[] = [
{ label: "2022", revenue: 420000000, orders: 15120 },
{ label: "2023", revenue: 485000000, orders: 17460 },
{ label: "2024", revenue: 530000000, orders: 19080 },
{ label: "2025", revenue: 598000000, orders: 21528 },
{ label: "2026", revenue: 180000000, orders: 6480 },
];
/**
* Generate mock shift slots for the weeks around today (April 2026).
* Covers Mon 6 Apr Sun 26 Apr 2026.
*/
function generateMockShifts(): ShiftSlot[] {
const shifts: ShiftSlot[] = [];
const departments = ["bar", "kitchen", "cashier", "janitor"];
const timeSlots = [
{ start: "07:00", end: "11:00", hours: 4, wage: 120000 },
{ start: "11:00", end: "15:00", hours: 4, wage: 120000 },
{ start: "15:00", end: "19:00", hours: 4, wage: 120000 },
{ start: "19:00", end: "22:00", hours: 3, wage: 100000 },
];
const staffPool = [
{ id: 2, name: "Alex Nguyen" },
{ id: 3, name: "Binh Tran" },
{ id: 4, name: "Cuong Le" },
];
// Generate shifts from April 6 to April 26, 2026
let shiftCounter = 0;
for (let day = 6; day <= 26; day++) {
const dateStr = `2026-04-${day.toString().padStart(2, "0")}`;
for (const dept of departments) {
// Not every department has shifts every day
if (dept === "janitor" && day % 3 !== 0) continue;
for (const slot of timeSlots) {
// Skip some slots randomly for variety
if (dept === "kitchen" && slot.start === "19:00") continue;
if (dept === "cashier" && slot.start === "07:00" && day % 2 === 0)
continue;
shiftCounter++;
const shiftId = `shift_${shiftCounter.toString().padStart(3, "0")}`;
// Determine registration status
const registered: { id: number; name: string }[] = [];
let status: ShiftSlot["status"] = "available";
// Past shifts (before April 10) are mostly registered
if (day < 10) {
const staffIdx = shiftCounter % staffPool.length;
registered.push(staffPool[staffIdx]);
if (shiftCounter % 7 === 0) {
registered.push(staffPool[(staffIdx + 1) % staffPool.length]);
}
status = "registered";
// Some past shifts have leave/absent
if (shiftCounter % 11 === 0) status = "approved_leave";
if (shiftCounter % 13 === 0) status = "absent";
}
// Current week (April 6-12): mix of registered and available
else if (day >= 10 && day <= 12) {
if (shiftCounter % 3 === 0) {
registered.push(staffPool[shiftCounter % staffPool.length]);
status = "registered";
}
}
// Future shifts: mostly available, some registered
else {
if (shiftCounter % 5 === 0) {
registered.push(staffPool[shiftCounter % staffPool.length]);
status = "registered";
}
}
shifts.push({
id: "shiftId",
date: dateStr,
startTime: slot.start,
endTime: slot.end,
durationHours: slot.hours,
wage: slot.wage,
department: dept,
maxStaff: dept === "bar" ? 3 : 2,
registeredStaff: registered,
status,
});
}
}
}
return shifts;
}
export const MOCK_SHIFT_SLOTS: ShiftSlot[] = generateMockShifts();
export const DEPARTMENTS: Department[] = [
{ id: "bar", name: "Bar Staff", icon: "fa-solid fa-martini-glass-citrus" },
{ id: "kitchen", name: "Kitchen", icon: "fa-solid fa-kitchen-set" },
{ id: "cashier", name: "Cashier", icon: "fa-solid fa-cash-register" },
{ id: "janitor", name: "Janitor", icon: "fa-solid fa-broom" },
];