@classytic/pos-ui 0.1.0 → 1.2.0
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/LICENSE +75 -0
- package/dist/components/CartSidebar.d.ts +56 -0
- package/dist/components/CartSidebar.js +10 -9
- package/dist/components/PosTopBar.d.ts +19 -0
- package/dist/components/PosTopBar.js +4 -4
- package/dist/components/PrinterSettingsDialog.d.ts +8 -0
- package/dist/components/PrinterSettingsDialog.js +506 -20
- package/dist/components/ReceiptDeliveryDialog.d.ts +11 -0
- package/dist/components/ReceiptDeliveryDialog.js +98 -0
- package/dist/components/ReceiptReprintDialog.d.ts +10 -0
- package/dist/components/ReceiptReprintDialog.js +49 -22
- package/dist/components/index.d.ts +6 -0
- package/dist/components/index.js +7 -0
- package/dist/dashboard/components/CustomerLookupDialog.js +108 -90
- package/dist/dashboard/components/CustomerQuickAddDialog.js +3 -1
- package/dist/dashboard/components/DeliveryPanel.js +134 -0
- package/dist/dashboard/components/ProductCard.js +17 -7
- package/dist/dashboard/components/ProductsPanel.js +4 -4
- package/dist/dashboard/components/SplitPaymentPanel.js +5 -5
- package/dist/dashboard/components/VariantSelectorDialog.js +53 -11
- package/dist/dashboard/components/cart/AddChargeDialog.js +3 -2
- package/dist/dashboard/components/cart/CartItems.js +5 -5
- package/dist/dashboard/components/cart/CartSummary.js +6 -6
- package/dist/dashboard/components/cart/CustomerSection.js +3 -3
- package/dist/dashboard/components/cart/DiscountSection.js +4 -3
- package/dist/dashboard/components/cart/PointsRedemptionSection.js +5 -4
- package/dist/dashboard/pos.types.d.ts +32 -0
- package/dist/hardware/agent-adapter.js +127 -0
- package/dist/hardware/agent-pairing.d.ts +18 -0
- package/dist/hardware/agent-pairing.js +63 -0
- package/dist/hardware/context.d.ts +1 -5
- package/dist/hardware/index.d.ts +4 -3
- package/dist/hardware/index.js +3 -2
- package/dist/hardware/ports.d.ts +21 -4
- package/dist/hardware/tauri-adapter.d.ts +0 -1
- package/dist/hardware/tauri-adapter.js +19 -5
- package/dist/hardware/web-adapter.d.ts +22 -7
- package/dist/hardware/web-adapter.js +56 -14
- package/dist/hooks/branch-scoped-key.js +64 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.js +7 -0
- package/dist/hooks/sale-attempt.js +62 -0
- package/dist/hooks/useManagerAuth.js +9 -1
- package/dist/hooks/usePosCart.d.ts +55 -0
- package/dist/hooks/usePosCart.js +224 -117
- package/dist/hooks/usePosCustomer.d.ts +31 -0
- package/dist/hooks/usePosCustomer.js +32 -78
- package/dist/hooks/usePosDelivery.d.ts +28 -0
- package/dist/hooks/usePosDelivery.js +133 -0
- package/dist/hooks/usePosMultiOrder.d.ts +22 -0
- package/dist/hooks/usePosMultiOrder.js +14 -4
- package/dist/hooks/usePosPayment.d.ts +22 -0
- package/dist/lib/delivery-payload.js +83 -0
- package/dist/lib/money.js +96 -23
- package/dist/node_modules/react-hook-form/dist/index.esm.js +468 -332
- package/dist/runtime/auth-port.d.ts +1 -5
- package/dist/runtime/branch-port.d.ts +1 -5
- package/dist/runtime/config.d.ts +43 -6
- package/dist/runtime/config.js +18 -1
- package/dist/runtime/index.d.ts +2 -2
- package/dist/runtime/index.js +2 -2
- package/dist/screens/OrderHistoryDrawer.d.ts +8 -0
- package/dist/screens/OrderHistoryDrawer.js +15 -15
- package/dist/screens/ParkedOrdersDrawer.d.ts +12 -0
- package/dist/screens/ParkedOrdersDrawer.js +3 -3
- package/dist/screens/PaymentScreen.d.ts +4 -0
- package/dist/screens/PaymentScreen.js +194 -33
- package/dist/screens/ProductScreen.d.ts +4 -0
- package/dist/screens/ProductScreen.js +13 -10
- package/dist/screens/ReceiptScreen.d.ts +4 -0
- package/dist/screens/ReceiptScreen.js +96 -72
- package/dist/screens/ShiftCloseScreen.d.ts +4 -0
- package/dist/screens/ShiftCloseScreen.js +18 -15
- package/dist/screens/ShiftOpenScreen.d.ts +4 -0
- package/dist/screens/ShiftOpenScreen.js +75 -19
- package/dist/screens/index.d.ts +8 -0
- package/dist/screens/index.js +9 -0
- package/dist/shell/index.d.ts +2 -0
- package/dist/shell/pos-shell.d.ts +41 -8
- package/dist/shell/pos-shell.js +25 -18
- package/dist/state/index.d.ts +3 -0
- package/dist/state/index.js +4 -0
- package/dist/state/pos-context.d.ts +13 -0
- package/dist/state/pos-state.d.ts +49 -0
- package/dist/state/pos-state.js +6 -7
- package/dist/utils/pos-helpers.js +137 -34
- package/package.json +27 -7
package/LICENSE
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
Classytic Source-Available License (Community & Commercial), Version 1.0
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Classytic LLC. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This software is source-available, not open source. Please read this License
|
|
6
|
+
before using it.
|
|
7
|
+
|
|
8
|
+
1. DEFINITIONS
|
|
9
|
+
"Software" means the contents of this package and any accompanying source
|
|
10
|
+
code, object code, or documentation, in any form.
|
|
11
|
+
"Licensor" means Classytic LLC, a limited liability company organized in the
|
|
12
|
+
United States.
|
|
13
|
+
"You" means the individual or legal entity exercising rights under this
|
|
14
|
+
License.
|
|
15
|
+
"Evaluation Use" means use for evaluation, development, testing,
|
|
16
|
+
experimentation, or internal non-commercial purposes only.
|
|
17
|
+
"Production Use" means any use of the Software that is live, commercial,
|
|
18
|
+
revenue-generating, or customer-facing, or any use other than Evaluation Use.
|
|
19
|
+
"Commercial License" means a separate written agreement executed with
|
|
20
|
+
Licensor that grants Production Use rights.
|
|
21
|
+
|
|
22
|
+
2. OWNERSHIP
|
|
23
|
+
The Software is licensed, not sold. Licensor retains all right, title, and
|
|
24
|
+
interest in and to the Software, including all intellectual property rights.
|
|
25
|
+
All rights not expressly granted in this License are reserved by Licensor.
|
|
26
|
+
|
|
27
|
+
3. EVALUATION GRANT
|
|
28
|
+
Subject to Your compliance with this License, Licensor grants You a
|
|
29
|
+
worldwide, royalty-free, non-exclusive, non-transferable, revocable license
|
|
30
|
+
to download, install, run, and modify the Software solely for Evaluation Use.
|
|
31
|
+
|
|
32
|
+
4. PRODUCTION USE REQUIRES A COMMERCIAL LICENSE
|
|
33
|
+
Production Use of the Software is NOT permitted under this License and
|
|
34
|
+
requires a Commercial License from Licensor. A Commercial License may be
|
|
35
|
+
granted at Licensor's discretion, with or without a fee, and may confer
|
|
36
|
+
perpetual, irrevocable, and transferable Production Use rights as set out in
|
|
37
|
+
that agreement. Contact licensing@classytic.com to obtain one.
|
|
38
|
+
|
|
39
|
+
5. RESTRICTIONS
|
|
40
|
+
You may not:
|
|
41
|
+
(a) make any Production Use of the Software without a Commercial License;
|
|
42
|
+
(b) redistribute, resell, rent, sublicense, or otherwise make the Software
|
|
43
|
+
(in whole or in part, original or modified) available to third parties as
|
|
44
|
+
a stand-alone product, framework, library, or hosted/managed service that
|
|
45
|
+
competes with the Software or with Licensor;
|
|
46
|
+
(c) remove, obscure, or alter any copyright, license, or attribution notice.
|
|
47
|
+
|
|
48
|
+
6. FEEDBACK AND CONTRIBUTIONS
|
|
49
|
+
Any feedback, suggestions, or contributions You provide relating to the
|
|
50
|
+
Software may be used by Licensor for any purpose without obligation to You.
|
|
51
|
+
|
|
52
|
+
7. TERMINATION
|
|
53
|
+
This License and the Evaluation Grant terminate automatically if You breach
|
|
54
|
+
any term. Upon termination You must cease all use of the Software and destroy
|
|
55
|
+
all copies in Your possession. Rights under a Commercial License are governed
|
|
56
|
+
by that agreement's own terms and survive termination of this License to the
|
|
57
|
+
extent stated there.
|
|
58
|
+
|
|
59
|
+
8. DISCLAIMER OF WARRANTY
|
|
60
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
61
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
62
|
+
FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.
|
|
63
|
+
|
|
64
|
+
9. LIMITATION OF LIABILITY
|
|
65
|
+
TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL LICENSOR BE LIABLE
|
|
66
|
+
FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
67
|
+
TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE
|
|
68
|
+
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
69
|
+
|
|
70
|
+
10. GOVERNING LAW
|
|
71
|
+
This License is governed by the laws of the State of Delaware, United States,
|
|
72
|
+
without regard to its conflict-of-laws principles. (Adjust to Your LLC's state
|
|
73
|
+
of formation.)
|
|
74
|
+
|
|
75
|
+
For commercial licensing, contact: licensing@classytic.com
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { UsePosCartReturn } from "../hooks/usePosCart.js";
|
|
2
|
+
import { UsePosCustomerReturn } from "../hooks/usePosCustomer.js";
|
|
3
|
+
//#region src/components/CartSidebar.d.ts
|
|
4
|
+
interface CartSidebarProps {
|
|
5
|
+
cart: UsePosCartReturn;
|
|
6
|
+
customer: UsePosCustomerReturn;
|
|
7
|
+
/**
|
|
8
|
+
* `loyalty.membership` config. `pointValueMinor` is integer MINOR units per
|
|
9
|
+
* point (loyalty 0.6.0); the legacy `pointsPerBdt` it replaced was the
|
|
10
|
+
* RECIPROCAL quantity and the server no longer emits it.
|
|
11
|
+
*/
|
|
12
|
+
membership: {
|
|
13
|
+
enabled?: boolean;
|
|
14
|
+
redemption?: {
|
|
15
|
+
enabled?: boolean;
|
|
16
|
+
minRedeemPoints?: number;
|
|
17
|
+
pointValueMinor?: number;
|
|
18
|
+
};
|
|
19
|
+
} | null | undefined;
|
|
20
|
+
orderTotals: {
|
|
21
|
+
subtotal: number;
|
|
22
|
+
manualDiscount: number;
|
|
23
|
+
tierDiscount: number;
|
|
24
|
+
tierName: string | null;
|
|
25
|
+
redemptionDiscount: number;
|
|
26
|
+
total: number;
|
|
27
|
+
pointsToEarn: number;
|
|
28
|
+
pointsRedeemed: number;
|
|
29
|
+
redemptionError: string | null;
|
|
30
|
+
maxAllowedPoints: number;
|
|
31
|
+
};
|
|
32
|
+
discountAuth: {
|
|
33
|
+
isAuthorized: boolean;
|
|
34
|
+
authorizedBy: {
|
|
35
|
+
name: string;
|
|
36
|
+
} | null;
|
|
37
|
+
clearAuth: () => void;
|
|
38
|
+
};
|
|
39
|
+
onCheckout: () => void;
|
|
40
|
+
onRequestDiscountAuth: () => void;
|
|
41
|
+
onClearDiscountAuth: () => void;
|
|
42
|
+
/** Park-current-sale handler (F6). Disabled when cart is empty or
|
|
43
|
+
* the parked-orders store is full. */
|
|
44
|
+
onParkSale?: () => void;
|
|
45
|
+
/** Open the parked-sales drawer (F7). Always available so the cashier
|
|
46
|
+
* can review/restore pending holds. */
|
|
47
|
+
onOpenParked?: () => void;
|
|
48
|
+
/** Number of currently-parked sales — drives the badge on the
|
|
49
|
+
* "Parked" button so the cashier knows there are slots to revisit. */
|
|
50
|
+
parkedCount?: number;
|
|
51
|
+
/** Whether the parked-orders store has room for one more (≤ MAX). */
|
|
52
|
+
canPark?: boolean;
|
|
53
|
+
}
|
|
54
|
+
declare function CartSidebar({ cart, customer, membership, orderTotals, discountAuth, onCheckout, onRequestDiscountAuth, onClearDiscountAuth, onParkSale, onOpenParked, parkedCount, canPark }: CartSidebarProps): import("react").JSX.Element;
|
|
55
|
+
//#endregion
|
|
56
|
+
export { CartSidebar };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { formatMajor } from "../lib/money.js";
|
|
4
4
|
import { getReadableTextColor, getTierColor } from "../lib/loyalty.js";
|
|
5
5
|
import { CartItems } from "../dashboard/components/cart/CartItems.js";
|
|
6
6
|
import { CartSummary } from "../dashboard/components/cart/CartSummary.js";
|
|
@@ -63,7 +63,7 @@ function CartSidebar({ cart, customer, membership, orderTotals, discountAuth, on
|
|
|
63
63
|
pointsBalance: customer.selectedCustomer?.membership?.points?.current ?? 0,
|
|
64
64
|
minRedeemPoints: membership?.redemption?.minRedeemPoints ?? 0,
|
|
65
65
|
maxRedeemPoints: Math.min(orderTotals.maxAllowedPoints, customer.selectedCustomer?.membership?.points?.current ?? 0),
|
|
66
|
-
|
|
66
|
+
pointValueMinor: membership?.redemption?.pointValueMinor,
|
|
67
67
|
estimatedDiscount: orderTotals.redemptionDiscount,
|
|
68
68
|
error: orderTotals.redemptionError
|
|
69
69
|
}), [
|
|
@@ -100,11 +100,11 @@ function CartSidebar({ cart, customer, membership, orderTotals, discountAuth, on
|
|
|
100
100
|
onClick: onOpenParked,
|
|
101
101
|
"aria-label": `Parked sales (${parkedCount})`,
|
|
102
102
|
children: [
|
|
103
|
-
/* @__PURE__ */ jsx(Inbox, { className: "h-3.5 w-3.5
|
|
103
|
+
/* @__PURE__ */ jsx(Inbox, { className: "h-3.5 w-3.5 me-1" }),
|
|
104
104
|
"Parked",
|
|
105
105
|
parkedCount > 0 && /* @__PURE__ */ jsx(Badge, {
|
|
106
106
|
variant: "secondary",
|
|
107
|
-
className: "
|
|
107
|
+
className: "ms-1.5 h-4 px-1.5 text-[10px]",
|
|
108
108
|
children: parkedCount
|
|
109
109
|
})
|
|
110
110
|
]
|
|
@@ -116,14 +116,14 @@ function CartSidebar({ cart, customer, membership, orderTotals, discountAuth, on
|
|
|
116
116
|
onClick: onParkSale,
|
|
117
117
|
disabled: !canPark,
|
|
118
118
|
title: canPark ? "Park sale (F6)" : "Max 5 parked — resume one first",
|
|
119
|
-
children: [/* @__PURE__ */ jsx(PauseCircle, { className: "h-3.5 w-3.5
|
|
119
|
+
children: [/* @__PURE__ */ jsx(PauseCircle, { className: "h-3.5 w-3.5 me-1" }), "Park"]
|
|
120
120
|
}),
|
|
121
121
|
!isEmpty && /* @__PURE__ */ jsxs(Button, {
|
|
122
122
|
variant: "ghost",
|
|
123
123
|
size: "sm",
|
|
124
124
|
className: "h-7 text-xs text-destructive",
|
|
125
125
|
onClick: cart.clearCart,
|
|
126
|
-
children: [/* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5
|
|
126
|
+
children: [/* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5 me-1" }), "Clear"]
|
|
127
127
|
})
|
|
128
128
|
]
|
|
129
129
|
})]
|
|
@@ -195,7 +195,7 @@ function CartSidebar({ cart, customer, membership, orderTotals, discountAuth, on
|
|
|
195
195
|
pointsBalance: redemption.pointsBalance,
|
|
196
196
|
minRedeemPoints: redemption.minRedeemPoints,
|
|
197
197
|
maxRedeemPoints: redemption.maxRedeemPoints,
|
|
198
|
-
|
|
198
|
+
pointValueMinor: redemption.pointValueMinor,
|
|
199
199
|
estimatedDiscount: redemption.estimatedDiscount,
|
|
200
200
|
error: redemption.error,
|
|
201
201
|
value: cart.pointsToRedeemInput,
|
|
@@ -208,10 +208,11 @@ function CartSidebar({ cart, customer, membership, orderTotals, discountAuth, on
|
|
|
208
208
|
}),
|
|
209
209
|
!isEmpty && /* @__PURE__ */ jsx("div", {
|
|
210
210
|
className: "px-4 py-3 border-t bg-card",
|
|
211
|
-
children: /* @__PURE__ */
|
|
211
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
212
212
|
className: "w-full h-12 text-base font-semibold",
|
|
213
213
|
onClick: onCheckout,
|
|
214
|
-
|
|
214
|
+
disabled: !cart.ready,
|
|
215
|
+
children: cart.ready ? `Checkout ${formatMajor(orderTotals.total)}` : "Preparing register…"
|
|
215
216
|
})
|
|
216
217
|
})
|
|
217
218
|
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/components/PosTopBar.d.ts
|
|
2
|
+
interface PosTopBarProps {
|
|
3
|
+
userName?: string;
|
|
4
|
+
/**
|
|
5
|
+
* Host-supplied actions rendered before the built-in ones — a gym's
|
|
6
|
+
* "Find member" / "Day pass", a hotel's "Charge to room". Keeps a vertical
|
|
7
|
+
* out of this component's business.
|
|
8
|
+
*/
|
|
9
|
+
actions?: import("react").ReactNode;
|
|
10
|
+
onNewSale?: () => void;
|
|
11
|
+
onOpenHistory?: () => void;
|
|
12
|
+
/** Open the keyboard-shortcuts help dialog (also bound to `?`). */
|
|
13
|
+
onOpenHelp?: () => void;
|
|
14
|
+
/** Open the printer-settings dialog (host/port + test connection). */
|
|
15
|
+
onOpenPrinterSettings?: () => void;
|
|
16
|
+
}
|
|
17
|
+
declare function PosTopBar({ userName, actions, onNewSale, onOpenHistory, onOpenHelp, onOpenPrinterSettings }: PosTopBarProps): import("react").JSX.Element;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { PosTopBar, PosTopBarProps };
|
|
@@ -32,7 +32,7 @@ function useClock() {
|
|
|
32
32
|
}, []);
|
|
33
33
|
return time;
|
|
34
34
|
}
|
|
35
|
-
function PosTopBar({ userName, onNewSale, onOpenHistory, onOpenHelp, onOpenPrinterSettings }) {
|
|
35
|
+
function PosTopBar({ userName, actions, onNewSale, onOpenHistory, onOpenHelp, onOpenPrinterSettings }) {
|
|
36
36
|
const selectedBranch = usePosBranch();
|
|
37
37
|
const { onNavigate } = usePosRuntime();
|
|
38
38
|
const { state, dispatch } = usePosContext();
|
|
@@ -105,15 +105,15 @@ function PosTopBar({ userName, onNewSale, onOpenHistory, onOpenHelp, onOpenPrint
|
|
|
105
105
|
})
|
|
106
106
|
]
|
|
107
107
|
}),
|
|
108
|
-
/* @__PURE__ */
|
|
108
|
+
/* @__PURE__ */ jsxs("div", {
|
|
109
109
|
className: "flex-1 flex items-center justify-center gap-1 px-4",
|
|
110
|
-
children: state.screen === "products" && onNewSale && /* @__PURE__ */ jsxs(Button, {
|
|
110
|
+
children: [actions, state.screen === "products" && onNewSale && /* @__PURE__ */ jsxs(Button, {
|
|
111
111
|
variant: "ghost",
|
|
112
112
|
size: "sm",
|
|
113
113
|
onClick: onNewSale,
|
|
114
114
|
className: "h-8 text-xs gap-1",
|
|
115
115
|
children: [/* @__PURE__ */ jsx(Plus, { className: "h-3.5 w-3.5" }), "New Sale"]
|
|
116
|
-
})
|
|
116
|
+
})]
|
|
117
117
|
}),
|
|
118
118
|
/* @__PURE__ */ jsxs("div", {
|
|
119
119
|
className: "flex items-center gap-3 shrink-0",
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/components/PrinterSettingsDialog.d.ts
|
|
2
|
+
interface PrinterSettingsDialogProps {
|
|
3
|
+
open: boolean;
|
|
4
|
+
onOpenChange: (open: boolean) => void;
|
|
5
|
+
}
|
|
6
|
+
declare function PrinterSettingsDialog({ open, onOpenChange }: PrinterSettingsDialogProps): import("react").JSX.Element;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { PrinterSettingsDialog };
|