mirror of
http://88.130.71.182:3000/BlitTech/badoHair_fe.git
synced 2026-06-13 08:58:31 +00:00
Update May 12 by Elvis
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
"use client";
|
||||
|
||||
import React, { useContext, useState, ReactNode, createContext } from "react";
|
||||
import { Product, products } from "@/data/products";
|
||||
import React, { useContext, useState, useEffect, ReactNode, createContext } from "react";
|
||||
import { useAuth } from "@/contexts/AuthContext";
|
||||
import * as productsApi from "@/lib/api/products";
|
||||
import * as bookingsApi from "@/lib/api/bookings";
|
||||
import { Product } from "@/data/products";
|
||||
import { ApiError } from "@/lib/api";
|
||||
|
||||
// Adapter: maps BookingApi to the Reservation shape used by admin pages
|
||||
export interface Reservation {
|
||||
id: string;
|
||||
clientName: string;
|
||||
@@ -15,63 +20,99 @@ export interface Reservation {
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
const initialReservations: Reservation[] = [
|
||||
{ id: "r1", clientName: "Marie Dupont", email: "marie@example.com", phone: "+33 6 12 34 56 78", service: "Pose complète", date: "2026-04-22", time: "10:00", status: "confirmed", createdAt: "2026-04-15" },
|
||||
{ id: "r2", clientName: "Sophie Laurent", email: "sophie@example.com", phone: "+33 6 98 76 54 32", service: "Conseil personnalisé", date: "2026-04-23", time: "14:30", status: "pending", createdAt: "2026-04-16" },
|
||||
{ id: "r3", clientName: "Amira Benali", email: "amira@example.com", phone: "+33 7 11 22 33 44", service: "Retouche", date: "2026-04-25", time: "11:00", status: "confirmed", createdAt: "2026-04-17" },
|
||||
{ id: "r4", clientName: "Léa Martin", email: "lea@example.com", phone: "+33 6 55 44 33 22", service: "Pose complète", date: "2026-04-28", time: "15:00", status: "pending", createdAt: "2026-04-17" },
|
||||
];
|
||||
function toReservation(b: bookingsApi.BookingApi): Reservation {
|
||||
return {
|
||||
id: b.id,
|
||||
clientName: b.client_name ?? "—",
|
||||
email: b.client_email ?? "—",
|
||||
phone: b.client_phone ?? "—",
|
||||
service: b.service_note ?? "—",
|
||||
date: b.slot_date,
|
||||
time: b.slot_start,
|
||||
status: b.status === "completed" || b.status === "no_show" ? "confirmed" : b.status as Reservation["status"],
|
||||
createdAt: b.created_at.slice(0, 10),
|
||||
};
|
||||
}
|
||||
|
||||
interface AdminContextType {
|
||||
isAdmin: boolean;
|
||||
login: (password: string) => boolean;
|
||||
logout: () => void;
|
||||
products: Product[];
|
||||
addProduct: (product: Omit<Product, "id">) => void;
|
||||
updateProduct: (id: string, product: Partial<Product>) => void;
|
||||
deleteProduct: (id: string) => void;
|
||||
productsLoading: boolean;
|
||||
refreshProducts: () => Promise<void>;
|
||||
addProduct: (payload: productsApi.ProductPayload) => Promise<Product>;
|
||||
updateProduct: (id: string, payload: Partial<productsApi.ProductPayload>) => Promise<void>;
|
||||
deleteProduct: (id: string) => Promise<void>;
|
||||
reservations: Reservation[];
|
||||
updateReservationStatus: (id: string, status: Reservation["status"]) => void;
|
||||
deleteReservation: (id: string) => void;
|
||||
reservationsLoading: boolean;
|
||||
refreshReservations: () => Promise<void>;
|
||||
updateReservationStatus: (id: string, status: "confirmed" | "cancelled") => Promise<void>;
|
||||
deleteReservation: (id: string) => Promise<void>;
|
||||
}
|
||||
|
||||
const AdminContext = createContext<AdminContextType | undefined>(undefined);
|
||||
|
||||
const ADMIN_PASSWORD = "admin123";
|
||||
|
||||
export const AdminProvider = ({ children }: { children: ReactNode }) => {
|
||||
const [isAdmin, setIsAdmin] = useState(false);
|
||||
const [productList, setProducts] = useState<Product[]>(products);
|
||||
const [reservations, setReservations] = useState<Reservation[]>(initialReservations);
|
||||
const { isAdmin } = useAuth();
|
||||
const [products, setProducts] = useState<Product[]>([]);
|
||||
const [productsLoading, setProductsLoading] = useState(false);
|
||||
const [reservations, setReservations] = useState<Reservation[]>([]);
|
||||
const [reservationsLoading, setReservationsLoading] = useState(false);
|
||||
|
||||
const login = (password: string) => {
|
||||
if (password === ADMIN_PASSWORD) {
|
||||
setIsAdmin(true);
|
||||
return true;
|
||||
const refreshProducts = async () => {
|
||||
if (!isAdmin) return;
|
||||
setProductsLoading(true);
|
||||
try {
|
||||
const res = await productsApi.adminListProducts();
|
||||
setProducts(res.data);
|
||||
} finally {
|
||||
setProductsLoading(false);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const logout = () => setIsAdmin(false);
|
||||
const refreshReservations = async () => {
|
||||
if (!isAdmin) return;
|
||||
setReservationsLoading(true);
|
||||
try {
|
||||
const res = await bookingsApi.adminListBookings();
|
||||
setReservations(res.data.map(toReservation));
|
||||
} finally {
|
||||
setReservationsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const addProduct = (product: Omit<Product, "id">) => {
|
||||
const newProduct: Product = { ...product, id: `p-${Date.now()}` };
|
||||
useEffect(() => {
|
||||
if (isAdmin) {
|
||||
refreshProducts();
|
||||
refreshReservations();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isAdmin]);
|
||||
|
||||
const addProduct = async (payload: productsApi.ProductPayload): Promise<Product> => {
|
||||
const newProduct = await productsApi.adminCreateProduct(payload);
|
||||
setProducts((prev) => [newProduct, ...prev]);
|
||||
return newProduct;
|
||||
};
|
||||
|
||||
const updateProduct = (id: string, updates: Partial<Product>) => {
|
||||
setProducts((prev) => prev.map((p) => (p.id === id ? { ...p, ...updates } : p)));
|
||||
const updateProduct = async (id: string, payload: Partial<productsApi.ProductPayload>) => {
|
||||
const updated = await productsApi.adminUpdateProduct(id, payload);
|
||||
setProducts((prev) => prev.map((p) => (p.id === id ? updated : p)));
|
||||
};
|
||||
|
||||
const deleteProduct = (id: string) => {
|
||||
const deleteProduct = async (id: string) => {
|
||||
await productsApi.adminDeleteProduct(id);
|
||||
setProducts((prev) => prev.filter((p) => p.id !== id));
|
||||
};
|
||||
|
||||
const updateReservationStatus = (id: string, status: Reservation["status"]) => {
|
||||
setReservations((prev) => prev.map((r) => (r.id === id ? { ...r, status } : r)));
|
||||
const updateReservationStatus = async (id: string, status: "confirmed" | "cancelled") => {
|
||||
await bookingsApi.adminUpdateBookingStatus(id, status);
|
||||
setReservations((prev) =>
|
||||
prev.map((r) => (r.id === id ? { ...r, status } : r))
|
||||
);
|
||||
};
|
||||
|
||||
const deleteReservation = (id: string) => {
|
||||
const deleteReservation = async (id: string) => {
|
||||
await bookingsApi.adminDeleteBooking(id);
|
||||
setReservations((prev) => prev.filter((r) => r.id !== id));
|
||||
};
|
||||
|
||||
@@ -79,13 +120,15 @@ export const AdminProvider = ({ children }: { children: ReactNode }) => {
|
||||
<AdminContext.Provider
|
||||
value={{
|
||||
isAdmin,
|
||||
login,
|
||||
logout,
|
||||
products: productList,
|
||||
products,
|
||||
productsLoading,
|
||||
refreshProducts,
|
||||
addProduct,
|
||||
updateProduct,
|
||||
deleteProduct,
|
||||
reservations,
|
||||
reservationsLoading,
|
||||
refreshReservations,
|
||||
updateReservationStatus,
|
||||
deleteReservation,
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user