"use client"; import { gql } from "@apollo/client"; import { useMutation, useQuery } from "@apollo/client/react"; import { ReactNode, createContext, useContext, useEffect, useState, } from "react"; import { eateryClient } from "./apollo-clients"; import { EateryEntity, type MenuItemEntity, type addMenuItemMutation, type allEateriesQuery, deleteMenuItemMutation, updateMenuItemMutation, } from "./types"; // ─── Types ──────────────────────────────────────────────────────────────────── export type ManagerTab = "products" | "reviews"; interface ManagerContextType { // Data products: MenuItemEntity[]; eateryId: string | null; eatery?: EateryEntity; // Active tab activeTab: ManagerTab; setActiveTab: (tab: ManagerTab) => void; // MenuItemEntity actions addProduct: (product: MenuItemEntity) => void; updateProduct: (product: MenuItemEntity) => void; deleteProduct: (id: string) => void; toggleProductAvailability: (product: MenuItemEntity) => void; } // ─── Context ────────────────────────────────────────────────────────────────── const ManagerContext = createContext(undefined); // ___ Graphql __________________________________________________________________ const GET_EATERY_MENU = gql` query GetEateryMenu { allEateries { id name menuItems { id name imageUrl available description price } } } `; const ADD_MENU_ITEM = gql` mutation addMenuItem($menuItem: AddMenuItemInput!) { addMenuItem(menuItem: $menuItem) { id name imageUrl available description price } } `; const UPDATE_MENU_ITEM = gql` mutation updateMenuItem($menuItem: UpdateMenuItemInput!) { updateMenuItem(menuItem: $menuItem) { id name imageUrl available description price } } `; const DELETE_MENU_ITEM = gql` mutation deleteMenuItem($input: String!) { deleteMenuItem(menuItemId: $input) } `; // ─── Provider ───────────────────────────────────────────────────────────────── export function ManagerProvider({ children }: { children: ReactNode }) { const [products, setProducts] = useState([]); const [eatery, setEatery] = useState(); const [activeTab, setActiveTab] = useState("products"); const { data } = useQuery(GET_EATERY_MENU, { client: eateryClient, fetchPolicy: "network-only", }); const eateryId = data?.allEateries?.[0]?.id ?? null; const [mutateAddMenuItem] = useMutation(ADD_MENU_ITEM, { client: eateryClient, }); const [mutateUpdateMenuItem] = useMutation( UPDATE_MENU_ITEM, { client: eateryClient }, ); const [mutateDeleteMenuItem] = useMutation( DELETE_MENU_ITEM, { client: eateryClient }, ); useEffect(() => { if (data?.allEateries?.[0]) { setProducts(data.allEateries[0].menuItems); setEatery(data.allEateries[0]); } }, [data]); // ── MenuItemEntity actions ────────────────────────────────────────────────────── const addProduct = async (product: MenuItemEntity) => { const { data } = await mutateAddMenuItem({ variables: { menuItem: product, }, }); if (!data) return; // addMenuItem backend does not persist imageUrl (constructor only maps name+price). // If the caller provided an imageUrl, patch it immediately via updateMenuItem // which uses MapStruct and correctly saves all fields. if (product.imageUrl && data.addMenuItem?.id) { const { data: updated } = await mutateUpdateMenuItem({ variables: { menuItem: { id: data.addMenuItem.id, imageUrl: product.imageUrl }, }, }); if (updated) { setProducts((prev) => [...prev, updated.updateMenuItem]); return; } } setProducts((prev) => [...prev, data.addMenuItem]); }; const updateProduct = async (product: MenuItemEntity) => { const { data } = await mutateUpdateMenuItem({ variables: { menuItem: product, }, }); if (data) setProducts((prev) => prev.map((p) => (p.id === product.id ? data.updateMenuItem : p)), ); }; const deleteProduct = async (id: string) => { const { data } = await mutateDeleteMenuItem({ variables: { input: id } }); if (data) setProducts((prev) => prev.filter((p) => !(p.id == id && data.deleteMenuItem)), ); }; const toggleProductAvailability = async (product: MenuItemEntity) => { const { data } = await mutateUpdateMenuItem({ variables: { menuItem: { ...product, available: !product.available }, }, }); if (data) setProducts((prev) => prev.map((p) => (p.id === product.id ? data.updateMenuItem : p)), ); }; return ( {children} ); } // ─── Hook ───────────────────────────────────────────────────────────────────── export function useManager() { const context = useContext(ManagerContext); if (context === undefined) { throw new Error("useManager must be used within a ManagerProvider"); } return context; }