@fayz-ai/pos 0.22.4 → 0.23.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/index.js +84 -33
- package/dist/index.js.map +1 -1
- package/dist/screen/DeliveryBoard.d.ts +5 -1
- package/dist/screen/DeliveryBoard.d.ts.map +1 -1
- package/dist/screen/DispatchRail.d.ts +3 -1
- package/dist/screen/DispatchRail.d.ts.map +1 -1
- package/dist/screen/MarketplaceCancelSheet.d.ts.map +1 -1
- package/dist/screen/PosScreen.d.ts +9 -1
- package/dist/screen/PosScreen.d.ts.map +1 -1
- package/dist/styles.css +29 -2
- package/package.json +1 -1
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 { forwardRef, memo, useState, useRef, useCallback, useEffect, useMemo, useReducer, Fragment as Fragment$1 } from 'react';
|
|
4
|
-
import { UserPlus, X, Check, Phone, User, Receipt, RotateCcw, FileCheck, FileWarning, ChevronDown, Pencil, ChevronLeft, ChevronRight, Plus, ChevronUp, ChefHat, AlertTriangle, Printer, Percent, QrCode, CreditCard, Banknote, Trash2, Clock, Minus, Bike, PackageCheck, CheckCheck, Package, MapPin, ShieldCheck, Keyboard, CalendarClock, Users, UserRound, Search, Utensils, BellRing, UserX, UserCheck, Delete, UtensilsCrossed, Info, ClipboardList, LayoutGrid, ShoppingBag, ConciergeBell, Map as Map$1, Settings2, Square, Circle, PenLine, MoreHorizontal, Store, Tag, Star, Ticket, Ban, ArrowLeftRight, Gift, UserMinus, CheckCircle2, Crosshair, Unlink, MousePointerClick, PencilRuler, MapPinOff, Eye, EyeOff, Undo2, TriangleAlert, ArrowRight, Pizza, Wheat, Sandwich, IceCreamCone, CakeSlice, Coffee, Croissant, CupSoda, Salad, Beef, Wine, GlassWater, Soup, Fish, Wrench, CalendarCheck } from 'lucide-react';
|
|
4
|
+
import { UserPlus, X, Check, Phone, User, Receipt, RotateCcw, FileCheck, FileWarning, ChevronDown, Pencil, ChevronLeft, ChevronRight, Plus, ChevronUp, ChefHat, AlertTriangle, Printer, Percent, QrCode, CreditCard, Banknote, Trash2, Clock, Minus, Bike, History, PackageCheck, CheckCheck, Package, MapPin, ShieldCheck, Keyboard, CalendarClock, Users, UserRound, Search, Utensils, BellRing, UserX, UserCheck, Delete, UtensilsCrossed, Info, ClipboardList, LayoutGrid, ShoppingBag, ConciergeBell, Map as Map$1, Settings2, Square, Circle, PenLine, MoreHorizontal, Store, Tag, Star, Ticket, Ban, ArrowLeftRight, Gift, UserMinus, CheckCircle2, Crosshair, Unlink, MousePointerClick, PencilRuler, MapPinOff, Eye, EyeOff, Undo2, TriangleAlert, ArrowRight, Pizza, Wheat, Sandwich, IceCreamCone, CakeSlice, Coffee, Croissant, CupSoda, Salad, Beef, Wine, GlassWater, Soup, Fish, Wrench, CalendarCheck } from 'lucide-react';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
import { describeError, channelOfOrder } from '@fayz-ai/core';
|
|
7
7
|
import { createPortal } from 'react-dom';
|
|
@@ -4869,7 +4869,7 @@ function lateness(p, now) {
|
|
|
4869
4869
|
return Math.floor((now - new Date(p.dueAt).getTime()) / 6e4);
|
|
4870
4870
|
}
|
|
4871
4871
|
var GHOST_MS = 300;
|
|
4872
|
-
function DeliveryBoard({ orders, activeId, onSelect, now, channelsConnected }) {
|
|
4872
|
+
function DeliveryBoard({ orders, activeId, onSelect, now, channelsConnected, historyOpen, onToggleHistory }) {
|
|
4873
4873
|
const seen = useRef({});
|
|
4874
4874
|
const [ghosts, setGhosts] = useState([]);
|
|
4875
4875
|
useEffect(() => {
|
|
@@ -4897,7 +4897,14 @@ function DeliveryBoard({ orders, activeId, onSelect, now, channelsConnected }) {
|
|
|
4897
4897
|
Icon: Bike
|
|
4898
4898
|
}
|
|
4899
4899
|
),
|
|
4900
|
-
/* @__PURE__ */
|
|
4900
|
+
/* @__PURE__ */ jsxs("div", { className: "pos-board__bar", children: [
|
|
4901
|
+
/* @__PURE__ */ jsx("p", { className: "pos-board__note", children: DELIVERED_LINGER_NOTE }),
|
|
4902
|
+
onToggleHistory && /* @__PURE__ */ jsxs(PosButton, { className: "pos-pill", "aria-pressed": !!historyOpen, onClick: onToggleHistory, children: [
|
|
4903
|
+
/* @__PURE__ */ jsx(History, { size: 14 }),
|
|
4904
|
+
" ",
|
|
4905
|
+
historyOpen ? "Ocultar hist\xF3rico" : "Hist\xF3rico do dia"
|
|
4906
|
+
] })
|
|
4907
|
+
] }),
|
|
4901
4908
|
/* @__PURE__ */ jsx("div", { className: "pos-board", children: DELIVERY_COLUMNS.map(({ name, states, tone }) => {
|
|
4902
4909
|
const Icon = ICONE[name] ?? Clock;
|
|
4903
4910
|
const column = orders.filter((o) => stillOnBoard(o, now)).filter((o) => states.includes(deliveryStatus(o.dispatch)));
|
|
@@ -4997,6 +5004,7 @@ function DispatchRail({
|
|
|
4997
5004
|
totals,
|
|
4998
5005
|
onAdvance,
|
|
4999
5006
|
onCancel,
|
|
5007
|
+
onCloseDetails,
|
|
5000
5008
|
now,
|
|
5001
5009
|
open,
|
|
5002
5010
|
containerRef,
|
|
@@ -5016,7 +5024,18 @@ function DispatchRail({
|
|
|
5016
5024
|
/* @__PURE__ */ jsxs("header", { className: "pos-tkt", children: [
|
|
5017
5025
|
/* @__PURE__ */ jsxs("div", { className: "pos-tkt__row", children: [
|
|
5018
5026
|
/* @__PURE__ */ jsx("span", { className: "pos-t-xl", children: order.label }),
|
|
5019
|
-
/* @__PURE__ */ jsx("span", { className: "pos-badge", "data-status": status === "out" || status === "dispatched" ? "bill_requested" : "occupied", children: DISPATCH_LABEL[status] })
|
|
5027
|
+
/* @__PURE__ */ jsx("span", { className: "pos-badge", "data-status": status === "out" || status === "dispatched" ? "bill_requested" : "occupied", children: DISPATCH_LABEL[status] }),
|
|
5028
|
+
onCloseDetails && /* @__PURE__ */ jsx(
|
|
5029
|
+
PosButton,
|
|
5030
|
+
{
|
|
5031
|
+
className: "pos-icon-btn",
|
|
5032
|
+
style: { marginLeft: "auto" },
|
|
5033
|
+
onClick: onCloseDetails,
|
|
5034
|
+
"aria-label": "Fechar detalhes",
|
|
5035
|
+
title: "Fechar detalhes \xB7 Esc",
|
|
5036
|
+
children: /* @__PURE__ */ jsx(X, { size: 18 })
|
|
5037
|
+
}
|
|
5038
|
+
)
|
|
5020
5039
|
] }),
|
|
5021
5040
|
/* @__PURE__ */ jsx("div", { className: "pos-tkt__sub", children: [order.channel, order.customerName].filter(Boolean).join(" \xB7 ") })
|
|
5022
5041
|
] }),
|
|
@@ -7490,6 +7509,8 @@ function PosScreen({
|
|
|
7490
7509
|
onWaitlistLookupPhone,
|
|
7491
7510
|
onReservationArrived,
|
|
7492
7511
|
connection = "online",
|
|
7512
|
+
initialMenuId,
|
|
7513
|
+
onMenuChange,
|
|
7493
7514
|
operatorId,
|
|
7494
7515
|
onAction,
|
|
7495
7516
|
onOpenPosition,
|
|
@@ -7565,7 +7586,12 @@ function PosScreen({
|
|
|
7565
7586
|
}
|
|
7566
7587
|
return seeded;
|
|
7567
7588
|
});
|
|
7568
|
-
const [menuId, setMenuId] = useState(config.menus[0]?.id);
|
|
7589
|
+
const [menuId, setMenuId] = useState(() => config.menus.some((m) => m.id === initialMenuId && !m.hidden) ? initialMenuId : config.menus[0]?.id);
|
|
7590
|
+
const onMenuChangeRef = useRef(onMenuChange);
|
|
7591
|
+
onMenuChangeRef.current = onMenuChange;
|
|
7592
|
+
useEffect(() => {
|
|
7593
|
+
if (menuId) onMenuChangeRef.current?.(menuId);
|
|
7594
|
+
}, [menuId]);
|
|
7569
7595
|
useEffect(() => {
|
|
7570
7596
|
if (!initialTickets) return;
|
|
7571
7597
|
dispatchBook({ type: "hydrate", tickets: initialTickets, at: new Date(now).toISOString() });
|
|
@@ -7723,6 +7749,10 @@ function PosScreen({
|
|
|
7723
7749
|
return;
|
|
7724
7750
|
}
|
|
7725
7751
|
if (event.key === "Escape") {
|
|
7752
|
+
if (activeKindRef.current === "delivery") {
|
|
7753
|
+
closeDetailsRef.current();
|
|
7754
|
+
return;
|
|
7755
|
+
}
|
|
7726
7756
|
commandRef.current?.focus();
|
|
7727
7757
|
return;
|
|
7728
7758
|
}
|
|
@@ -7775,6 +7805,10 @@ function PosScreen({
|
|
|
7775
7805
|
return { ...p, itemCount: counts[p.id] ?? p.itemCount, totalCents: totalCents || p.totalCents };
|
|
7776
7806
|
}), [positions, opened, dispatched, settled, book, counts, config.serviceChargePercent, minhas]);
|
|
7777
7807
|
const activePosition = livePositions.find((p) => p.id === activePositionId);
|
|
7808
|
+
const activeIdRef = useRef(activePositionId);
|
|
7809
|
+
activeIdRef.current = activePositionId;
|
|
7810
|
+
const activeKindRef = useRef(activePosition?.kind);
|
|
7811
|
+
activeKindRef.current = activePosition?.kind;
|
|
7778
7812
|
const trocarCanal = useCallback((id) => {
|
|
7779
7813
|
if (channelSwitchDropsPosition(
|
|
7780
7814
|
{ menuId, activeKind: activePosition?.kind },
|
|
@@ -7798,8 +7832,20 @@ function PosScreen({
|
|
|
7798
7832
|
),
|
|
7799
7833
|
[closedTickets, canalMarcado, menu?.view]
|
|
7800
7834
|
);
|
|
7835
|
+
const [deliveryHistory, setDeliveryHistory] = useState(false);
|
|
7836
|
+
const closeDetailsRef = useRef(() => {
|
|
7837
|
+
});
|
|
7838
|
+
closeDetailsRef.current = () => {
|
|
7839
|
+
setActivePositionId(void 0);
|
|
7840
|
+
setSelectedLineId(void 0);
|
|
7841
|
+
setRailOpen(false);
|
|
7842
|
+
};
|
|
7801
7843
|
const escapeRef = useRef(() => false);
|
|
7802
7844
|
escapeRef.current = () => {
|
|
7845
|
+
if (activePosition?.kind === "delivery") {
|
|
7846
|
+
closeDetailsRef.current();
|
|
7847
|
+
return true;
|
|
7848
|
+
}
|
|
7803
7849
|
if (railOpen) {
|
|
7804
7850
|
setRailOpen(false);
|
|
7805
7851
|
return true;
|
|
@@ -7898,6 +7944,10 @@ function PosScreen({
|
|
|
7898
7944
|
return;
|
|
7899
7945
|
}
|
|
7900
7946
|
if (seatingRef.current) return;
|
|
7947
|
+
if (p.kind === "delivery" && p.id === activeIdRef.current) {
|
|
7948
|
+
closeDetailsRef.current();
|
|
7949
|
+
return;
|
|
7950
|
+
}
|
|
7901
7951
|
setActivePositionId(p.id);
|
|
7902
7952
|
onActivatePosition?.(p.id);
|
|
7903
7953
|
setRailOpen(true);
|
|
@@ -8334,7 +8384,7 @@ function PosScreen({
|
|
|
8334
8384
|
style,
|
|
8335
8385
|
"data-cart-open": railOpen || void 0,
|
|
8336
8386
|
children: [
|
|
8337
|
-
/* @__PURE__ */ jsxs("div", { className: "pos-body", children: [
|
|
8387
|
+
/* @__PURE__ */ jsxs("div", { className: "pos-body", "data-details": menu?.view === "list" && !activePosition && !deliveryHistory ? "closed" : void 0, children: [
|
|
8338
8388
|
/* @__PURE__ */ jsxs("nav", { className: "pos-rail", "aria-label": "Navega\xE7\xE3o principal", children: [
|
|
8339
8389
|
(brandMark || brandName || !railTop) && /* @__PURE__ */ jsxs("div", { className: "pos-brand", children: [
|
|
8340
8390
|
/* @__PURE__ */ jsx("span", { className: "pos-brand__mark", children: brandMark ?? config.name.slice(0, 1) }),
|
|
@@ -8642,7 +8692,9 @@ function PosScreen({
|
|
|
8642
8692
|
orders: livePositions.filter((p) => p.kind === "delivery"),
|
|
8643
8693
|
activeId: activePositionId,
|
|
8644
8694
|
onSelect: selectPosition,
|
|
8645
|
-
now
|
|
8695
|
+
now,
|
|
8696
|
+
historyOpen: deliveryHistory && !activePosition,
|
|
8697
|
+
onToggleHistory: activePosition ? void 0 : () => setDeliveryHistory((v) => !v)
|
|
8646
8698
|
}
|
|
8647
8699
|
),
|
|
8648
8700
|
menu?.view === "reservations" && /* @__PURE__ */ jsx(
|
|
@@ -8968,6 +9020,7 @@ function PosScreen({
|
|
|
8968
9020
|
void onDispatch?.(activePosition.id, to);
|
|
8969
9021
|
},
|
|
8970
9022
|
onCancel: () => handleAction("cancel_order"),
|
|
9023
|
+
onCloseDetails: () => closeDetailsRef.current(),
|
|
8971
9024
|
extra: renderDispatchExtra?.(activePosition, ticket)
|
|
8972
9025
|
}
|
|
8973
9026
|
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -10204,8 +10257,11 @@ function MarketplaceCancelSheet({ provider, orderLabel, loadReasons, onConfirm,
|
|
|
10204
10257
|
const [failed, setFailed] = useState(false);
|
|
10205
10258
|
const [chosen, setChosen] = useState(null);
|
|
10206
10259
|
const [sending, setSending] = useState(false);
|
|
10260
|
+
const [attempt, setAttempt] = useState(0);
|
|
10207
10261
|
useEffect(() => {
|
|
10208
10262
|
let alive = true;
|
|
10263
|
+
setFailed(false);
|
|
10264
|
+
setReasons(null);
|
|
10209
10265
|
loadReasons().then((r) => {
|
|
10210
10266
|
if (alive) setReasons(r);
|
|
10211
10267
|
}).catch(() => {
|
|
@@ -10214,7 +10270,7 @@ function MarketplaceCancelSheet({ provider, orderLabel, loadReasons, onConfirm,
|
|
|
10214
10270
|
return () => {
|
|
10215
10271
|
alive = false;
|
|
10216
10272
|
};
|
|
10217
|
-
}, [loadReasons]);
|
|
10273
|
+
}, [loadReasons, attempt]);
|
|
10218
10274
|
const reason = reasons?.find((r) => r.code === chosen);
|
|
10219
10275
|
return /* @__PURE__ */ jsxs(PosSheet, { label: "Cancelar pedido", onDismiss: onCancel, children: [
|
|
10220
10276
|
/* @__PURE__ */ jsxs("div", { className: "pos-sheet__head", children: [
|
|
@@ -10230,37 +10286,32 @@ function MarketplaceCancelSheet({ provider, orderLabel, loadReasons, onConfirm,
|
|
|
10230
10286
|
provider,
|
|
10231
10287
|
" decide o cancelamento. Escolha um dos motivos que ele aceita para este pedido."
|
|
10232
10288
|
] }),
|
|
10233
|
-
/* @__PURE__ */ jsx("div", { className: "pos-sheet__body",
|
|
10234
|
-
|
|
10235
|
-
provider,
|
|
10236
|
-
". Tente de novo."
|
|
10237
|
-
] }) : reasons === null ? /* @__PURE__ */ jsxs("p", { className: "pos-empty__h", children: [
|
|
10238
|
-
"Buscando os motivos no ",
|
|
10239
|
-
provider,
|
|
10240
|
-
"\u2026"
|
|
10241
|
-
] }) : reasons.length === 0 ? /* @__PURE__ */ jsxs("p", { className: "pos-empty__t", children: [
|
|
10242
|
-
"O ",
|
|
10243
|
-
provider,
|
|
10244
|
-
" n\xE3o aceita cancelar este pedido agora."
|
|
10245
|
-
] }) : reasons.map((r) => /* @__PURE__ */ jsx(
|
|
10246
|
-
PosButton,
|
|
10289
|
+
/* @__PURE__ */ jsx("div", { className: "pos-sheet__body", children: failed ? /* @__PURE__ */ jsx(
|
|
10290
|
+
EmptyState,
|
|
10247
10291
|
{
|
|
10248
|
-
|
|
10249
|
-
|
|
10250
|
-
|
|
10251
|
-
|
|
10252
|
-
|
|
10253
|
-
|
|
10254
|
-
|
|
10255
|
-
r
|
|
10256
|
-
|
|
10292
|
+
title: `N\xE3o foi poss\xEDvel buscar os motivos no ${provider}.`,
|
|
10293
|
+
Icon: Ban,
|
|
10294
|
+
action: { label: "Tentar de novo", onClick: () => setAttempt((n) => n + 1) }
|
|
10295
|
+
}
|
|
10296
|
+
) : reasons !== null && reasons.length === 0 ? /* @__PURE__ */ jsx(EmptyState, { title: `O ${provider} n\xE3o aceita cancelar este pedido agora.`, Icon: Ban }) : (
|
|
10297
|
+
// The same option rows the modifier and open-table sheets use: a box
|
|
10298
|
+
// that checks and an accent edge on the one chosen.
|
|
10299
|
+
/* @__PURE__ */ jsx("div", { className: "pos-mgroup__opts pos-mgroup__opts--stack", role: "group", "aria-label": `Motivos do ${provider}`, "aria-busy": reasons === null, children: reasons === null ? [0, 1, 2, 3].map((i) => /* @__PURE__ */ jsx("div", { className: "pos-mopt pos-skel", "aria-hidden": true, children: /* @__PURE__ */ jsx("span", { className: "pos-skel__b", style: { width: `${55 + i * 9}%`, height: 14 } }) }, i)) : reasons.map((r) => {
|
|
10300
|
+
const on = chosen === r.code;
|
|
10301
|
+
return /* @__PURE__ */ jsxs(PosButton, { className: "pos-mopt", "aria-pressed": on, onClick: () => setChosen(r.code), children: [
|
|
10302
|
+
/* @__PURE__ */ jsx("span", { className: "pos-mopt__check", children: on && /* @__PURE__ */ jsx(Check, { size: 14, strokeWidth: 3 }) }),
|
|
10303
|
+
/* @__PURE__ */ jsx("span", { className: "pos-mopt__label", children: r.description })
|
|
10304
|
+
] }, r.code);
|
|
10305
|
+
}) })
|
|
10306
|
+
) }),
|
|
10257
10307
|
/* @__PURE__ */ jsxs("div", { className: "pos-sheet__foot", children: [
|
|
10258
|
-
/* @__PURE__ */ jsx(PosButton, { className: "pos-btn pos-btn--ghost", onClick: onCancel, children: "Voltar" }),
|
|
10308
|
+
/* @__PURE__ */ jsx(PosButton, { className: "pos-btn pos-btn--ghost", onClick: onCancel, disabled: sending, children: "Voltar" }),
|
|
10259
10309
|
/* @__PURE__ */ jsx(
|
|
10260
10310
|
PosButton,
|
|
10261
10311
|
{
|
|
10262
|
-
className: "pos-btn",
|
|
10312
|
+
className: "pos-btn pos-btn--danger",
|
|
10263
10313
|
disabled: !reason || sending,
|
|
10314
|
+
"aria-busy": sending,
|
|
10264
10315
|
onClick: async () => {
|
|
10265
10316
|
if (!reason) return;
|
|
10266
10317
|
setSending(true);
|