"use client"; import React, { useContext, useState, useEffect, startTransition, 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; email: string; phone: string; service: string; date: string; time: string; status: "pending" | "confirmed" | "cancelled"; createdAt: string; } 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; products: Product[]; productsLoading: boolean; refreshProducts: () => Promise; addProduct: (payload: productsApi.ProductPayload) => Promise; updateProduct: (id: string, payload: Partial) => Promise; deleteProduct: (id: string) => Promise; reservations: Reservation[]; reservationsLoading: boolean; refreshReservations: (silent?: boolean) => Promise; updateReservationStatus: (id: string, status: "confirmed" | "cancelled") => Promise; deleteReservation: (id: string) => Promise; } const AdminContext = createContext(undefined); export const AdminProvider = ({ children }: { children: ReactNode }) => { const { isAdmin } = useAuth(); const [products, setProducts] = useState([]); const [productsLoading, setProductsLoading] = useState(false); const [reservations, setReservations] = useState([]); const [reservationsLoading, setReservationsLoading] = useState(false); const refreshProducts = async () => { if (!isAdmin) return; setProductsLoading(true); try { const res = await productsApi.adminListProducts(); setProducts(res.data); } finally { setProductsLoading(false); } }; const refreshReservations = async (silent = false) => { if (!isAdmin) return; if (!silent) setReservationsLoading(true); try { const res = await bookingsApi.adminListBookings(); setReservations(res.data.map(toReservation)); } finally { if (!silent) setReservationsLoading(false); } }; useEffect(() => { if (isAdmin) { startTransition(() => { refreshProducts(); refreshReservations(); }); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [isAdmin]); const addProduct = async (payload: productsApi.ProductPayload): Promise => { const newProduct = await productsApi.adminCreateProduct(payload); setProducts((prev) => [newProduct, ...prev]); return newProduct; }; const updateProduct = async (id: string, payload: Partial) => { const updated = await productsApi.adminUpdateProduct(id, payload); setProducts((prev) => prev.map((p) => (p.id === id ? updated : p))); }; const deleteProduct = async (id: string) => { await productsApi.adminDeleteProduct(id); setProducts((prev) => prev.filter((p) => p.id !== id)); }; const updateReservationStatus = async (id: string, status: "confirmed" | "cancelled") => { await bookingsApi.adminUpdateBookingStatus(id, status); setReservations((prev) => prev.map((r) => (r.id === id ? { ...r, status } : r)) ); // Sync with server silently — no loading flash refreshReservations(true); }; const deleteReservation = async (id: string) => { await bookingsApi.adminDeleteBooking(id); setReservations((prev) => prev.filter((r) => r.id !== id)); }; return ( {children} ); }; export const useAdmin = () => { const ctx = useContext(AdminContext); if (!ctx) throw new Error("useAdmin must be used within AdminProvider"); return ctx; };