@tallyui/components 3.9.0 → 3.9.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 +16 -3
- package/dist/index.js +24 -3
- package/package.json +9 -9
- package/src/index.ts +1 -1
- package/src/sale/index.ts +1 -1
- package/src/sale/orders-list.tsx +27 -4
package/dist/index.d.ts
CHANGED
|
@@ -1456,16 +1456,29 @@ declare function SyncStatus({ state, registerState, pluginName, pullNotice }: {
|
|
|
1456
1456
|
pullNotice?: SyncNotice;
|
|
1457
1457
|
}): react_jsx_runtime.JSX.Element;
|
|
1458
1458
|
|
|
1459
|
+
/** One order from the store's own history (ADR-052 amendment 1), mapped by the app from its platform. */
|
|
1460
|
+
type OrderHistoryRow = {
|
|
1461
|
+
id: string;
|
|
1462
|
+
clientOrderId?: string;
|
|
1463
|
+
reference: string;
|
|
1464
|
+
placedAt: string;
|
|
1465
|
+
totalMinor: number;
|
|
1466
|
+
currency: string;
|
|
1467
|
+
itemCount: number;
|
|
1468
|
+
stateLabel: string;
|
|
1469
|
+
};
|
|
1459
1470
|
/** The "Needs attention" (when not empty) and "Recent" orders, lifted from medusapos/app's orders screen (ADR-052).
|
|
1460
1471
|
* `onRetry` is the outbox's `requeue`; `formatDate` replaces the app's date util; `footer` is the app's own content
|
|
1461
1472
|
* (medusapos: the feedback link). The router and session redirect stay in the app. `stuck` is the outbox's
|
|
1462
|
-
* `state.stuck` (`useOrderOutbox`): those pending orders need attention too, each with its own entry's reason and since.
|
|
1463
|
-
|
|
1473
|
+
* `state.stuck` (`useOrderOutbox`): those pending orders need attention too, each with its own entry's reason and since.
|
|
1474
|
+
* `history` adds read-only store order rows to Recent (ADR-052 amendment 1). */
|
|
1475
|
+
declare function OrdersList({ orders, onRetry, formatDate, footer, stuck, history }: {
|
|
1464
1476
|
orders: PosOrder[];
|
|
1465
1477
|
onRetry(orderIds: string[]): Promise<number>;
|
|
1466
1478
|
formatDate?: (iso: string) => string;
|
|
1467
1479
|
footer?: ReactNode;
|
|
1468
1480
|
stuck?: OutboxState['stuck'];
|
|
1481
|
+
history?: OrderHistoryRow[];
|
|
1469
1482
|
}): react_jsx_runtime.JSX.Element;
|
|
1470
1483
|
|
|
1471
1484
|
/** Pass `useParkedSales(drafts)`'s `parked` and `discard`, or your own parked store's list and handlers (`onPark`, `onResume`, `onDiscard`) with the same results. */
|
|
@@ -1560,4 +1573,4 @@ interface StoreSettingsChoiceScreenProps extends Omit<ViewProps, 'children'> {
|
|
|
1560
1573
|
*/
|
|
1561
1574
|
declare function StoreSettingsChoiceScreen({ choices, initial, onSubmit, countryName, locale, title, body, regionLabel, countryLabel, channelLabel, submitLabel, className, ...viewProps }: StoreSettingsChoiceScreenProps): react_jsx_runtime.JSX.Element;
|
|
1562
1575
|
|
|
1563
|
-
export { APPROVAL_REQUIRED_TEXT, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Avatar, type AvatarProps, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Cart, type CartAction, CartBar, CartLine, CartLineActions, type CartLineActionsProps, type CartLineProps, CartNoteInput, type CartNoteInputProps, CartPanel, type CartPanelProps, CartTotal, type CartTotalProps, CashCountInput, type CashCountInputProps, CashTendered, type CashTenderedProps, Catalogue, type CategoryItem, CategoryNav, type CategoryNavProps, ChangeDisplay, type ChangeDisplayProps, ChargeForm, type ChargeFormProps, Checkbox, CheckoutLayout, type CheckoutLayoutProps, type ChipItem, ClosureSheet, type ClosureSheetProps, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxTrigger, type ConnectionStatus, ConnectorStatus, type ConnectorStatusProps, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CustomerCard, type CustomerCardProps, CustomerForm, type CustomerFormProps, type CustomerFormValues, CustomerOrderHistory, type CustomerOrderHistoryProps, CustomerPicker, type CustomerPickerProps, CustomerSelect, type CustomerSelectProps, type Denomination, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiscountBadge, type DiscountBadgeProps, DiscountChips, DiscountForm, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, FilterChip, FilterChipGroup, type FilterChipGroupProps, type FilterChipProps, HStack, type HStackProps, HoverCard, HoverCardContent, HoverCardTrigger, Icon, IconButton, type IconButtonProps, type IconProps, Input, InputField, InputRoot, type InputRootProps, InputSlot, Label, type LabelProps, LiveTabScreen, type LiveTabScreenProps, type LiveTabScreenState, Loader, type LoaderProps, MovementSheet, type MovementSheetProps, OpenRegisterCard, type OpenRegisterCardProps, OrderCard, type OrderCardProps, OrderDetail, type OrderDetailLineItem, type OrderDetailProps, OrderList, type OrderListProps, type OrderStatus, OrderStatusBadge, type OrderStatusBadgeProps, OrderSummary, OrderSummaryLine, type OrderSummaryLineProps, type OrderSummaryPayment, type OrderSummaryProps, OrdersList, POSLayout, type POSLayoutProps, ParkedSales, type ParkedSalesProps, type PaymentMethod, PaymentMethodCard, type PaymentMethodCardProps, PaymentSelector, type PaymentSelectorProps, Popover, PopoverContent, PopoverTrigger, PriceForm, ProductCard, type ProductCardProps, ProductGrid, type ProductGridProps, ProductImage, type ProductImageProps, ProductList, type ProductListProps, ProductPrice, type ProductPriceProps, ProductSku, type ProductSkuProps, ProductStockBadge, type ProductStockBadgeProps, ProductTable, type ProductTableColumn, type ProductTableProps, ProductTitle, type ProductTitleProps, ProductVariantPicker, type ProductVariantPickerProps, Progress, type ProgressProps, QuantityStepper, type QuantityStepperProps, RadioGroup, RadioGroupItem, Receipt, type ReceiptItem, ReceiptPreview, type ReceiptPreviewProps, RegisterBar, type RegisterBarPill, type RegisterBarProps, RegisterColumn, type RegisterColumnProps, RegisterCount, type RegisterCountProps, RegisterOpenClose, type RegisterOpenCloseProps, RegisterPanel, type RegisterPanelProps, RegisterPicker, type RegisterPickerProps, type RegisterPickerRegister, RegisterSummary, type RegisterSummaryProps, SearchIcon, SearchInput, type SearchInputProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, type SeparatorProps, SettingsGroup, type SettingsGroupProps, SettingsLayout, type SettingsLayoutProps, SettingsRow, type SettingsRowProps, Slider, type SliderProps, SplitTender, StoreSettingsChoiceScreen, type StoreSettingsChoiceScreenProps, type SvgIconProps, Switch, SyncStatus, Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tender, Text, type TextProps, Textarea, type TextareaProps, Toast, ToastClose, ToastDescription, type ToastProps, ToastTitle, Toggle, ToggleGroup, ToggleGroupItem, type ToggleGroupItemProps, type ToggleGroupProps, type ToggleProps, Tooltip, TooltipContent, TooltipTrigger, type TransactionSummary, VStack, type VStackProps, type VariantOption, ViewToggle, type ViewToggleProps, XIcon, avatarVariants, badgeTextVariants, badgeVariants, buttonTextVariants, buttonVariants, createSvgIcon, defaultProductColumns, describeRegisterBarPill, discountLabel, formatStockSyncTime, hstackVariants, iconButtonVariants, iconVariants, injectPrintStyle, loaderVariants, orderReference, parseDiscount, parsePrice, textVariants, toastVariants, toggleTextVariants, toggleVariants, useDefaultProductColumns, useInputContext, vstackVariants };
|
|
1576
|
+
export { APPROVAL_REQUIRED_TEXT, Accordion, AccordionContent, AccordionItem, AccordionTrigger, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, Avatar, type AvatarProps, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Cart, type CartAction, CartBar, CartLine, CartLineActions, type CartLineActionsProps, type CartLineProps, CartNoteInput, type CartNoteInputProps, CartPanel, type CartPanelProps, CartTotal, type CartTotalProps, CashCountInput, type CashCountInputProps, CashTendered, type CashTenderedProps, Catalogue, type CategoryItem, CategoryNav, type CategoryNavProps, ChangeDisplay, type ChangeDisplayProps, ChargeForm, type ChargeFormProps, Checkbox, CheckoutLayout, type CheckoutLayoutProps, type ChipItem, ClosureSheet, type ClosureSheetProps, Collapsible, CollapsibleContent, CollapsibleTrigger, Combobox, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxTrigger, type ConnectionStatus, ConnectorStatus, type ConnectorStatusProps, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CustomerCard, type CustomerCardProps, CustomerForm, type CustomerFormProps, type CustomerFormValues, CustomerOrderHistory, type CustomerOrderHistoryProps, CustomerPicker, type CustomerPickerProps, CustomerSelect, type CustomerSelectProps, type Denomination, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DiscountBadge, type DiscountBadgeProps, DiscountChips, DiscountForm, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, FilterChip, FilterChipGroup, type FilterChipGroupProps, type FilterChipProps, HStack, type HStackProps, HoverCard, HoverCardContent, HoverCardTrigger, Icon, IconButton, type IconButtonProps, type IconProps, Input, InputField, InputRoot, type InputRootProps, InputSlot, Label, type LabelProps, LiveTabScreen, type LiveTabScreenProps, type LiveTabScreenState, Loader, type LoaderProps, MovementSheet, type MovementSheetProps, OpenRegisterCard, type OpenRegisterCardProps, OrderCard, type OrderCardProps, OrderDetail, type OrderDetailLineItem, type OrderDetailProps, type OrderHistoryRow, OrderList, type OrderListProps, type OrderStatus, OrderStatusBadge, type OrderStatusBadgeProps, OrderSummary, OrderSummaryLine, type OrderSummaryLineProps, type OrderSummaryPayment, type OrderSummaryProps, OrdersList, POSLayout, type POSLayoutProps, ParkedSales, type ParkedSalesProps, type PaymentMethod, PaymentMethodCard, type PaymentMethodCardProps, PaymentSelector, type PaymentSelectorProps, Popover, PopoverContent, PopoverTrigger, PriceForm, ProductCard, type ProductCardProps, ProductGrid, type ProductGridProps, ProductImage, type ProductImageProps, ProductList, type ProductListProps, ProductPrice, type ProductPriceProps, ProductSku, type ProductSkuProps, ProductStockBadge, type ProductStockBadgeProps, ProductTable, type ProductTableColumn, type ProductTableProps, ProductTitle, type ProductTitleProps, ProductVariantPicker, type ProductVariantPickerProps, Progress, type ProgressProps, QuantityStepper, type QuantityStepperProps, RadioGroup, RadioGroupItem, Receipt, type ReceiptItem, ReceiptPreview, type ReceiptPreviewProps, RegisterBar, type RegisterBarPill, type RegisterBarProps, RegisterColumn, type RegisterColumnProps, RegisterCount, type RegisterCountProps, RegisterOpenClose, type RegisterOpenCloseProps, RegisterPanel, type RegisterPanelProps, RegisterPicker, type RegisterPickerProps, type RegisterPickerRegister, RegisterSummary, type RegisterSummaryProps, SearchIcon, SearchInput, type SearchInputProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, Separator, type SeparatorProps, SettingsGroup, type SettingsGroupProps, SettingsLayout, type SettingsLayoutProps, SettingsRow, type SettingsRowProps, Slider, type SliderProps, SplitTender, StoreSettingsChoiceScreen, type StoreSettingsChoiceScreenProps, type SvgIconProps, Switch, SyncStatus, Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, Tender, Text, type TextProps, Textarea, type TextareaProps, Toast, ToastClose, ToastDescription, type ToastProps, ToastTitle, Toggle, ToggleGroup, ToggleGroupItem, type ToggleGroupItemProps, type ToggleGroupProps, type ToggleProps, Tooltip, TooltipContent, TooltipTrigger, type TransactionSummary, VStack, type VStackProps, type VariantOption, ViewToggle, type ViewToggleProps, XIcon, avatarVariants, badgeTextVariants, badgeVariants, buttonTextVariants, buttonVariants, createSvgIcon, defaultProductColumns, describeRegisterBarPill, discountLabel, formatStockSyncTime, hstackVariants, iconButtonVariants, iconVariants, injectPrintStyle, loaderVariants, orderReference, parseDiscount, parsePrice, textVariants, toastVariants, toggleTextVariants, toggleVariants, useDefaultProductColumns, useInputContext, vstackVariants };
|
package/dist/index.js
CHANGED
|
@@ -5226,7 +5226,7 @@ function defaultFormatDate2(iso) {
|
|
|
5226
5226
|
const date = new Date(iso);
|
|
5227
5227
|
return Number.isNaN(date.getTime()) ? iso : new Intl.DateTimeFormat(void 0, { dateStyle: "medium", timeStyle: "short" }).format(date);
|
|
5228
5228
|
}
|
|
5229
|
-
function OrdersList({ orders, onRetry, formatDate = defaultFormatDate2, footer, stuck }) {
|
|
5229
|
+
function OrdersList({ orders, onRetry, formatDate = defaultFormatDate2, footer, stuck, history }) {
|
|
5230
5230
|
const retrying = useRef8(/* @__PURE__ */ new Set());
|
|
5231
5231
|
const [retryingIds, setRetryingIds] = useState24(/* @__PURE__ */ new Set());
|
|
5232
5232
|
const [expanded, setExpanded] = useState24(/* @__PURE__ */ new Set());
|
|
@@ -5236,11 +5236,32 @@ function OrdersList({ orders, onRetry, formatDate = defaultFormatDate2, footer,
|
|
|
5236
5236
|
}
|
|
5237
5237
|
setRetryingIds(new Set(retrying.current));
|
|
5238
5238
|
}, [orders]);
|
|
5239
|
+
const shown = (history ?? []).filter((row) => row.clientOrderId === void 0 || !orders.some((order) => order.id === row.clientOrderId));
|
|
5240
|
+
const recent = shown.length === 0 ? orders : [...orders, ...shown].sort((a, b) => {
|
|
5241
|
+
const aTime = Date.parse("placedAt" in a ? a.placedAt : a.createdAt);
|
|
5242
|
+
const bTime = Date.parse("placedAt" in b ? b.placedAt : b.createdAt);
|
|
5243
|
+
if (Number.isNaN(aTime)) return Number.isNaN(bTime) ? 0 : 1;
|
|
5244
|
+
if (Number.isNaN(bTime)) return -1;
|
|
5245
|
+
return bTime - aTime;
|
|
5246
|
+
});
|
|
5239
5247
|
return /* @__PURE__ */ jsxs58(ScrollView13, { className: "flex-1 bg-background p-4", children: [
|
|
5240
|
-
[{ title: "Needs attention", orders: needsAttention(orders, { stuckCommandIds: stuck?.commandIds }) }, { title: "Recent", orders }].filter((section) => section.title === "Recent" || section.orders.length > 0).map((section) => /* @__PURE__ */ jsxs58(View65, { className: "mb-6 gap-3", children: [
|
|
5248
|
+
[{ title: "Needs attention", orders: needsAttention(orders, { stuckCommandIds: stuck?.commandIds }) }, { title: "Recent", orders: recent }].filter((section) => section.title === "Recent" || section.orders.length > 0).map((section) => /* @__PURE__ */ jsxs58(View65, { className: "mb-6 gap-3", children: [
|
|
5241
5249
|
/* @__PURE__ */ jsx100(Text43, { accessibilityRole: "header", className: "text-xl font-semibold text-foreground", children: section.title }),
|
|
5242
|
-
section.title === "Recent" && orders.length === 0 ? /* @__PURE__ */ jsx100(Text43, { testID: "orders-empty", className: "text-muted-foreground", children: "No sales yet. Completed sales appear here." }) : null,
|
|
5250
|
+
section.title === "Recent" && orders.length === 0 && shown.length === 0 ? /* @__PURE__ */ jsx100(Text43, { testID: "orders-empty", className: "text-muted-foreground", children: "No sales yet. Completed sales appear here." }) : null,
|
|
5243
5251
|
section.orders.map((order) => {
|
|
5252
|
+
if ("placedAt" in order) {
|
|
5253
|
+
const row = order;
|
|
5254
|
+
return /* @__PURE__ */ jsxs58(View65, { testID: `history-row-${row.id}`, className: "gap-1 rounded-md border border-border bg-card p-3", children: [
|
|
5255
|
+
/* @__PURE__ */ jsx100(Text43, { className: "text-foreground", children: `Order ${row.reference} \xB7 ${row.itemCount} ${row.itemCount === 1 ? "item" : "items"}` }),
|
|
5256
|
+
/* @__PURE__ */ jsxs58(Text43, { className: "text-muted-foreground", children: [
|
|
5257
|
+
formatDate(row.placedAt),
|
|
5258
|
+
" \xB7 ",
|
|
5259
|
+
formatMoney17({ amount: row.totalMinor, currency: row.currency }),
|
|
5260
|
+
" \xB7 ",
|
|
5261
|
+
row.stateLabel
|
|
5262
|
+
] })
|
|
5263
|
+
] }, `history:${row.id}`);
|
|
5264
|
+
}
|
|
5244
5265
|
const count2 = order.lines.reduce((sum, line) => sum + line.quantity, 0);
|
|
5245
5266
|
const key = `${section.title}:${order.id}`;
|
|
5246
5267
|
const isExpanded = expanded.has(key);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tallyui/components",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Universal POS UI components for Tally UI",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -28,22 +28,22 @@
|
|
|
28
28
|
"directory": "packages/components"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@tallyui/core": "^3.9.
|
|
32
|
-
"@tallyui/primitives": "^3.9.
|
|
33
|
-
"@tallyui/theme": "^3.9.
|
|
31
|
+
"@tallyui/core": "^3.9.1",
|
|
32
|
+
"@tallyui/primitives": "^3.9.1",
|
|
33
|
+
"@tallyui/theme": "^3.9.1",
|
|
34
34
|
"react": ">=18",
|
|
35
35
|
"react-native": ">=0.74",
|
|
36
36
|
"react-native-svg": ">=15"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"class-variance-authority": "^0.7.1",
|
|
40
|
-
"@tallyui/pos": "3.9.
|
|
40
|
+
"@tallyui/pos": "3.9.1"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@tallyui/connector-medusa": "3.9.
|
|
44
|
-
"@tallyui/connector-vendure": "3.9.
|
|
45
|
-
"@tallyui/connector-woocommerce": "3.9.
|
|
46
|
-
"@tallyui/mock-api": "3.9.
|
|
43
|
+
"@tallyui/connector-medusa": "3.9.1",
|
|
44
|
+
"@tallyui/connector-vendure": "3.9.1",
|
|
45
|
+
"@tallyui/connector-woocommerce": "3.9.1",
|
|
46
|
+
"@tallyui/mock-api": "3.9.1",
|
|
47
47
|
"@types/react": ">=18",
|
|
48
48
|
"react": "^19.2.4",
|
|
49
49
|
"react-native-svg": "15.12.1",
|
package/src/index.ts
CHANGED
|
@@ -164,7 +164,7 @@ export {
|
|
|
164
164
|
Cart, CartBar, Tender, SplitTender, DiscountForm, DiscountChips, parseDiscount, discountLabel,
|
|
165
165
|
PriceForm, parsePrice,
|
|
166
166
|
ChargeForm, type ChargeFormProps,
|
|
167
|
-
Catalogue, formatStockSyncTime, Receipt, injectPrintStyle, SyncStatus, OrdersList, orderReference,
|
|
167
|
+
Catalogue, formatStockSyncTime, Receipt, injectPrintStyle, SyncStatus, OrdersList, type OrderHistoryRow, orderReference,
|
|
168
168
|
ParkedSales, type ParkedSalesProps,
|
|
169
169
|
} from './sale';
|
|
170
170
|
|
package/src/sale/index.ts
CHANGED
|
@@ -10,5 +10,5 @@ export { Receipt } from './receipt';
|
|
|
10
10
|
export { orderReference } from './order-reference';
|
|
11
11
|
export { injectPrintStyle } from './print-style';
|
|
12
12
|
export { SyncStatus } from './sync-status';
|
|
13
|
-
export { OrdersList } from './orders-list';
|
|
13
|
+
export { OrdersList, type OrderHistoryRow } from './orders-list';
|
|
14
14
|
export { ParkedSales, type ParkedSalesProps } from './parked-sales';
|
package/src/sale/orders-list.tsx
CHANGED
|
@@ -5,6 +5,12 @@ import { needsAttention, type OutboxState, type PosOrder } from '@tallyui/pos';
|
|
|
5
5
|
import { orderReference } from './order-reference';
|
|
6
6
|
import { sinceText } from './since-text';
|
|
7
7
|
|
|
8
|
+
/** One order from the store's own history (ADR-052 amendment 1), mapped by the app from its platform. */
|
|
9
|
+
export type OrderHistoryRow = {
|
|
10
|
+
id: string; clientOrderId?: string; reference: string; placedAt: string;
|
|
11
|
+
totalMinor: number; currency: string; itemCount: number; stateLabel: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
8
14
|
const STATUS_LABEL = { pending: 'Waiting to sync', applied: 'Synced', rejected: 'Not accepted' };
|
|
9
15
|
/** `figures_mismatch`'s labels; a field a newer store sends that isn't here is shown by its raw name. */
|
|
10
16
|
const FIGURE_LABELS = new Map([['subtotalMinor', 'Subtotal'], ['taxMinor', 'Tax'], ['discountMinor', 'Discount']]);
|
|
@@ -36,10 +42,12 @@ function defaultFormatDate(iso: string) {
|
|
|
36
42
|
/** The "Needs attention" (when not empty) and "Recent" orders, lifted from medusapos/app's orders screen (ADR-052).
|
|
37
43
|
* `onRetry` is the outbox's `requeue`; `formatDate` replaces the app's date util; `footer` is the app's own content
|
|
38
44
|
* (medusapos: the feedback link). The router and session redirect stay in the app. `stuck` is the outbox's
|
|
39
|
-
* `state.stuck` (`useOrderOutbox`): those pending orders need attention too, each with its own entry's reason and since.
|
|
40
|
-
|
|
45
|
+
* `state.stuck` (`useOrderOutbox`): those pending orders need attention too, each with its own entry's reason and since.
|
|
46
|
+
* `history` adds read-only store order rows to Recent (ADR-052 amendment 1). */
|
|
47
|
+
export function OrdersList({ orders, onRetry, formatDate = defaultFormatDate, footer, stuck, history }: {
|
|
41
48
|
orders: PosOrder[]; onRetry(orderIds: string[]): Promise<number>; formatDate?: (iso: string) => string; footer?: ReactNode;
|
|
42
49
|
stuck?: OutboxState['stuck'];
|
|
50
|
+
history?: OrderHistoryRow[];
|
|
43
51
|
}) {
|
|
44
52
|
const retrying = useRef(new Set<string>());
|
|
45
53
|
const [retryingIds, setRetryingIds] = useState(new Set<string>());
|
|
@@ -50,12 +58,27 @@ export function OrdersList({ orders, onRetry, formatDate = defaultFormatDate, fo
|
|
|
50
58
|
}
|
|
51
59
|
setRetryingIds(new Set(retrying.current));
|
|
52
60
|
}, [orders]);
|
|
61
|
+
const shown = (history ?? []).filter((row) => row.clientOrderId === undefined || !orders.some((order) => order.id === row.clientOrderId));
|
|
62
|
+
const recent = shown.length === 0 ? orders : [...orders, ...shown].sort((a, b) => {
|
|
63
|
+
const aTime = Date.parse('placedAt' in a ? a.placedAt : a.createdAt);
|
|
64
|
+
const bTime = Date.parse('placedAt' in b ? b.placedAt : b.createdAt);
|
|
65
|
+
if (Number.isNaN(aTime)) return Number.isNaN(bTime) ? 0 : 1;
|
|
66
|
+
if (Number.isNaN(bTime)) return -1;
|
|
67
|
+
return bTime - aTime;
|
|
68
|
+
});
|
|
53
69
|
return <ScrollView className="flex-1 bg-background p-4">
|
|
54
|
-
{[{ title: 'Needs attention', orders: needsAttention(orders, { stuckCommandIds: stuck?.commandIds }) }, { title: 'Recent', orders }].filter((section) => section.title === 'Recent' || section.orders.length > 0).map((section) => (
|
|
70
|
+
{[{ title: 'Needs attention', orders: needsAttention(orders, { stuckCommandIds: stuck?.commandIds }) }, { title: 'Recent', orders: recent }].filter((section) => section.title === 'Recent' || section.orders.length > 0).map((section) => (
|
|
55
71
|
<View key={section.title} className="mb-6 gap-3">
|
|
56
72
|
<Text accessibilityRole="header" className="text-xl font-semibold text-foreground">{section.title}</Text>
|
|
57
|
-
{section.title === 'Recent' && orders.length === 0 ? <Text testID="orders-empty" className="text-muted-foreground">No sales yet. Completed sales appear here.</Text> : null}
|
|
73
|
+
{section.title === 'Recent' && orders.length === 0 && shown.length === 0 ? <Text testID="orders-empty" className="text-muted-foreground">No sales yet. Completed sales appear here.</Text> : null}
|
|
58
74
|
{section.orders.map((order) => {
|
|
75
|
+
if ('placedAt' in order) {
|
|
76
|
+
const row = order;
|
|
77
|
+
return <View key={`history:${row.id}`} testID={`history-row-${row.id}`} className="gap-1 rounded-md border border-border bg-card p-3">
|
|
78
|
+
<Text className="text-foreground">{`Order ${row.reference} · ${row.itemCount} ${row.itemCount === 1 ? 'item' : 'items'}`}</Text>
|
|
79
|
+
<Text className="text-muted-foreground">{formatDate(row.placedAt)} · {formatMoney({ amount: row.totalMinor, currency: row.currency })} · {row.stateLabel}</Text>
|
|
80
|
+
</View>;
|
|
81
|
+
}
|
|
59
82
|
const count = order.lines.reduce((sum, line) => sum + line.quantity, 0);
|
|
60
83
|
const key = `${section.title}:${order.id}`;
|
|
61
84
|
const isExpanded = expanded.has(key);
|