@fayz-ai/pos 0.20.0 → 0.20.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/config.d.ts +10 -0
- package/dist/app/config.d.ts.map +1 -1
- package/dist/index.js +593 -307
- package/dist/index.js.map +1 -1
- package/dist/screen/OpenTableSheet.d.ts +18 -1
- package/dist/screen/OpenTableSheet.d.ts.map +1 -1
- package/dist/screen/PosScreen.d.ts +44 -1
- package/dist/screen/PosScreen.d.ts.map +1 -1
- package/dist/screen/TicketRail.d.ts +9 -1
- package/dist/screen/TicketRail.d.ts.map +1 -1
- package/dist/screen/views.d.ts +26 -1
- package/dist/screen/views.d.ts.map +1 -1
- package/dist/styles.css +501 -34
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { haptic, createKeymap, directionOf, moveFocus } from '@fayz-ai/core/interaction';
|
|
2
2
|
export { comboOf, createKeymap, haptic, setHapticsEnabled } from '@fayz-ai/core/interaction';
|
|
3
3
|
import { useState, useRef, useCallback, useEffect, useMemo, useReducer } from 'react';
|
|
4
|
-
import { Pencil, Receipt,
|
|
4
|
+
import { ChevronDown, Pencil, Receipt, ChefHat, AlertTriangle, ChevronLeft, QrCode, CreditCard, Banknote, Trash2, Minus, Plus, Bike, Package, CheckCheck, Clock, MapPin, ShieldCheck, Keyboard, X, CalendarClock, Users, Phone, Check, UserRound, User, Delete, UtensilsCrossed, Info, LayoutGrid, ClipboardList, ChevronUp, MoreHorizontal, Search, Utensils, CheckCircle2, CookingPot } from 'lucide-react';
|
|
5
5
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
// src/keyboard/index.ts
|
|
@@ -232,6 +232,28 @@ function elapsed(openedAt, now = Date.now()) {
|
|
|
232
232
|
if (minutes < 0 || !Number.isFinite(minutes)) return void 0;
|
|
233
233
|
return minutes < 60 ? `${minutes}min` : `${Math.floor(minutes / 60)}h${String(minutes % 60).padStart(2, "0")}`;
|
|
234
234
|
}
|
|
235
|
+
function FloorSkeleton({ count = 8 }) {
|
|
236
|
+
return /* @__PURE__ */ jsx("div", { className: "pos-floor pos-scroll", "aria-busy": "true", "aria-label": "Carregando as mesas", children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsxs("div", { className: "pos-tbl pos-skel", "aria-hidden": true, children: [
|
|
237
|
+
/* @__PURE__ */ jsx("span", { className: "pos-skel__b", style: { width: "46%", height: 21 } }),
|
|
238
|
+
/* @__PURE__ */ jsx("span", { className: "pos-skel__b", style: { width: "58%", height: 22 } }),
|
|
239
|
+
/* @__PURE__ */ jsx("span", { className: "pos-skel__b", style: { width: "34%", height: 12, marginTop: "auto" } })
|
|
240
|
+
] }, i)) });
|
|
241
|
+
}
|
|
242
|
+
function CatalogSkeleton({ categories = 6, items = 6 }) {
|
|
243
|
+
return /* @__PURE__ */ jsxs("div", { className: "pos-scroll", style: { flex: 1, minHeight: 0 }, "aria-busy": "true", "aria-label": "Carregando o card\xE1pio", children: [
|
|
244
|
+
/* @__PURE__ */ jsx("div", { className: "pos-cats", children: Array.from({ length: categories }, (_, i) => /* @__PURE__ */ jsx("div", { className: "pos-cat pos-skel", "aria-hidden": true, children: /* @__PURE__ */ jsx("span", { className: "pos-skel__b", style: { width: "70%", height: 13 } }) }, i)) }),
|
|
245
|
+
/* @__PURE__ */ jsx("div", { className: "pos-items", children: Array.from({ length: items }, (_, i) => /* @__PURE__ */ jsxs("div", { className: "pos-item pos-skel", "aria-hidden": true, children: [
|
|
246
|
+
/* @__PURE__ */ jsxs("span", { className: "pos-item__top", children: [
|
|
247
|
+
/* @__PURE__ */ jsx("span", { className: "pos-skel__b", style: { width: 52, height: 52, flex: "none" } }),
|
|
248
|
+
/* @__PURE__ */ jsxs("span", { className: "pos-item__id", children: [
|
|
249
|
+
/* @__PURE__ */ jsx("span", { className: "pos-skel__b", style: { width: "80%", height: 14 } }),
|
|
250
|
+
/* @__PURE__ */ jsx("span", { className: "pos-skel__b", style: { width: "45%", height: 12 } })
|
|
251
|
+
] })
|
|
252
|
+
] }),
|
|
253
|
+
/* @__PURE__ */ jsx("span", { className: "pos-skel__b", style: { width: "100%", height: 34, marginTop: "auto" } })
|
|
254
|
+
] }, i)) })
|
|
255
|
+
] });
|
|
256
|
+
}
|
|
235
257
|
function EmptyState({ title, hint, Icon = Search, action }) {
|
|
236
258
|
return /* @__PURE__ */ jsxs("div", { className: "pos-empty", children: [
|
|
237
259
|
/* @__PURE__ */ jsx("span", { className: "pos-empty__icon", children: /* @__PURE__ */ jsx(Icon, { size: 20, strokeWidth: 2, "aria-hidden": true }) }),
|
|
@@ -243,11 +265,11 @@ function EmptyState({ title, hint, Icon = Search, action }) {
|
|
|
243
265
|
}, children: action.label })
|
|
244
266
|
] });
|
|
245
267
|
}
|
|
246
|
-
function FloorView({ positions, config, activeId, onSelect, now, picking }) {
|
|
268
|
+
function FloorView({ positions, config, activeId, onSelect, now, picking, layout }) {
|
|
247
269
|
if (positions.length === 0) {
|
|
248
270
|
return /* @__PURE__ */ jsx(EmptyState, { title: "Nenhuma mesa nesta \xE1rea", hint: "Escolha outra \xE1rea acima.", Icon: Utensils });
|
|
249
271
|
}
|
|
250
|
-
return
|
|
272
|
+
return layout === "plan" ? /* @__PURE__ */ jsx(PlanFloor, { positions, config, activeId, onSelect, picking }) : /* @__PURE__ */ jsx(GridFloor, { positions, activeId, onSelect, now, picking });
|
|
251
273
|
}
|
|
252
274
|
function GridFloor({ positions, activeId, onSelect, now, picking }) {
|
|
253
275
|
return /* @__PURE__ */ jsx("div", { className: "pos-floor pos-scroll", "data-picking": picking, children: positions.map((p, index) => {
|
|
@@ -449,11 +471,16 @@ function CatalogView({
|
|
|
449
471
|
delayMs: Math.min(index, 11) * 24,
|
|
450
472
|
tone: category?.tone,
|
|
451
473
|
children: [
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
474
|
+
/* @__PURE__ */ jsxs("span", { className: "pos-item__top", children: [
|
|
475
|
+
item.imageUrl ? /* @__PURE__ */ jsx("span", { className: "pos-item__img", children: /* @__PURE__ */ jsx("img", { src: item.imageUrl, alt: "", loading: "lazy", decoding: "async" }) }) : null,
|
|
476
|
+
/* @__PURE__ */ jsxs("span", { className: "pos-item__id", children: [
|
|
477
|
+
item.route && /* @__PURE__ */ jsx("span", { className: "pos-item__route", children: item.route }),
|
|
478
|
+
/* @__PURE__ */ jsx("span", { className: "pos-item__name", children: item.name }),
|
|
479
|
+
/* @__PURE__ */ jsxs("span", { className: "pos-item__price pos-num", children: [
|
|
480
|
+
formatCents(item.priceCents),
|
|
481
|
+
item.code && ` \xB7 ${item.code}`
|
|
482
|
+
] })
|
|
483
|
+
] })
|
|
457
484
|
] }),
|
|
458
485
|
/* @__PURE__ */ jsx("span", { className: "pos-item__foot", onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsxs("span", { className: "pos-step", children: [
|
|
459
486
|
/* @__PURE__ */ jsx(
|
|
@@ -546,7 +573,36 @@ var PAY_ICON = {
|
|
|
546
573
|
"cart\xE3o": CreditCard,
|
|
547
574
|
pix: QrCode
|
|
548
575
|
};
|
|
576
|
+
function useSheetDrag(onDismiss) {
|
|
577
|
+
const [offset, setOffset] = useState(0);
|
|
578
|
+
const [dragging, setDragging] = useState(false);
|
|
579
|
+
const startRef = useRef(0);
|
|
580
|
+
if (!onDismiss) return { offset: 0, dragging: false, handlers: {} };
|
|
581
|
+
return {
|
|
582
|
+
offset,
|
|
583
|
+
dragging,
|
|
584
|
+
handlers: {
|
|
585
|
+
onPointerDown: (e) => {
|
|
586
|
+
startRef.current = e.clientY;
|
|
587
|
+
setDragging(true);
|
|
588
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
589
|
+
},
|
|
590
|
+
onPointerMove: (e) => {
|
|
591
|
+
if (!dragging) return;
|
|
592
|
+
setOffset(Math.max(0, e.clientY - startRef.current));
|
|
593
|
+
},
|
|
594
|
+
onPointerUp: (e) => {
|
|
595
|
+
setDragging(false);
|
|
596
|
+
const el = e.currentTarget.closest(".pos-aside");
|
|
597
|
+
const height = el?.getBoundingClientRect().height ?? window.innerHeight;
|
|
598
|
+
if (offset > height / 3) onDismiss();
|
|
599
|
+
setOffset(0);
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
}
|
|
549
604
|
function TicketRail({
|
|
605
|
+
onCollapse,
|
|
550
606
|
ticket,
|
|
551
607
|
totals,
|
|
552
608
|
vocabulary,
|
|
@@ -573,6 +629,7 @@ function TicketRail({
|
|
|
573
629
|
onFire,
|
|
574
630
|
fireShortcut
|
|
575
631
|
}) {
|
|
632
|
+
const drag = useSheetDrag(onCollapse);
|
|
576
633
|
const [tab, setTab] = useState("order");
|
|
577
634
|
const [paid, setPaid] = useState(false);
|
|
578
635
|
const [stage, setStage] = useState("order");
|
|
@@ -588,12 +645,40 @@ function TicketRail({
|
|
|
588
645
|
className: "pos-aside",
|
|
589
646
|
ref: containerRef,
|
|
590
647
|
"data-open": open ?? true,
|
|
648
|
+
"data-dragging": drag.dragging || void 0,
|
|
649
|
+
style: drag.offset ? { transform: `translateY(${drag.offset}px)` } : void 0,
|
|
591
650
|
"aria-label": vocabulary.ticket,
|
|
592
651
|
children: [
|
|
652
|
+
onCollapse && /* @__PURE__ */ jsx(
|
|
653
|
+
"div",
|
|
654
|
+
{
|
|
655
|
+
className: "pos-aside__grab",
|
|
656
|
+
role: "button",
|
|
657
|
+
tabIndex: 0,
|
|
658
|
+
"aria-label": "Arraste para baixo para minimizar a comanda",
|
|
659
|
+
onKeyDown: (e) => {
|
|
660
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
661
|
+
e.preventDefault();
|
|
662
|
+
onCollapse();
|
|
663
|
+
}
|
|
664
|
+
},
|
|
665
|
+
...drag.handlers
|
|
666
|
+
}
|
|
667
|
+
),
|
|
593
668
|
/* @__PURE__ */ jsxs("header", { className: "pos-tkt", children: [
|
|
594
669
|
/* @__PURE__ */ jsxs("div", { className: "pos-tkt__row", children: [
|
|
595
670
|
/* @__PURE__ */ jsx("span", { className: "pos-t-xl", children: ticket.positionLabel ?? "Balc\xE3o" }),
|
|
596
671
|
status && /* @__PURE__ */ jsx(StatusBadge, { status }),
|
|
672
|
+
onCollapse && /* @__PURE__ */ jsx(
|
|
673
|
+
"button",
|
|
674
|
+
{
|
|
675
|
+
className: "pos-tkt__collapse",
|
|
676
|
+
onClick: onCollapse,
|
|
677
|
+
"aria-label": "Fechar a comanda",
|
|
678
|
+
title: "Fechar a comanda",
|
|
679
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { size: 18, strokeWidth: 2.4 })
|
|
680
|
+
}
|
|
681
|
+
),
|
|
597
682
|
onEditIdentity && /* @__PURE__ */ jsx(
|
|
598
683
|
"button",
|
|
599
684
|
{
|
|
@@ -705,10 +790,6 @@ function TicketRail({
|
|
|
705
790
|
and offering it as the big button is how a bill gets paid for food
|
|
706
791
|
the kitchen never heard about. */
|
|
707
792
|
/* @__PURE__ */ jsx("div", { className: "pos-cta pos-cta--stack", children: pendingCount > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
708
|
-
/* @__PURE__ */ jsxs("p", { className: "pos-hint", children: [
|
|
709
|
-
/* @__PURE__ */ jsx(AlertTriangle, { size: 14, strokeWidth: 2.4, "aria-hidden": true }),
|
|
710
|
-
pendingCount === 1 ? "1 item marcado ainda n\xE3o foi para a cozinha" : `${pendingCount} itens marcados ainda n\xE3o foram para a cozinha`
|
|
711
|
-
] }),
|
|
712
793
|
/* @__PURE__ */ jsxs(
|
|
713
794
|
"button",
|
|
714
795
|
{
|
|
@@ -728,11 +809,17 @@ function TicketRail({
|
|
|
728
809
|
/* @__PURE__ */ jsxs(
|
|
729
810
|
"button",
|
|
730
811
|
{
|
|
731
|
-
className: "pos-btn pos-btn--ghost pos-btn--wide",
|
|
812
|
+
className: "pos-btn pos-btn--ghost pos-btn--wide pos-btn--warn",
|
|
732
813
|
onClick: () => setStage("checkout"),
|
|
733
814
|
children: [
|
|
734
|
-
"
|
|
735
|
-
|
|
815
|
+
/* @__PURE__ */ jsxs("span", { className: "pos-btn__l1", children: [
|
|
816
|
+
"Fechar mesmo assim \xB7 ",
|
|
817
|
+
formatCents(totals.totalCents)
|
|
818
|
+
] }),
|
|
819
|
+
/* @__PURE__ */ jsxs("span", { className: "pos-btn__l2", children: [
|
|
820
|
+
/* @__PURE__ */ jsx(AlertTriangle, { size: 12, strokeWidth: 2.4, "aria-hidden": true }),
|
|
821
|
+
pendingCount === 1 ? "1 item n\xE3o foi para a cozinha" : `${pendingCount} itens n\xE3o foram para a cozinha`
|
|
822
|
+
] })
|
|
736
823
|
]
|
|
737
824
|
}
|
|
738
825
|
)
|
|
@@ -896,7 +983,7 @@ var STATE_LABEL = {
|
|
|
896
983
|
function StateIcon({ state }) {
|
|
897
984
|
if (state === "fired") return /* @__PURE__ */ jsx(CookingPot, { size: 15, strokeWidth: 2.2, "aria-hidden": true });
|
|
898
985
|
if (state === "delivered") return /* @__PURE__ */ jsx(UtensilsCrossed, { size: 15, strokeWidth: 2.2, "aria-hidden": true });
|
|
899
|
-
return
|
|
986
|
+
return null;
|
|
900
987
|
}
|
|
901
988
|
function clock(iso) {
|
|
902
989
|
return new Date(iso).toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" });
|
|
@@ -1512,13 +1599,14 @@ function OpenTableSheet({
|
|
|
1512
1599
|
position,
|
|
1513
1600
|
vocabulary,
|
|
1514
1601
|
staff,
|
|
1602
|
+
operator,
|
|
1515
1603
|
defaultSeats,
|
|
1516
1604
|
seatingName,
|
|
1517
1605
|
onCancel,
|
|
1518
1606
|
onConfirm
|
|
1519
1607
|
}) {
|
|
1520
1608
|
const [guests, setGuests] = useState(defaultSeats ?? position.seats ?? 2);
|
|
1521
|
-
const [attendantId, setAttendantId] = useState(staff[0]?.id);
|
|
1609
|
+
const [attendantId, setAttendantId] = useState(operator?.id ?? staff[0]?.id);
|
|
1522
1610
|
useEffect(() => {
|
|
1523
1611
|
function onKey(event) {
|
|
1524
1612
|
if (event.key === "Escape") {
|
|
@@ -1595,7 +1683,11 @@ function OpenTableSheet({
|
|
|
1595
1683
|
guests,
|
|
1596
1684
|
" pessoas."
|
|
1597
1685
|
] }),
|
|
1598
|
-
|
|
1686
|
+
operator && /* @__PURE__ */ jsxs("p", { className: "pos-sheet__who", children: [
|
|
1687
|
+
"Abrindo no nome de ",
|
|
1688
|
+
/* @__PURE__ */ jsx("strong", { children: operator.name })
|
|
1689
|
+
] }),
|
|
1690
|
+
!operator && staff.length > 0 && /* @__PURE__ */ jsxs("section", { className: "pos-mgroup", children: [
|
|
1599
1691
|
/* @__PURE__ */ jsx("div", { className: "pos-mgroup__head", children: /* @__PURE__ */ jsx("span", { className: "pos-t-xs", children: "Atendente" }) }),
|
|
1600
1692
|
/* @__PURE__ */ jsx("div", { className: "pos-mgroup__opts", children: staff.map((s) => /* @__PURE__ */ jsxs(
|
|
1601
1693
|
"button",
|
|
@@ -1934,6 +2026,26 @@ var MENU_ICON = {
|
|
|
1934
2026
|
shift: Banknote,
|
|
1935
2027
|
reservations: CalendarClock
|
|
1936
2028
|
};
|
|
2029
|
+
function useMedia(query) {
|
|
2030
|
+
const [matches, setMatches] = useState(
|
|
2031
|
+
() => typeof window !== "undefined" && window.matchMedia(query).matches
|
|
2032
|
+
);
|
|
2033
|
+
useEffect(() => {
|
|
2034
|
+
if (typeof window === "undefined") return;
|
|
2035
|
+
const mq = window.matchMedia(query);
|
|
2036
|
+
const on = () => setMatches(mq.matches);
|
|
2037
|
+
setMatches(mq.matches);
|
|
2038
|
+
mq.addEventListener("change", on);
|
|
2039
|
+
return () => mq.removeEventListener("change", on);
|
|
2040
|
+
}, [query]);
|
|
2041
|
+
return matches;
|
|
2042
|
+
}
|
|
2043
|
+
function usePhone() {
|
|
2044
|
+
return useMedia("(max-width: 640px)");
|
|
2045
|
+
}
|
|
2046
|
+
function useWideRail() {
|
|
2047
|
+
return useMedia("(min-width: 1181px)");
|
|
2048
|
+
}
|
|
1937
2049
|
var lineSeq = 0;
|
|
1938
2050
|
var nextLineId = () => `line-${++lineSeq}`;
|
|
1939
2051
|
function PosScreen({
|
|
@@ -1946,6 +2058,7 @@ function PosScreen({
|
|
|
1946
2058
|
terminalName,
|
|
1947
2059
|
operatorName,
|
|
1948
2060
|
connection = "online",
|
|
2061
|
+
operatorId,
|
|
1949
2062
|
onAction,
|
|
1950
2063
|
onOpenPosition,
|
|
1951
2064
|
onFire,
|
|
@@ -1958,7 +2071,10 @@ function PosScreen({
|
|
|
1958
2071
|
brandMark,
|
|
1959
2072
|
brandName,
|
|
1960
2073
|
className,
|
|
2074
|
+
style,
|
|
1961
2075
|
railTop,
|
|
2076
|
+
unitSwitcher,
|
|
2077
|
+
loading = false,
|
|
1962
2078
|
now = Date.now()
|
|
1963
2079
|
}) {
|
|
1964
2080
|
const [book, dispatchBook] = useReducer(bookReducer, void 0, () => {
|
|
@@ -2146,8 +2262,13 @@ function PosScreen({
|
|
|
2146
2262
|
text: seating ? `${seating.name} na ${config.vocabulary.position} ${p.label}` : `${config.vocabulary.position} ${p.label} aberta`,
|
|
2147
2263
|
tone: "ok"
|
|
2148
2264
|
});
|
|
2265
|
+
const catalog = config.menus.find((m) => m.view === "catalog");
|
|
2266
|
+
if (catalog) {
|
|
2267
|
+
setMenuId(catalog.id);
|
|
2268
|
+
requestAnimationFrame(() => commandRef.current?.focus());
|
|
2269
|
+
}
|
|
2149
2270
|
onOpenPosition?.(p.id, guests, attendantId);
|
|
2150
|
-
}, [openingPosition, staff, now, seating, onOpenPosition, config.vocabulary.position]);
|
|
2271
|
+
}, [openingPosition, staff, now, seating, onOpenPosition, config.vocabulary.position, config.menus]);
|
|
2151
2272
|
const runAction = useCallback((actionId) => {
|
|
2152
2273
|
if (actionId === "fire") {
|
|
2153
2274
|
const at = new Date(now).toISOString();
|
|
@@ -2245,323 +2366,488 @@ function PosScreen({
|
|
|
2245
2366
|
seatingRef.current = seating;
|
|
2246
2367
|
}, [seating]);
|
|
2247
2368
|
const openCount = livePositions.filter((p) => p.status !== "free").length;
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2369
|
+
const TABS_ON_PHONE = 3;
|
|
2370
|
+
const [moreOpen, setMoreOpen] = useState(false);
|
|
2371
|
+
const pendingCount = ticket.lines.filter((l) => (l.state ?? "pending") === "pending").length;
|
|
2372
|
+
const [floorLayout, setFloorLayout] = useState("grid");
|
|
2373
|
+
const isPhone = usePhone();
|
|
2374
|
+
const wideRail = useWideRail();
|
|
2375
|
+
const phoneTabs = config.menus.slice(0, TABS_ON_PHONE);
|
|
2376
|
+
const overflowTabs = config.menus.slice(TABS_ON_PHONE);
|
|
2377
|
+
const searchField = /* @__PURE__ */ jsxs("label", { className: "pos-field", children: [
|
|
2378
|
+
/* @__PURE__ */ jsx("span", { className: "pos-field__icon", children: /* @__PURE__ */ jsx(Search, { size: 17, strokeWidth: 2.2, "aria-hidden": true }) }),
|
|
2379
|
+
/* @__PURE__ */ jsx(
|
|
2380
|
+
"input",
|
|
2381
|
+
{
|
|
2382
|
+
ref: commandRef,
|
|
2383
|
+
value: query,
|
|
2384
|
+
onChange: (e) => {
|
|
2385
|
+
setQuery(e.target.value);
|
|
2386
|
+
const cat = config.menus.find((m) => m.view === "catalog");
|
|
2387
|
+
if (e.target.value && cat && menu?.view !== "catalog") setMenuId(cat.id);
|
|
2388
|
+
},
|
|
2389
|
+
placeholder: "Buscar",
|
|
2390
|
+
"aria-label": "Buscar item por c\xF3digo ou nome"
|
|
2391
|
+
}
|
|
2392
|
+
),
|
|
2393
|
+
query ? /* @__PURE__ */ jsx(
|
|
2394
|
+
"button",
|
|
2395
|
+
{
|
|
2396
|
+
type: "button",
|
|
2397
|
+
className: "pos-field__clear",
|
|
2398
|
+
onClick: () => {
|
|
2399
|
+
setQuery("");
|
|
2400
|
+
commandRef.current?.focus();
|
|
2401
|
+
},
|
|
2402
|
+
"aria-label": "Limpar busca",
|
|
2403
|
+
children: /* @__PURE__ */ jsx(X, { size: 14, strokeWidth: 2.6 })
|
|
2404
|
+
}
|
|
2405
|
+
) : (
|
|
2406
|
+
// Esc is the way back to this field from anywhere; saying so
|
|
2407
|
+
// costs one chip and saves the operator from hunting for it.
|
|
2408
|
+
/* @__PURE__ */ jsx("kbd", { className: "pos-field__hint", "aria-hidden": true, children: "Esc" })
|
|
2409
|
+
)
|
|
2410
|
+
] });
|
|
2411
|
+
return /* @__PURE__ */ jsxs(
|
|
2412
|
+
"div",
|
|
2413
|
+
{
|
|
2414
|
+
className: className ? `pos ${className}` : "pos",
|
|
2415
|
+
style,
|
|
2416
|
+
"data-cart-open": railOpen || void 0,
|
|
2417
|
+
children: [
|
|
2418
|
+
/* @__PURE__ */ jsxs("div", { className: "pos-body", children: [
|
|
2419
|
+
/* @__PURE__ */ jsxs("nav", { className: "pos-rail", "aria-label": "Navega\xE7\xE3o principal", children: [
|
|
2420
|
+
/* @__PURE__ */ jsxs("div", { className: "pos-brand", children: [
|
|
2421
|
+
/* @__PURE__ */ jsx("span", { className: "pos-brand__mark", children: brandMark ?? config.name.slice(0, 1) }),
|
|
2422
|
+
/* @__PURE__ */ jsx("span", { className: "pos-brand__name", children: brandName ?? config.name })
|
|
2423
|
+
] }),
|
|
2424
|
+
railTop && /* @__PURE__ */ jsx("div", { className: "pos-rail__top", children: railTop }),
|
|
2425
|
+
wideRail && /* @__PURE__ */ jsx("div", { className: "pos-rail__search", children: searchField }),
|
|
2426
|
+
/* @__PURE__ */ jsx("div", { className: "pos-rail__label pos-t-xs", children: "Opera\xE7\xE3o" }),
|
|
2427
|
+
/* @__PURE__ */ jsx("div", { className: "pos-nav", children: config.menus.map((m) => {
|
|
2428
|
+
const Icon = MENU_ICON[m.view] ?? ClipboardList;
|
|
2429
|
+
return /* @__PURE__ */ jsxs(
|
|
2430
|
+
"button",
|
|
2431
|
+
{
|
|
2432
|
+
className: "pos-nav__item",
|
|
2433
|
+
"aria-current": m.id === menu?.id ? "page" : void 0,
|
|
2434
|
+
onClick: () => setMenuId(m.id),
|
|
2435
|
+
title: m.label,
|
|
2436
|
+
children: [
|
|
2437
|
+
/* @__PURE__ */ jsx("span", { className: "pos-nav__icon", children: /* @__PURE__ */ jsx(Icon, { size: 19, strokeWidth: 2.1, "aria-hidden": true }) }),
|
|
2438
|
+
/* @__PURE__ */ jsx("span", { className: "pos-nav__text", children: m.label }),
|
|
2439
|
+
m.badge != null && m.badge > 0 && /* @__PURE__ */ jsx("span", { className: "pos-nav__count pos-num", children: m.badge })
|
|
2440
|
+
]
|
|
2441
|
+
},
|
|
2442
|
+
m.id
|
|
2443
|
+
);
|
|
2444
|
+
}) }),
|
|
2445
|
+
/* @__PURE__ */ jsxs("div", { className: "pos-user", "data-state": connection, children: [
|
|
2446
|
+
/* @__PURE__ */ jsx("span", { className: "pos-user__av", children: (operatorName ?? config.name).slice(0, 1) }),
|
|
2447
|
+
/* @__PURE__ */ jsxs("span", { className: "pos-user__txt", children: [
|
|
2448
|
+
/* @__PURE__ */ jsxs("span", { className: terminalName ? "pos-user__name" : "pos-user__name pos-user__name--dotted", children: [
|
|
2449
|
+
!terminalName && /* @__PURE__ */ jsx("span", { className: "pos-user__dot", "aria-hidden": true }),
|
|
2450
|
+
operatorName ?? config.name
|
|
2451
|
+
] }),
|
|
2452
|
+
terminalName && /* @__PURE__ */ jsxs("span", { className: "pos-user__meta", children: [
|
|
2453
|
+
/* @__PURE__ */ jsx("span", { className: "pos-user__dot", "aria-hidden": true }),
|
|
2454
|
+
terminalName
|
|
2455
|
+
] })
|
|
2456
|
+
] }),
|
|
2457
|
+
/* @__PURE__ */ jsx(
|
|
2458
|
+
"button",
|
|
2459
|
+
{
|
|
2460
|
+
className: "pos-user__act",
|
|
2461
|
+
onClick: () => setShowKeys(true),
|
|
2462
|
+
"aria-label": "Atalhos",
|
|
2463
|
+
title: "Atalhos (F1)",
|
|
2464
|
+
children: /* @__PURE__ */ jsx(Keyboard, { size: 15, strokeWidth: 2.2, "aria-hidden": true })
|
|
2465
|
+
}
|
|
2466
|
+
)
|
|
2467
|
+
] })
|
|
2468
|
+
] }),
|
|
2469
|
+
/* @__PURE__ */ jsxs("main", { className: "pos-main", ref: mainRef, children: [
|
|
2470
|
+
/* @__PURE__ */ jsxs("div", { className: "pos-head", children: [
|
|
2471
|
+
/* @__PURE__ */ jsxs("div", { className: "pos-head__where", children: [
|
|
2472
|
+
/* @__PURE__ */ jsx("span", { className: "pos-head__title", children: menu?.label }),
|
|
2473
|
+
unitSwitcher
|
|
2474
|
+
] }),
|
|
2475
|
+
!wideRail && searchField,
|
|
2476
|
+
/* @__PURE__ */ jsxs("span", { className: "pos-head__views", children: [
|
|
2477
|
+
menu?.view === "floor" && !isPhone && /* @__PURE__ */ jsx("span", { className: "pos-seg", role: "group", "aria-label": "Como ver as mesas", children: [["grid", "Grade"], ["plan", "Planta"]].map(([value, label]) => /* @__PURE__ */ jsx(
|
|
2478
|
+
"button",
|
|
2479
|
+
{
|
|
2480
|
+
className: "pos-seg__btn",
|
|
2481
|
+
"aria-pressed": floorLayout === value,
|
|
2482
|
+
onClick: () => {
|
|
2483
|
+
haptic("tap");
|
|
2484
|
+
setFloorLayout(value);
|
|
2485
|
+
},
|
|
2486
|
+
children: label
|
|
2487
|
+
},
|
|
2488
|
+
value
|
|
2489
|
+
)) }),
|
|
2490
|
+
menu?.view === "floor" && (config.positions.zones ?? []).length > 0 && /* @__PURE__ */ jsx("span", { className: "pos-seg", role: "group", "aria-label": "\xC1reas", children: config.positions.zones.map((z) => /* @__PURE__ */ jsx(
|
|
2491
|
+
"button",
|
|
2492
|
+
{
|
|
2493
|
+
className: "pos-seg__btn",
|
|
2494
|
+
"aria-pressed": z.id === activeZoneId,
|
|
2495
|
+
onClick: () => setActiveZoneId(z.id),
|
|
2496
|
+
children: z.label
|
|
2497
|
+
},
|
|
2498
|
+
z.id
|
|
2499
|
+
)) })
|
|
2500
|
+
] })
|
|
2501
|
+
] }),
|
|
2502
|
+
menu?.view === "floor" && loading && /* @__PURE__ */ jsx(FloorSkeleton, {}),
|
|
2503
|
+
menu?.view === "floor" && !loading && /* @__PURE__ */ jsx(
|
|
2504
|
+
FloorView,
|
|
2505
|
+
{
|
|
2506
|
+
layout: isPhone ? "grid" : floorLayout,
|
|
2507
|
+
positions: zonePositions,
|
|
2508
|
+
config: config.positions,
|
|
2509
|
+
activeId: activePositionId,
|
|
2510
|
+
onSelect: selectPosition,
|
|
2511
|
+
now,
|
|
2512
|
+
picking: seating != null
|
|
2513
|
+
}
|
|
2514
|
+
),
|
|
2515
|
+
menu?.view === "catalog" && loading && /* @__PURE__ */ jsx(CatalogSkeleton, {}),
|
|
2516
|
+
menu?.view === "catalog" && !loading && /* @__PURE__ */ jsx(
|
|
2517
|
+
CatalogView,
|
|
2518
|
+
{
|
|
2519
|
+
categories,
|
|
2520
|
+
items,
|
|
2521
|
+
activeCategoryId,
|
|
2522
|
+
onCategoryChange: (id) => {
|
|
2523
|
+
setActiveCategoryId(id);
|
|
2524
|
+
setQuery("");
|
|
2525
|
+
},
|
|
2526
|
+
quantities,
|
|
2527
|
+
onAdd: addItem,
|
|
2528
|
+
onRemove: removeItem,
|
|
2529
|
+
query
|
|
2530
|
+
}
|
|
2531
|
+
),
|
|
2532
|
+
menu?.view === "list" && /* @__PURE__ */ jsx(
|
|
2533
|
+
DeliveryBoard,
|
|
2534
|
+
{
|
|
2535
|
+
orders: livePositions.filter((p) => p.kind === "delivery"),
|
|
2536
|
+
activeId: activePositionId,
|
|
2537
|
+
onSelect: selectPosition,
|
|
2538
|
+
now
|
|
2539
|
+
}
|
|
2540
|
+
),
|
|
2541
|
+
menu?.view === "reservations" && /* @__PURE__ */ jsx(
|
|
2542
|
+
ReservationsView,
|
|
2543
|
+
{
|
|
2544
|
+
reservations: reservations.map((r) => ({
|
|
2545
|
+
...r,
|
|
2546
|
+
...bookings[r.id] ? { status: bookings[r.id] } : {},
|
|
2547
|
+
...seatedAt[r.id] ? { positionId: seatedAt[r.id] } : {}
|
|
2548
|
+
})),
|
|
2549
|
+
positions: livePositions,
|
|
2550
|
+
now,
|
|
2551
|
+
onOpenPosition: (id) => {
|
|
2552
|
+
const p = livePositions.find((x) => x.id === id);
|
|
2553
|
+
if (p) selectPosition(p);
|
|
2554
|
+
},
|
|
2555
|
+
onMarkArrived: (id) => setBookings((prev) => ({ ...prev, [id]: "arrived" })),
|
|
2556
|
+
onSeat: (reservation) => {
|
|
2557
|
+
setSeating(reservation);
|
|
2558
|
+
const floor = config.menus.find((m) => m.view === "floor");
|
|
2559
|
+
if (floor) setMenuId(floor.id);
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
),
|
|
2563
|
+
menu?.view === "shift" && /* @__PURE__ */ jsx(ShiftView, { positions: livePositions, staff }),
|
|
2564
|
+
/* @__PURE__ */ jsx(
|
|
2565
|
+
Dock,
|
|
2566
|
+
{
|
|
2567
|
+
positions: livePositions.filter((p) => p.status !== "free" && p.kind !== "delivery"),
|
|
2568
|
+
activeId: activePositionId,
|
|
2569
|
+
onSelect: selectPosition,
|
|
2570
|
+
now,
|
|
2571
|
+
openCount,
|
|
2572
|
+
seating,
|
|
2573
|
+
onCancelSeating: () => setSeating(void 0)
|
|
2574
|
+
}
|
|
2575
|
+
),
|
|
2576
|
+
/* @__PURE__ */ jsx(Notice, { notice, onDone: () => setNotice(void 0) })
|
|
2577
|
+
] }),
|
|
2578
|
+
ticket.lines.length > 0 && !railOpen && /* @__PURE__ */ jsxs(
|
|
2272
2579
|
"button",
|
|
2273
2580
|
{
|
|
2274
2581
|
type: "button",
|
|
2275
|
-
className: "pos-
|
|
2582
|
+
className: "pos-cartbar",
|
|
2276
2583
|
onClick: () => {
|
|
2277
|
-
|
|
2278
|
-
|
|
2584
|
+
haptic("tap");
|
|
2585
|
+
setRailOpen(true);
|
|
2279
2586
|
},
|
|
2280
|
-
"aria-
|
|
2281
|
-
children: /* @__PURE__ */ jsx(X, { size: 14, strokeWidth: 2.6 })
|
|
2282
|
-
}
|
|
2283
|
-
) : (
|
|
2284
|
-
// Esc is the way back to this field from anywhere; saying so
|
|
2285
|
-
// costs one chip and saves the operator from hunting for it.
|
|
2286
|
-
/* @__PURE__ */ jsx("kbd", { className: "pos-field__hint", "aria-hidden": true, children: "Esc" })
|
|
2287
|
-
)
|
|
2288
|
-
] }),
|
|
2289
|
-
railTop && /* @__PURE__ */ jsx("div", { className: "pos-rail__top", children: railTop }),
|
|
2290
|
-
/* @__PURE__ */ jsx("div", { className: "pos-rail__label pos-t-xs", children: "Opera\xE7\xE3o" }),
|
|
2291
|
-
/* @__PURE__ */ jsx("div", { className: "pos-nav", children: config.menus.map((m) => {
|
|
2292
|
-
const Icon = MENU_ICON[m.view] ?? ClipboardList;
|
|
2293
|
-
return /* @__PURE__ */ jsxs(
|
|
2294
|
-
"button",
|
|
2295
|
-
{
|
|
2296
|
-
className: "pos-nav__item",
|
|
2297
|
-
"aria-current": m.id === menu?.id ? "page" : void 0,
|
|
2298
|
-
onClick: () => setMenuId(m.id),
|
|
2299
|
-
title: m.label,
|
|
2587
|
+
"aria-expanded": false,
|
|
2300
2588
|
children: [
|
|
2301
|
-
/* @__PURE__ */
|
|
2302
|
-
|
|
2303
|
-
|
|
2589
|
+
/* @__PURE__ */ jsxs("span", { className: "pos-cartbar__id", children: [
|
|
2590
|
+
/* @__PURE__ */ jsx("span", { className: "pos-cartbar__where", children: activePosition?.label ?? config.vocabulary.ticket }),
|
|
2591
|
+
/* @__PURE__ */ jsxs("span", { className: "pos-cartbar__meta", children: [
|
|
2592
|
+
ticket.lines.length,
|
|
2593
|
+
" ",
|
|
2594
|
+
ticket.lines.length === 1 ? "item" : "itens",
|
|
2595
|
+
pendingCount > 0 && ` \xB7 ${pendingCount} a enviar`
|
|
2596
|
+
] })
|
|
2597
|
+
] }),
|
|
2598
|
+
/* @__PURE__ */ jsx("span", { className: "pos-cartbar__total pos-num", children: formatCents(totals.totalCents) }),
|
|
2599
|
+
/* @__PURE__ */ jsx(ChevronUp, { size: 18, strokeWidth: 2.4, "aria-hidden": true })
|
|
2304
2600
|
]
|
|
2305
|
-
}
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2601
|
+
}
|
|
2602
|
+
),
|
|
2603
|
+
/* @__PURE__ */ jsxs("nav", { className: "pos-navbar", "aria-label": "Vis\xF5es do PDV", children: [
|
|
2604
|
+
phoneTabs.map((m) => {
|
|
2605
|
+
const Icon = MENU_ICON[m.view] ?? ClipboardList;
|
|
2606
|
+
return /* @__PURE__ */ jsxs(
|
|
2607
|
+
"button",
|
|
2608
|
+
{
|
|
2609
|
+
type: "button",
|
|
2610
|
+
className: "pos-navbar__item",
|
|
2611
|
+
"aria-current": m.id === menu?.id ? "page" : void 0,
|
|
2612
|
+
onClick: () => {
|
|
2613
|
+
haptic("tap");
|
|
2614
|
+
setMenuId(m.id);
|
|
2615
|
+
},
|
|
2616
|
+
children: [
|
|
2617
|
+
/* @__PURE__ */ jsxs("span", { className: "pos-navbar__icon", children: [
|
|
2618
|
+
/* @__PURE__ */ jsx(Icon, { size: 20, strokeWidth: 2.1, "aria-hidden": true }),
|
|
2619
|
+
m.badge != null && m.badge > 0 && /* @__PURE__ */ jsx("span", { className: "pos-navbar__count pos-num", children: m.badge })
|
|
2620
|
+
] }),
|
|
2621
|
+
/* @__PURE__ */ jsx("span", { className: "pos-navbar__text", children: m.label })
|
|
2622
|
+
]
|
|
2623
|
+
},
|
|
2624
|
+
m.id
|
|
2625
|
+
);
|
|
2626
|
+
}),
|
|
2627
|
+
/* @__PURE__ */ jsxs(
|
|
2628
|
+
"button",
|
|
2629
|
+
{
|
|
2630
|
+
type: "button",
|
|
2631
|
+
className: "pos-navbar__item",
|
|
2632
|
+
"aria-expanded": moreOpen,
|
|
2633
|
+
onClick: () => {
|
|
2634
|
+
haptic("tap");
|
|
2635
|
+
setMoreOpen(true);
|
|
2636
|
+
},
|
|
2637
|
+
children: [
|
|
2638
|
+
/* @__PURE__ */ jsx("span", { className: "pos-navbar__icon", children: /* @__PURE__ */ jsx(MoreHorizontal, { size: 20, strokeWidth: 2.1, "aria-hidden": true }) }),
|
|
2639
|
+
/* @__PURE__ */ jsx("span", { className: "pos-navbar__text", children: "Mais" })
|
|
2640
|
+
]
|
|
2641
|
+
}
|
|
2642
|
+
)
|
|
2643
|
+
] }),
|
|
2644
|
+
moreOpen && /* @__PURE__ */ jsxs("div", { className: "pos-more", role: "dialog", "aria-label": "Mais op\xE7\xF5es", children: [
|
|
2645
|
+
/* @__PURE__ */ jsx("button", { className: "pos-more__scrim", "aria-label": "Fechar menu", onClick: () => setMoreOpen(false) }),
|
|
2646
|
+
/* @__PURE__ */ jsxs("div", { className: "pos-more__panel", children: [
|
|
2647
|
+
/* @__PURE__ */ jsxs("div", { className: "pos-more__head", children: [
|
|
2648
|
+
/* @__PURE__ */ jsx("span", { className: "pos-brand__mark", children: brandMark ?? config.name.slice(0, 1) }),
|
|
2649
|
+
/* @__PURE__ */ jsx("span", { className: "pos-brand__name", children: brandName ?? config.name }),
|
|
2650
|
+
/* @__PURE__ */ jsx(
|
|
2651
|
+
"button",
|
|
2652
|
+
{
|
|
2653
|
+
type: "button",
|
|
2654
|
+
className: "pos-more__close",
|
|
2655
|
+
"aria-label": "Fechar menu",
|
|
2656
|
+
onClick: () => setMoreOpen(false),
|
|
2657
|
+
children: /* @__PURE__ */ jsx(X, { size: 18, strokeWidth: 2.4 })
|
|
2658
|
+
}
|
|
2659
|
+
)
|
|
2660
|
+
] }),
|
|
2661
|
+
railTop && /* @__PURE__ */ jsx("div", { className: "pos-more__top", children: railTop }),
|
|
2662
|
+
overflowTabs.length > 0 && /* @__PURE__ */ jsx("div", { className: "pos-more__nav", children: overflowTabs.map((m) => {
|
|
2663
|
+
const Icon = MENU_ICON[m.view] ?? ClipboardList;
|
|
2664
|
+
return /* @__PURE__ */ jsxs(
|
|
2665
|
+
"button",
|
|
2666
|
+
{
|
|
2667
|
+
type: "button",
|
|
2668
|
+
className: "pos-nav__item",
|
|
2669
|
+
"aria-current": m.id === menu?.id ? "page" : void 0,
|
|
2670
|
+
onClick: () => {
|
|
2671
|
+
haptic("tap");
|
|
2672
|
+
setMenuId(m.id);
|
|
2673
|
+
setMoreOpen(false);
|
|
2674
|
+
},
|
|
2675
|
+
children: [
|
|
2676
|
+
/* @__PURE__ */ jsx("span", { className: "pos-nav__icon", children: /* @__PURE__ */ jsx(Icon, { size: 19, strokeWidth: 2.1, "aria-hidden": true }) }),
|
|
2677
|
+
/* @__PURE__ */ jsx("span", { className: "pos-nav__text", children: m.label }),
|
|
2678
|
+
m.badge != null && m.badge > 0 && /* @__PURE__ */ jsx("span", { className: "pos-nav__count pos-num", children: m.badge })
|
|
2679
|
+
]
|
|
2680
|
+
},
|
|
2681
|
+
m.id
|
|
2682
|
+
);
|
|
2683
|
+
}) }),
|
|
2684
|
+
unitSwitcher && /* @__PURE__ */ jsx("div", { className: "pos-more__unit", children: unitSwitcher }),
|
|
2685
|
+
/* @__PURE__ */ jsxs("div", { className: "pos-more__foot", children: [
|
|
2686
|
+
/* @__PURE__ */ jsx("span", { className: "pos-user__av", children: (operatorName ?? config.name).slice(0, 1) }),
|
|
2687
|
+
/* @__PURE__ */ jsx("span", { className: "pos-user__txt", children: operatorName ?? config.name })
|
|
2688
|
+
] })
|
|
2319
2689
|
] })
|
|
2320
2690
|
] }),
|
|
2321
|
-
/* @__PURE__ */ jsx(
|
|
2322
|
-
|
|
2691
|
+
activePosition?.kind === "delivery" ? /* @__PURE__ */ jsx(
|
|
2692
|
+
DispatchRail,
|
|
2323
2693
|
{
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2694
|
+
containerRef: asideRef,
|
|
2695
|
+
order: activePosition,
|
|
2696
|
+
ticket,
|
|
2697
|
+
totals,
|
|
2698
|
+
now,
|
|
2699
|
+
open: railOpen,
|
|
2700
|
+
onAdvance: (to) => {
|
|
2701
|
+
setDispatched((prev) => ({ ...prev, [activePosition.id]: to }));
|
|
2702
|
+
void onDispatch?.(activePosition.id, to);
|
|
2703
|
+
},
|
|
2704
|
+
onCancel: () => handleAction("cancel_order")
|
|
2329
2705
|
}
|
|
2330
|
-
)
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2706
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2707
|
+
railOpen && /* @__PURE__ */ jsx(
|
|
2708
|
+
"button",
|
|
2709
|
+
{
|
|
2710
|
+
className: "pos-sheet-scrim",
|
|
2711
|
+
"aria-label": "Minimizar a comanda",
|
|
2712
|
+
onClick: () => setRailOpen(false)
|
|
2713
|
+
}
|
|
2714
|
+
),
|
|
2715
|
+
/* @__PURE__ */ jsx(
|
|
2716
|
+
TicketRail,
|
|
2717
|
+
{
|
|
2718
|
+
containerRef: asideRef,
|
|
2719
|
+
onCollapse: () => setRailOpen(false),
|
|
2720
|
+
ticket: {
|
|
2721
|
+
...ticket,
|
|
2722
|
+
positionLabel: activePosition?.label,
|
|
2723
|
+
attendantName: activePosition?.attendantName,
|
|
2724
|
+
seatedAt: ticket.seatedAt ?? activePosition?.openedAt
|
|
2725
|
+
},
|
|
2726
|
+
totals,
|
|
2727
|
+
vocabulary: config.vocabulary,
|
|
2728
|
+
paymentMethods: config.paymentMethods,
|
|
2729
|
+
selectedPaymentId: paymentId,
|
|
2730
|
+
onSelectPayment: setPaymentId,
|
|
2731
|
+
onChangeQuantity: (lineId, delta) => dispatch({ type: "change_quantity", lineId, delta }),
|
|
2732
|
+
selectedLineId,
|
|
2733
|
+
onSelectLine: setSelectedLineId,
|
|
2734
|
+
onClose: () => handleAction("close_bill"),
|
|
2735
|
+
onFire: () => handleAction("fire"),
|
|
2736
|
+
fireShortcut: config.actions.find((a) => a.id === "fire")?.shortcut,
|
|
2737
|
+
closeShortcut: config.actions.find((a) => a.id === "close_bill")?.shortcut,
|
|
2738
|
+
onBrowseCatalog: () => {
|
|
2739
|
+
const cat = config.menus.find((m) => m.view === "catalog");
|
|
2740
|
+
if (cat) setMenuId(cat.id);
|
|
2741
|
+
setRailOpen(false);
|
|
2742
|
+
commandRef.current?.focus();
|
|
2743
|
+
},
|
|
2744
|
+
alias: activePositionId ? named[activePositionId]?.alias : void 0,
|
|
2745
|
+
customerPhone: activePositionId ? named[activePositionId]?.phone : void 0,
|
|
2746
|
+
onEditIdentity: activePosition ? () => setNaming(activePosition) : void 0,
|
|
2747
|
+
onEditLine: (lineId) => {
|
|
2748
|
+
const line = ticket.lines.find((l) => l.id === lineId);
|
|
2749
|
+
const item = line && items.find((i) => i.id === line.itemId);
|
|
2750
|
+
if (line && item) setEditing({ item, line });
|
|
2751
|
+
},
|
|
2752
|
+
guests: activePosition?.seats,
|
|
2753
|
+
status: activePosition?.status,
|
|
2754
|
+
zoneLabel: config.positions.zones?.find((z) => z.id === activePosition?.zoneId)?.label,
|
|
2755
|
+
request: activePosition?.request,
|
|
2756
|
+
now,
|
|
2757
|
+
open: railOpen
|
|
2758
|
+
}
|
|
2759
|
+
)
|
|
2760
|
+
] })
|
|
2346
2761
|
] }),
|
|
2347
|
-
|
|
2348
|
-
|
|
2762
|
+
showKeys && /* @__PURE__ */ jsx(ShortcutsOverlay, { actions: config.actions, onClose: () => setShowKeys(false) }),
|
|
2763
|
+
pinFor && /* @__PURE__ */ jsx(
|
|
2764
|
+
PinSheet,
|
|
2349
2765
|
{
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2766
|
+
actionLabel: pinFor.label,
|
|
2767
|
+
onCancel: () => setPinFor(void 0),
|
|
2768
|
+
onVerify: (pin) => verifyPin(pin, pinFor.id),
|
|
2769
|
+
onGranted: (by) => {
|
|
2770
|
+
const id = pinFor.id;
|
|
2771
|
+
setPinFor(void 0);
|
|
2772
|
+
onAuthorised?.(id, by);
|
|
2773
|
+
runAction(id);
|
|
2774
|
+
}
|
|
2356
2775
|
}
|
|
2357
2776
|
),
|
|
2358
|
-
|
|
2359
|
-
|
|
2777
|
+
splitting && /* @__PURE__ */ jsx(
|
|
2778
|
+
SplitSheet,
|
|
2360
2779
|
{
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
setQuery("");
|
|
2367
|
-
},
|
|
2368
|
-
quantities,
|
|
2369
|
-
onAdd: addItem,
|
|
2370
|
-
onRemove: removeItem,
|
|
2371
|
-
query
|
|
2780
|
+
ticket,
|
|
2781
|
+
totals,
|
|
2782
|
+
guests: activePosition?.seats,
|
|
2783
|
+
onCancel: () => setSplitting(false),
|
|
2784
|
+
onConfirm: () => setSplitting(false)
|
|
2372
2785
|
}
|
|
2373
2786
|
),
|
|
2374
|
-
|
|
2375
|
-
|
|
2787
|
+
openingPosition && /* @__PURE__ */ jsx(
|
|
2788
|
+
OpenTableSheet,
|
|
2376
2789
|
{
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2790
|
+
position: openingPosition,
|
|
2791
|
+
vocabulary: config.vocabulary,
|
|
2792
|
+
staff,
|
|
2793
|
+
operator: operatorId ? { id: operatorId, name: operatorName ?? operatorId } : void 0,
|
|
2794
|
+
defaultSeats: seating?.party,
|
|
2795
|
+
seatingName: seating?.name,
|
|
2796
|
+
onCancel: () => {
|
|
2797
|
+
setOpeningPosition(void 0);
|
|
2798
|
+
setSeating(void 0);
|
|
2799
|
+
},
|
|
2800
|
+
onConfirm: confirmOpen
|
|
2381
2801
|
}
|
|
2382
2802
|
),
|
|
2383
|
-
|
|
2384
|
-
|
|
2803
|
+
naming && /* @__PURE__ */ jsx(
|
|
2804
|
+
IdentitySheet,
|
|
2385
2805
|
{
|
|
2386
|
-
|
|
2387
|
-
...
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
})),
|
|
2391
|
-
positions: livePositions,
|
|
2392
|
-
now,
|
|
2393
|
-
onOpenPosition: (id) => {
|
|
2394
|
-
const p = livePositions.find((x) => x.id === id);
|
|
2395
|
-
if (p) selectPosition(p);
|
|
2806
|
+
position: {
|
|
2807
|
+
...naming,
|
|
2808
|
+
alias: named[naming.id]?.alias ?? naming.alias,
|
|
2809
|
+
customerPhone: named[naming.id]?.phone ?? naming.customerPhone
|
|
2396
2810
|
},
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
if (floor) setMenuId(floor.id);
|
|
2811
|
+
onCancel: () => setNaming(void 0),
|
|
2812
|
+
onSave: (alias, phone) => {
|
|
2813
|
+
setNamed((prev) => ({ ...prev, [naming.id]: { alias, phone } }));
|
|
2814
|
+
setNaming(void 0);
|
|
2402
2815
|
}
|
|
2403
2816
|
}
|
|
2404
2817
|
),
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
Dock,
|
|
2818
|
+
editing && /* @__PURE__ */ jsx(
|
|
2819
|
+
ModifierSheet,
|
|
2408
2820
|
{
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2821
|
+
item: editing.item,
|
|
2822
|
+
mode: "edit",
|
|
2823
|
+
initial: { modifiers: editing.line.modifiers, note: editing.line.note },
|
|
2824
|
+
onCancel: () => setEditing(void 0),
|
|
2825
|
+
onConfirm: (modifiers, note) => {
|
|
2826
|
+
dispatch({
|
|
2827
|
+
type: "edit_line",
|
|
2828
|
+
lineId: editing.line.id,
|
|
2829
|
+
modifiers,
|
|
2830
|
+
note,
|
|
2831
|
+
basePriceCents: editing.line.basePriceCents ?? editing.item.priceCents
|
|
2832
|
+
});
|
|
2833
|
+
setEditing(void 0);
|
|
2834
|
+
}
|
|
2416
2835
|
}
|
|
2417
2836
|
),
|
|
2418
|
-
/* @__PURE__ */ jsx(
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
},
|
|
2433
|
-
onCancel: () => handleAction("cancel_order")
|
|
2434
|
-
}
|
|
2435
|
-
) : /* @__PURE__ */ jsx(
|
|
2436
|
-
TicketRail,
|
|
2437
|
-
{
|
|
2438
|
-
containerRef: asideRef,
|
|
2439
|
-
ticket: {
|
|
2440
|
-
...ticket,
|
|
2441
|
-
positionLabel: activePosition?.label,
|
|
2442
|
-
attendantName: activePosition?.attendantName,
|
|
2443
|
-
seatedAt: ticket.seatedAt ?? activePosition?.openedAt
|
|
2444
|
-
},
|
|
2445
|
-
totals,
|
|
2446
|
-
vocabulary: config.vocabulary,
|
|
2447
|
-
paymentMethods: config.paymentMethods,
|
|
2448
|
-
selectedPaymentId: paymentId,
|
|
2449
|
-
onSelectPayment: setPaymentId,
|
|
2450
|
-
onChangeQuantity: (lineId, delta) => dispatch({ type: "change_quantity", lineId, delta }),
|
|
2451
|
-
selectedLineId,
|
|
2452
|
-
onSelectLine: setSelectedLineId,
|
|
2453
|
-
onClose: () => handleAction("close_bill"),
|
|
2454
|
-
onFire: () => handleAction("fire"),
|
|
2455
|
-
fireShortcut: config.actions.find((a) => a.id === "fire")?.shortcut,
|
|
2456
|
-
closeShortcut: config.actions.find((a) => a.id === "close_bill")?.shortcut,
|
|
2457
|
-
onBrowseCatalog: () => {
|
|
2458
|
-
const cat = config.menus.find((m) => m.view === "catalog");
|
|
2459
|
-
if (cat) setMenuId(cat.id);
|
|
2460
|
-
commandRef.current?.focus();
|
|
2461
|
-
},
|
|
2462
|
-
alias: activePositionId ? named[activePositionId]?.alias : void 0,
|
|
2463
|
-
customerPhone: activePositionId ? named[activePositionId]?.phone : void 0,
|
|
2464
|
-
onEditIdentity: activePosition ? () => setNaming(activePosition) : void 0,
|
|
2465
|
-
onEditLine: (lineId) => {
|
|
2466
|
-
const line = ticket.lines.find((l) => l.id === lineId);
|
|
2467
|
-
const item = line && items.find((i) => i.id === line.itemId);
|
|
2468
|
-
if (line && item) setEditing({ item, line });
|
|
2469
|
-
},
|
|
2470
|
-
guests: activePosition?.seats,
|
|
2471
|
-
status: activePosition?.status,
|
|
2472
|
-
zoneLabel: config.positions.zones?.find((z) => z.id === activePosition?.zoneId)?.label,
|
|
2473
|
-
request: activePosition?.request,
|
|
2474
|
-
now,
|
|
2475
|
-
open: railOpen
|
|
2476
|
-
}
|
|
2477
|
-
)
|
|
2478
|
-
] }),
|
|
2479
|
-
showKeys && /* @__PURE__ */ jsx(ShortcutsOverlay, { actions: config.actions, onClose: () => setShowKeys(false) }),
|
|
2480
|
-
pinFor && /* @__PURE__ */ jsx(
|
|
2481
|
-
PinSheet,
|
|
2482
|
-
{
|
|
2483
|
-
actionLabel: pinFor.label,
|
|
2484
|
-
onCancel: () => setPinFor(void 0),
|
|
2485
|
-
onVerify: (pin) => verifyPin(pin, pinFor.id),
|
|
2486
|
-
onGranted: (by) => {
|
|
2487
|
-
const id = pinFor.id;
|
|
2488
|
-
setPinFor(void 0);
|
|
2489
|
-
onAuthorised?.(id, by);
|
|
2490
|
-
runAction(id);
|
|
2491
|
-
}
|
|
2492
|
-
}
|
|
2493
|
-
),
|
|
2494
|
-
splitting && /* @__PURE__ */ jsx(
|
|
2495
|
-
SplitSheet,
|
|
2496
|
-
{
|
|
2497
|
-
ticket,
|
|
2498
|
-
totals,
|
|
2499
|
-
guests: activePosition?.seats,
|
|
2500
|
-
onCancel: () => setSplitting(false),
|
|
2501
|
-
onConfirm: () => setSplitting(false)
|
|
2502
|
-
}
|
|
2503
|
-
),
|
|
2504
|
-
openingPosition && /* @__PURE__ */ jsx(
|
|
2505
|
-
OpenTableSheet,
|
|
2506
|
-
{
|
|
2507
|
-
position: openingPosition,
|
|
2508
|
-
vocabulary: config.vocabulary,
|
|
2509
|
-
staff,
|
|
2510
|
-
defaultSeats: seating?.party,
|
|
2511
|
-
seatingName: seating?.name,
|
|
2512
|
-
onCancel: () => {
|
|
2513
|
-
setOpeningPosition(void 0);
|
|
2514
|
-
setSeating(void 0);
|
|
2515
|
-
},
|
|
2516
|
-
onConfirm: confirmOpen
|
|
2517
|
-
}
|
|
2518
|
-
),
|
|
2519
|
-
naming && /* @__PURE__ */ jsx(
|
|
2520
|
-
IdentitySheet,
|
|
2521
|
-
{
|
|
2522
|
-
position: {
|
|
2523
|
-
...naming,
|
|
2524
|
-
alias: named[naming.id]?.alias ?? naming.alias,
|
|
2525
|
-
customerPhone: named[naming.id]?.phone ?? naming.customerPhone
|
|
2526
|
-
},
|
|
2527
|
-
onCancel: () => setNaming(void 0),
|
|
2528
|
-
onSave: (alias, phone) => {
|
|
2529
|
-
setNamed((prev) => ({ ...prev, [naming.id]: { alias, phone } }));
|
|
2530
|
-
setNaming(void 0);
|
|
2531
|
-
}
|
|
2532
|
-
}
|
|
2533
|
-
),
|
|
2534
|
-
editing && /* @__PURE__ */ jsx(
|
|
2535
|
-
ModifierSheet,
|
|
2536
|
-
{
|
|
2537
|
-
item: editing.item,
|
|
2538
|
-
mode: "edit",
|
|
2539
|
-
initial: { modifiers: editing.line.modifiers, note: editing.line.note },
|
|
2540
|
-
onCancel: () => setEditing(void 0),
|
|
2541
|
-
onConfirm: (modifiers, note) => {
|
|
2542
|
-
dispatch({
|
|
2543
|
-
type: "edit_line",
|
|
2544
|
-
lineId: editing.line.id,
|
|
2545
|
-
modifiers,
|
|
2546
|
-
note,
|
|
2547
|
-
basePriceCents: editing.line.basePriceCents ?? editing.item.priceCents
|
|
2548
|
-
});
|
|
2549
|
-
setEditing(void 0);
|
|
2550
|
-
}
|
|
2551
|
-
}
|
|
2552
|
-
),
|
|
2553
|
-
pendingItem && /* @__PURE__ */ jsx(
|
|
2554
|
-
ModifierSheet,
|
|
2555
|
-
{
|
|
2556
|
-
item: pendingItem,
|
|
2557
|
-
onCancel: () => setPendingItem(void 0),
|
|
2558
|
-
onConfirm: (modifiers, note) => {
|
|
2559
|
-
ring(pendingItem, modifiers, note || void 0);
|
|
2560
|
-
setPendingItem(void 0);
|
|
2561
|
-
}
|
|
2562
|
-
}
|
|
2563
|
-
)
|
|
2564
|
-
] });
|
|
2837
|
+
pendingItem && /* @__PURE__ */ jsx(
|
|
2838
|
+
ModifierSheet,
|
|
2839
|
+
{
|
|
2840
|
+
item: pendingItem,
|
|
2841
|
+
onCancel: () => setPendingItem(void 0),
|
|
2842
|
+
onConfirm: (modifiers, note) => {
|
|
2843
|
+
ring(pendingItem, modifiers, note || void 0);
|
|
2844
|
+
setPendingItem(void 0);
|
|
2845
|
+
}
|
|
2846
|
+
}
|
|
2847
|
+
)
|
|
2848
|
+
]
|
|
2849
|
+
}
|
|
2850
|
+
);
|
|
2565
2851
|
}
|
|
2566
2852
|
function Dock({ positions, activeId, onSelect, now, openCount, seating, onCancelSeating }) {
|
|
2567
2853
|
const activeRef = useRef(null);
|