resolve conflict

This commit is contained in:
Thanh Quy - wolf
2026-03-29 22:29:44 +07:00
30 changed files with 4926 additions and 880 deletions
+90 -14
View File
@@ -1,6 +1,13 @@
"use client";
import { createContext, useContext, useState, useEffect, ReactNode } from "react";
import {
ReactNode,
createContext,
useContext,
useEffect,
useState,
} from "react";
import type { User } from "./types";
interface AuthContextType {
@@ -17,16 +24,76 @@ const AuthContext = createContext<AuthContextType | undefined>(undefined);
// Mock user database
const MOCK_AUTH_DB = {
// Admin
admin: { username: "admin", password: "admin", user: { id: 1, name: "Quản lý", role: "manager" as const, avatar: null, phone: "0912345678" } },
admin: {
username: "admin",
password: "admin",
user: {
id: 1,
name: "Quản lý",
role: "manager" as const,
avatar: null,
phone: "0912345678",
},
},
// Staff (username and password are their names)
"Nguyễn Văn An": { username: "Nguyễn Văn An", password: "Nguyễn Văn An", user: { id: 2, name: "Nguyễn Văn An", role: "staff" as const, avatar: null, phone: "0901234567" } },
"Trần Thị Bình": { username: "Trần Thị Bình", password: "Trần Thị Bình", user: { id: 3, name: "Trần Thị Bình", role: "staff" as const, avatar: null, phone: "0902345678" } },
"Lê Văn Cường": { username: "Lê Văn Cường", password: "Lê Văn Cường", user: { id: 4, name: "Lê Văn Cường", role: "staff" as const, avatar: null, phone: "0903456789" } },
"Nguyễn Văn An": {
username: "Nguyễn Văn An",
password: "Nguyễn Văn An",
user: {
id: 2,
name: "Nguyễn Văn An",
role: "staff" as const,
avatar: null,
phone: "0901234567",
},
},
"Trần Thị Bình": {
username: "Trần Thị Bình",
password: "Trần Thị Bình",
user: {
id: 3,
name: "Trần Thị Bình",
role: "staff" as const,
avatar: null,
phone: "0902345678",
},
},
"Lê Văn Cường": {
username: "Lê Văn Cường",
password: "Lê Văn Cường",
user: {
id: 4,
name: "Lê Văn Cường",
role: "staff" as const,
avatar: null,
phone: "0903456789",
},
},
// Customers (username is phone number, password is custom)
"0987654321": { username: "0987654321", password: "user1", user: { id: 5, name: "Khách hàng", role: "customer" as const, avatar: null, phone: "0987654321" } },
"0976543210": { username: "0976543210", password: "user1", user: { id: 6, name: "Khách hàng", role: "customer" as const, avatar: null, phone: "0976543210" } },
"0987654321": {
username: "0987654321",
password: "user1",
user: {
id: 5,
name: "Khách hàng",
role: "customer" as const,
avatar: null,
phone: "0987654321",
},
},
"0976543210": {
username: "0976543210",
password: "user1",
user: {
id: 6,
name: "Khách hàng",
role: "customer" as const,
avatar: null,
phone: "0976543210",
},
},
};
export function AuthProvider({ children }: { children: ReactNode }) {
@@ -47,13 +114,13 @@ export function AuthProvider({ children }: { children: ReactNode }) {
const login = (username: string, password: string): boolean => {
const authEntry = MOCK_AUTH_DB[username as keyof typeof MOCK_AUTH_DB];
if (authEntry && authEntry.password === password) {
setUser(authEntry.user);
localStorage.setItem("coffee-shop-user", JSON.stringify(authEntry.user));
return true;
}
return false;
};
@@ -71,21 +138,30 @@ export function AuthProvider({ children }: { children: ReactNode }) {
avatar: null,
phone,
};
// Add to mock database (in real app, this would be API call)
(MOCK_AUTH_DB as any)[phone] = {
username: phone,
password: "user1", // Default password for new customers
user: newUser,
};
setUser(newUser);
localStorage.setItem("coffee-shop-user", JSON.stringify(newUser));
setRegisterPhone(null);
};
return (
<AuthContext.Provider value={{ user, login, logout, registerPhone, setRegisterPhone, completeRegistration }}>
<AuthContext.Provider
value={{
user,
login,
logout,
registerPhone,
setRegisterPhone,
completeRegistration,
}}
>
{children}
</AuthContext.Provider>
);
+14 -10
View File
@@ -1,7 +1,7 @@
"use client";
import { createContext, useContext, useEffect, useMemo, useState } from "react";
import type { Product } from "@/lib/types";
import { createContext, useContext, useEffect, useMemo, useState } from "react";
export interface CartItem {
id: number;
@@ -70,8 +70,8 @@ export function CartProvider({ children }: { children: React.ReactNode }) {
const increaseQty = (id: number) => {
setItems((prev) =>
prev.map((item) =>
item.id === id ? { ...item, quantity: item.quantity + 1 } : item
)
item.id === id ? { ...item, quantity: item.quantity + 1 } : item,
),
);
};
@@ -81,9 +81,9 @@ export function CartProvider({ children }: { children: React.ReactNode }) {
.map((item) =>
item.id === id
? { ...item, quantity: Math.max(0, item.quantity - 1) }
: item
: item,
)
.filter((item) => item.quantity > 0)
.filter((item) => item.quantity > 0),
);
};
@@ -92,25 +92,29 @@ export function CartProvider({ children }: { children: React.ReactNode }) {
};
const setQuantity = (id: number, quantity: number) => {
const safeQty = Number.isFinite(quantity) ? Math.max(0, Math.floor(quantity)) : 0;
const safeQty = Number.isFinite(quantity)
? Math.max(0, Math.floor(quantity))
: 0;
if (safeQty === 0) {
removeFromCart(id);
return;
}
setItems((prev) =>
prev.map((item) => (item.id === id ? { ...item, quantity: safeQty } : item))
prev.map((item) =>
item.id === id ? { ...item, quantity: safeQty } : item,
),
);
};
const totalItems = useMemo(
() => items.reduce((sum, item) => sum + item.quantity, 0),
[items]
[items],
);
const totalPrice = useMemo(
() => items.reduce((sum, item) => sum + item.price * item.quantity, 0),
[items]
[items],
);
const value = useMemo(
@@ -124,7 +128,7 @@ export function CartProvider({ children }: { children: React.ReactNode }) {
removeFromCart,
setQuantity,
}),
[items, totalItems, totalPrice]
[items, totalItems, totalPrice],
);
return <CartContext.Provider value={value}>{children}</CartContext.Provider>;
+41 -19
View File
@@ -32,7 +32,11 @@ export const MENU_CATEGORIES: MenuCategory[] = [
{ 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: "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" },
];
@@ -45,7 +49,8 @@ export const MOCK_PRODUCTS: Product[] = [
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.",
description:
"Cà phê đen truyền thống, đậm đà hương vị Việt Nam, pha phin thủ công.",
available: true,
},
{
@@ -54,7 +59,8 @@ export const MOCK_PRODUCTS: Product[] = [
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.",
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.",
available: true,
},
{
@@ -63,7 +69,8 @@ export const MOCK_PRODUCTS: Product[] = [
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ê.",
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ê.",
available: true,
},
{
@@ -72,7 +79,8 @@ export const MOCK_PRODUCTS: Product[] = [
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 đà.",
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 đà.",
available: true,
},
{
@@ -81,7 +89,8 @@ export const MOCK_PRODUCTS: Product[] = [
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.",
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.",
available: true,
},
{
@@ -90,7 +99,8 @@ export const MOCK_PRODUCTS: Product[] = [
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.",
description:
"Matcha Nhật Bản nguyên chất, vị đắng nhẹ đặc trưng, thơm mát và bổ dưỡng.",
available: true,
},
{
@@ -99,7 +109,8 @@ export const MOCK_PRODUCTS: Product[] = [
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.",
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.",
available: true,
},
{
@@ -108,7 +119,8 @@ export const MOCK_PRODUCTS: Product[] = [
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.",
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.",
available: true,
},
{
@@ -117,7 +129,8 @@ export const MOCK_PRODUCTS: Product[] = [
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.",
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.",
available: true,
},
{
@@ -126,7 +139,8 @@ export const MOCK_PRODUCTS: Product[] = [
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.",
description:
"Nước ép cam tươi nguyên chất, giàu vitamin C, tốt cho sức khỏe.",
available: true,
},
{
@@ -135,7 +149,8 @@ export const MOCK_PRODUCTS: Product[] = [
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.",
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.",
available: true,
},
{
@@ -144,7 +159,8 @@ export const MOCK_PRODUCTS: Product[] = [
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.",
description:
"Latte caramel ngọt ngào, thơm béo với lớp foam sữa mịn và sốt caramel.",
available: true,
},
{
@@ -153,7 +169,8 @@ export const MOCK_PRODUCTS: Product[] = [
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.",
description:
"Latte vanilla nhẹ nhàng, hương thơm dịu dàng từ vanilla tự nhiên.",
available: true,
},
{
@@ -162,7 +179,8 @@ export const MOCK_PRODUCTS: Product[] = [
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.",
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.",
available: true,
},
{
@@ -171,7 +189,8 @@ export const MOCK_PRODUCTS: Product[] = [
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.",
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.",
available: true,
},
{
@@ -180,7 +199,8 @@ export const MOCK_PRODUCTS: Product[] = [
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ị.",
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ị.",
available: true,
},
{
@@ -189,7 +209,8 @@ export const MOCK_PRODUCTS: Product[] = [
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.",
description:
"Thạch cà phê mát lạnh, thêm hương vị đặc biệt cho đồ uống của bạn.",
available: true,
},
{
@@ -198,7 +219,8 @@ export const MOCK_PRODUCTS: Product[] = [
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ị.",
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ị.",
available: true,
},
];