Files
meezi/web/dashboard/src/lib/pos2/use-pos2.ts
T
soroush.asadi 59486cdf24
CI/CD / CI · API (dotnet build + test) (push) Failing after 3m20s
CI/CD / CI · Admin API (dotnet build) (push) Failing after 3m19s
CI/CD / CI · Dashboard (tsc) (push) Successful in 1m5s
CI/CD / CI · Admin Web (tsc) (push) Successful in 41s
CI/CD / CI · Website (tsc) (push) Successful in 44s
CI/CD / CI · Koja (tsc) (push) Successful in 52s
CI/CD / Deploy · all services (push) Has been cancelled
fix(pos2): wait for branch before fetching menu + add left category sidebar
Race fix: orderBranchId now returns `undefined` (not null) while the /branches
query is in flight. usePos2Menu treats undefined as "not yet determined" and
skips the fetch, preventing getBranchMenu(cafeId, null) → empty array.
Once branchesFetched=true, orderBranchId resolves to the correct branchId
(or null for café-wide fallback).

Layout: desktop order screen now shows a left vertical category sidebar
(116 px, md+) instead of horizontal chips, giving the classic POS sidebar
feel. Horizontal chips kept for mobile (<md). Menu grid columns adjusted.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 07:10:03 +03:30

66 lines
2.8 KiB
TypeScript

"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
* 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
*/
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`);
},
// branchId === undefined means "still determining" — don't fire yet
enabled: !!cafeId && branchId !== undefined,
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 };