2026-06-04 00:16:37 +03:30
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
// POS v2 data hooks — thin wrappers over the EXISTING data layer so the new POS
|
|
|
|
|
// UI reuses the same endpoints/query keys as the classic POS (cache-shared).
|
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
import { useMemo } from "react";
|
|
|
|
|
import { useQuery } from "@tanstack/react-query";
|
|
|
|
|
import { apiGet } from "@/lib/api/client";
|
|
|
|
|
import { getBranchMenu, branchMenuItemToMenuItem } from "@/lib/api/branch-menu";
|
|
|
|
|
import { fetchCafeTableBoard } from "@/lib/api/branch-tables";
|
|
|
|
|
import type { MenuCategory, MenuItem, TableBoardItem } from "@/lib/api/types";
|
|
|
|
|
|
|
|
|
|
export function usePos2Categories(cafeId?: string | null) {
|
|
|
|
|
return useQuery({
|
|
|
|
|
queryKey: ["menu-categories", cafeId],
|
|
|
|
|
queryFn: () => apiGet<MenuCategory[]>(`/api/cafes/${cafeId}/menu/categories`),
|
|
|
|
|
enabled: !!cafeId,
|
|
|
|
|
staleTime: 60_000,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Branch-scoped menu (effective prices) when a branch is selected; otherwise the
|
2026-06-07 07:10:03 +03:30
|
|
|
* café-wide menu. Both normalize to MenuItem so the cart store can consume them.
|
|
|
|
|
*
|
|
|
|
|
* Pass `branchId = undefined` (not null) while still determining which branch to
|
|
|
|
|
* use — the query will pause until branchId is resolved. Once resolved:
|
|
|
|
|
* • string → branch-scoped menu via getBranchMenu
|
|
|
|
|
* • null → café-wide fallback via /menu/items
|
|
|
|
|
*/
|
2026-06-04 00:16:37 +03:30
|
|
|
export function usePos2Menu(cafeId?: string | null, branchId?: string | null) {
|
|
|
|
|
return useQuery({
|
|
|
|
|
queryKey: ["pos2-menu", cafeId, branchId ?? "cafe"],
|
|
|
|
|
queryFn: async (): Promise<MenuItem[]> => {
|
|
|
|
|
if (branchId) {
|
|
|
|
|
const rows = await getBranchMenu(cafeId as string, branchId);
|
|
|
|
|
return rows.map(branchMenuItemToMenuItem);
|
|
|
|
|
}
|
|
|
|
|
return apiGet<MenuItem[]>(`/api/cafes/${cafeId}/menu/items`);
|
|
|
|
|
},
|
2026-06-07 07:10:03 +03:30
|
|
|
// branchId === undefined means "still determining" — don't fire yet
|
|
|
|
|
enabled: !!cafeId && branchId !== undefined,
|
2026-06-04 00:16:37 +03:30
|
|
|
staleTime: 30_000,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function usePos2Tables(cafeId?: string | null, branchId?: string | null) {
|
|
|
|
|
return useQuery({
|
|
|
|
|
queryKey: ["tables-board", cafeId, branchId, "pos"],
|
|
|
|
|
queryFn: () => fetchCafeTableBoard(cafeId as string, branchId ?? undefined),
|
|
|
|
|
enabled: !!cafeId,
|
|
|
|
|
refetchInterval: 15_000,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useMenuById(items: MenuItem[] | undefined): Map<string, MenuItem> {
|
|
|
|
|
return useMemo(() => {
|
|
|
|
|
const m = new Map<string, MenuItem>();
|
|
|
|
|
for (const it of items ?? []) m.set(it.id, it);
|
|
|
|
|
return m;
|
|
|
|
|
}, [items]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export type { MenuCategory, MenuItem, TableBoardItem };
|