@tallyui/components 3.0.4 → 3.1.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.d.ts +37 -3
- package/dist/index.js +456 -263
- package/package.json +9 -9
- package/src/customer/customer-picker.tsx +1 -1
- package/src/customer/customer-select.tsx +16 -0
- package/src/index.ts +2 -0
- package/src/sale/cart.tsx +24 -7
- package/src/sale/index.ts +2 -0
- package/src/sale/parked-sales.tsx +103 -0
- package/src/sale/price-form.tsx +51 -0
package/dist/index.js
CHANGED
|
@@ -2308,6 +2308,7 @@ function CustomerCard({ doc, traits, className, ...props }) {
|
|
|
2308
2308
|
}
|
|
2309
2309
|
|
|
2310
2310
|
// src/customer/customer-select.tsx
|
|
2311
|
+
import { useState as useState6 } from "react";
|
|
2311
2312
|
import { Pressable as Pressable14, ScrollView as ScrollView6, View as View29 } from "react-native";
|
|
2312
2313
|
import { Select as Select2 } from "@tallyui/primitives";
|
|
2313
2314
|
import { useCustomerTraits as useCustomerTraits2 } from "@tallyui/core";
|
|
@@ -2325,10 +2326,12 @@ function CustomerSelectView({
|
|
|
2325
2326
|
onSelect,
|
|
2326
2327
|
onSearch,
|
|
2327
2328
|
placeholder = "Search customers...",
|
|
2329
|
+
showSearch = true,
|
|
2328
2330
|
className,
|
|
2329
2331
|
traits,
|
|
2330
2332
|
...props
|
|
2331
2333
|
}) {
|
|
2334
|
+
const [search, setSearch] = useState6("");
|
|
2332
2335
|
const selectedOption = selected && traits ? { value: traits.getId(selected), label: traits.getName(selected) } : void 0;
|
|
2333
2336
|
const customerById = /* @__PURE__ */ new Map();
|
|
2334
2337
|
if (traits) {
|
|
@@ -2347,6 +2350,19 @@ function CustomerSelectView({
|
|
|
2347
2350
|
onValueChange: handleValueChange,
|
|
2348
2351
|
defaultOpen: true,
|
|
2349
2352
|
children: /* @__PURE__ */ jsxs19(VStack, { space: "sm", className: cn56(className), ...props, children: [
|
|
2353
|
+
showSearch && /* @__PURE__ */ jsx59(
|
|
2354
|
+
SearchInput,
|
|
2355
|
+
{
|
|
2356
|
+
value: search,
|
|
2357
|
+
onChangeText: (text) => {
|
|
2358
|
+
setSearch(text);
|
|
2359
|
+
onSearch(text);
|
|
2360
|
+
},
|
|
2361
|
+
placeholder,
|
|
2362
|
+
testID: "customer-select-search",
|
|
2363
|
+
accessibilityLabel: "Search customers"
|
|
2364
|
+
}
|
|
2365
|
+
),
|
|
2350
2366
|
selected && traits && /* @__PURE__ */ jsx59(Select2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx59(View29, { className: "rounded-lg border border-primary bg-primary/5 px-3 py-2", children: /* @__PURE__ */ jsx59(CustomerCard, { doc: selected, traits }) }) }),
|
|
2351
2367
|
customers.length > 0 && /* @__PURE__ */ jsx59(Select2.Content, { asChild: true, forceMount: true, disablePositioningStyle: true, children: /* @__PURE__ */ jsx59(ScrollView6, { className: "max-h-60", children: customers.map((customer, index) => {
|
|
2352
2368
|
const id = traits?.getId(customer) ?? String(index);
|
|
@@ -2431,7 +2447,7 @@ function CustomerOrderHistory({
|
|
|
2431
2447
|
}
|
|
2432
2448
|
|
|
2433
2449
|
// src/customer/customer-picker.tsx
|
|
2434
|
-
import { useEffect, useRef, useState as
|
|
2450
|
+
import { useEffect, useRef, useState as useState7 } from "react";
|
|
2435
2451
|
import { Pressable as Pressable16, Text as Text19, TextInput as TextInput7, View as View32 } from "react-native";
|
|
2436
2452
|
import { customerTraits, CustomerServiceError, ConnectorUnauthorizedError } from "@tallyui/core";
|
|
2437
2453
|
import { cn as cn59 } from "@tallyui/theme";
|
|
@@ -2439,16 +2455,16 @@ import { jsx as jsx62, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
|
2439
2455
|
var EMAIL_MAX = 254;
|
|
2440
2456
|
var EMAIL_SHAPE = /^[^\s@\u0000]+@[^\s@\u0000]+\.[^\s@\u0000]+$/u;
|
|
2441
2457
|
function CustomerPicker({ search, create, selected, onSelect, onError, online, debounceMs = 250, className }) {
|
|
2442
|
-
const [query, setQuery] =
|
|
2443
|
-
const [customers, setCustomers] =
|
|
2444
|
-
const [error, setError] =
|
|
2445
|
-
const [showForm, setShowForm] =
|
|
2446
|
-
const [creating, setCreating] =
|
|
2447
|
-
const [values, setValues] =
|
|
2458
|
+
const [query, setQuery] = useState7("");
|
|
2459
|
+
const [customers, setCustomers] = useState7([]);
|
|
2460
|
+
const [error, setError] = useState7(null);
|
|
2461
|
+
const [showForm, setShowForm] = useState7(false);
|
|
2462
|
+
const [creating, setCreating] = useState7(false);
|
|
2463
|
+
const [values, setValues] = useState7({ firstName: "", lastName: "", email: "", phone: "", address: "" });
|
|
2448
2464
|
const sequence = useRef(0);
|
|
2449
2465
|
const searchRef = useRef(search);
|
|
2450
2466
|
searchRef.current = search;
|
|
2451
|
-
const [noResults, setNoResults] =
|
|
2467
|
+
const [noResults, setNoResults] = useState7(false);
|
|
2452
2468
|
function handleError(error2) {
|
|
2453
2469
|
if (error2 instanceof CustomerServiceError) {
|
|
2454
2470
|
setError(error2.code === "network" ? "Couldn't reach the store. Try again." : error2.code === "server" ? "The store couldn't do that. Try again." : error2.message);
|
|
@@ -2530,6 +2546,7 @@ function CustomerPicker({ search, create, selected, onSelect, onError, online, d
|
|
|
2530
2546
|
customers,
|
|
2531
2547
|
traits: customerTraits,
|
|
2532
2548
|
onSearch: setQuery,
|
|
2549
|
+
showSearch: false,
|
|
2533
2550
|
onSelect: (customer) => {
|
|
2534
2551
|
onSelect(customer);
|
|
2535
2552
|
setQuery("");
|
|
@@ -2675,7 +2692,7 @@ function ChangeDisplay({ change, locale, className, ...viewProps }) {
|
|
|
2675
2692
|
}
|
|
2676
2693
|
|
|
2677
2694
|
// src/checkout/cash-tendered.tsx
|
|
2678
|
-
import { useEffect as useEffect2, useRef as useRef2, useState as
|
|
2695
|
+
import { useEffect as useEffect2, useRef as useRef2, useState as useState8 } from "react";
|
|
2679
2696
|
import { Pressable as Pressable18, Text as Text21, TextInput as TextInput8, View as View36 } from "react-native";
|
|
2680
2697
|
import { formatMoney as formatMoney5, minorUnitDigits as minorUnitDigits2, moneyFromDecimalString } from "@tallyui/core";
|
|
2681
2698
|
import { cn as cn65 } from "@tallyui/theme";
|
|
@@ -2700,13 +2717,13 @@ function CashTendered({
|
|
|
2700
2717
|
className,
|
|
2701
2718
|
...viewProps
|
|
2702
2719
|
}) {
|
|
2703
|
-
const [internalAmount, setInternalAmount] =
|
|
2720
|
+
const [internalAmount, setInternalAmount] = useState8(defaultAmount ?? total);
|
|
2704
2721
|
const amount = controlledAmount ?? internalAmount;
|
|
2705
2722
|
const buttons = quickAmounts ?? defaultQuickAmounts(total);
|
|
2706
2723
|
const digits = minorUnitDigits2(amount.currency);
|
|
2707
2724
|
const amountText = String(Math.abs(amount.amount)).padStart(digits + 1, "0");
|
|
2708
2725
|
const decimal2 = (amount.amount < 0 ? "-" : "") + (digits ? `${amountText.slice(0, -digits)}.${amountText.slice(-digits)}` : amountText);
|
|
2709
|
-
const [text, setText] =
|
|
2726
|
+
const [text, setText] = useState8(decimal2);
|
|
2710
2727
|
const lastTextAmount = useRef2(amount);
|
|
2711
2728
|
useEffect2(() => {
|
|
2712
2729
|
if (amount.amount !== lastTextAmount.current.amount || amount.currency !== lastTextAmount.current.currency) {
|
|
@@ -2946,7 +2963,7 @@ function OrderDetail({
|
|
|
2946
2963
|
}
|
|
2947
2964
|
|
|
2948
2965
|
// src/register/cash-count-input.tsx
|
|
2949
|
-
import { useState as
|
|
2966
|
+
import { useState as useState9 } from "react";
|
|
2950
2967
|
import { Text as Text26, View as View42 } from "react-native";
|
|
2951
2968
|
import { cn as cn71 } from "@tallyui/theme";
|
|
2952
2969
|
import { jsx as jsx74, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
@@ -2971,7 +2988,7 @@ function CashCountInput({
|
|
|
2971
2988
|
className,
|
|
2972
2989
|
...viewProps
|
|
2973
2990
|
}) {
|
|
2974
|
-
const [internalCounts, setInternalCounts] =
|
|
2991
|
+
const [internalCounts, setInternalCounts] = useState9(defaultCounts ?? {});
|
|
2975
2992
|
const counts = controlledCounts ?? internalCounts;
|
|
2976
2993
|
const total = denominations2.reduce(
|
|
2977
2994
|
(sum, d) => sum + d.value * (counts[d.value] ?? 0),
|
|
@@ -3118,7 +3135,7 @@ function RegisterPicker({ registers, onPick, className }) {
|
|
|
3118
3135
|
}
|
|
3119
3136
|
|
|
3120
3137
|
// src/register/open-register-card.tsx
|
|
3121
|
-
import { useState as
|
|
3138
|
+
import { useState as useState10 } from "react";
|
|
3122
3139
|
import { View as View45 } from "react-native";
|
|
3123
3140
|
import { parseMinor, validAmount } from "@tallyui/pos";
|
|
3124
3141
|
import { currencySymbol, formatMoney as formatMoney6, minorUnitDigits as minorUnitDigits3 } from "@tallyui/core";
|
|
@@ -3129,10 +3146,10 @@ function OpenRegisterCard({ register, currency, configuredFloatMinor, className
|
|
|
3129
3146
|
const digits = minorUnitDigits3(currency);
|
|
3130
3147
|
const lastCountedMinor = register.lastClosure?.counted?.cash ?? null;
|
|
3131
3148
|
const expectedFloatMinor = configuredFloatMinor ?? lastCountedMinor ?? null;
|
|
3132
|
-
const [enteredAmount, setEnteredAmount] =
|
|
3149
|
+
const [enteredAmount, setEnteredAmount] = useState10(null);
|
|
3133
3150
|
const amount = enteredAmount ?? (expectedFloatMinor != null ? decimal(expectedFloatMinor, digits) : "");
|
|
3134
|
-
const [busy, setBusy] =
|
|
3135
|
-
const [error, setError] =
|
|
3151
|
+
const [busy, setBusy] = useState10(false);
|
|
3152
|
+
const [error, setError] = useState10("");
|
|
3136
3153
|
const valid = validAmount(amount, digits);
|
|
3137
3154
|
const countedMinor = valid ? parseMinor(amount, digits) : NaN;
|
|
3138
3155
|
const open = async () => {
|
|
@@ -3267,7 +3284,7 @@ function RegisterBar({
|
|
|
3267
3284
|
}
|
|
3268
3285
|
|
|
3269
3286
|
// src/register/movement-sheet.tsx
|
|
3270
|
-
import { useRef as useRef3, useState as
|
|
3287
|
+
import { useRef as useRef3, useState as useState11 } from "react";
|
|
3271
3288
|
import { movementFieldError, normalizeAmount, parseMinor as parseMinor2 } from "@tallyui/pos";
|
|
3272
3289
|
import { currencySymbol as currencySymbol2, minorUnitDigits as minorUnitDigits4 } from "@tallyui/core";
|
|
3273
3290
|
import { Fragment as Fragment3, jsx as jsx80, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
@@ -3280,11 +3297,11 @@ var AMOUNT_LABEL_ID2 = "movement-amount-label";
|
|
|
3280
3297
|
var REASON_LABEL_ID = "movement-reason-label";
|
|
3281
3298
|
function MovementSheet({ register, type, currency, onDone, onOpenChange, onOpenDrawer }) {
|
|
3282
3299
|
const digits = minorUnitDigits4(currency);
|
|
3283
|
-
const [amount, setAmount] =
|
|
3284
|
-
const [reason, setReason] =
|
|
3285
|
-
const [busy, setBusy] =
|
|
3300
|
+
const [amount, setAmount] = useState11("");
|
|
3301
|
+
const [reason, setReason] = useState11("");
|
|
3302
|
+
const [busy, setBusy] = useState11(false);
|
|
3286
3303
|
const busyRef = useRef3(false);
|
|
3287
|
-
const [error, setError] =
|
|
3304
|
+
const [error, setError] = useState11("");
|
|
3288
3305
|
const invalid = movementFieldError({ type, amount, reason });
|
|
3289
3306
|
const confirm = async () => {
|
|
3290
3307
|
if (invalid || busyRef.current) return;
|
|
@@ -3341,12 +3358,12 @@ function MovementSheet({ register, type, currency, onDone, onOpenChange, onOpenD
|
|
|
3341
3358
|
}
|
|
3342
3359
|
|
|
3343
3360
|
// src/register/register-panel.tsx
|
|
3344
|
-
import { useState as
|
|
3361
|
+
import { useState as useState13 } from "react";
|
|
3345
3362
|
import { ScrollView as ScrollView12, useWindowDimensions as useWindowDimensions2, View as View48 } from "react-native";
|
|
3346
3363
|
import { formatMoney as formatMoney8 } from "@tallyui/core";
|
|
3347
3364
|
|
|
3348
3365
|
// src/register/register-count.tsx
|
|
3349
|
-
import { useEffect as useEffect3, useRef as useRef4, useState as
|
|
3366
|
+
import { useEffect as useEffect3, useRef as useRef4, useState as useState12 } from "react";
|
|
3350
3367
|
import { Platform, Pressable as Pressable22, ScrollView as ScrollView11, useWindowDimensions, View as View47 } from "react-native";
|
|
3351
3368
|
import {
|
|
3352
3369
|
closeNeedsApproval,
|
|
@@ -3425,18 +3442,18 @@ function RegisterCount({ register, currency, approve, className }) {
|
|
|
3425
3442
|
const faces = denominations[currency] ?? denominations.default;
|
|
3426
3443
|
const { width } = useWindowDimensions();
|
|
3427
3444
|
const columns = width < 480 ? 3 : 4;
|
|
3428
|
-
const [pieces, setPieces] =
|
|
3429
|
-
const [cashText, setCashText] =
|
|
3445
|
+
const [pieces, setPieces] = useState12({});
|
|
3446
|
+
const [cashText, setCashText] = useState12(
|
|
3430
3447
|
() => session?.counted?.cash != null ? minorToDecimal(session.counted.cash, digits) : ""
|
|
3431
3448
|
);
|
|
3432
|
-
const [others, setOthers] =
|
|
3449
|
+
const [others, setOthers] = useState12(
|
|
3433
3450
|
() => Object.fromEntries(
|
|
3434
3451
|
Object.entries(session?.counted ?? {}).filter(([method]) => method !== "cash").map(([method, minor]) => [method, minorToDecimal(minor, digits)])
|
|
3435
3452
|
)
|
|
3436
3453
|
);
|
|
3437
|
-
const [busy, setBusy] =
|
|
3438
|
-
const [error, setError] =
|
|
3439
|
-
const [refusal, setRefusal] =
|
|
3454
|
+
const [busy, setBusy] = useState12(false);
|
|
3455
|
+
const [error, setError] = useState12("");
|
|
3456
|
+
const [refusal, setRefusal] = useState12("");
|
|
3440
3457
|
const usingTiles = Object.keys(pieces).length > 0;
|
|
3441
3458
|
const tilesTotal = denominationTotal(pieces);
|
|
3442
3459
|
const displayAmount = usingTiles ? minorToDecimal(tilesTotal, digits) : cashText;
|
|
@@ -3591,9 +3608,9 @@ function RegisterPanel({ register, currency, registerName, open, onOpenChange, c
|
|
|
3591
3608
|
const otherTenders = Object.entries(expected).filter(([method, amount]) => method !== "cash" && amount !== 0);
|
|
3592
3609
|
const { height: windowHeight } = useWindowDimensions2();
|
|
3593
3610
|
const maxHeight = Math.max(280, windowHeight - DIALOG_VERTICAL_MARGIN);
|
|
3594
|
-
const [movementType, setMovementType] =
|
|
3595
|
-
const [expanded, setExpanded] =
|
|
3596
|
-
const [error, setError] =
|
|
3611
|
+
const [movementType, setMovementType] = useState13(null);
|
|
3612
|
+
const [expanded, setExpanded] = useState13(false);
|
|
3613
|
+
const [error, setError] = useState13("");
|
|
3597
3614
|
const attempt = async (action) => {
|
|
3598
3615
|
try {
|
|
3599
3616
|
await action();
|
|
@@ -3710,7 +3727,7 @@ function RegisterPanel({ register, currency, registerName, open, onOpenChange, c
|
|
|
3710
3727
|
}
|
|
3711
3728
|
|
|
3712
3729
|
// src/register/register-column.tsx
|
|
3713
|
-
import { useState as
|
|
3730
|
+
import { useState as useState14 } from "react";
|
|
3714
3731
|
import { View as View49 } from "react-native";
|
|
3715
3732
|
import { Fragment as Fragment4, jsx as jsx83, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
3716
3733
|
function RegisterColumn({
|
|
@@ -3724,7 +3741,7 @@ function RegisterColumn({
|
|
|
3724
3741
|
cartEmpty,
|
|
3725
3742
|
children
|
|
3726
3743
|
}) {
|
|
3727
|
-
const [finishing, setFinishing] =
|
|
3744
|
+
const [finishing, setFinishing] = useState14(false);
|
|
3728
3745
|
if (registerId === null) {
|
|
3729
3746
|
return /* @__PURE__ */ jsx83(RegisterPicker, { registers, onPick, className: "flex-1" });
|
|
3730
3747
|
}
|
|
@@ -3755,7 +3772,7 @@ function RegisterColumn({
|
|
|
3755
3772
|
] });
|
|
3756
3773
|
}
|
|
3757
3774
|
function FinishClose({ register, busy, setBusy }) {
|
|
3758
|
-
const [error, setError] =
|
|
3775
|
+
const [error, setError] = useState14("");
|
|
3759
3776
|
const finish = async () => {
|
|
3760
3777
|
setBusy(true);
|
|
3761
3778
|
setError("");
|
|
@@ -3775,7 +3792,7 @@ function FinishClose({ register, busy, setBusy }) {
|
|
|
3775
3792
|
}
|
|
3776
3793
|
|
|
3777
3794
|
// src/register/closure-sheet.tsx
|
|
3778
|
-
import { useEffect as useEffect4, useRef as useRef5, useState as
|
|
3795
|
+
import { useEffect as useEffect4, useRef as useRef5, useState as useState15 } from "react";
|
|
3779
3796
|
import { AccessibilityInfo, Animated, View as View50 } from "react-native";
|
|
3780
3797
|
import { countVariance as countVariance2, TAX_ROUNDING_MIXED_NOTE, varianceText as varianceText2 } from "@tallyui/pos";
|
|
3781
3798
|
import { formatMoney as formatMoney9, minorUnitDigits as minorUnitDigits6 } from "@tallyui/core";
|
|
@@ -3807,8 +3824,8 @@ function ClosureSheet({ register, currency, onPrint, onDone }) {
|
|
|
3807
3824
|
const { lastClosure: closure, blind } = register;
|
|
3808
3825
|
const digits = minorUnitDigits6(currency);
|
|
3809
3826
|
const { opacity, scale } = useCompletionMotion();
|
|
3810
|
-
const [busy, setBusy] =
|
|
3811
|
-
const [error, setError] =
|
|
3827
|
+
const [busy, setBusy] = useState15(false);
|
|
3828
|
+
const [error, setError] = useState15("");
|
|
3812
3829
|
if (!closure) return null;
|
|
3813
3830
|
const methods = Object.keys(closure.counted);
|
|
3814
3831
|
const approvedByName = closure.breakdowns.approved_by_name;
|
|
@@ -3945,12 +3962,12 @@ function ConnectorStatus({
|
|
|
3945
3962
|
}
|
|
3946
3963
|
|
|
3947
3964
|
// src/sale/cart.tsx
|
|
3948
|
-
import { useState as
|
|
3949
|
-
import { Pressable as
|
|
3965
|
+
import { useState as useState18 } from "react";
|
|
3966
|
+
import { Pressable as Pressable25, Text as Text34, View as View56 } from "react-native";
|
|
3950
3967
|
import { buildReceiptData } from "@tallyui/pos";
|
|
3951
3968
|
|
|
3952
3969
|
// src/sale/discount-form.tsx
|
|
3953
|
-
import { useState as
|
|
3970
|
+
import { useState as useState16 } from "react";
|
|
3954
3971
|
import { Pressable as Pressable23, Text as Text32, TextInput as TextInput9, View as View54 } from "react-native";
|
|
3955
3972
|
import { formatMoney as formatMoney10, minorUnitDigits as minorUnitDigits7, moneyFromDecimalString as moneyFromDecimalString2 } from "@tallyui/core";
|
|
3956
3973
|
import { jsx as jsx88, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
@@ -3970,9 +3987,9 @@ function parseDiscount(type, text, currency) {
|
|
|
3970
3987
|
var discountLabel = (discount, currency) => discount.type === "percentage" ? `${discount.value}%` : formatMoney10({ amount: discount.amountMinor, currency }) ?? String(discount.amountMinor);
|
|
3971
3988
|
var button = "rounded-md border border-border px-3 py-2 min-h-11 items-center justify-center";
|
|
3972
3989
|
function DiscountForm({ title, currency, onApply, onClose }) {
|
|
3973
|
-
const [type, setType] =
|
|
3974
|
-
const [text, setText] =
|
|
3975
|
-
const [error, setError] =
|
|
3990
|
+
const [type, setType] = useState16("percentage");
|
|
3991
|
+
const [text, setText] = useState16("");
|
|
3992
|
+
const [error, setError] = useState16(null);
|
|
3976
3993
|
function apply() {
|
|
3977
3994
|
const parsed = parseDiscount(type, text, currency);
|
|
3978
3995
|
const refused = typeof parsed === "string" ? parsed : onApply(parsed);
|
|
@@ -4040,17 +4057,79 @@ function DiscountChips({ discounts, currency, onRemove, prefix, amounts = [] })
|
|
|
4040
4057
|
}) });
|
|
4041
4058
|
}
|
|
4042
4059
|
|
|
4060
|
+
// src/sale/price-form.tsx
|
|
4061
|
+
import { useState as useState17 } from "react";
|
|
4062
|
+
import { Pressable as Pressable24, Text as Text33, TextInput as TextInput10, View as View55 } from "react-native";
|
|
4063
|
+
import { formatMoney as formatMoney11, minorUnitDigits as minorUnitDigits8, moneyFromDecimalString as moneyFromDecimalString3 } from "@tallyui/core";
|
|
4064
|
+
import { jsx as jsx89, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
4065
|
+
function parsePrice(text, currency) {
|
|
4066
|
+
const raw = text.trim();
|
|
4067
|
+
const trimmed = raw.split(",").length === 2 ? raw.replace(",", ".") : raw;
|
|
4068
|
+
if (!trimmed) return "Enter a price.";
|
|
4069
|
+
if (!/^-?\d+(\.\d+)?$/.test(trimmed)) return "Enter a number.";
|
|
4070
|
+
if (Number(trimmed) < 0) return "Enter a price of 0 or more.";
|
|
4071
|
+
const digits = Math.min(2, minorUnitDigits8(currency));
|
|
4072
|
+
if ((trimmed.split(".")[1]?.length ?? 0) > digits) return digits ? `Use at most ${digits} decimal places.` : "Use a whole amount.";
|
|
4073
|
+
return moneyFromDecimalString3(trimmed, currency)?.amount ?? "Enter a number.";
|
|
4074
|
+
}
|
|
4075
|
+
var button2 = "rounded-md border border-border px-3 py-2 min-h-11 items-center justify-center";
|
|
4076
|
+
function PriceForm({ lineName, currency, currentMinor, onApply, onClose }) {
|
|
4077
|
+
const [text, setText] = useState17("");
|
|
4078
|
+
const [reason, setReason] = useState17("");
|
|
4079
|
+
const [error, setError] = useState17(null);
|
|
4080
|
+
const title = `Price for ${lineName}`;
|
|
4081
|
+
function apply() {
|
|
4082
|
+
const parsed = parsePrice(text, currency);
|
|
4083
|
+
const refused = typeof parsed === "string" ? parsed : onApply(parsed, reason.trim() || void 0);
|
|
4084
|
+
setError(refused);
|
|
4085
|
+
if (refused === null) onClose();
|
|
4086
|
+
}
|
|
4087
|
+
return /* @__PURE__ */ jsxs48(View55, { testID: "price-form", role: "group", accessibilityLabel: title, className: "gap-2 px-3 py-2", children: [
|
|
4088
|
+
/* @__PURE__ */ jsx89(Text33, { className: "font-semibold text-foreground", children: title }),
|
|
4089
|
+
/* @__PURE__ */ jsx89(Text33, { className: "text-muted-foreground", children: formatMoney11({ amount: currentMinor, currency }) }),
|
|
4090
|
+
/* @__PURE__ */ jsx89(
|
|
4091
|
+
TextInput10,
|
|
4092
|
+
{
|
|
4093
|
+
testID: "price-input",
|
|
4094
|
+
accessibilityLabel: "Price value",
|
|
4095
|
+
value: text,
|
|
4096
|
+
onChangeText: setText,
|
|
4097
|
+
onSubmitEditing: apply,
|
|
4098
|
+
inputMode: "decimal",
|
|
4099
|
+
placeholder: currency,
|
|
4100
|
+
className: "min-w-0 rounded-md border border-border bg-background px-3 py-2 text-foreground"
|
|
4101
|
+
}
|
|
4102
|
+
),
|
|
4103
|
+
/* @__PURE__ */ jsx89(
|
|
4104
|
+
TextInput10,
|
|
4105
|
+
{
|
|
4106
|
+
testID: "price-reason",
|
|
4107
|
+
accessibilityLabel: "Reason (optional)",
|
|
4108
|
+
placeholder: "Reason (optional)",
|
|
4109
|
+
value: reason,
|
|
4110
|
+
onChangeText: setReason,
|
|
4111
|
+
className: "min-w-0 rounded-md border border-border bg-background px-3 py-2 text-foreground"
|
|
4112
|
+
}
|
|
4113
|
+
),
|
|
4114
|
+
error ? /* @__PURE__ */ jsx89(Text33, { testID: "price-error", accessibilityRole: "alert", className: "text-destructive", children: error }) : null,
|
|
4115
|
+
/* @__PURE__ */ jsxs48(View55, { className: "flex-row gap-2", children: [
|
|
4116
|
+
/* @__PURE__ */ jsx89(Pressable24, { testID: "price-apply", accessibilityRole: "button", onPress: apply, className: `${button2} bg-primary`, children: /* @__PURE__ */ jsx89(Text33, { className: "font-semibold text-primary-foreground", children: "Apply" }) }),
|
|
4117
|
+
/* @__PURE__ */ jsx89(Pressable24, { testID: "price-cancel", accessibilityRole: "button", onPress: onClose, className: `${button2} bg-card`, children: /* @__PURE__ */ jsx89(Text33, { className: "text-foreground", children: "Cancel" }) })
|
|
4118
|
+
] })
|
|
4119
|
+
] });
|
|
4120
|
+
}
|
|
4121
|
+
|
|
4043
4122
|
// src/sale/cart.tsx
|
|
4044
|
-
import { Fragment as Fragment5, jsx as
|
|
4045
|
-
function Cart({ sale, taxLabel = (ratePpm) => `Tax ${ratePpm / 1e4}
|
|
4123
|
+
import { Fragment as Fragment5, jsx as jsx90, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
4124
|
+
function Cart({ sale, taxLabel = (ratePpm) => `Tax ${ratePpm / 1e4}%`, canEditPrice = false, onPriceChange }) {
|
|
4046
4125
|
const { order } = sale;
|
|
4047
4126
|
const money = (amount) => ({ amount, currency: order.currency });
|
|
4048
4127
|
const { totals } = buildReceiptData(order, { storeName: "" });
|
|
4049
4128
|
const taxRows = totals.taxLines.map((line) => ({ label: taxLabel(line.ratePpm), amount: money(line.amountMinor) }));
|
|
4050
4129
|
const display = (lineId) => order.display.lines.find((line) => line.lineId === lineId);
|
|
4051
4130
|
const orderAmounts = order.discounts.length === 1 ? [{ discountId: order.discounts[0].id, amountMinor: order.display.orderDiscountMinor }] : [];
|
|
4052
|
-
const [form, setForm] =
|
|
4053
|
-
const discountForm = (lineId, title) => form?.lineId === lineId ? /* @__PURE__ */
|
|
4131
|
+
const [form, setForm] = useState18(null);
|
|
4132
|
+
const discountForm = (lineId, title) => form?.type === "discount" && form.lineId === lineId ? /* @__PURE__ */ jsx90(
|
|
4054
4133
|
DiscountForm,
|
|
4055
4134
|
{
|
|
4056
4135
|
title,
|
|
@@ -4061,8 +4140,11 @@ function Cart({ sale, taxLabel = (ratePpm) => `Tax ${ratePpm / 1e4}%` }) {
|
|
|
4061
4140
|
lineId ?? "order"
|
|
4062
4141
|
) : null;
|
|
4063
4142
|
const pay = `min-h-12 flex-1 justify-center rounded-md bg-primary px-4 py-3 ${!order.lineItems.length ? "opacity-50" : ""}`;
|
|
4064
|
-
const renderItem = (line) => /* @__PURE__ */
|
|
4065
|
-
/* @__PURE__ */
|
|
4143
|
+
const renderItem = (line) => /* @__PURE__ */ jsxs49(Fragment5, { children: [
|
|
4144
|
+
/* @__PURE__ */ jsx90(CartLineActions, { actions: [
|
|
4145
|
+
{ id: "discount", label: "Discount", color: "text-primary", onPress: () => setForm({ type: "discount", lineId: line.id }) },
|
|
4146
|
+
...canEditPrice ? [{ id: "price", label: "Price", color: "text-primary", onPress: () => setForm({ type: "price", lineId: line.id }) }] : []
|
|
4147
|
+
], children: /* @__PURE__ */ jsx90(
|
|
4066
4148
|
CartLine,
|
|
4067
4149
|
{
|
|
4068
4150
|
name: line.name,
|
|
@@ -4071,50 +4153,66 @@ function Cart({ sale, taxLabel = (ratePpm) => `Tax ${ratePpm / 1e4}%` }) {
|
|
|
4071
4153
|
lineTotal: money(display(line.id).amountMinor)
|
|
4072
4154
|
}
|
|
4073
4155
|
) }),
|
|
4074
|
-
/* @__PURE__ */
|
|
4075
|
-
/* @__PURE__ */
|
|
4076
|
-
/* @__PURE__ */
|
|
4077
|
-
|
|
4156
|
+
/* @__PURE__ */ jsx90(DiscountChips, { discounts: line.discounts, amounts: display(line.id).discounts, currency: order.currency, onRemove: sale.removeDiscount }),
|
|
4157
|
+
/* @__PURE__ */ jsxs49(View56, { className: "flex-row gap-4 px-3 py-2", children: [
|
|
4158
|
+
/* @__PURE__ */ jsx90(
|
|
4159
|
+
Pressable25,
|
|
4078
4160
|
{
|
|
4079
4161
|
accessibilityRole: "button",
|
|
4080
4162
|
accessibilityLabel: `Decrease ${line.name}`,
|
|
4081
4163
|
onPress: () => sale.setQuantity(line.id, line.quantity - 1),
|
|
4082
4164
|
className: "rounded-md border border-border bg-card px-3 py-2 min-h-11 min-w-11 items-center justify-center",
|
|
4083
|
-
children: /* @__PURE__ */
|
|
4165
|
+
children: /* @__PURE__ */ jsx90(Text34, { className: "text-center text-foreground", children: "\u2212" })
|
|
4084
4166
|
}
|
|
4085
4167
|
),
|
|
4086
|
-
/* @__PURE__ */
|
|
4087
|
-
|
|
4168
|
+
/* @__PURE__ */ jsx90(
|
|
4169
|
+
Pressable25,
|
|
4088
4170
|
{
|
|
4089
4171
|
accessibilityRole: "button",
|
|
4090
4172
|
accessibilityLabel: `Increase ${line.name}`,
|
|
4091
4173
|
onPress: () => sale.setQuantity(line.id, line.quantity + 1),
|
|
4092
4174
|
className: "rounded-md border border-border bg-card px-3 py-2 min-h-11 min-w-11 items-center justify-center",
|
|
4093
|
-
children: /* @__PURE__ */
|
|
4175
|
+
children: /* @__PURE__ */ jsx90(Text34, { className: "text-center text-foreground", children: "+" })
|
|
4094
4176
|
}
|
|
4095
4177
|
),
|
|
4096
|
-
/* @__PURE__ */
|
|
4097
|
-
|
|
4178
|
+
/* @__PURE__ */ jsx90(
|
|
4179
|
+
Pressable25,
|
|
4098
4180
|
{
|
|
4099
4181
|
accessibilityRole: "button",
|
|
4100
4182
|
accessibilityLabel: `Remove ${line.name}`,
|
|
4101
4183
|
onPress: () => sale.remove(line.id),
|
|
4102
4184
|
className: "rounded-md border border-border bg-card px-3 py-2 min-h-11 min-w-11 items-center justify-center",
|
|
4103
|
-
children: /* @__PURE__ */
|
|
4185
|
+
children: /* @__PURE__ */ jsx90(Text34, { className: "text-center text-foreground", children: "Remove" })
|
|
4104
4186
|
}
|
|
4105
4187
|
)
|
|
4106
4188
|
] }),
|
|
4107
|
-
discountForm(line.id, `Discount on ${line.name}`)
|
|
4189
|
+
discountForm(line.id, `Discount on ${line.name}`),
|
|
4190
|
+
canEditPrice && form?.type === "price" && form.lineId === line.id ? /* @__PURE__ */ jsx90(
|
|
4191
|
+
PriceForm,
|
|
4192
|
+
{
|
|
4193
|
+
lineName: line.name,
|
|
4194
|
+
currency: order.currency,
|
|
4195
|
+
currentMinor: line.unitPriceMinor,
|
|
4196
|
+
onClose: () => setForm(null),
|
|
4197
|
+
onApply: (amount, reason) => {
|
|
4198
|
+
const fromMinor = line.unitPriceMinor;
|
|
4199
|
+
const refused = sale.setUnitPrice(line.id, amount);
|
|
4200
|
+
if (refused === null) onPriceChange?.({ lineId: line.id, fromMinor, toMinor: amount, reason });
|
|
4201
|
+
return refused;
|
|
4202
|
+
}
|
|
4203
|
+
},
|
|
4204
|
+
line.id
|
|
4205
|
+
) : null
|
|
4108
4206
|
] });
|
|
4109
|
-
return /* @__PURE__ */
|
|
4207
|
+
return /* @__PURE__ */ jsx90(
|
|
4110
4208
|
CartPanel,
|
|
4111
4209
|
{
|
|
4112
4210
|
dataSet: { print: "hide" },
|
|
4113
4211
|
items: order.lineItems,
|
|
4114
4212
|
renderItem,
|
|
4115
|
-
emptyState: /* @__PURE__ */
|
|
4116
|
-
afterItems: order.lineItems.length ? /* @__PURE__ */
|
|
4117
|
-
/* @__PURE__ */
|
|
4213
|
+
emptyState: /* @__PURE__ */ jsx90(Text34, { testID: "cart-empty", className: "px-3 py-2 text-muted-foreground", children: "Scan or tap a product to start a sale." }),
|
|
4214
|
+
afterItems: order.lineItems.length ? /* @__PURE__ */ jsxs49(View56, { className: "gap-3 px-3 py-2", children: [
|
|
4215
|
+
/* @__PURE__ */ jsx90(
|
|
4118
4216
|
DiscountChips,
|
|
4119
4217
|
{
|
|
4120
4218
|
discounts: order.discounts,
|
|
@@ -4124,18 +4222,18 @@ function Cart({ sale, taxLabel = (ratePpm) => `Tax ${ratePpm / 1e4}%` }) {
|
|
|
4124
4222
|
prefix: "Order discount"
|
|
4125
4223
|
}
|
|
4126
4224
|
),
|
|
4127
|
-
form?.lineId === null ? discountForm(null, "Order discount") : /* @__PURE__ */
|
|
4128
|
-
|
|
4225
|
+
form?.lineId === null ? discountForm(null, "Order discount") : /* @__PURE__ */ jsx90(
|
|
4226
|
+
Pressable25,
|
|
4129
4227
|
{
|
|
4130
4228
|
accessibilityRole: "button",
|
|
4131
|
-
onPress: () => setForm({ lineId: null }),
|
|
4229
|
+
onPress: () => setForm({ type: "discount", lineId: null }),
|
|
4132
4230
|
className: "self-start rounded-md border border-border bg-card px-4 py-2 min-h-11 justify-center",
|
|
4133
|
-
children: /* @__PURE__ */
|
|
4231
|
+
children: /* @__PURE__ */ jsx90(Text34, { className: "text-foreground", children: "Order discount" })
|
|
4134
4232
|
}
|
|
4135
4233
|
)
|
|
4136
4234
|
] }) : void 0,
|
|
4137
|
-
footer: /* @__PURE__ */
|
|
4138
|
-
/* @__PURE__ */
|
|
4235
|
+
footer: /* @__PURE__ */ jsxs49(View56, { testID: "cart-footer", className: "gap-3 pb-4", children: [
|
|
4236
|
+
/* @__PURE__ */ jsx90(
|
|
4139
4237
|
CartTotal,
|
|
4140
4238
|
{
|
|
4141
4239
|
subtotal: money(totals.subtotalMinor),
|
|
@@ -4145,10 +4243,10 @@ function Cart({ sale, taxLabel = (ratePpm) => `Tax ${ratePpm / 1e4}%` }) {
|
|
|
4145
4243
|
taxInclusive: totals.taxInclusive
|
|
4146
4244
|
}
|
|
4147
4245
|
),
|
|
4148
|
-
sale.error ? /* @__PURE__ */
|
|
4149
|
-
/* @__PURE__ */
|
|
4150
|
-
/* @__PURE__ */
|
|
4151
|
-
/* @__PURE__ */
|
|
4246
|
+
sale.error ? /* @__PURE__ */ jsx90(Text34, { accessibilityRole: "alert", className: "text-destructive", children: sale.error }) : null,
|
|
4247
|
+
/* @__PURE__ */ jsxs49(View56, { className: "flex-row gap-3", children: [
|
|
4248
|
+
/* @__PURE__ */ jsx90(Pressable25, { accessibilityRole: "button", disabled: !order.lineItems.length, onPress: () => sale.startTender("cash"), className: pay, children: /* @__PURE__ */ jsx90(Text34, { className: "text-center font-semibold text-primary-foreground", children: "Cash" }) }),
|
|
4249
|
+
/* @__PURE__ */ jsx90(Pressable25, { accessibilityRole: "button", disabled: !order.lineItems.length, onPress: () => sale.startTender("external"), className: pay, children: /* @__PURE__ */ jsx90(Text34, { className: "text-center font-semibold text-primary-foreground", children: "Card terminal" }) })
|
|
4152
4250
|
] })
|
|
4153
4251
|
] })
|
|
4154
4252
|
}
|
|
@@ -4156,17 +4254,17 @@ function Cart({ sale, taxLabel = (ratePpm) => `Tax ${ratePpm / 1e4}%` }) {
|
|
|
4156
4254
|
}
|
|
4157
4255
|
|
|
4158
4256
|
// src/sale/cart-bar.tsx
|
|
4159
|
-
import { Pressable as
|
|
4160
|
-
import { formatMoney as
|
|
4257
|
+
import { Pressable as Pressable26, Text as Text35 } from "react-native";
|
|
4258
|
+
import { formatMoney as formatMoney12 } from "@tallyui/core";
|
|
4161
4259
|
import { buildReceiptData as buildReceiptData2 } from "@tallyui/pos";
|
|
4162
|
-
import { jsx as
|
|
4260
|
+
import { jsx as jsx91, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
4163
4261
|
function CartBar({ sale, onOpen }) {
|
|
4164
4262
|
const { order } = sale;
|
|
4165
4263
|
const count2 = order.lineItems.reduce((sum, line) => sum + line.quantity, 0);
|
|
4166
|
-
const total =
|
|
4264
|
+
const total = formatMoney12({ amount: buildReceiptData2(order, { storeName: "" }).totals.totalMinor, currency: order.currency });
|
|
4167
4265
|
const items = `${count2} ${count2 === 1 ? "item" : "items"}`;
|
|
4168
|
-
return /* @__PURE__ */
|
|
4169
|
-
|
|
4266
|
+
return /* @__PURE__ */ jsxs50(
|
|
4267
|
+
Pressable26,
|
|
4170
4268
|
{
|
|
4171
4269
|
accessibilityRole: "button",
|
|
4172
4270
|
accessibilityLabel: count2 ? `Open cart, ${items}, ${total}` : "Cart is empty",
|
|
@@ -4174,8 +4272,8 @@ function CartBar({ sale, onOpen }) {
|
|
|
4174
4272
|
onPress: onOpen,
|
|
4175
4273
|
className: `min-h-14 mx-3 mb-3 flex-row items-center justify-between rounded-md bg-primary px-4 py-3 ${count2 ? "" : "opacity-50"}`,
|
|
4176
4274
|
children: [
|
|
4177
|
-
/* @__PURE__ */
|
|
4178
|
-
count2 ? /* @__PURE__ */
|
|
4275
|
+
/* @__PURE__ */ jsx91(Text35, { className: "font-bold text-primary-foreground", children: count2 ? `Cart \xB7 ${items}` : "Cart is empty" }),
|
|
4276
|
+
count2 ? /* @__PURE__ */ jsxs50(Text35, { className: "font-bold text-primary-foreground", children: [
|
|
4179
4277
|
total,
|
|
4180
4278
|
" \u203A"
|
|
4181
4279
|
] }) : null
|
|
@@ -4185,17 +4283,17 @@ function CartBar({ sale, onOpen }) {
|
|
|
4185
4283
|
}
|
|
4186
4284
|
|
|
4187
4285
|
// src/sale/tender.tsx
|
|
4188
|
-
import { Pressable as
|
|
4189
|
-
import { formatMoney as
|
|
4190
|
-
import { Fragment as Fragment6, jsx as
|
|
4286
|
+
import { Pressable as Pressable27, Text as Text36, TextInput as TextInput11, View as View57 } from "react-native";
|
|
4287
|
+
import { formatMoney as formatMoney13 } from "@tallyui/core";
|
|
4288
|
+
import { Fragment as Fragment6, jsx as jsx92, jsxs as jsxs51 } from "react/jsx-runtime";
|
|
4191
4289
|
var REFERENCE_MAX = 255;
|
|
4192
4290
|
function Tender({ sale }) {
|
|
4193
4291
|
const { order, stage } = sale;
|
|
4194
4292
|
if (stage.kind !== "tender") return null;
|
|
4195
4293
|
const money = (amount) => ({ amount, currency: order.currency });
|
|
4196
|
-
return /* @__PURE__ */
|
|
4197
|
-
stage.method === "cash" ? /* @__PURE__ */
|
|
4198
|
-
/* @__PURE__ */
|
|
4294
|
+
return /* @__PURE__ */ jsxs51(View57, { dataSet: { print: "hide" }, className: "gap-4 p-4", children: [
|
|
4295
|
+
stage.method === "cash" ? /* @__PURE__ */ jsxs51(Fragment6, { children: [
|
|
4296
|
+
/* @__PURE__ */ jsx92(
|
|
4199
4297
|
CashTendered,
|
|
4200
4298
|
{
|
|
4201
4299
|
total: money(order.totalMinor),
|
|
@@ -4203,19 +4301,19 @@ function Tender({ sale }) {
|
|
|
4203
4301
|
onChangeAmount: (amount) => sale.setTender({ method: "cash", amountMinor: amount.amount })
|
|
4204
4302
|
}
|
|
4205
4303
|
),
|
|
4206
|
-
/* @__PURE__ */
|
|
4207
|
-
order.balanceDueMinor > 0 ? /* @__PURE__ */
|
|
4304
|
+
/* @__PURE__ */ jsx92(ChangeDisplay, { change: money(order.changeDueMinor) }),
|
|
4305
|
+
order.balanceDueMinor > 0 ? /* @__PURE__ */ jsxs51(Text36, { className: "text-foreground", children: [
|
|
4208
4306
|
"Balance due: ",
|
|
4209
|
-
|
|
4307
|
+
formatMoney13(money(order.balanceDueMinor))
|
|
4210
4308
|
] }) : null,
|
|
4211
|
-
/* @__PURE__ */
|
|
4212
|
-
] }) : /* @__PURE__ */
|
|
4213
|
-
/* @__PURE__ */
|
|
4309
|
+
/* @__PURE__ */ jsx92(Pressable27, { accessibilityRole: "button", disabled: order.balanceDueMinor > 0, onPress: sale.complete, className: `rounded-md bg-primary px-4 py-3 ${order.balanceDueMinor > 0 ? "opacity-50" : ""}`, children: /* @__PURE__ */ jsx92(Text36, { className: "text-center font-semibold text-primary-foreground", children: "Complete sale" }) })
|
|
4310
|
+
] }) : /* @__PURE__ */ jsxs51(Fragment6, { children: [
|
|
4311
|
+
/* @__PURE__ */ jsxs51(Text36, { className: "text-foreground", children: [
|
|
4214
4312
|
"Card terminal: ",
|
|
4215
|
-
|
|
4313
|
+
formatMoney13(money(order.totalMinor))
|
|
4216
4314
|
] }),
|
|
4217
|
-
/* @__PURE__ */
|
|
4218
|
-
|
|
4315
|
+
/* @__PURE__ */ jsx92(
|
|
4316
|
+
TextInput11,
|
|
4219
4317
|
{
|
|
4220
4318
|
accessibilityLabel: "Terminal reference",
|
|
4221
4319
|
placeholder: "Terminal reference",
|
|
@@ -4225,23 +4323,23 @@ function Tender({ sale }) {
|
|
|
4225
4323
|
className: "rounded-md border border-border px-3 py-2 text-foreground"
|
|
4226
4324
|
}
|
|
4227
4325
|
),
|
|
4228
|
-
/* @__PURE__ */
|
|
4326
|
+
/* @__PURE__ */ jsx92(Pressable27, { accessibilityRole: "button", onPress: sale.complete, className: "rounded-md bg-primary px-4 py-3", children: /* @__PURE__ */ jsx92(Text36, { className: "text-center font-semibold text-primary-foreground", children: "Payment approved on terminal" }) })
|
|
4229
4327
|
] }),
|
|
4230
|
-
sale.error ? /* @__PURE__ */
|
|
4231
|
-
sale.canContinue ? /* @__PURE__ */
|
|
4232
|
-
/* @__PURE__ */
|
|
4233
|
-
/* @__PURE__ */
|
|
4328
|
+
sale.error ? /* @__PURE__ */ jsx92(Text36, { accessibilityRole: "alert", className: "text-destructive", children: sale.error }) : null,
|
|
4329
|
+
sale.canContinue ? /* @__PURE__ */ jsxs51(Fragment6, { children: [
|
|
4330
|
+
/* @__PURE__ */ jsx92(Text36, { className: "text-foreground", children: "This sale is stored and will be sent. Continue to the next sale." }),
|
|
4331
|
+
/* @__PURE__ */ jsx92(Pressable27, { accessibilityRole: "button", onPress: () => sale.continueSale(), className: "rounded-md bg-primary px-4 py-3", children: /* @__PURE__ */ jsx92(Text36, { className: "text-center font-semibold text-primary-foreground", children: "Continue" }) })
|
|
4234
4332
|
] }) : null,
|
|
4235
|
-
/* @__PURE__ */
|
|
4333
|
+
/* @__PURE__ */ jsx92(Pressable27, { accessibilityRole: "button", onPress: sale.cancelTender, className: "rounded-md border border-border bg-card px-4 py-3", children: /* @__PURE__ */ jsx92(Text36, { className: "text-center text-foreground", children: "Back" }) })
|
|
4236
4334
|
] });
|
|
4237
4335
|
}
|
|
4238
4336
|
|
|
4239
4337
|
// src/sale/catalogue.tsx
|
|
4240
|
-
import { useEffect as useEffect5, useMemo as useMemo2, useState as
|
|
4241
|
-
import { Pressable as
|
|
4338
|
+
import { useEffect as useEffect5, useMemo as useMemo2, useState as useState19 } from "react";
|
|
4339
|
+
import { Pressable as Pressable28, Text as Text37, View as View58 } from "react-native";
|
|
4242
4340
|
import { useStockOverlaid, useStockOverlayAsOf } from "@tallyui/core";
|
|
4243
4341
|
import { catalogueEntries, findEntryByCode, searchProducts, variantPriceLabel } from "@tallyui/pos";
|
|
4244
|
-
import { jsx as
|
|
4342
|
+
import { jsx as jsx93, jsxs as jsxs52 } from "react/jsx-runtime";
|
|
4245
4343
|
var MIN_TILE_WIDTH = 160;
|
|
4246
4344
|
var STOCK_LABEL = {
|
|
4247
4345
|
in_stock: "In Stock",
|
|
@@ -4267,9 +4365,9 @@ function Catalogue({ products, traits, currency, onSelect, statusText, statusAcc
|
|
|
4267
4365
|
const parsedOverlayAsOf = overlayAsOf ? new Date(overlayAsOf) : void 0;
|
|
4268
4366
|
const validOverlayAsOf = parsedOverlayAsOf && !isNaN(parsedOverlayAsOf.getTime()) ? parsedOverlayAsOf : void 0;
|
|
4269
4367
|
const stockAsOf = laterOf(laterOf(lastStockCheckAt, validOverlayAsOf), lastSyncedAt);
|
|
4270
|
-
const [query, setQuery] =
|
|
4271
|
-
const [chooserId, setChooserId] =
|
|
4272
|
-
const [width, setWidth] =
|
|
4368
|
+
const [query, setQuery] = useState19("");
|
|
4369
|
+
const [chooserId, setChooserId] = useState19(null);
|
|
4370
|
+
const [width, setWidth] = useState19(0);
|
|
4273
4371
|
const columns = Math.max(2, Math.min(6, Math.floor((width - 8) / (MIN_TILE_WIDTH + 8))));
|
|
4274
4372
|
const entries = useMemo2(() => catalogueEntries(shown, traits, { currency }), [shown, traits, currency]);
|
|
4275
4373
|
const results = useMemo2(() => searchProducts(shown, query, traits), [shown, query, traits]);
|
|
@@ -4281,9 +4379,9 @@ function Catalogue({ products, traits, currency, onSelect, statusText, statusAcc
|
|
|
4281
4379
|
onSelect(entry);
|
|
4282
4380
|
setChooserId(null);
|
|
4283
4381
|
}
|
|
4284
|
-
return /* @__PURE__ */
|
|
4285
|
-
/* @__PURE__ */
|
|
4286
|
-
/* @__PURE__ */
|
|
4382
|
+
return /* @__PURE__ */ jsxs52(View58, { className: "flex-1", onLayout: (event) => setWidth(event.nativeEvent.layout.width), children: [
|
|
4383
|
+
/* @__PURE__ */ jsxs52(View58, { className: "gap-2 border-b border-border bg-card px-4 pb-3 pt-3", children: [
|
|
4384
|
+
/* @__PURE__ */ jsx93(
|
|
4287
4385
|
SearchInput,
|
|
4288
4386
|
{
|
|
4289
4387
|
value: query,
|
|
@@ -4300,25 +4398,25 @@ function Catalogue({ products, traits, currency, onSelect, statusText, statusAcc
|
|
|
4300
4398
|
}
|
|
4301
4399
|
}
|
|
4302
4400
|
),
|
|
4303
|
-
statusText || statusAccessory ? /* @__PURE__ */
|
|
4304
|
-
statusText ? /* @__PURE__ */
|
|
4401
|
+
statusText || statusAccessory ? /* @__PURE__ */ jsxs52(View58, { testID: "catalogue-status-row", className: "flex-row items-center gap-2", children: [
|
|
4402
|
+
statusText ? /* @__PURE__ */ jsxs52(Text37, { className: "flex-1 text-xs text-muted-foreground", numberOfLines: statusAccessory ? 1 : void 0, children: [
|
|
4305
4403
|
statusText,
|
|
4306
4404
|
query.trim() ? ` \xB7 ${results.length.toLocaleString()} matching` : ""
|
|
4307
4405
|
] }) : null,
|
|
4308
4406
|
statusAccessory
|
|
4309
4407
|
] }) : null,
|
|
4310
|
-
choices.length > 0 ? /* @__PURE__ */
|
|
4311
|
-
choices.map((entry) => /* @__PURE__ */
|
|
4312
|
-
|
|
4408
|
+
choices.length > 0 ? /* @__PURE__ */ jsxs52(View58, { accessibilityLabel: "Choose variant", className: "gap-2", children: [
|
|
4409
|
+
choices.map((entry) => /* @__PURE__ */ jsxs52(
|
|
4410
|
+
Pressable28,
|
|
4313
4411
|
{
|
|
4314
4412
|
accessibilityRole: "button",
|
|
4315
4413
|
onPress: () => select(entry),
|
|
4316
4414
|
className: "gap-1 rounded-md border border-border p-3",
|
|
4317
4415
|
children: [
|
|
4318
|
-
/* @__PURE__ */
|
|
4319
|
-
/* @__PURE__ */
|
|
4320
|
-
/* @__PURE__ */
|
|
4321
|
-
/* @__PURE__ */
|
|
4416
|
+
/* @__PURE__ */ jsx93(Text37, { className: "font-semibold text-foreground", children: entry.variant.title }),
|
|
4417
|
+
/* @__PURE__ */ jsx93(Text37, { className: "text-muted-foreground", children: entry.variant.sku }),
|
|
4418
|
+
/* @__PURE__ */ jsx93(Text37, { className: "text-foreground", children: variantPriceLabel(entry.variant, currency) }),
|
|
4419
|
+
/* @__PURE__ */ jsxs52(Text37, { className: "text-muted-foreground", children: [
|
|
4322
4420
|
STOCK_LABEL[entry.variant.stock.status],
|
|
4323
4421
|
" \xB7 ",
|
|
4324
4422
|
stockAsOf ? `as of ${formatStockSyncTime(stockAsOf, void 0, hour12)}` : "not yet synced"
|
|
@@ -4327,10 +4425,10 @@ function Catalogue({ products, traits, currency, onSelect, statusText, statusAcc
|
|
|
4327
4425
|
},
|
|
4328
4426
|
entry.variant.id
|
|
4329
4427
|
)),
|
|
4330
|
-
/* @__PURE__ */
|
|
4428
|
+
/* @__PURE__ */ jsx93(Pressable28, { accessibilityRole: "button", onPress: () => setChooserId(null), className: "rounded-md border border-border bg-card px-4 py-3", children: /* @__PURE__ */ jsx93(Text37, { className: "text-center text-foreground", children: "Cancel" }) })
|
|
4331
4429
|
] }) : null
|
|
4332
4430
|
] }),
|
|
4333
|
-
/* @__PURE__ */
|
|
4431
|
+
/* @__PURE__ */ jsx93(
|
|
4334
4432
|
ProductGrid,
|
|
4335
4433
|
{
|
|
4336
4434
|
items: results,
|
|
@@ -4339,18 +4437,18 @@ function Catalogue({ products, traits, currency, onSelect, statusText, statusAcc
|
|
|
4339
4437
|
// TallyUI's ProductCard has no children slot, so the tile is composed directly here
|
|
4340
4438
|
// (same structure/classes as ProductCard) to add the stock badge as a fourth child,
|
|
4341
4439
|
// inside the card and centred with the rest, rather than adding a slot to ProductCard (out of scope for TV6b).
|
|
4342
|
-
/* @__PURE__ */
|
|
4440
|
+
/* @__PURE__ */ jsx93(Pressable28, { accessibilityRole: "button", testID: `product-tile-${traits.getName(product)}`, onPress: () => {
|
|
4343
4441
|
const variants = entries.filter((entry) => entry.product === product);
|
|
4344
4442
|
if (variants.length === 1) select(variants[0]);
|
|
4345
4443
|
else setChooserId(traits.getId(product));
|
|
4346
|
-
}, children: /* @__PURE__ */
|
|
4347
|
-
/* @__PURE__ */
|
|
4348
|
-
/* @__PURE__ */
|
|
4349
|
-
/* @__PURE__ */
|
|
4350
|
-
/* @__PURE__ */
|
|
4444
|
+
}, children: /* @__PURE__ */ jsxs52(VStack, { space: "sm", className: "items-center rounded-lg border border-border bg-card p-3", children: [
|
|
4445
|
+
/* @__PURE__ */ jsx93(ProductImage, { doc: product, size: 80, className: "rounded-md" }),
|
|
4446
|
+
/* @__PURE__ */ jsx93(ProductTitle, { doc: product, className: "text-sm", numberOfLines: 2 }),
|
|
4447
|
+
/* @__PURE__ */ jsx93(ProductPrice, { doc: product }),
|
|
4448
|
+
/* @__PURE__ */ jsx93(ProductStockBadge, { doc: product, showAsOf: false, className: "self-center" })
|
|
4351
4449
|
] }) })
|
|
4352
4450
|
),
|
|
4353
|
-
emptyState: /* @__PURE__ */
|
|
4451
|
+
emptyState: /* @__PURE__ */ jsx93(Text37, { className: "mt-10 text-center text-sm text-muted-foreground", children: query.trim() ? `No products match "${query.trim()}".` : isLoading ? "Loading products\u2026" : "No products yet." })
|
|
4354
4452
|
}
|
|
4355
4453
|
)
|
|
4356
4454
|
] });
|
|
@@ -4358,8 +4456,8 @@ function Catalogue({ products, traits, currency, onSelect, statusText, statusAcc
|
|
|
4358
4456
|
|
|
4359
4457
|
// src/sale/receipt.tsx
|
|
4360
4458
|
import { useEffect as useEffect6 } from "react";
|
|
4361
|
-
import { Pressable as
|
|
4362
|
-
import { formatMoney as
|
|
4459
|
+
import { Pressable as Pressable29, Text as Text38, View as View59 } from "react-native";
|
|
4460
|
+
import { formatMoney as formatMoney14 } from "@tallyui/core";
|
|
4363
4461
|
import { buildReceiptData as buildReceiptData3 } from "@tallyui/pos";
|
|
4364
4462
|
|
|
4365
4463
|
// src/sale/print-style.ts
|
|
@@ -4379,7 +4477,7 @@ function orderReference(order) {
|
|
|
4379
4477
|
}
|
|
4380
4478
|
|
|
4381
4479
|
// src/sale/receipt.tsx
|
|
4382
|
-
import { Fragment as Fragment7, jsx as
|
|
4480
|
+
import { Fragment as Fragment7, jsx as jsx94, jsxs as jsxs53 } from "react/jsx-runtime";
|
|
4383
4481
|
var defaultFormatDate = (iso) => new Intl.DateTimeFormat(void 0, { dateStyle: "medium", timeStyle: "short" }).format(new Date(iso));
|
|
4384
4482
|
function Receipt({
|
|
4385
4483
|
order,
|
|
@@ -4399,33 +4497,33 @@ function Receipt({
|
|
|
4399
4497
|
cashier,
|
|
4400
4498
|
register: registerId
|
|
4401
4499
|
});
|
|
4402
|
-
const money = (amount) =>
|
|
4403
|
-
const row = (label, amount, bold = false, key) => /* @__PURE__ */
|
|
4404
|
-
/* @__PURE__ */
|
|
4405
|
-
/* @__PURE__ */
|
|
4500
|
+
const money = (amount) => formatMoney14({ amount, currency: receipt.currency }) ?? "";
|
|
4501
|
+
const row = (label, amount, bold = false, key) => /* @__PURE__ */ jsxs53(View59, { accessibilityLabel: `${label}: ${amount}`, className: "flex-row justify-between gap-4", children: [
|
|
4502
|
+
/* @__PURE__ */ jsx94(Text38, { className: `text-foreground ${bold ? "font-semibold" : ""}`, children: label }),
|
|
4503
|
+
/* @__PURE__ */ jsx94(Text38, { className: `text-right text-foreground ${bold ? "font-semibold" : ""}`, children: amount })
|
|
4406
4504
|
] }, key);
|
|
4407
4505
|
const { totals } = receipt;
|
|
4408
4506
|
const lineDiscountMinor = totals.discountMinor - receipt.orderDiscountMinor;
|
|
4409
4507
|
const taxRows = totals.taxLines.map((line, index) => row(`${totals.taxInclusive ? "incl. " : ""}${taxLabel(line.ratePpm)}`, money(line.amountMinor), false, index));
|
|
4410
|
-
return /* @__PURE__ */
|
|
4411
|
-
topInset > 0 ? /* @__PURE__ */
|
|
4412
|
-
/* @__PURE__ */
|
|
4413
|
-
/* @__PURE__ */
|
|
4414
|
-
receipt.header.storeAddress ? /* @__PURE__ */
|
|
4415
|
-
/* @__PURE__ */
|
|
4416
|
-
/* @__PURE__ */
|
|
4417
|
-
/* @__PURE__ */
|
|
4508
|
+
return /* @__PURE__ */ jsxs53(Fragment7, { children: [
|
|
4509
|
+
topInset > 0 ? /* @__PURE__ */ jsx94(View59, { dataSet: { print: "hide" }, style: { height: topInset, flexShrink: 0 } }) : null,
|
|
4510
|
+
/* @__PURE__ */ jsxs53(View59, { className: "w-full max-w-md self-center gap-3 p-4 bg-card", children: [
|
|
4511
|
+
/* @__PURE__ */ jsx94(Text38, { className: "text-lg font-semibold text-foreground", children: receipt.header.storeName }),
|
|
4512
|
+
receipt.header.storeAddress ? /* @__PURE__ */ jsx94(Text38, { className: "text-muted-foreground", children: receipt.header.storeAddress }) : null,
|
|
4513
|
+
/* @__PURE__ */ jsx94(Text38, { testID: "receipt-order", className: "text-foreground", children: posOrder ? `Order ${orderReference(posOrder)}` : `Order ${receipt.header.orderNumber.slice(-8)} (draft)` }),
|
|
4514
|
+
/* @__PURE__ */ jsx94(Text38, { className: "text-muted-foreground", children: formatDate(posOrder?.createdAt ?? receipt.header.date) }),
|
|
4515
|
+
/* @__PURE__ */ jsxs53(Text38, { className: "text-muted-foreground", children: [
|
|
4418
4516
|
"Cashier: ",
|
|
4419
4517
|
receipt.header.cashier
|
|
4420
4518
|
] }),
|
|
4421
|
-
receipt.header.customer && /* @__PURE__ */
|
|
4519
|
+
receipt.header.customer && /* @__PURE__ */ jsxs53(Text38, { className: "text-muted-foreground", children: [
|
|
4422
4520
|
"Customer: ",
|
|
4423
4521
|
receipt.header.customer
|
|
4424
4522
|
] }),
|
|
4425
|
-
receipt.lineItems.map((line, index) => /* @__PURE__ */
|
|
4426
|
-
/* @__PURE__ */
|
|
4523
|
+
receipt.lineItems.map((line, index) => /* @__PURE__ */ jsxs53(View59, { children: [
|
|
4524
|
+
/* @__PURE__ */ jsx94(Text38, { className: "text-foreground", children: line.name }),
|
|
4427
4525
|
row(`${line.quantity} \xD7 ${money(line.unitPriceMinor)}`, money(line.displayAmountMinor)),
|
|
4428
|
-
line.displayDiscounts.map((discount, i) => /* @__PURE__ */
|
|
4526
|
+
line.displayDiscounts.map((discount, i) => /* @__PURE__ */ jsx94(View59, { className: "pl-4", children: row(`${discountLabel(
|
|
4429
4527
|
order.lineItems[index].discounts[i],
|
|
4430
4528
|
receipt.currency
|
|
4431
4529
|
)} off`, `\u2212${money(discount.amountMinor)}`) }, i))
|
|
@@ -4442,19 +4540,19 @@ function Receipt({
|
|
|
4442
4540
|
index
|
|
4443
4541
|
)),
|
|
4444
4542
|
row("Change", money(receipt.changeDueMinor)),
|
|
4445
|
-
/* @__PURE__ */
|
|
4446
|
-
/* @__PURE__ */
|
|
4543
|
+
/* @__PURE__ */ jsxs53(View59, { dataSet: { print: "hide" }, className: "flex-row gap-4", children: [
|
|
4544
|
+
/* @__PURE__ */ jsx94(Pressable29, { accessibilityRole: "button", onPress: () => {
|
|
4447
4545
|
if (typeof window !== "undefined" && typeof window.print === "function") window.print();
|
|
4448
|
-
}, className: "rounded-md border border-border bg-card px-4 py-3", children: /* @__PURE__ */
|
|
4449
|
-
/* @__PURE__ */
|
|
4546
|
+
}, className: "rounded-md border border-border bg-card px-4 py-3", children: /* @__PURE__ */ jsx94(Text38, { className: "text-center text-foreground", children: "Print receipt" }) }),
|
|
4547
|
+
/* @__PURE__ */ jsx94(Pressable29, { accessibilityRole: "button", onPress: newSale, className: "rounded-md bg-primary px-4 py-3", children: /* @__PURE__ */ jsx94(Text38, { className: "text-center font-semibold text-primary-foreground", children: "New sale" }) })
|
|
4450
4548
|
] })
|
|
4451
4549
|
] })
|
|
4452
4550
|
] });
|
|
4453
4551
|
}
|
|
4454
4552
|
|
|
4455
4553
|
// src/sale/sync-status.tsx
|
|
4456
|
-
import { useEffect as useEffect7, useRef as useRef6, useState as
|
|
4457
|
-
import { AccessibilityInfo as AccessibilityInfo2, Platform as Platform3, Text as
|
|
4554
|
+
import { useEffect as useEffect7, useRef as useRef6, useState as useState20 } from "react";
|
|
4555
|
+
import { AccessibilityInfo as AccessibilityInfo2, Platform as Platform3, Text as Text39, View as View60 } from "react-native";
|
|
4458
4556
|
|
|
4459
4557
|
// src/sale/since-text.ts
|
|
4460
4558
|
function sinceText(clock) {
|
|
@@ -4463,7 +4561,7 @@ function sinceText(clock) {
|
|
|
4463
4561
|
}
|
|
4464
4562
|
|
|
4465
4563
|
// src/sale/sync-status.tsx
|
|
4466
|
-
import { Fragment as Fragment8, jsx as
|
|
4564
|
+
import { Fragment as Fragment8, jsx as jsx95, jsxs as jsxs54 } from "react/jsx-runtime";
|
|
4467
4565
|
var PULL_NOTICE_TEXT = {
|
|
4468
4566
|
unauthorized: {
|
|
4469
4567
|
line: () => "Products aren't updating: this till needs to sign in to the online store again.",
|
|
@@ -4515,7 +4613,7 @@ function useAnnounceOnIos(...texts) {
|
|
|
4515
4613
|
function SyncStatus({ state, registerState, pluginName = "the POS plugin", pullNotice }) {
|
|
4516
4614
|
const updates = registerState?.pending ?? 0;
|
|
4517
4615
|
const outbox = state.pending === 0 && registerState?.pending ? registerState : state;
|
|
4518
|
-
const [now, setNow] =
|
|
4616
|
+
const [now, setNow] = useState20(Date.now);
|
|
4519
4617
|
useEffect7(() => {
|
|
4520
4618
|
setNow(Date.now());
|
|
4521
4619
|
if (!outbox.nextAttemptAt) return;
|
|
@@ -4539,24 +4637,24 @@ function SyncStatus({ state, registerState, pluginName = "the POS plugin", pullN
|
|
|
4539
4637
|
const notice = pullNotice && text && { line: text.line(pluginName), detail: text.detail(pullNotice, pluginName) };
|
|
4540
4638
|
useAnnounceOnIos(notice?.line, spoken);
|
|
4541
4639
|
const oneDetail = pullNotice?.code === "missing_plugin" && !!backendMissing;
|
|
4542
|
-
return /* @__PURE__ */
|
|
4543
|
-
notice ? /* @__PURE__ */
|
|
4544
|
-
/* @__PURE__ */
|
|
4545
|
-
oneDetail ? null : /* @__PURE__ */
|
|
4640
|
+
return /* @__PURE__ */ jsxs54(View60, { children: [
|
|
4641
|
+
notice ? /* @__PURE__ */ jsxs54(Fragment8, { children: [
|
|
4642
|
+
/* @__PURE__ */ jsx95(Text39, { accessibilityLiveRegion: "polite", className: "px-4 py-2 text-xs text-muted-foreground", children: notice.line }),
|
|
4643
|
+
oneDetail ? null : /* @__PURE__ */ jsx95(Text39, { className: "px-4 pb-2 text-xs text-muted-foreground", children: notice.detail })
|
|
4546
4644
|
] }) : null,
|
|
4547
|
-
/* @__PURE__ */
|
|
4548
|
-
doing ? /* @__PURE__ */
|
|
4549
|
-
refused ? /* @__PURE__ */
|
|
4550
|
-
oneDetail && notice ? /* @__PURE__ */
|
|
4645
|
+
/* @__PURE__ */ jsx95(Text39, { accessibilityLabel: spoken, accessibilityLiveRegion: "polite", className: "px-4 py-2 text-xs text-muted-foreground", children: spoken }),
|
|
4646
|
+
doing ? /* @__PURE__ */ jsx95(Text39, { className: "px-4 pb-2 text-xs text-muted-foreground", children: doing }) : null,
|
|
4647
|
+
refused ? /* @__PURE__ */ jsx95(Text39, { className: "px-4 pb-2 text-xs text-muted-foreground", children: REFUSED_DETAIL }) : null,
|
|
4648
|
+
oneDetail && notice ? /* @__PURE__ */ jsx95(Text39, { className: "px-4 pb-2 text-xs text-muted-foreground", children: notice.detail }) : backendMissing ? /* @__PURE__ */ jsx95(Text39, { className: "px-4 pb-2 text-xs text-muted-foreground", children: BACKEND_MISSING_DETAIL.replace("{pluginName}", () => pluginName).replace("{lastTime}", () => upToDate ? " the last time it checked" : "") }) : null
|
|
4551
4649
|
] });
|
|
4552
4650
|
}
|
|
4553
4651
|
|
|
4554
4652
|
// src/sale/orders-list.tsx
|
|
4555
|
-
import { useEffect as useEffect8, useRef as useRef7, useState as
|
|
4556
|
-
import { Pressable as
|
|
4557
|
-
import { formatMoney as
|
|
4653
|
+
import { useEffect as useEffect8, useRef as useRef7, useState as useState21 } from "react";
|
|
4654
|
+
import { Pressable as Pressable30, ScrollView as ScrollView13, Text as Text40, View as View61 } from "react-native";
|
|
4655
|
+
import { formatMoney as formatMoney15, knownWarnings } from "@tallyui/core";
|
|
4558
4656
|
import { needsAttention } from "@tallyui/pos";
|
|
4559
|
-
import { jsx as
|
|
4657
|
+
import { jsx as jsx96, jsxs as jsxs55 } from "react/jsx-runtime";
|
|
4560
4658
|
var STATUS_LABEL = { pending: "Waiting to sync", applied: "Synced", rejected: "Not accepted" };
|
|
4561
4659
|
var FIGURE_LABELS = /* @__PURE__ */ new Map([["subtotalMinor", "Subtotal"], ["taxMinor", "Tax"], ["discountMinor", "Discount"]]);
|
|
4562
4660
|
var REFUSAL_SENTENCES = /* @__PURE__ */ new Map([
|
|
@@ -4580,26 +4678,26 @@ function defaultFormatDate2(iso) {
|
|
|
4580
4678
|
}
|
|
4581
4679
|
function OrdersList({ orders, onRetry, formatDate = defaultFormatDate2, footer, stuck }) {
|
|
4582
4680
|
const retrying = useRef7(/* @__PURE__ */ new Set());
|
|
4583
|
-
const [retryingIds, setRetryingIds] =
|
|
4584
|
-
const [expanded, setExpanded] =
|
|
4681
|
+
const [retryingIds, setRetryingIds] = useState21(/* @__PURE__ */ new Set());
|
|
4682
|
+
const [expanded, setExpanded] = useState21(/* @__PURE__ */ new Set());
|
|
4585
4683
|
useEffect8(() => {
|
|
4586
4684
|
for (const id of retrying.current) {
|
|
4587
4685
|
if (!orders.some((order) => order.id === id && order.syncStatus === "rejected")) retrying.current.delete(id);
|
|
4588
4686
|
}
|
|
4589
4687
|
setRetryingIds(new Set(retrying.current));
|
|
4590
4688
|
}, [orders]);
|
|
4591
|
-
return /* @__PURE__ */
|
|
4592
|
-
[{ title: "Needs attention", orders: needsAttention(orders, { stuckCommandIds: stuck?.commandIds }) }, { title: "Recent", orders }].filter((section) => section.title === "Recent" || section.orders.length > 0).map((section) => /* @__PURE__ */
|
|
4593
|
-
/* @__PURE__ */
|
|
4594
|
-
section.title === "Recent" && orders.length === 0 ? /* @__PURE__ */
|
|
4689
|
+
return /* @__PURE__ */ jsxs55(ScrollView13, { className: "flex-1 bg-background p-4", children: [
|
|
4690
|
+
[{ title: "Needs attention", orders: needsAttention(orders, { stuckCommandIds: stuck?.commandIds }) }, { title: "Recent", orders }].filter((section) => section.title === "Recent" || section.orders.length > 0).map((section) => /* @__PURE__ */ jsxs55(View61, { className: "mb-6 gap-3", children: [
|
|
4691
|
+
/* @__PURE__ */ jsx96(Text40, { accessibilityRole: "header", className: "text-xl font-semibold text-foreground", children: section.title }),
|
|
4692
|
+
section.title === "Recent" && orders.length === 0 ? /* @__PURE__ */ jsx96(Text40, { testID: "orders-empty", className: "text-muted-foreground", children: "No sales yet. Completed sales appear here." }) : null,
|
|
4595
4693
|
section.orders.map((order) => {
|
|
4596
4694
|
const count2 = order.lines.reduce((sum, line) => sum + line.quantity, 0);
|
|
4597
4695
|
const key = `${section.title}:${order.id}`;
|
|
4598
4696
|
const isExpanded = expanded.has(key);
|
|
4599
4697
|
const stuckEntry = order.syncStatus === "pending" ? stuck?.orders.find((entry) => entry.commandId === order.commandId) : void 0;
|
|
4600
|
-
return /* @__PURE__ */
|
|
4601
|
-
/* @__PURE__ */
|
|
4602
|
-
|
|
4698
|
+
return /* @__PURE__ */ jsxs55(View61, { className: "gap-1 rounded-md border border-border bg-card p-3", children: [
|
|
4699
|
+
/* @__PURE__ */ jsxs55(
|
|
4700
|
+
Pressable30,
|
|
4603
4701
|
{
|
|
4604
4702
|
accessibilityRole: "button",
|
|
4605
4703
|
"aria-expanded": isExpanded,
|
|
@@ -4613,26 +4711,26 @@ function OrdersList({ orders, onRetry, formatDate = defaultFormatDate2, footer,
|
|
|
4613
4711
|
return next;
|
|
4614
4712
|
}),
|
|
4615
4713
|
children: [
|
|
4616
|
-
/* @__PURE__ */
|
|
4617
|
-
/* @__PURE__ */
|
|
4714
|
+
/* @__PURE__ */ jsx96(Text40, { className: "text-foreground", children: `Order ${orderReference(order)} \xB7 ${count2} ${count2 === 1 ? "item" : "items"}` }),
|
|
4715
|
+
/* @__PURE__ */ jsxs55(Text40, { className: "text-muted-foreground", children: [
|
|
4618
4716
|
formatDate(order.createdAt),
|
|
4619
4717
|
" \xB7 ",
|
|
4620
|
-
|
|
4718
|
+
formatMoney15({ amount: order.totalMinor, currency: order.currency }),
|
|
4621
4719
|
" \xB7 ",
|
|
4622
4720
|
STATUS_LABEL[order.syncStatus]
|
|
4623
4721
|
] })
|
|
4624
4722
|
]
|
|
4625
4723
|
}
|
|
4626
4724
|
),
|
|
4627
|
-
isExpanded ? /* @__PURE__ */
|
|
4628
|
-
order.lines.map((line) => /* @__PURE__ */
|
|
4629
|
-
order.payments.map((payment) => /* @__PURE__ */
|
|
4725
|
+
isExpanded ? /* @__PURE__ */ jsxs55(View61, { testID: `order-detail-${order.id}`, className: "mt-1 gap-1 border-t border-border pt-2", children: [
|
|
4726
|
+
order.lines.map((line) => /* @__PURE__ */ jsx96(Text40, { className: "text-foreground", children: `${line.quantity} \xD7 ${line.name}` }, line.id)),
|
|
4727
|
+
order.payments.map((payment) => /* @__PURE__ */ jsx96(Text40, { className: "text-muted-foreground", children: `${payment.method === "cash" ? "Cash" : "Card terminal"} ${formatMoney15({ amount: payment.amountMinor, currency: order.currency })}${payment.reference ? ` \xB7 ${payment.reference}` : ""}` }, payment.id))
|
|
4630
4728
|
] }) : null,
|
|
4631
|
-
stuckEntry ? /* @__PURE__ */
|
|
4632
|
-
order.syncStatus === "rejected" ? /* @__PURE__ */
|
|
4633
|
-
order.lateSessionId !== void 0 ? /* @__PURE__ */
|
|
4634
|
-
order.localWarnings?.map((warning, index) => /* @__PURE__ */
|
|
4635
|
-
section.title === "Needs attention" && order.syncStatus === "rejected" && order.error?.code !== "idempotency_mismatch" ? /* @__PURE__ */
|
|
4729
|
+
stuckEntry ? /* @__PURE__ */ jsx96(Text40, { className: "text-destructive", children: `Hasn't reached the online store since ${sinceText(stuckEntry)}.` }) : null,
|
|
4730
|
+
order.syncStatus === "rejected" ? /* @__PURE__ */ jsx96(Text40, { className: "text-destructive", children: refusalSentence(order.error?.code) }) : null,
|
|
4731
|
+
order.lateSessionId !== void 0 ? /* @__PURE__ */ jsx96(Text40, { className: "text-foreground", children: "Taken after the register closed. It is not in that register's closure." }) : null,
|
|
4732
|
+
order.localWarnings?.map((warning, index) => /* @__PURE__ */ jsx96(Text40, { className: "text-foreground", children: warning.code === "customer_omitted" ? `The customer's ${warning.field} couldn't be sent to the store, so the order isn't linked to them.` : "The terminal's payment reference couldn't be kept; the payment is recorded without it." }, index)),
|
|
4733
|
+
section.title === "Needs attention" && order.syncStatus === "rejected" && order.error?.code !== "idempotency_mismatch" ? /* @__PURE__ */ jsx96(Pressable30, { accessibilityRole: "button", disabled: retryingIds.has(order.id), onPress: async () => {
|
|
4636
4734
|
if (retrying.current.has(order.id)) return;
|
|
4637
4735
|
retrying.current.add(order.id);
|
|
4638
4736
|
setRetryingIds(new Set(retrying.current));
|
|
@@ -4640,8 +4738,8 @@ function OrdersList({ orders, onRetry, formatDate = defaultFormatDate2, footer,
|
|
|
4640
4738
|
retrying.current.delete(order.id);
|
|
4641
4739
|
setRetryingIds(new Set(retrying.current));
|
|
4642
4740
|
}
|
|
4643
|
-
}, className: "rounded-md bg-primary px-4 py-2", children: /* @__PURE__ */
|
|
4644
|
-
knownWarnings(order.warnings).map((warning, index) => /* @__PURE__ */
|
|
4741
|
+
}, className: "rounded-md bg-primary px-4 py-2", children: /* @__PURE__ */ jsx96(Text40, { className: "text-center font-semibold text-primary-foreground", children: "Retry" }) }) : null,
|
|
4742
|
+
knownWarnings(order.warnings).map((warning, index) => /* @__PURE__ */ jsx96(View61, { className: "border-l-4 border-warning pl-2", children: /* @__PURE__ */ jsx96(Text40, { className: "text-foreground", children: warning.code === "insufficient_stock" ? `Stock short by ${warning.quantity} for ${order.lines.find((line) => line.variantId === warning.variantId)?.name}` : warning.code === "tax_rate_mismatch" ? `Tax at ${(warning.ratePpm / 1e4).toLocaleString(void 0, { maximumFractionDigits: 4 })}%: store ${formatMoney15({ amount: warning.serverMinor, currency: order.currency })} vs POS ${formatMoney15({ amount: warning.expectedMinor, currency: order.currency })}` : warning.code === "customer_ignored" ? `The online store didn't recognise the customer on this sale, so it was saved as a guest sale. Customer id: ${warning.customerId}.` : warning.code === "figures_mismatch" ? `The online store worked out different figures for this sale. ${warning.fields.map(({ field, tillMinor, serverMinor }) => `${FIGURE_LABELS.get(field) ?? field}: till ${formatMoney15({ amount: tillMinor, currency: order.currency })}, store ${formatMoney15({ amount: serverMinor, currency: order.currency })}.`).join(" ")}` : warning.bridgeMinor !== void 0 ? `Store calculated ${formatMoney15({ amount: warning.serverMinor, currency: order.currency })}; a rounding line of ${warning.bridgeMinor > 0 ? "+" : ""}${formatMoney15({ amount: warning.bridgeMinor, currency: order.currency })} brought it to ${formatMoney15({ amount: warning.expectedMinor, currency: order.currency })}` : `Store total ${formatMoney15({ amount: warning.serverMinor, currency: order.currency })} vs POS ${formatMoney15({ amount: warning.expectedMinor, currency: order.currency })}` }) }, index))
|
|
4645
4743
|
] }, order.id);
|
|
4646
4744
|
})
|
|
4647
4745
|
] }, section.title)),
|
|
@@ -4649,11 +4747,103 @@ function OrdersList({ orders, onRetry, formatDate = defaultFormatDate2, footer,
|
|
|
4649
4747
|
] });
|
|
4650
4748
|
}
|
|
4651
4749
|
|
|
4750
|
+
// src/sale/parked-sales.tsx
|
|
4751
|
+
import { useState as useState22 } from "react";
|
|
4752
|
+
import { ScrollView as ScrollView14, useWindowDimensions as useWindowDimensions3, View as View62 } from "react-native";
|
|
4753
|
+
import { formatMoney as formatMoney16 } from "@tallyui/core";
|
|
4754
|
+
import { Fragment as Fragment9, jsx as jsx97, jsxs as jsxs56 } from "react/jsx-runtime";
|
|
4755
|
+
function ParkedSales({ sale, parked, onDiscard, currency, open, onOpenChange, hour12 }) {
|
|
4756
|
+
const { height: windowHeight } = useWindowDimensions3();
|
|
4757
|
+
const maxHeight = Math.max(280, windowHeight - 64);
|
|
4758
|
+
const [confirming, setConfirming] = useState22(null);
|
|
4759
|
+
const [error, setError] = useState22("");
|
|
4760
|
+
const attempt = async (action) => {
|
|
4761
|
+
setError("");
|
|
4762
|
+
try {
|
|
4763
|
+
await action();
|
|
4764
|
+
} catch (e) {
|
|
4765
|
+
setError(String(e));
|
|
4766
|
+
}
|
|
4767
|
+
};
|
|
4768
|
+
return /* @__PURE__ */ jsx97(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs56(DialogContent, { testID: "parked-sales", className: "flex-col overflow-hidden", style: { maxHeight }, children: [
|
|
4769
|
+
/* @__PURE__ */ jsxs56(View62, { className: "flex-row items-center justify-between gap-2", children: [
|
|
4770
|
+
/* @__PURE__ */ jsx97(DialogTitle, { children: "Parked sales" }),
|
|
4771
|
+
/* @__PURE__ */ jsx97(DialogClose, { asChild: true, children: /* @__PURE__ */ jsx97(IconButton, { variant: "ghost", size: "sm", testID: "parked-sales-dismiss", accessibilityLabel: "Close panel", children: /* @__PURE__ */ jsx97(XIcon, { size: 16 }) }) })
|
|
4772
|
+
] }),
|
|
4773
|
+
/* @__PURE__ */ jsxs56(ScrollView14, { className: "flex-1", contentContainerClassName: "gap-3", children: [
|
|
4774
|
+
/* @__PURE__ */ jsx97(
|
|
4775
|
+
Button,
|
|
4776
|
+
{
|
|
4777
|
+
testID: "parked-sales-park",
|
|
4778
|
+
accessibilityLabel: "Park this sale",
|
|
4779
|
+
disabled: sale.order.lineItems.length === 0,
|
|
4780
|
+
onPress: () => attempt(async () => setError(await sale.park() ?? "")),
|
|
4781
|
+
children: /* @__PURE__ */ jsx97(Text, { children: "Park this sale" })
|
|
4782
|
+
}
|
|
4783
|
+
),
|
|
4784
|
+
!!error && /* @__PURE__ */ jsx97(Text, { testID: "parked-sales-error", className: "text-destructive", children: error }),
|
|
4785
|
+
parked.length === 0 && /* @__PURE__ */ jsx97(Text, { testID: "parked-sales-empty", children: "No parked sales." }),
|
|
4786
|
+
parked.map((row) => /* @__PURE__ */ jsx97(View62, { testID: `parked-row-${row.id}`, className: "gap-2 rounded-md border border-border p-3", children: confirming === row.id ? /* @__PURE__ */ jsxs56(Fragment9, { children: [
|
|
4787
|
+
/* @__PURE__ */ jsx97(Text, { children: "Discard this parked sale?" }),
|
|
4788
|
+
/* @__PURE__ */ jsxs56(View62, { className: "flex-row gap-2", children: [
|
|
4789
|
+
/* @__PURE__ */ jsx97(
|
|
4790
|
+
Button,
|
|
4791
|
+
{
|
|
4792
|
+
testID: `parked-discard-confirm-${row.id}`,
|
|
4793
|
+
variant: "destructive",
|
|
4794
|
+
onPress: () => attempt(async () => {
|
|
4795
|
+
await onDiscard(row.id);
|
|
4796
|
+
setConfirming(null);
|
|
4797
|
+
}),
|
|
4798
|
+
children: /* @__PURE__ */ jsx97(Text, { children: "Discard" })
|
|
4799
|
+
}
|
|
4800
|
+
),
|
|
4801
|
+
/* @__PURE__ */ jsx97(Button, { testID: `parked-discard-cancel-${row.id}`, variant: "outline", onPress: () => setConfirming(null), children: /* @__PURE__ */ jsx97(Text, { children: "Cancel" }) })
|
|
4802
|
+
] })
|
|
4803
|
+
] }) : /* @__PURE__ */ jsxs56(Fragment9, { children: [
|
|
4804
|
+
/* @__PURE__ */ jsx97(Text, { children: formatStockSyncTime(new Date(row.parkedAt), void 0, hour12) }),
|
|
4805
|
+
/* @__PURE__ */ jsxs56(Text, { children: [
|
|
4806
|
+
row.itemCount,
|
|
4807
|
+
" ",
|
|
4808
|
+
row.itemCount === 1 ? "item" : "items"
|
|
4809
|
+
] }),
|
|
4810
|
+
/* @__PURE__ */ jsx97(Text, { children: formatMoney16({ amount: row.totalMinor, currency }) }),
|
|
4811
|
+
!!row.customerName && /* @__PURE__ */ jsx97(Text, { children: row.customerName }),
|
|
4812
|
+
/* @__PURE__ */ jsxs56(View62, { className: "flex-row gap-2", children: [
|
|
4813
|
+
/* @__PURE__ */ jsx97(
|
|
4814
|
+
Button,
|
|
4815
|
+
{
|
|
4816
|
+
testID: `parked-resume-${row.id}`,
|
|
4817
|
+
accessibilityLabel: "Resume parked sale",
|
|
4818
|
+
onPress: () => attempt(async () => {
|
|
4819
|
+
const refusal = await sale.resume(row.id);
|
|
4820
|
+
if (refusal === null) onOpenChange(false);
|
|
4821
|
+
else setError(refusal);
|
|
4822
|
+
}),
|
|
4823
|
+
children: /* @__PURE__ */ jsx97(Text, { children: "Resume" })
|
|
4824
|
+
}
|
|
4825
|
+
),
|
|
4826
|
+
/* @__PURE__ */ jsx97(
|
|
4827
|
+
Button,
|
|
4828
|
+
{
|
|
4829
|
+
testID: `parked-discard-${row.id}`,
|
|
4830
|
+
accessibilityLabel: "Discard parked sale",
|
|
4831
|
+
variant: "outline",
|
|
4832
|
+
onPress: () => setConfirming(row.id),
|
|
4833
|
+
children: /* @__PURE__ */ jsx97(Text, { children: "Discard" })
|
|
4834
|
+
}
|
|
4835
|
+
)
|
|
4836
|
+
] })
|
|
4837
|
+
] }) }, row.id))
|
|
4838
|
+
] })
|
|
4839
|
+
] }) });
|
|
4840
|
+
}
|
|
4841
|
+
|
|
4652
4842
|
// src/layout/pos-layout.tsx
|
|
4653
|
-
import { useState as
|
|
4654
|
-
import { Pressable as
|
|
4843
|
+
import { useState as useState23 } from "react";
|
|
4844
|
+
import { Pressable as Pressable31, Text as Text41, View as View63, useWindowDimensions as useWindowDimensions4 } from "react-native";
|
|
4655
4845
|
import { cn as cn80 } from "@tallyui/theme";
|
|
4656
|
-
import { Fragment as
|
|
4846
|
+
import { Fragment as Fragment10, jsx as jsx98, jsxs as jsxs57 } from "react/jsx-runtime";
|
|
4657
4847
|
function POSLayout({
|
|
4658
4848
|
browseSlot,
|
|
4659
4849
|
cartSlot,
|
|
@@ -4663,42 +4853,42 @@ function POSLayout({
|
|
|
4663
4853
|
className,
|
|
4664
4854
|
...viewProps
|
|
4665
4855
|
}) {
|
|
4666
|
-
const { width } =
|
|
4856
|
+
const { width } = useWindowDimensions4();
|
|
4667
4857
|
const layout = layoutProp ?? (width >= breakpoint ? "split" : "stacked");
|
|
4668
|
-
const [activeTab, setActiveTab] =
|
|
4669
|
-
return /* @__PURE__ */
|
|
4670
|
-
headerSlot && /* @__PURE__ */
|
|
4671
|
-
layout === "split" ? /* @__PURE__ */
|
|
4672
|
-
/* @__PURE__ */
|
|
4673
|
-
/* @__PURE__ */
|
|
4674
|
-
] }) : /* @__PURE__ */
|
|
4675
|
-
/* @__PURE__ */
|
|
4676
|
-
/* @__PURE__ */
|
|
4677
|
-
|
|
4858
|
+
const [activeTab, setActiveTab] = useState23("browse");
|
|
4859
|
+
return /* @__PURE__ */ jsxs57(View63, { className: cn80("flex-1 bg-bg", className), ...viewProps, children: [
|
|
4860
|
+
headerSlot && /* @__PURE__ */ jsx98(View63, { className: "border-b border-border", children: headerSlot }),
|
|
4861
|
+
layout === "split" ? /* @__PURE__ */ jsxs57(View63, { className: "flex-1 flex-row", children: [
|
|
4862
|
+
/* @__PURE__ */ jsx98(View63, { className: "flex-[3]", children: browseSlot }),
|
|
4863
|
+
/* @__PURE__ */ jsx98(View63, { className: "flex-[2] border-l border-border", children: cartSlot })
|
|
4864
|
+
] }) : /* @__PURE__ */ jsxs57(Fragment10, { children: [
|
|
4865
|
+
/* @__PURE__ */ jsxs57(View63, { className: "flex-row border-b border-border", children: [
|
|
4866
|
+
/* @__PURE__ */ jsx98(
|
|
4867
|
+
Pressable31,
|
|
4678
4868
|
{
|
|
4679
4869
|
onPress: () => setActiveTab("browse"),
|
|
4680
4870
|
className: cn80("flex-1 py-3", activeTab === "browse" && "border-b-2 border-primary"),
|
|
4681
|
-
children: /* @__PURE__ */
|
|
4871
|
+
children: /* @__PURE__ */ jsx98(Text41, { className: cn80("text-center text-sm font-semibold", activeTab === "browse" ? "text-primary" : "text-muted-foreground"), children: "Browse" })
|
|
4682
4872
|
}
|
|
4683
4873
|
),
|
|
4684
|
-
/* @__PURE__ */
|
|
4685
|
-
|
|
4874
|
+
/* @__PURE__ */ jsx98(
|
|
4875
|
+
Pressable31,
|
|
4686
4876
|
{
|
|
4687
4877
|
onPress: () => setActiveTab("cart"),
|
|
4688
4878
|
className: cn80("flex-1 py-3", activeTab === "cart" && "border-b-2 border-primary"),
|
|
4689
|
-
children: /* @__PURE__ */
|
|
4879
|
+
children: /* @__PURE__ */ jsx98(Text41, { className: cn80("text-center text-sm font-semibold", activeTab === "cart" ? "text-primary" : "text-muted-foreground"), children: "Cart" })
|
|
4690
4880
|
}
|
|
4691
4881
|
)
|
|
4692
4882
|
] }),
|
|
4693
|
-
/* @__PURE__ */
|
|
4883
|
+
/* @__PURE__ */ jsx98(View63, { className: "flex-1", children: activeTab === "browse" ? browseSlot : cartSlot })
|
|
4694
4884
|
] })
|
|
4695
4885
|
] });
|
|
4696
4886
|
}
|
|
4697
4887
|
|
|
4698
4888
|
// src/layout/checkout-layout.tsx
|
|
4699
|
-
import { ScrollView as
|
|
4889
|
+
import { ScrollView as ScrollView15, View as View64, useWindowDimensions as useWindowDimensions5 } from "react-native";
|
|
4700
4890
|
import { cn as cn81 } from "@tallyui/theme";
|
|
4701
|
-
import { jsx as
|
|
4891
|
+
import { jsx as jsx99, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
4702
4892
|
function CheckoutLayout({
|
|
4703
4893
|
summarySlot,
|
|
4704
4894
|
paymentSlot,
|
|
@@ -4708,14 +4898,14 @@ function CheckoutLayout({
|
|
|
4708
4898
|
className,
|
|
4709
4899
|
...viewProps
|
|
4710
4900
|
}) {
|
|
4711
|
-
const { width } =
|
|
4901
|
+
const { width } = useWindowDimensions5();
|
|
4712
4902
|
const layout = layoutProp ?? (width >= breakpoint ? "split" : "stacked");
|
|
4713
|
-
return /* @__PURE__ */
|
|
4714
|
-
headerSlot && /* @__PURE__ */
|
|
4715
|
-
layout === "split" ? /* @__PURE__ */
|
|
4716
|
-
/* @__PURE__ */
|
|
4717
|
-
/* @__PURE__ */
|
|
4718
|
-
] }) : /* @__PURE__ */
|
|
4903
|
+
return /* @__PURE__ */ jsxs58(View64, { className: cn81("flex-1 bg-bg", className), ...viewProps, children: [
|
|
4904
|
+
headerSlot && /* @__PURE__ */ jsx99(View64, { className: "border-b border-border", children: headerSlot }),
|
|
4905
|
+
layout === "split" ? /* @__PURE__ */ jsxs58(View64, { className: "flex-1 flex-row", children: [
|
|
4906
|
+
/* @__PURE__ */ jsx99(View64, { className: "flex-1 border-r border-border", children: summarySlot }),
|
|
4907
|
+
/* @__PURE__ */ jsx99(View64, { className: "flex-1", children: paymentSlot })
|
|
4908
|
+
] }) : /* @__PURE__ */ jsx99(ScrollView15, { className: "flex-1", children: /* @__PURE__ */ jsxs58(View64, { className: "gap-4 p-4", children: [
|
|
4719
4909
|
summarySlot,
|
|
4720
4910
|
paymentSlot
|
|
4721
4911
|
] }) })
|
|
@@ -4723,10 +4913,10 @@ function CheckoutLayout({
|
|
|
4723
4913
|
}
|
|
4724
4914
|
|
|
4725
4915
|
// src/layout/settings-layout.tsx
|
|
4726
|
-
import { useState as
|
|
4727
|
-
import { Pressable as
|
|
4916
|
+
import { useState as useState24 } from "react";
|
|
4917
|
+
import { Pressable as Pressable32, Text as Text42, View as View65, useWindowDimensions as useWindowDimensions6 } from "react-native";
|
|
4728
4918
|
import { cn as cn82 } from "@tallyui/theme";
|
|
4729
|
-
import { jsx as
|
|
4919
|
+
import { jsx as jsx100, jsxs as jsxs59 } from "react/jsx-runtime";
|
|
4730
4920
|
function SettingsLayout({
|
|
4731
4921
|
navSlot,
|
|
4732
4922
|
contentSlot,
|
|
@@ -4736,28 +4926,28 @@ function SettingsLayout({
|
|
|
4736
4926
|
className,
|
|
4737
4927
|
...viewProps
|
|
4738
4928
|
}) {
|
|
4739
|
-
const { width } =
|
|
4929
|
+
const { width } = useWindowDimensions6();
|
|
4740
4930
|
const layout = layoutProp ?? (width >= breakpoint ? "split" : "stacked");
|
|
4741
|
-
const [showNav, setShowNav] =
|
|
4742
|
-
return /* @__PURE__ */
|
|
4743
|
-
headerSlot && /* @__PURE__ */
|
|
4744
|
-
layout === "split" ? /* @__PURE__ */
|
|
4745
|
-
/* @__PURE__ */
|
|
4746
|
-
/* @__PURE__ */
|
|
4747
|
-
] }) : /* @__PURE__ */
|
|
4931
|
+
const [showNav, setShowNav] = useState24(false);
|
|
4932
|
+
return /* @__PURE__ */ jsxs59(View65, { className: cn82("flex-1 bg-bg", className), ...viewProps, children: [
|
|
4933
|
+
headerSlot && /* @__PURE__ */ jsx100(View65, { className: "border-b border-border", children: headerSlot }),
|
|
4934
|
+
layout === "split" ? /* @__PURE__ */ jsxs59(View65, { className: "flex-1 flex-row", children: [
|
|
4935
|
+
/* @__PURE__ */ jsx100(View65, { className: "w-64 border-r border-border", children: navSlot }),
|
|
4936
|
+
/* @__PURE__ */ jsx100(View65, { className: "flex-1", children: contentSlot })
|
|
4937
|
+
] }) : /* @__PURE__ */ jsx100(View65, { className: "flex-1", children: showNav ? /* @__PURE__ */ jsxs59(View65, { className: "flex-1", children: [
|
|
4748
4938
|
navSlot,
|
|
4749
|
-
/* @__PURE__ */
|
|
4750
|
-
] }) : /* @__PURE__ */
|
|
4751
|
-
/* @__PURE__ */
|
|
4939
|
+
/* @__PURE__ */ jsx100(Pressable32, { onPress: () => setShowNav(false), className: "border-t border-border p-3", children: /* @__PURE__ */ jsx100(Text42, { className: "text-center text-sm font-medium text-primary", children: "Done" }) })
|
|
4940
|
+
] }) : /* @__PURE__ */ jsxs59(View65, { className: "flex-1", children: [
|
|
4941
|
+
/* @__PURE__ */ jsx100(Pressable32, { onPress: () => setShowNav(true), className: "border-b border-border px-4 py-2", children: /* @__PURE__ */ jsx100(Text42, { className: "text-sm font-medium text-primary", children: "Menu" }) }),
|
|
4752
4942
|
contentSlot
|
|
4753
4943
|
] }) })
|
|
4754
4944
|
] });
|
|
4755
4945
|
}
|
|
4756
4946
|
|
|
4757
4947
|
// src/layout/live-tab-screen.tsx
|
|
4758
|
-
import { Pressable as
|
|
4948
|
+
import { Pressable as Pressable33, Text as Text43, View as View66 } from "react-native";
|
|
4759
4949
|
import { cn as cn83 } from "@tallyui/theme";
|
|
4760
|
-
import { jsx as
|
|
4950
|
+
import { jsx as jsx101, jsxs as jsxs60 } from "react/jsx-runtime";
|
|
4761
4951
|
function LiveTabScreen({
|
|
4762
4952
|
state,
|
|
4763
4953
|
onUseHere,
|
|
@@ -4774,21 +4964,21 @@ function LiveTabScreen({
|
|
|
4774
4964
|
const body = state === "parked" ? parkedBody : blockedBody;
|
|
4775
4965
|
const buttonLabel = state === "parked" ? useHereLabel : reloadLabel;
|
|
4776
4966
|
const onPress = state === "parked" ? onUseHere : onReload;
|
|
4777
|
-
return /* @__PURE__ */
|
|
4778
|
-
/* @__PURE__ */
|
|
4779
|
-
/* @__PURE__ */
|
|
4780
|
-
/* @__PURE__ */
|
|
4967
|
+
return /* @__PURE__ */ jsxs60(View66, { className: cn83("flex-1 items-center justify-center gap-4 bg-bg p-6", className), ...viewProps, children: [
|
|
4968
|
+
/* @__PURE__ */ jsx101(Text43, { className: "text-center text-lg font-bold text-foreground", children: parkedTitle }),
|
|
4969
|
+
/* @__PURE__ */ jsx101(Text43, { className: "text-center text-sm text-muted-foreground", children: body }),
|
|
4970
|
+
/* @__PURE__ */ jsx101(Pressable33, { onPress, className: "items-center rounded-lg bg-primary px-4 py-3", children: /* @__PURE__ */ jsx101(Text43, { className: "text-sm font-semibold text-primary-foreground", children: buttonLabel }) })
|
|
4781
4971
|
] });
|
|
4782
4972
|
}
|
|
4783
4973
|
|
|
4784
4974
|
// src/layout/store-settings-choice-screen.tsx
|
|
4785
|
-
import { useState as
|
|
4786
|
-
import { Pressable as
|
|
4975
|
+
import { useState as useState25 } from "react";
|
|
4976
|
+
import { Pressable as Pressable34, Text as Text44, View as View67 } from "react-native";
|
|
4787
4977
|
import { cn as cn84 } from "@tallyui/theme";
|
|
4788
|
-
import { jsx as
|
|
4978
|
+
import { jsx as jsx102, jsxs as jsxs61 } from "react/jsx-runtime";
|
|
4789
4979
|
function useSectionSelection(options, initialValue) {
|
|
4790
4980
|
const preset = options.length === 1 ? options[0].value : options.find((o) => o.value === initialValue)?.value;
|
|
4791
|
-
return
|
|
4981
|
+
return useState25(preset);
|
|
4792
4982
|
}
|
|
4793
4983
|
function defaultCountryName(code, locale) {
|
|
4794
4984
|
try {
|
|
@@ -4834,32 +5024,32 @@ function StoreSettingsChoiceScreen({
|
|
|
4834
5024
|
else if (initial?.channel !== void 0) choice.channel = initial.channel;
|
|
4835
5025
|
onSubmit(choice);
|
|
4836
5026
|
};
|
|
4837
|
-
return /* @__PURE__ */
|
|
4838
|
-
/* @__PURE__ */
|
|
4839
|
-
/* @__PURE__ */
|
|
4840
|
-
/* @__PURE__ */
|
|
5027
|
+
return /* @__PURE__ */ jsxs61(View67, { className: cn84("w-full max-w-[560px] flex-1 self-center gap-6 bg-bg p-6", className), ...viewProps, children: [
|
|
5028
|
+
/* @__PURE__ */ jsxs61(View67, { className: "gap-2", children: [
|
|
5029
|
+
/* @__PURE__ */ jsx102(Text44, { className: "text-lg font-bold text-foreground", children: title }),
|
|
5030
|
+
/* @__PURE__ */ jsx102(Text44, { className: "text-sm text-muted-foreground", children: body })
|
|
4841
5031
|
] }),
|
|
4842
|
-
showRegions && /* @__PURE__ */
|
|
4843
|
-
showCountries && /* @__PURE__ */
|
|
4844
|
-
showChannels && /* @__PURE__ */
|
|
4845
|
-
/* @__PURE__ */
|
|
4846
|
-
|
|
5032
|
+
showRegions && /* @__PURE__ */ jsx102(ChoiceSection, { label: regionLabel, options: regionOptions, selected: region, onSelect: setRegion }),
|
|
5033
|
+
showCountries && /* @__PURE__ */ jsx102(ChoiceSection, { label: countryLabel, options: countryOptions, selected: country, onSelect: setCountry }),
|
|
5034
|
+
showChannels && /* @__PURE__ */ jsx102(ChoiceSection, { label: channelLabel, options: channelOptions, selected: channel, onSelect: setChannel }),
|
|
5035
|
+
/* @__PURE__ */ jsx102(
|
|
5036
|
+
Pressable34,
|
|
4847
5037
|
{
|
|
4848
5038
|
onPress: handleSubmit,
|
|
4849
5039
|
disabled: !complete,
|
|
4850
5040
|
className: cn84("items-center rounded-lg bg-primary px-4 py-3", !complete && "opacity-50"),
|
|
4851
|
-
children: /* @__PURE__ */
|
|
5041
|
+
children: /* @__PURE__ */ jsx102(Text44, { className: "text-sm font-semibold text-primary-foreground", children: submitLabel })
|
|
4852
5042
|
}
|
|
4853
5043
|
)
|
|
4854
5044
|
] });
|
|
4855
5045
|
}
|
|
4856
5046
|
function ChoiceSection({ label, options, selected, onSelect }) {
|
|
4857
|
-
return /* @__PURE__ */
|
|
4858
|
-
/* @__PURE__ */
|
|
4859
|
-
/* @__PURE__ */
|
|
5047
|
+
return /* @__PURE__ */ jsxs61(View67, { className: "gap-1.5", children: [
|
|
5048
|
+
/* @__PURE__ */ jsx102(Text44, { className: "text-xs font-semibold text-muted-foreground", children: label }),
|
|
5049
|
+
/* @__PURE__ */ jsx102(View67, { className: "rounded-lg border border-border", children: options.map((option, index) => {
|
|
4860
5050
|
const checked = option.value === selected;
|
|
4861
|
-
return /* @__PURE__ */
|
|
4862
|
-
|
|
5051
|
+
return /* @__PURE__ */ jsxs61(
|
|
5052
|
+
Pressable34,
|
|
4863
5053
|
{
|
|
4864
5054
|
onPress: () => onSelect(option.value),
|
|
4865
5055
|
accessibilityRole: "radio",
|
|
@@ -4867,8 +5057,8 @@ function ChoiceSection({ label, options, selected, onSelect }) {
|
|
|
4867
5057
|
testID: `choice-option-${option.value}`,
|
|
4868
5058
|
className: cn84("flex-row items-center gap-3 px-4 py-3", index > 0 && "border-t border-border", checked && "bg-primary/10"),
|
|
4869
5059
|
children: [
|
|
4870
|
-
/* @__PURE__ */
|
|
4871
|
-
/* @__PURE__ */
|
|
5060
|
+
/* @__PURE__ */ jsx102(View67, { className: "h-4 w-4 items-center justify-center rounded-full border border-primary", children: checked && /* @__PURE__ */ jsx102(View67, { testID: `choice-option-${option.value}-dot`, className: "h-2.5 w-2.5 rounded-full bg-primary" }) }),
|
|
5061
|
+
/* @__PURE__ */ jsx102(Text44, { className: cn84("text-sm", checked ? "font-semibold text-primary" : "text-foreground"), children: option.label })
|
|
4872
5062
|
]
|
|
4873
5063
|
},
|
|
4874
5064
|
option.value
|
|
@@ -4998,11 +5188,13 @@ export {
|
|
|
4998
5188
|
OrderSummaryLine,
|
|
4999
5189
|
OrdersList,
|
|
5000
5190
|
POSLayout,
|
|
5191
|
+
ParkedSales,
|
|
5001
5192
|
PaymentMethodCard,
|
|
5002
5193
|
PaymentSelector,
|
|
5003
5194
|
Popover,
|
|
5004
5195
|
PopoverContent,
|
|
5005
5196
|
PopoverTrigger,
|
|
5197
|
+
PriceForm,
|
|
5006
5198
|
ProductCard,
|
|
5007
5199
|
ProductGrid,
|
|
5008
5200
|
ProductImage,
|
|
@@ -5086,6 +5278,7 @@ export {
|
|
|
5086
5278
|
loaderVariants,
|
|
5087
5279
|
orderReference,
|
|
5088
5280
|
parseDiscount,
|
|
5281
|
+
parsePrice,
|
|
5089
5282
|
textVariants,
|
|
5090
5283
|
toastVariants,
|
|
5091
5284
|
toggleTextVariants,
|