Files
frontend/lib/manager-context.tsx
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

196 lines
5.2 KiB
TypeScript

"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 {
type MenuItemEntity,
type addMenuItemMutation,
type allEateriesQuery,
deleteMenuItemMutation,
updateMenuItemMutation,
} from "./types";
// ─── Types ────────────────────────────────────────────────────────────────────
export type ManagerTab = "products";
interface ManagerContextType {
// Data
products: MenuItemEntity[];
// 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<ManagerContextType | undefined>(undefined);
// ___ Graphql __________________________________________________________________
const GET_EATERY_MENU = gql`
query GetEateryMenu {
allEateries {
id
menuItems {
id
name
available
description
price
}
}
}
`;
const ADD_MENU_ITEM = gql`
mutation addMenuItem($menuItem: AddMenuItemInput!) {
addMenuItem(menuItem: $menuItem) {
id
name
available
description
price
}
}
`;
const UPDATE_MENU_ITEM = gql`
mutation updateMenuItem($menuItem: UpdateMenuItemInput!) {
updateMenuItem(menuItem: $menuItem) {
id
name
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<MenuItemEntity[]>([]);
const [activeTab, setActiveTab] = useState<ManagerTab>("products");
const { data } = useQuery<allEateriesQuery>(GET_EATERY_MENU, {
client: eateryClient,
fetchPolicy: "network-only",
});
const [mutateAddMenuItem] = useMutation<addMenuItemMutation>(ADD_MENU_ITEM, {
client: eateryClient,
});
const [mutateUpdateMenuItem] = useMutation<updateMenuItemMutation>(
UPDATE_MENU_ITEM,
{ client: eateryClient },
);
const [mutateDeleteMenuItem] = useMutation<deleteMenuItemMutation>(
DELETE_MENU_ITEM,
{ client: eateryClient },
);
useEffect(() => {
if (data?.allEateries?.[0]) {
setProducts(data.allEateries[0].menuItems);
}
}, [data]);
// ── MenuItemEntity actions ──────────────────────────────────────────────────────
const addProduct = async (product: MenuItemEntity) => {
const { data } = await mutateAddMenuItem({
variables: {
menuItem: product,
},
});
if (data) 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 (
<ManagerContext.Provider
value={{
products,
activeTab,
setActiveTab,
addProduct,
updateProduct,
deleteProduct,
toggleProductAvailability,
}}
>
{children}
</ManagerContext.Provider>
);
}
// ─── Hook ─────────────────────────────────────────────────────────────────────
export function useManager() {
const context = useContext(ManagerContext);
if (context === undefined) {
throw new Error("useManager must be used within a ManagerProvider");
}
return context;
}