@aglyn/plugins-commerce 1.0.0-beta.233 → 1.0.0-beta.235

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.
Files changed (135) hide show
  1. package/package.json +13 -13
  2. package/src/lib/components/cart.js +3 -2
  3. package/src/lib/components/cart.js.map +1 -1
  4. package/src/lib/components/console/commerce-analytics-card.component.js +3 -6
  5. package/src/lib/components/console/commerce-analytics-card.component.js.map +1 -1
  6. package/src/lib/components/console/commerce-glance-card.component.js +9 -3
  7. package/src/lib/components/console/commerce-glance-card.component.js.map +1 -1
  8. package/src/lib/components/console/customer-notifications-card.component.js +3 -1
  9. package/src/lib/components/console/customer-notifications-card.component.js.map +1 -1
  10. package/src/lib/components/console/discounts-card.component.js +2 -3
  11. package/src/lib/components/console/discounts-card.component.js.map +1 -1
  12. package/src/lib/components/console/host-coupons-card.component.js +3 -4
  13. package/src/lib/components/console/host-coupons-card.component.js.map +1 -1
  14. package/src/lib/components/console/local-delivery-settings-card.component.js +2 -2
  15. package/src/lib/components/console/local-delivery-settings-card.component.js.map +1 -1
  16. package/src/lib/components/console/locations-card.component.js +1 -1
  17. package/src/lib/components/console/locations-card.component.js.map +1 -1
  18. package/src/lib/components/console/member-posts-card.component.js +2 -2
  19. package/src/lib/components/console/member-posts-card.component.js.map +1 -1
  20. package/src/lib/components/console/order-detail-dialog.component.js +35 -30
  21. package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
  22. package/src/lib/components/console/order-fulfillment-panel.component.d.ts +11 -1
  23. package/src/lib/components/console/order-fulfillment-panel.component.js +75 -4
  24. package/src/lib/components/console/order-fulfillment-panel.component.js.map +1 -1
  25. package/src/lib/components/console/order-zones.d.ts +45 -1
  26. package/src/lib/components/console/order-zones.js +8 -0
  27. package/src/lib/components/console/order-zones.js.map +1 -1
  28. package/src/lib/components/console/pickup-delivery-queue-card.component.js +15 -1
  29. package/src/lib/components/console/pickup-delivery-queue-card.component.js.map +1 -1
  30. package/src/lib/components/console/pos-page.component.js +3 -2
  31. package/src/lib/components/console/pos-page.component.js.map +1 -1
  32. package/src/lib/components/console/product-editor-dialog.component.d.ts +2 -0
  33. package/src/lib/components/console/product-editor-dialog.component.js +30 -12
  34. package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
  35. package/src/lib/components/console/products-hub-card.component.js +13 -4
  36. package/src/lib/components/console/products-hub-card.component.js.map +1 -1
  37. package/src/lib/components/console/products-hub-zone.component.d.ts +2 -1
  38. package/src/lib/components/console/products-hub-zone.component.js +1 -1
  39. package/src/lib/components/console/products-hub-zone.component.js.map +1 -1
  40. package/src/lib/components/console/reviews-moderation-card.component.js +1 -2
  41. package/src/lib/components/console/reviews-moderation-card.component.js.map +1 -1
  42. package/src/lib/components/console/shipping-settings-card.component.js +2 -2
  43. package/src/lib/components/console/shipping-settings-card.component.js.map +1 -1
  44. package/src/lib/components/console/shippingeasy-card.component.js +1 -1
  45. package/src/lib/components/console/shippingeasy-card.component.js.map +1 -1
  46. package/src/lib/components/console/shipstation-card.component.js +1 -2
  47. package/src/lib/components/console/shipstation-card.component.js.map +1 -1
  48. package/src/lib/components/console/store-settings-card.component.js +3 -1
  49. package/src/lib/components/console/store-settings-card.component.js.map +1 -1
  50. package/src/lib/components/console/tax-settings-card.component.js +4 -1
  51. package/src/lib/components/console/tax-settings-card.component.js.map +1 -1
  52. package/src/lib/components/order-status.js +24 -1
  53. package/src/lib/components/order-status.js.map +1 -1
  54. package/src/lib/components/product-detail.js +30 -16
  55. package/src/lib/components/product-detail.js.map +1 -1
  56. package/src/lib/components/product-grid.d.ts +7 -0
  57. package/src/lib/components/product-grid.js +50 -7
  58. package/src/lib/components/product-grid.js.map +1 -1
  59. package/src/lib/components/related-products.js +1 -1
  60. package/src/lib/components/related-products.js.map +1 -1
  61. package/src/lib/components/wishlist.js +1 -1
  62. package/src/lib/components/wishlist.js.map +1 -1
  63. package/src/lib/declarations.server.js +11 -0
  64. package/src/lib/declarations.server.js.map +1 -1
  65. package/src/lib/model/commerce-orders.d.ts +8 -0
  66. package/src/lib/model/commerce-orders.js.map +1 -1
  67. package/src/lib/model/commerce.d.ts +21 -0
  68. package/src/lib/model/commerce.js +39 -1
  69. package/src/lib/model/commerce.js.map +1 -1
  70. package/src/lib/model/index.d.ts +1 -0
  71. package/src/lib/model/index.js +1 -0
  72. package/src/lib/model/index.js.map +1 -1
  73. package/src/lib/model/order-annotations.d.ts +54 -0
  74. package/src/lib/model/order-annotations.js +76 -0
  75. package/src/lib/model/order-annotations.js.map +1 -0
  76. package/src/lib/model/order-events.d.ts +2 -0
  77. package/src/lib/model/order-events.js.map +1 -1
  78. package/src/lib/model/order-fulfillment.d.ts +29 -0
  79. package/src/lib/model/order-fulfillment.js +63 -0
  80. package/src/lib/model/order-fulfillment.js.map +1 -1
  81. package/src/lib/model/order-local-fulfillment.d.ts +36 -0
  82. package/src/lib/model/order-local-fulfillment.js +19 -1
  83. package/src/lib/model/order-local-fulfillment.js.map +1 -1
  84. package/src/lib/model/order-status-view.d.ts +11 -0
  85. package/src/lib/model/order-status-view.js +20 -3
  86. package/src/lib/model/order-status-view.js.map +1 -1
  87. package/src/lib/model/product-write.js +8 -4
  88. package/src/lib/model/product-write.js.map +1 -1
  89. package/src/lib/server/api-v1/openapi.js +1 -0
  90. package/src/lib/server/api-v1/openapi.js.map +1 -1
  91. package/src/lib/server/api-v1/order-view.d.ts +1 -0
  92. package/src/lib/server/api-v1/order-view.js +10 -0
  93. package/src/lib/server/api-v1/order-view.js.map +1 -1
  94. package/src/lib/server/cart-checkout.js +9 -1
  95. package/src/lib/server/cart-checkout.js.map +1 -1
  96. package/src/lib/server/catalog.d.ts +6 -0
  97. package/src/lib/server/catalog.js +3 -1
  98. package/src/lib/server/catalog.js.map +1 -1
  99. package/src/lib/server/checkout.js +11 -1
  100. package/src/lib/server/checkout.js.map +1 -1
  101. package/src/lib/server/fulfill-order.d.ts +12 -0
  102. package/src/lib/server/fulfill-order.js +13 -0
  103. package/src/lib/server/fulfill-order.js.map +1 -1
  104. package/src/lib/server/local-delivery-records.d.ts +30 -0
  105. package/src/lib/server/local-delivery-records.js +284 -0
  106. package/src/lib/server/local-delivery-records.js.map +1 -0
  107. package/src/lib/server/order-annotations.d.ts +28 -0
  108. package/src/lib/server/order-annotations.js +143 -0
  109. package/src/lib/server/order-annotations.js.map +1 -0
  110. package/src/lib/server/order-events.js +2 -1
  111. package/src/lib/server/order-events.js.map +1 -1
  112. package/src/lib/server/order-notifications.js +39 -8
  113. package/src/lib/server/order-notifications.js.map +1 -1
  114. package/src/lib/server/pos-payment.js +9 -3
  115. package/src/lib/server/pos-payment.js.map +1 -1
  116. package/src/lib/server/product-catalog.js +6 -2
  117. package/src/lib/server/product-catalog.js.map +1 -1
  118. package/src/lib/server/product-drafts.d.ts +36 -9
  119. package/src/lib/server/product-drafts.js +24 -5
  120. package/src/lib/server/product-drafts.js.map +1 -1
  121. package/src/lib/server/product.d.ts +6 -1
  122. package/src/lib/server/product.js +1 -1
  123. package/src/lib/server/product.js.map +1 -1
  124. package/src/lib/server/products-write.d.ts +29 -0
  125. package/src/lib/server/products-write.js +7 -7
  126. package/src/lib/server/products-write.js.map +1 -1
  127. package/src/lib/server/shipment-records.js +2 -0
  128. package/src/lib/server/shipment-records.js.map +1 -1
  129. package/src/lib/server/site-page-resolver.d.ts +13 -0
  130. package/src/lib/server/site-page-resolver.js +138 -1
  131. package/src/lib/server/site-page-resolver.js.map +1 -1
  132. package/src/lib/server.js +5 -0
  133. package/src/lib/server.js.map +1 -1
  134. package/src/lib/utils/use-storefront-purchase-event.js +8 -2
  135. package/src/lib/utils/use-storefront-purchase-event.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/order-fulfillment-panel.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport * as CommerceModel from '../../model'\nimport {\n Button,\n Checkbox,\n Chip,\n FormControlLabel,\n IconButton,\n Link,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { useCallback, useMemo, useState, type ReactNode } from 'react'\nimport type {\n ConsoleFulfillmentTracking,\n ConsoleOrderZoneAddress,\n ConsoleOrderZoneFulfillment,\n ConsoleOrderZoneOrder,\n} from './order-zones'\n\n/**\n * The order dialog's fulfillment surfaces (AGL-3611): the Fulfill items panel,\n * with a quantity per line, a carrier, a tracking number and the notify\n * switch; and the list of recorded shipments, each editable and cancellable.\n *\n * Neither writes. Every act goes through the dialog's `fulfill-order` route,\n * which re-checks the quantities and the transition under the write; these\n * only collect what the merchant means and hand it up.\n */\n\n/** The carrier select's value for a carrier typed by hand. */\nconst OTHER_CARRIER = 'other'\n\n/** What the panel asks the dialog to record. */\nexport interface FulfillItemsSubmission {\n /** Absent when the picked units are everything still to ship. */\n lineItems?: Array<{ lineItemId: number; quantity: number }>\n carrier: string\n trackingNumber: string\n trackingUrl?: string\n labelUrl?: string\n notify: boolean\n}\n\n/** The order a widget reads: the dialog's order in the zone's words. */\nexport function consoleOrderZoneOrder(\n order: CommerceModel.HostOrder,\n orderId: string,\n): ConsoleOrderZoneOrder {\n const states = CommerceModel.orderLineFulfillmentStates(order)\n const address = order.shippingAddress\n const shippingAddress: ConsoleOrderZoneAddress | null = address\n ? {\n name: address.name ?? null,\n line1: address.line1 ?? null,\n line2: address.line2 ?? null,\n city: address.city ?? null,\n state: address.state ?? null,\n postalCode: address.postalCode ?? null,\n country: address.country ?? null,\n phone: address.phone ?? null,\n }\n : null\n return {\n id: orderId,\n number: CommerceModel.formatOrderNumber(order, orderId),\n status: order.status,\n channel: order.channel ?? 'online',\n // Orders are charged in US dollars today, as the public API reports them.\n currency: 'USD',\n customerEmail: order.customerEmail ?? null,\n customerName: order.customerName ?? null,\n shippingAddress,\n lines: (order.lineItems ?? []).map((line, index) => ({\n lineItemId: index,\n productId: line.productId,\n variantId: line.variantId ?? null,\n name: line.name,\n variantLabel: line.variantLabel ?? null,\n sku: line.sku ?? null,\n productType: line.productType ?? null,\n quantity: states[index]?.quantity ?? 0,\n unitAmountCents: line.unitAmountCents,\n fulfilledQuantity: states[index]?.fulfilledQuantity ?? 0,\n remainingQuantity: states[index]?.remainingQuantity ?? 0,\n requiresShipping: states[index]?.requiresShipping ?? true,\n })),\n fulfillments: (order.fulfillments ?? []).map((entry) => toZoneFulfillment(order, entry)),\n totals: {\n itemsCents: order.totals?.itemsCents ?? 0,\n shippingCents: order.totals?.shippingCents ?? 0,\n taxCents: order.totals?.taxCents ?? 0,\n discountCents: order.totals?.discountCents ?? 0,\n totalCents: order.totals?.totalCents ?? Number(order.amountCents ?? 0),\n },\n testMode: CommerceModel.orderIsTestMode(order),\n }\n}\n\n/** One recorded shipment in the zone's words. */\nexport function toZoneFulfillment(\n order: Pick<CommerceModel.HostOrder, 'lineItems'>,\n entry: CommerceModel.OrderFulfillment,\n): ConsoleOrderZoneFulfillment {\n return {\n id: entry.id,\n lines: CommerceModel.fulfillmentLineQuantities(order, entry),\n carrier: entry.carrier ?? null,\n trackingNumber: entry.trackingNumber ?? null,\n trackingUrl: CommerceModel.fulfillmentTrackingUrl(entry),\n labelUrl: entry.labelUrl ?? null,\n status: CommerceModel.fulfillmentIsActive(entry) ? 'active' : 'cancelled',\n atMs: entry.atMs,\n }\n}\n\n/** The select's value for a typed carrier: a known name, or Other. */\nfunction carrierChoiceFor(carrier: string): string {\n if (!carrier) return ''\n const label = CommerceModel.carrierLabelFor(carrier)\n return CommerceModel.FULFILLMENT_CARRIER_CHOICES.includes(label) ? label : OTHER_CARRIER\n}\n\ninterface CarrierFieldsProps {\n carrier: string\n trackingNumber: string\n trackingUrl: string\n onChange: (patch: { carrier?: string; trackingNumber?: string; trackingUrl?: string }) => void\n}\n\n/**\n * Carrier, tracking number and, for a carrier without a known tracker, the\n * link. A native select so the choice is one keystroke and one change event.\n */\nfunction CarrierFields(props: CarrierFieldsProps) {\n const { carrier, trackingNumber, trackingUrl, onChange } = props\n const [other, setOther] = useState(() => carrierChoiceFor(carrier) === OTHER_CARRIER)\n const choice = other ? OTHER_CARRIER : carrierChoiceFor(carrier)\n const derived = CommerceModel.trackingUrlFor(carrier, trackingNumber)\n return (\n <Stack spacing={1}>\n <Stack direction=\"row\" spacing={1}>\n <TextField\n select\n label=\"Carrier\"\n value={choice}\n onChange={(event) => {\n const value = event.target.value\n setOther(value === OTHER_CARRIER)\n onChange({ carrier: value === OTHER_CARRIER ? '' : value })\n }}\n size=\"small\"\n sx={{ width: 160 }}\n slotProps={{ select: { native: true }, inputLabel: { shrink: true } }}\n >\n <option value=\"\">{'None'}</option>\n {CommerceModel.FULFILLMENT_CARRIER_CHOICES.map((name) => (\n <option key={name} value={name}>\n {name}\n </option>\n ))}\n <option value={OTHER_CARRIER}>{'Other'}</option>\n </TextField>\n {other ? (\n <TextField\n label=\"Carrier name\"\n value={carrier}\n onChange={(event) => onChange({ carrier: event.target.value })}\n size=\"small\"\n sx={{ width: 160 }}\n />\n ) : null}\n <TextField\n label=\"Tracking number\"\n value={trackingNumber}\n onChange={(event) => onChange({ trackingNumber: event.target.value })}\n size=\"small\"\n sx={{ flex: 1 }}\n />\n </Stack>\n {trackingNumber && !derived ? (\n <TextField\n label=\"Tracking link\"\n value={trackingUrl}\n onChange={(event) => onChange({ trackingUrl: event.target.value })}\n size=\"small\"\n placeholder=\"https://\"\n helperText=\"Optional. USPS, UPS, FedEx, DHL, Canada Post, Royal Mail and Australia Post get a link on their own.\"\n />\n ) : null}\n </Stack>\n )\n}\n\nexport interface FulfillItemsPanelProps {\n order: CommerceModel.HostOrder\n busy: boolean\n onSubmit: (submission: FulfillItemsSubmission) => Promise<boolean>\n onCancel: () => void\n /** Draws the `orderFulfillment` zone with the panel's current selection. */\n renderZone?: (\n selection: ReadonlyArray<{ lineItemId: number; quantity: number }>,\n applyTracking: (tracking: ConsoleFulfillmentTracking) => void,\n ) => ReactNode\n}\n\n/**\n * Fulfill items: one quantity per line, starting at what is left of each\n * shippable line, so the common case — ship everything — is one click.\n */\nexport function FulfillItemsPanel(props: FulfillItemsPanelProps) {\n const { order, busy, onSubmit, onCancel, renderZone } = props\n const states = useMemo(() => CommerceModel.orderLineFulfillmentStates(order), [order])\n const [quantities, setQuantities] = useState<Record<number, number>>(() =>\n Object.fromEntries(\n states.map((state) => [\n state.lineItemId,\n // Digital and service lines start at zero: nothing to ship. When the\n // order has nothing physical left, they start full instead, so the\n // panel still closes a digital-only order in one click.\n states.some((candidate) => candidate.requiresShipping && candidate.remainingQuantity > 0)\n ? state.requiresShipping\n ? state.remainingQuantity\n : 0\n : state.remainingQuantity,\n ]),\n ),\n )\n const [tracking, setTracking] = useState({ carrier: '', trackingNumber: '', trackingUrl: '', labelUrl: '' })\n const [notify, setNotify] = useState(true)\n const [zoneKey, setZoneKey] = useState(0)\n\n const selection = useMemo(\n () =>\n states\n .map((state) => ({ lineItemId: state.lineItemId, quantity: quantities[state.lineItemId] ?? 0 }))\n .filter((entry) => entry.quantity > 0),\n [states, quantities],\n )\n const everything = useMemo(() => {\n const remaining = CommerceModel.remainingFulfillmentLines(order)\n return (\n remaining.length > 0 &&\n remaining.length === selection.length &&\n remaining.every(\n (entry, index) =>\n selection[index]?.lineItemId === entry.lineItemId && selection[index]?.quantity === entry.quantity,\n )\n )\n }, [order, selection])\n\n const setQuantity = (lineItemId: number, value: number, max: number) =>\n setQuantities((current) => ({\n ...current,\n [lineItemId]: Math.max(0, Math.min(max, Math.floor(Number.isFinite(value) ? value : 0))),\n }))\n\n const applyTracking = useCallback((next: ConsoleFulfillmentTracking) => {\n setTracking({\n carrier: String(next.carrier ?? ''),\n trackingNumber: String(next.trackingNumber ?? ''),\n trackingUrl: String(next.trackingUrl ?? ''),\n labelUrl: String(next.labelUrl ?? ''),\n })\n // The carrier select reads its Other state once; a remount re-reads it.\n setZoneKey((key) => key + 1)\n }, [])\n\n const submit = async () => {\n await onSubmit({\n ...(everything ? {} : { lineItems: selection }),\n carrier: tracking.carrier.trim(),\n trackingNumber: tracking.trackingNumber.trim(),\n ...(tracking.trackingUrl.trim() ? { trackingUrl: tracking.trackingUrl.trim() } : {}),\n ...(tracking.labelUrl ? { labelUrl: tracking.labelUrl } : {}),\n notify,\n })\n }\n\n return (\n <Stack spacing={1} sx={{ border: 1, borderColor: 'divider', borderRadius: 1, p: 1.5 }}>\n <Typography variant=\"subtitle2\">{'Fulfill items'}</Typography>\n {(order.lineItems ?? []).map((line, index) => {\n const state = states[index]\n if (!state || state.remainingQuantity === 0) return null\n return (\n <Stack key={index} direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" sx={{ flex: 1 }}>\n {line.name + (line.variantLabel ? ` — ${line.variantLabel}` : '')}\n {state.requiresShipping ? null : (\n <Typography component=\"span\" variant=\"caption\" color=\"text.secondary\">\n {' · no shipping needed'}\n </Typography>\n )}\n </Typography>\n <IconButton\n size=\"small\"\n aria-label={`One fewer ${line.name}`}\n disabled={busy || (quantities[index] ?? 0) <= 0}\n onClick={() => setQuantity(index, (quantities[index] ?? 0) - 1, state.remainingQuantity)}\n >\n {'−'}\n </IconButton>\n <TextField\n size=\"small\"\n type=\"number\"\n value={quantities[index] ?? 0}\n onChange={(event) => setQuantity(index, Number(event.target.value), state.remainingQuantity)}\n sx={{ width: 72 }}\n slotProps={{\n htmlInput: {\n min: 0,\n max: state.remainingQuantity,\n 'aria-label': `Quantity of ${line.name} to fulfill`,\n },\n }}\n />\n <IconButton\n size=\"small\"\n aria-label={`One more ${line.name}`}\n disabled={busy || (quantities[index] ?? 0) >= state.remainingQuantity}\n onClick={() => setQuantity(index, (quantities[index] ?? 0) + 1, state.remainingQuantity)}\n >\n {'+'}\n </IconButton>\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ width: 56 }}>\n {`of ${state.remainingQuantity}`}\n </Typography>\n </Stack>\n )\n })}\n <CarrierFields\n key={zoneKey}\n carrier={tracking.carrier}\n trackingNumber={tracking.trackingNumber}\n trackingUrl={tracking.trackingUrl}\n onChange={(patch) => setTracking((current) => ({ ...current, ...patch }))}\n />\n {tracking.labelUrl ? (\n <Link href={tracking.labelUrl} target=\"_blank\" rel=\"noopener noreferrer\" variant=\"caption\">\n {'Shipping label'}\n </Link>\n ) : null}\n {renderZone ? renderZone(selection, applyTracking) : null}\n <FormControlLabel\n control={<Checkbox checked={notify} onChange={(event) => setNotify(event.target.checked)} />}\n label=\"Notify customer\"\n />\n <Stack direction=\"row\" spacing={1} sx={{ justifyContent: 'flex-end' }}>\n <Button size=\"small\" onClick={onCancel} disabled={busy}>\n {'Cancel'}\n </Button>\n <Button\n size=\"small\"\n variant=\"contained\"\n color=\"primary\"\n disabled={busy || selection.length === 0}\n onClick={submit}\n >\n {'Fulfill'}\n </Button>\n </Stack>\n </Stack>\n )\n}\n\nexport interface FulfillmentListProps {\n order: CommerceModel.HostOrder\n busy: boolean\n onUpdateTracking: (\n fulfillmentId: string,\n tracking: { carrier: string; trackingNumber: string; trackingUrl?: string },\n ) => Promise<boolean>\n onCancelFulfillment: (fulfillmentId: string) => Promise<void>\n}\n\n/** The shipments recorded on the order, newest last, with edit and cancel. */\nexport function FulfillmentList(props: FulfillmentListProps) {\n const { order, busy, onUpdateTracking, onCancelFulfillment } = props\n const [editing, setEditing] = useState<{\n id: string\n carrier: string\n trackingNumber: string\n trackingUrl: string\n } | null>(null)\n const fulfillments = order.fulfillments ?? []\n if (fulfillments.length === 0) return null\n const editable = CommerceModel.orderFulfillmentsEditable(order)\n return (\n <Stack spacing={1}>\n <Typography variant=\"subtitle2\">{'Shipments'}</Typography>\n {fulfillments.map((entry) => {\n const active = CommerceModel.fulfillmentIsActive(entry)\n const lines = CommerceModel.fulfillmentLineQuantities(order, entry)\n const url = CommerceModel.fulfillmentTrackingUrl(entry)\n const carrier = entry.carrier ? CommerceModel.carrierLabelFor(entry.carrier) : ''\n return (\n <Stack key={entry.id} spacing={0.5}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography\n variant=\"body2\"\n sx={{ flex: 1, ...(active ? {} : { textDecoration: 'line-through' }) }}\n color={active ? 'text.primary' : 'text.secondary'}\n >\n {CommerceModel.describeFulfillmentLines(order, lines) || 'Fulfilled'}\n </Typography>\n {active ? null : <Chip label=\"canceled\" size=\"small\" variant=\"outlined\" />}\n {active && editable && editing?.id !== entry.id ? (\n <>\n <Button\n size=\"small\"\n disabled={busy}\n onClick={() =>\n setEditing({\n id: entry.id,\n carrier: entry.carrier ?? '',\n trackingNumber: entry.trackingNumber ?? '',\n trackingUrl: entry.trackingUrl ?? '',\n })\n }\n >\n {'Edit tracking'}\n </Button>\n <Button size=\"small\" color=\"error\" disabled={busy} onClick={() => onCancelFulfillment(entry.id)}>\n {'Cancel shipment'}\n </Button>\n </>\n ) : null}\n </Stack>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`${new Date(entry.atMs).toLocaleString()}`}\n {entry.trackingNumber ? ` · ${carrier || 'Tracking'} ` : ''}\n {entry.trackingNumber ? (\n url ? (\n <Link href={url} target=\"_blank\" rel=\"noopener noreferrer\">\n {entry.trackingNumber}\n </Link>\n ) : (\n entry.trackingNumber\n )\n ) : null}\n {entry.labelUrl ? (\n <>\n {' · '}\n <Link href={entry.labelUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n {'Label'}\n </Link>\n </>\n ) : null}\n </Typography>\n {editing?.id === entry.id ? (\n <Stack spacing={1}>\n <CarrierFields\n carrier={editing.carrier}\n trackingNumber={editing.trackingNumber}\n trackingUrl={editing.trackingUrl}\n onChange={(patch) => setEditing({ ...editing, ...patch })}\n />\n <Stack direction=\"row\" spacing={1} sx={{ justifyContent: 'flex-end' }}>\n <Button size=\"small\" disabled={busy} onClick={() => setEditing(null)}>\n {'Discard'}\n </Button>\n <Button\n size=\"small\"\n variant=\"contained\"\n disabled={busy}\n onClick={async () => {\n const saved = await onUpdateTracking(entry.id, {\n carrier: editing.carrier.trim(),\n trackingNumber: editing.trackingNumber.trim(),\n ...(editing.trackingUrl.trim() ? { trackingUrl: editing.trackingUrl.trim() } : {}),\n })\n if (saved) setEditing(null)\n }}\n >\n {'Save tracking'}\n </Button>\n </Stack>\n </Stack>\n ) : null}\n </Stack>\n )\n })}\n </Stack>\n )\n}\n"],"names":["CommerceModel","Button","Checkbox","Chip","FormControlLabel","IconButton","Link","Stack","TextField","Typography","useCallback","useMemo","useState","OTHER_CARRIER","consoleOrderZoneOrder","order","orderId","address","states","orderLineFulfillmentStates","shippingAddress","name","line1","line2","city","state","postalCode","country","phone","id","number","formatOrderNumber","status","channel","currency","customerEmail","customerName","lines","lineItems","map","line","index","lineItemId","productId","variantId","variantLabel","sku","productType","quantity","unitAmountCents","fulfilledQuantity","remainingQuantity","requiresShipping","fulfillments","entry","toZoneFulfillment","totals","itemsCents","shippingCents","taxCents","discountCents","totalCents","Number","amountCents","testMode","orderIsTestMode","fulfillmentLineQuantities","carrier","trackingNumber","trackingUrl","fulfillmentTrackingUrl","labelUrl","fulfillmentIsActive","atMs","carrierChoiceFor","label","carrierLabelFor","FULFILLMENT_CARRIER_CHOICES","includes","CarrierFields","props","onChange","other","setOther","choice","derived","trackingUrlFor","spacing","direction","select","value","event","target","size","sx","width","slotProps","native","inputLabel","shrink","option","flex","placeholder","helperText","FulfillItemsPanel","busy","onSubmit","onCancel","renderZone","quantities","setQuantities","Object","fromEntries","some","candidate","tracking","setTracking","notify","setNotify","zoneKey","setZoneKey","selection","filter","everything","remaining","remainingFulfillmentLines","length","every","setQuantity","max","current","Math","min","floor","isFinite","applyTracking","next","String","key","submit","trim","border","borderColor","borderRadius","p","variant","alignItems","component","color","aria-label","disabled","onClick","type","htmlInput","patch","href","rel","control","checked","justifyContent","FulfillmentList","onUpdateTracking","onCancelFulfillment","editing","setEditing","editable","orderFulfillmentsEditable","active","url","textDecoration","describeFulfillmentLines","Date","toLocaleString","saved"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/order-fulfillment-panel.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport * as CommerceModel from '../../model'\nimport {\n Button,\n Checkbox,\n Chip,\n FormControlLabel,\n IconButton,\n InputAdornment,\n Link,\n Stack,\n TextField,\n Typography,\n} from '@mui/material'\nimport { useCallback, useMemo, useState, type ReactNode } from 'react'\nimport type {\n ConsoleFulfillmentTracking,\n ConsoleOrderZoneAddress,\n ConsoleOrderZoneFulfillment,\n ConsoleOrderZoneLocalDelivery,\n ConsoleOrderZoneOrder,\n} from './order-zones'\n\n/**\n * The order dialog's fulfillment surfaces (AGL-3611): the Fulfill items panel,\n * with a quantity per line, a carrier, a tracking number and the notify\n * switch; and the list of recorded shipments, each editable and cancellable.\n *\n * Neither writes. Every act goes through the dialog's `fulfill-order` route,\n * which re-checks the quantities and the transition under the write; these\n * only collect what the merchant means and hand it up.\n */\n\n/** The carrier select's value for a carrier typed by hand. */\nconst OTHER_CARRIER = 'other'\n\n/** What the panel asks the dialog to record. */\nexport interface FulfillItemsSubmission {\n /** Absent when the picked units are everything still to ship. */\n lineItems?: Array<{ lineItemId: number; quantity: number }>\n carrier: string\n trackingNumber: string\n trackingUrl?: string\n labelUrl?: string\n /**\n * What sending the shipment cost, typed by hand (AGL-3705): integer minor\n * units of the store's currency, 0 for free. Absent when the field was\n * left empty (not known) or a label was applied, whose own cost is kept.\n */\n shippingCostCents?: number\n notify: boolean\n}\n\n/** The currency's symbol as the merchant reads it (`$`, `€`, `¥`), or its code. */\nfunction currencySymbol(currency: string): string {\n try {\n const part = new Intl.NumberFormat('en-US', { style: 'currency', currency })\n .formatToParts(0)\n .find((entry) => entry.type === 'currency')\n return part?.value ?? currency\n } catch {\n return currency\n }\n}\n\n/** The order a widget reads: the dialog's order in the zone's words. */\nexport function consoleOrderZoneOrder(\n order: CommerceModel.HostOrder,\n orderId: string,\n): ConsoleOrderZoneOrder {\n const states = CommerceModel.orderLineFulfillmentStates(order)\n const address = order.shippingAddress\n const shippingAddress: ConsoleOrderZoneAddress | null = address\n ? {\n name: address.name ?? null,\n line1: address.line1 ?? null,\n line2: address.line2 ?? null,\n city: address.city ?? null,\n state: address.state ?? null,\n postalCode: address.postalCode ?? null,\n country: address.country ?? null,\n phone: address.phone ?? null,\n }\n : null\n return {\n id: orderId,\n number: CommerceModel.formatOrderNumber(order, orderId),\n status: order.status,\n channel: order.channel ?? 'online',\n // Orders are charged in US dollars today, as the public API reports them.\n currency: 'USD',\n customerEmail: order.customerEmail ?? null,\n customerName: order.customerName ?? null,\n shippingAddress,\n lines: (order.lineItems ?? []).map((line, index) => ({\n lineItemId: index,\n productId: line.productId,\n variantId: line.variantId ?? null,\n name: line.name,\n variantLabel: line.variantLabel ?? null,\n sku: line.sku ?? null,\n productType: line.productType ?? null,\n quantity: states[index]?.quantity ?? 0,\n unitAmountCents: line.unitAmountCents,\n fulfilledQuantity: states[index]?.fulfilledQuantity ?? 0,\n remainingQuantity: states[index]?.remainingQuantity ?? 0,\n requiresShipping: states[index]?.requiresShipping ?? true,\n })),\n fulfillments: (order.fulfillments ?? []).map((entry) => toZoneFulfillment(order, entry)),\n totals: {\n itemsCents: order.totals?.itemsCents ?? 0,\n shippingCents: order.totals?.shippingCents ?? 0,\n taxCents: order.totals?.taxCents ?? 0,\n discountCents: order.totals?.discountCents ?? 0,\n totalCents: order.totals?.totalCents ?? Number(order.amountCents ?? 0),\n },\n testMode: CommerceModel.orderIsTestMode(order),\n fulfillmentMethod: order.fulfillmentMethod ?? 'shipping',\n localDelivery: zoneLocalDelivery(order),\n }\n}\n\n/** The order's local delivery in the zone's words, or `null` on any other order (AGL-3695). */\nexport function zoneLocalDelivery(order: CommerceModel.HostOrder): ConsoleOrderZoneLocalDelivery | null {\n const delivery = order.fulfillmentMethod === 'local_delivery' ? order.localDelivery : undefined\n if (!delivery) return null\n const courier = delivery.courier\n return {\n status: CommerceModel.orderLocalDeliveryStatus(delivery.status),\n windowStartMs: Number(delivery.windowStartMs) || null,\n windowEndMs: Number(delivery.windowEndMs) || null,\n windowLabel: delivery.windowLabel ?? null,\n courier: courier\n ? {\n provider: String(courier.provider ?? ''),\n providerLabel: String(courier.providerLabel ?? courier.provider ?? 'Courier'),\n deliveryRef: String(courier.deliveryRef ?? ''),\n state: String(courier.state ?? ''),\n trackingUrl: courier.trackingUrl ?? null,\n etaMs: Number(courier.etaMs) || null,\n reason: courier.reason ?? null,\n testMode: courier.testMode === true,\n updatedAtMs: Number(courier.updatedAtMs) || 0,\n }\n : null,\n }\n}\n\n/** One recorded shipment in the zone's words. */\nexport function toZoneFulfillment(\n order: Pick<CommerceModel.HostOrder, 'lineItems'>,\n entry: CommerceModel.OrderFulfillment,\n): ConsoleOrderZoneFulfillment {\n return {\n id: entry.id,\n lines: CommerceModel.fulfillmentLineQuantities(order, entry),\n carrier: entry.carrier ?? null,\n trackingNumber: entry.trackingNumber ?? null,\n trackingUrl: CommerceModel.fulfillmentTrackingUrl(entry),\n labelUrl: entry.labelUrl ?? null,\n status: CommerceModel.fulfillmentIsActive(entry) ? 'active' : 'cancelled',\n atMs: entry.atMs,\n }\n}\n\n/** The select's value for a typed carrier: a known name, or Other. */\nfunction carrierChoiceFor(carrier: string): string {\n if (!carrier) return ''\n const label = CommerceModel.carrierLabelFor(carrier)\n return CommerceModel.FULFILLMENT_CARRIER_CHOICES.includes(label) ? label : OTHER_CARRIER\n}\n\ninterface CarrierFieldsProps {\n carrier: string\n trackingNumber: string\n trackingUrl: string\n onChange: (patch: { carrier?: string; trackingNumber?: string; trackingUrl?: string }) => void\n}\n\n/**\n * Carrier, tracking number and, for a carrier without a known tracker, the\n * link. A native select so the choice is one keystroke and one change event.\n */\nfunction CarrierFields(props: CarrierFieldsProps) {\n const { carrier, trackingNumber, trackingUrl, onChange } = props\n const [other, setOther] = useState(() => carrierChoiceFor(carrier) === OTHER_CARRIER)\n const choice = other ? OTHER_CARRIER : carrierChoiceFor(carrier)\n const derived = CommerceModel.trackingUrlFor(carrier, trackingNumber)\n return (\n <Stack spacing={1}>\n <Stack direction=\"row\" spacing={1}>\n <TextField\n select\n label=\"Carrier\"\n value={choice}\n onChange={(event) => {\n const value = event.target.value\n setOther(value === OTHER_CARRIER)\n onChange({ carrier: value === OTHER_CARRIER ? '' : value })\n }}\n size=\"small\"\n sx={{ width: 160 }}\n slotProps={{ select: { native: true }, inputLabel: { shrink: true } }}\n >\n <option value=\"\">{'None'}</option>\n {CommerceModel.FULFILLMENT_CARRIER_CHOICES.map((name) => (\n <option key={name} value={name}>\n {name}\n </option>\n ))}\n <option value={OTHER_CARRIER}>{'Other'}</option>\n </TextField>\n {other ? (\n <TextField\n label=\"Carrier name\"\n value={carrier}\n onChange={(event) => onChange({ carrier: event.target.value })}\n size=\"small\"\n sx={{ width: 160 }}\n />\n ) : null}\n <TextField\n label=\"Tracking number\"\n value={trackingNumber}\n onChange={(event) => onChange({ trackingNumber: event.target.value })}\n size=\"small\"\n sx={{ flex: 1 }}\n />\n </Stack>\n {trackingNumber && !derived ? (\n <TextField\n label=\"Tracking link\"\n value={trackingUrl}\n onChange={(event) => onChange({ trackingUrl: event.target.value })}\n size=\"small\"\n placeholder=\"https://\"\n helperText=\"Optional. USPS, UPS, FedEx, DHL, Canada Post, Royal Mail and Australia Post get a link on their own.\"\n />\n ) : null}\n </Stack>\n )\n}\n\nexport interface FulfillItemsPanelProps {\n order: CommerceModel.HostOrder\n busy: boolean\n onSubmit: (submission: FulfillItemsSubmission) => Promise<boolean>\n onCancel: () => void\n /** The store's currency (ISO 4217), which a hand-entered shipping cost is in. Default USD. */\n currency?: string\n /** Draws the `orderFulfillment` zone with the panel's current selection. */\n renderZone?: (\n selection: ReadonlyArray<{ lineItemId: number; quantity: number }>,\n applyTracking: (tracking: ConsoleFulfillmentTracking) => void,\n ) => ReactNode\n}\n\n/**\n * Fulfill items: one quantity per line, starting at what is left of each\n * shippable line, so the common case — ship everything — is one click.\n */\nexport function FulfillItemsPanel(props: FulfillItemsPanelProps) {\n const { order, busy, onSubmit, onCancel, renderZone } = props\n const currency = String(props.currency || 'USD').toUpperCase()\n const states = useMemo(() => CommerceModel.orderLineFulfillmentStates(order), [order])\n const [quantities, setQuantities] = useState<Record<number, number>>(() =>\n Object.fromEntries(\n states.map((state) => [\n state.lineItemId,\n // Digital and service lines start at zero: nothing to ship. When the\n // order has nothing physical left, they start full instead, so the\n // panel still closes a digital-only order in one click.\n states.some((candidate) => candidate.requiresShipping && candidate.remainingQuantity > 0)\n ? state.requiresShipping\n ? state.remainingQuantity\n : 0\n : state.remainingQuantity,\n ]),\n ),\n )\n const [tracking, setTracking] = useState({ carrier: '', trackingNumber: '', trackingUrl: '', labelUrl: '' })\n const [notify, setNotify] = useState(true)\n const [shippingCost, setShippingCost] = useState('')\n // A label applied by a widget carries its own cost, recorded where it was\n // bought; the hand-entered field is for a shipment sent some other way.\n const handEntered = !tracking.labelUrl\n const cost = useMemo(() => CommerceModel.parseShippingCostInput(shippingCost, currency), [shippingCost, currency])\n const costError = handEntered && 'error' in cost ? cost.error : null\n const [zoneKey, setZoneKey] = useState(0)\n\n const selection = useMemo(\n () =>\n states\n .map((state) => ({ lineItemId: state.lineItemId, quantity: quantities[state.lineItemId] ?? 0 }))\n .filter((entry) => entry.quantity > 0),\n [states, quantities],\n )\n const everything = useMemo(() => {\n const remaining = CommerceModel.remainingFulfillmentLines(order)\n return (\n remaining.length > 0 &&\n remaining.length === selection.length &&\n remaining.every(\n (entry, index) =>\n selection[index]?.lineItemId === entry.lineItemId && selection[index]?.quantity === entry.quantity,\n )\n )\n }, [order, selection])\n\n const setQuantity = (lineItemId: number, value: number, max: number) =>\n setQuantities((current) => ({\n ...current,\n [lineItemId]: Math.max(0, Math.min(max, Math.floor(Number.isFinite(value) ? value : 0))),\n }))\n\n const applyTracking = useCallback((next: ConsoleFulfillmentTracking) => {\n setTracking({\n carrier: String(next.carrier ?? ''),\n trackingNumber: String(next.trackingNumber ?? ''),\n trackingUrl: String(next.trackingUrl ?? ''),\n labelUrl: String(next.labelUrl ?? ''),\n })\n // The carrier select reads its Other state once; a remount re-reads it.\n setZoneKey((key) => key + 1)\n }, [])\n\n const submit = async () => {\n await onSubmit({\n ...(everything ? {} : { lineItems: selection }),\n carrier: tracking.carrier.trim(),\n trackingNumber: tracking.trackingNumber.trim(),\n ...(tracking.trackingUrl.trim() ? { trackingUrl: tracking.trackingUrl.trim() } : {}),\n ...(tracking.labelUrl ? { labelUrl: tracking.labelUrl } : {}),\n ...(handEntered && 'cents' in cost && cost.cents !== null ? { shippingCostCents: cost.cents } : {}),\n notify,\n })\n }\n\n return (\n <Stack spacing={1} sx={{ border: 1, borderColor: 'divider', borderRadius: 1, p: 1.5 }}>\n <Typography variant=\"subtitle2\">{'Fulfill items'}</Typography>\n {(order.lineItems ?? []).map((line, index) => {\n const state = states[index]\n if (!state || state.remainingQuantity === 0) return null\n return (\n <Stack key={index} direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography variant=\"body2\" sx={{ flex: 1 }}>\n {line.name + (line.variantLabel ? ` — ${line.variantLabel}` : '')}\n {state.requiresShipping ? null : (\n <Typography component=\"span\" variant=\"caption\" color=\"text.secondary\">\n {' · no shipping needed'}\n </Typography>\n )}\n </Typography>\n <IconButton\n size=\"small\"\n aria-label={`One fewer ${line.name}`}\n disabled={busy || (quantities[index] ?? 0) <= 0}\n onClick={() => setQuantity(index, (quantities[index] ?? 0) - 1, state.remainingQuantity)}\n >\n {'−'}\n </IconButton>\n <TextField\n size=\"small\"\n type=\"number\"\n value={quantities[index] ?? 0}\n onChange={(event) => setQuantity(index, Number(event.target.value), state.remainingQuantity)}\n sx={{ width: 72 }}\n slotProps={{\n htmlInput: {\n min: 0,\n max: state.remainingQuantity,\n 'aria-label': `Quantity of ${line.name} to fulfill`,\n },\n }}\n />\n <IconButton\n size=\"small\"\n aria-label={`One more ${line.name}`}\n disabled={busy || (quantities[index] ?? 0) >= state.remainingQuantity}\n onClick={() => setQuantity(index, (quantities[index] ?? 0) + 1, state.remainingQuantity)}\n >\n {'+'}\n </IconButton>\n <Typography variant=\"caption\" color=\"text.secondary\" sx={{ width: 56 }}>\n {`of ${state.remainingQuantity}`}\n </Typography>\n </Stack>\n )\n })}\n <CarrierFields\n key={zoneKey}\n carrier={tracking.carrier}\n trackingNumber={tracking.trackingNumber}\n trackingUrl={tracking.trackingUrl}\n onChange={(patch) => setTracking((current) => ({ ...current, ...patch }))}\n />\n {tracking.labelUrl ? (\n <Link href={tracking.labelUrl} target=\"_blank\" rel=\"noopener noreferrer\" variant=\"caption\">\n {'Shipping label'}\n </Link>\n ) : null}\n {handEntered ? (\n <TextField\n label=\"Shipping cost\"\n value={shippingCost}\n onChange={(event) => setShippingCost(event.target.value)}\n size=\"small\"\n sx={{ width: 220 }}\n error={Boolean(costError)}\n helperText={costError ?? `Optional. What sending this shipment cost you, in ${currency}.`}\n slotProps={{\n input: { startAdornment: <InputAdornment position=\"start\">{currencySymbol(currency)}</InputAdornment> },\n htmlInput: { inputMode: 'decimal' },\n }}\n />\n ) : null}\n {renderZone ? renderZone(selection, applyTracking) : null}\n <FormControlLabel\n control={<Checkbox checked={notify} onChange={(event) => setNotify(event.target.checked)} />}\n label=\"Notify customer\"\n />\n <Stack direction=\"row\" spacing={1} sx={{ justifyContent: 'flex-end' }}>\n <Button size=\"small\" onClick={onCancel} disabled={busy}>\n {'Cancel'}\n </Button>\n <Button\n size=\"small\"\n variant=\"contained\"\n color=\"primary\"\n disabled={busy || selection.length === 0 || Boolean(costError)}\n onClick={submit}\n >\n {'Fulfill'}\n </Button>\n </Stack>\n </Stack>\n )\n}\n\nexport interface FulfillmentListProps {\n order: CommerceModel.HostOrder\n busy: boolean\n onUpdateTracking: (\n fulfillmentId: string,\n tracking: { carrier: string; trackingNumber: string; trackingUrl?: string },\n ) => Promise<boolean>\n onCancelFulfillment: (fulfillmentId: string) => Promise<void>\n}\n\n/** The shipments recorded on the order, newest last, with edit and cancel. */\nexport function FulfillmentList(props: FulfillmentListProps) {\n const { order, busy, onUpdateTracking, onCancelFulfillment } = props\n const [editing, setEditing] = useState<{\n id: string\n carrier: string\n trackingNumber: string\n trackingUrl: string\n } | null>(null)\n const fulfillments = order.fulfillments ?? []\n if (fulfillments.length === 0) return null\n const editable = CommerceModel.orderFulfillmentsEditable(order)\n return (\n <Stack spacing={1}>\n <Typography variant=\"subtitle2\">{'Shipments'}</Typography>\n {fulfillments.map((entry) => {\n const active = CommerceModel.fulfillmentIsActive(entry)\n const lines = CommerceModel.fulfillmentLineQuantities(order, entry)\n const url = CommerceModel.fulfillmentTrackingUrl(entry)\n const carrier = entry.carrier ? CommerceModel.carrierLabelFor(entry.carrier) : ''\n return (\n <Stack key={entry.id} spacing={0.5}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Typography\n variant=\"body2\"\n sx={{ flex: 1, ...(active ? {} : { textDecoration: 'line-through' }) }}\n color={active ? 'text.primary' : 'text.secondary'}\n >\n {CommerceModel.describeFulfillmentLines(order, lines) || 'Fulfilled'}\n </Typography>\n {active ? null : <Chip label=\"canceled\" size=\"small\" variant=\"outlined\" />}\n {active && editable && editing?.id !== entry.id ? (\n <>\n <Button\n size=\"small\"\n disabled={busy}\n onClick={() =>\n setEditing({\n id: entry.id,\n carrier: entry.carrier ?? '',\n trackingNumber: entry.trackingNumber ?? '',\n trackingUrl: entry.trackingUrl ?? '',\n })\n }\n >\n {'Edit tracking'}\n </Button>\n <Button size=\"small\" color=\"error\" disabled={busy} onClick={() => onCancelFulfillment(entry.id)}>\n {'Cancel shipment'}\n </Button>\n </>\n ) : null}\n </Stack>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`${new Date(entry.atMs).toLocaleString()}`}\n {entry.trackingNumber ? ` · ${carrier || 'Tracking'} ` : ''}\n {entry.trackingNumber ? (\n url ? (\n <Link href={url} target=\"_blank\" rel=\"noopener noreferrer\">\n {entry.trackingNumber}\n </Link>\n ) : (\n entry.trackingNumber\n )\n ) : null}\n {entry.labelUrl ? (\n <>\n {' · '}\n <Link href={entry.labelUrl} target=\"_blank\" rel=\"noopener noreferrer\">\n {'Label'}\n </Link>\n </>\n ) : null}\n </Typography>\n {editing?.id === entry.id ? (\n <Stack spacing={1}>\n <CarrierFields\n carrier={editing.carrier}\n trackingNumber={editing.trackingNumber}\n trackingUrl={editing.trackingUrl}\n onChange={(patch) => setEditing({ ...editing, ...patch })}\n />\n <Stack direction=\"row\" spacing={1} sx={{ justifyContent: 'flex-end' }}>\n <Button size=\"small\" disabled={busy} onClick={() => setEditing(null)}>\n {'Discard'}\n </Button>\n <Button\n size=\"small\"\n variant=\"contained\"\n disabled={busy}\n onClick={async () => {\n const saved = await onUpdateTracking(entry.id, {\n carrier: editing.carrier.trim(),\n trackingNumber: editing.trackingNumber.trim(),\n ...(editing.trackingUrl.trim() ? { trackingUrl: editing.trackingUrl.trim() } : {}),\n })\n if (saved) setEditing(null)\n }}\n >\n {'Save tracking'}\n </Button>\n </Stack>\n </Stack>\n ) : null}\n </Stack>\n )\n })}\n </Stack>\n )\n}\n"],"names":["CommerceModel","Button","Checkbox","Chip","FormControlLabel","IconButton","InputAdornment","Link","Stack","TextField","Typography","useCallback","useMemo","useState","OTHER_CARRIER","currencySymbol","currency","part","Intl","NumberFormat","style","formatToParts","find","entry","type","value","consoleOrderZoneOrder","order","orderId","address","states","orderLineFulfillmentStates","shippingAddress","name","line1","line2","city","state","postalCode","country","phone","id","number","formatOrderNumber","status","channel","customerEmail","customerName","lines","lineItems","map","line","index","lineItemId","productId","variantId","variantLabel","sku","productType","quantity","unitAmountCents","fulfilledQuantity","remainingQuantity","requiresShipping","fulfillments","toZoneFulfillment","totals","itemsCents","shippingCents","taxCents","discountCents","totalCents","Number","amountCents","testMode","orderIsTestMode","fulfillmentMethod","localDelivery","zoneLocalDelivery","delivery","courier","undefined","orderLocalDeliveryStatus","windowStartMs","windowEndMs","windowLabel","provider","String","providerLabel","deliveryRef","trackingUrl","etaMs","reason","updatedAtMs","fulfillmentLineQuantities","carrier","trackingNumber","fulfillmentTrackingUrl","labelUrl","fulfillmentIsActive","atMs","carrierChoiceFor","label","carrierLabelFor","FULFILLMENT_CARRIER_CHOICES","includes","CarrierFields","props","onChange","other","setOther","choice","derived","trackingUrlFor","spacing","direction","select","event","target","size","sx","width","slotProps","native","inputLabel","shrink","option","flex","placeholder","helperText","FulfillItemsPanel","busy","onSubmit","onCancel","renderZone","toUpperCase","quantities","setQuantities","Object","fromEntries","some","candidate","tracking","setTracking","notify","setNotify","shippingCost","setShippingCost","handEntered","cost","parseShippingCostInput","costError","error","zoneKey","setZoneKey","selection","filter","everything","remaining","remainingFulfillmentLines","length","every","setQuantity","max","current","Math","min","floor","isFinite","applyTracking","next","key","submit","trim","cents","shippingCostCents","border","borderColor","borderRadius","p","variant","alignItems","component","color","aria-label","disabled","onClick","htmlInput","patch","href","rel","Boolean","input","startAdornment","position","inputMode","control","checked","justifyContent","FulfillmentList","onUpdateTracking","onCancelFulfillment","editing","setEditing","editable","orderFulfillmentsEditable","active","url","textDecoration","describeFulfillmentLines","Date","toLocaleString","saved"],"mappings":"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"}
@@ -16,7 +16,9 @@
16
16
  */
17
17
  /**
18
18
  * The zones the order dialog hosts (AGL-3611): `orderDetail`, beside the
19
- * order's actions, and `orderFulfillment`, inside the Fulfill items panel.
19
+ * order's actions, and `orderFulfillment`, inside the Fulfill items panel;
20
+ * and `localDeliveryRow`, in a delivery's row of the Pickup & delivery queue
21
+ * (AGL-3695).
20
22
  *
21
23
  * Declared here because zones are declared by the plugin that hosts them (the
22
24
  * product zones are the precedent). A widget from another plugin — a shipping
@@ -91,6 +93,47 @@ export interface ConsoleOrderZoneOrder {
91
93
  };
92
94
  /** Whether the order was paid in Stripe test mode. */
93
95
  testMode: boolean;
96
+ /**
97
+ * How the buyer receives it (AGL-3624): `shipping`, `pickup` or
98
+ * `local_delivery`. Optional, so a widget written before reads it as shipped.
99
+ */
100
+ fulfillmentMethod?: string;
101
+ /** The store's own delivery, on a `local_delivery` order (AGL-3695); `null` otherwise. */
102
+ localDelivery?: ConsoleOrderZoneLocalDelivery | null;
103
+ }
104
+ /**
105
+ * A local delivery as a widget reads it (AGL-3695): where it stands, the
106
+ * window the buyer booked, and the outside courier on it, if one was sent.
107
+ */
108
+ export interface ConsoleOrderZoneLocalDelivery {
109
+ /** `scheduled`, `out_for_delivery`, `delivered` or `failed`. */
110
+ status: string;
111
+ windowStartMs: number | null;
112
+ windowEndMs: number | null;
113
+ windowLabel: string | null;
114
+ courier: {
115
+ provider: string;
116
+ providerLabel: string;
117
+ deliveryRef: string;
118
+ state: string;
119
+ trackingUrl: string | null;
120
+ etaMs: number | null;
121
+ reason: string | null;
122
+ testMode: boolean;
123
+ updatedAtMs: number;
124
+ } | null;
125
+ }
126
+ /**
127
+ * What the `localDeliveryRow` zone hands each widget (AGL-3695): one local
128
+ * delivery in the Pickup & delivery queue, beside the row's own step
129
+ * buttons. A widget there is a compact control — a courier's "Send a
130
+ * courier" — and moves nothing itself: the courier's progress comes back
131
+ * through core's `core.local-delivery-records`.
132
+ */
133
+ export interface ConsoleLocalDeliveryRowZoneProps {
134
+ hostId: string;
135
+ orgId: string | undefined;
136
+ order: ConsoleOrderZoneOrder;
94
137
  }
95
138
  /** A shipment a widget asks the dialog to record. */
96
139
  export interface ConsoleFulfillmentRequest {
@@ -151,5 +194,6 @@ export interface ConsoleOrderFulfillmentZoneProps extends ConsoleOrderDetailZone
151
194
  }
152
195
  export declare const ORDER_DETAIL_ZONE: import("@aglyn/aglyn/plugin-manager/plugin-zones").PluginZone<ConsoleOrderDetailZoneProps>;
153
196
  export declare const ORDER_FULFILLMENT_ZONE: import("@aglyn/aglyn/plugin-manager/plugin-zones").PluginZone<ConsoleOrderFulfillmentZoneProps>;
197
+ export declare const LOCAL_DELIVERY_ROW_ZONE: import("@aglyn/aglyn/plugin-manager/plugin-zones").PluginZone<ConsoleLocalDeliveryRowZoneProps>;
154
198
  /** Declares the two order zones, from the console registrar. */
155
199
  export declare function registerCommerceOrderZones(): void;
@@ -17,6 +17,7 @@
17
17
  import { BUNDLE_ID } from "../../constants/bundle-common.js";
18
18
  export const ORDER_DETAIL_ZONE = definePluginZone('orderDetail');
19
19
  export const ORDER_FULFILLMENT_ZONE = definePluginZone('orderFulfillment');
20
+ export const LOCAL_DELIVERY_ROW_ZONE = definePluginZone('localDeliveryRow');
20
21
  /** Declares the two order zones, from the console registrar. */ export function registerCommerceOrderZones() {
21
22
  const owner = {
22
23
  pluginId: BUNDLE_ID
@@ -35,6 +36,13 @@ export const ORDER_FULFILLMENT_ZONE = definePluginZone('orderFulfillment');
35
36
  layout: 'bare',
36
37
  description: 'Inside the order dialog’s Fulfill items panel. A widget here reads the units picked and fills the carrier and tracking through `applyTracking` (a bought label’s), for the merchant to confirm with Fulfill.'
37
38
  }, owner);
39
+ registerPluginZone({
40
+ zone: LOCAL_DELIVERY_ROW_ZONE,
41
+ label: 'Local delivery row',
42
+ surface: 'console',
43
+ layout: 'bare',
44
+ description: 'In a local delivery’s row of the Pickup & delivery queue, beside its step buttons. A widget here is a compact control that reads the order and its delivery — the window, the status and any courier on it — such as sending an outside courier.'
45
+ }, owner);
38
46
  }
39
47
 
40
48
  //# sourceMappingURL=order-zones.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/order-zones.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n definePluginZone,\n registerPluginZone,\n} from '@aglyn/aglyn/plugin-manager/plugin-zones'\nimport { BUNDLE_ID } from '../../constants/bundle-common'\n\n/**\n * The zones the order dialog hosts (AGL-3611): `orderDetail`, beside the\n * order's actions, and `orderFulfillment`, inside the Fulfill items panel.\n *\n * Declared here because zones are declared by the plugin that hosts them (the\n * product zones are the precedent). A widget from another plugin — a shipping\n * plugin's \"Buy label\" — restates the props it reads rather than importing\n * this package. A widget proposes and never writes the order itself: the\n * shipment it records goes through `recordFulfillment`, which is this\n * plugin's own route with its role gate, its quantity check and its\n * transition rule.\n */\n\n/** One order line as a widget reads it. `lineItemId` is the line's index. */\nexport interface ConsoleOrderZoneLine {\n lineItemId: number\n productId: string\n variantId: string | null\n name: string\n variantLabel: string | null\n sku: string | null\n /** `physical`, `digital` or `service`; `null` on a line written before types. */\n productType: string | null\n quantity: number\n unitAmountCents: number\n fulfilledQuantity: number\n remainingQuantity: number\n /** Whether the line has to be shipped at all. */\n requiresShipping: boolean\n}\n\n/** An address on the order, as the buyer gave it. */\nexport interface ConsoleOrderZoneAddress {\n name: string | null\n line1: string | null\n line2: string | null\n city: string | null\n state: string | null\n postalCode: string | null\n country: string | null\n phone: string | null\n}\n\n/** One recorded shipment. */\nexport interface ConsoleOrderZoneFulfillment {\n id: string\n lines: ReadonlyArray<{ lineItemId: number; quantity: number }>\n carrier: string | null\n trackingNumber: string | null\n trackingUrl: string | null\n labelUrl: string | null\n status: 'active' | 'cancelled'\n atMs: number\n}\n\n/** The order a widget is handed. Money is integer cents in `currency`. */\nexport interface ConsoleOrderZoneOrder {\n id: string\n /** The human number, e.g. `#1042`. */\n number: string\n status: string\n channel: string\n /** ISO 4217, upper case. */\n currency: string\n customerEmail: string | null\n customerName: string | null\n shippingAddress: ConsoleOrderZoneAddress | null\n lines: readonly ConsoleOrderZoneLine[]\n fulfillments: readonly ConsoleOrderZoneFulfillment[]\n totals: {\n itemsCents: number\n shippingCents: number\n taxCents: number\n discountCents: number\n totalCents: number\n }\n /** Whether the order was paid in Stripe test mode. */\n testMode: boolean\n}\n\n/** A shipment a widget asks the dialog to record. */\nexport interface ConsoleFulfillmentRequest {\n /** The units shipped. Omitted, the shipment covers everything still to ship. */\n lineItems?: ReadonlyArray<{ lineItemId: number; quantity: number }>\n carrier: string\n trackingNumber: string\n /** An explicit https tracking link; derived from the carrier when absent. */\n trackingUrl?: string\n /** The label the widget bought, an https URL. */\n labelUrl?: string\n /** Whether the buyer is told. Defaults to true. */\n notify?: boolean\n /**\n * One attempt. A retry with the same key finds the shipment it recorded,\n * so a widget that lost a response can ask again without shipping twice.\n */\n idempotencyKey: string\n}\n\n/**\n * What the `orderDetail` zone hands each widget, in the order dialog beside\n * its actions. `recordFulfillment` resolves with the shipment recorded (or\n * found, on a retry) and throws with a message a person can act on when the\n * dialog's route refuses it: more units than are left, an order refunded in\n * another tab.\n */\nexport interface ConsoleOrderDetailZoneProps {\n hostId: string\n /** The org the page names; `undefined` where the host does not know it. */\n orgId: string | undefined\n order: ConsoleOrderZoneOrder\n recordFulfillment: (request: ConsoleFulfillmentRequest) => Promise<ConsoleOrderZoneFulfillment>\n}\n\n/** The tracking a widget fills into the Fulfill items panel. */\nexport interface ConsoleFulfillmentTracking {\n carrier: string\n trackingNumber: string\n trackingUrl?: string\n labelUrl?: string\n}\n\n/**\n * What the `orderFulfillment` zone hands each widget, inside the Fulfill\n * items panel: the units the merchant has picked, and `applyTracking`, which\n * fills the panel's carrier and tracking fields (a bought label's) for the\n * merchant to confirm with Fulfill. `recordFulfillment` is there for a widget\n * that records the shipment itself.\n */\nexport interface ConsoleOrderFulfillmentZoneProps extends ConsoleOrderDetailZoneProps {\n /** The units picked in the panel, lines with a zero count left out. */\n selection: ReadonlyArray<{ lineItemId: number; quantity: number }>\n applyTracking: (tracking: ConsoleFulfillmentTracking) => void\n}\n\nexport const ORDER_DETAIL_ZONE =\n definePluginZone<ConsoleOrderDetailZoneProps>('orderDetail')\n\nexport const ORDER_FULFILLMENT_ZONE =\n definePluginZone<ConsoleOrderFulfillmentZoneProps>('orderFulfillment')\n\n/** Declares the two order zones, from the console registrar. */\nexport function registerCommerceOrderZones(): void {\n const owner = { pluginId: BUNDLE_ID }\n registerPluginZone(\n {\n zone: ORDER_DETAIL_ZONE,\n label: 'Order detail',\n surface: 'console',\n layout: 'bare',\n description:\n 'In the order dialog, above its actions. A widget here reads the order — lines, what is left to ship, the ship-to address — and records a shipment through `recordFulfillment`, the dialog’s own route with its quantity check.',\n },\n owner,\n )\n registerPluginZone(\n {\n zone: ORDER_FULFILLMENT_ZONE,\n label: 'Order fulfillment',\n surface: 'console',\n layout: 'bare',\n description:\n 'Inside the order dialog’s Fulfill items panel. A widget here reads the units picked and fills the carrier and tracking through `applyTracking` (a bought label’s), for the merchant to confirm with Fulfill.',\n },\n owner,\n )\n}\n"],"names":["definePluginZone","registerPluginZone","BUNDLE_ID","ORDER_DETAIL_ZONE","ORDER_FULFILLMENT_ZONE","registerCommerceOrderZones","owner","pluginId","zone","label","surface","layout","description"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,gBAAgB,EAChBC,kBAAkB,QACb,2CAA0C;AACjD,SAASC,SAAS,QAAQ,mCAA+B;AAyIzD,OAAO,MAAMC,oBACXH,iBAA8C,eAAc;AAE9D,OAAO,MAAMI,yBACXJ,iBAAmD,oBAAmB;AAExE,8DAA8D,GAC9D,OAAO,SAASK;IACd,MAAMC,QAAQ;QAAEC,UAAUL;IAAU;IACpCD,mBACE;QACEO,MAAML;QACNM,OAAO;QACPC,SAAS;QACTC,QAAQ;QACRC,aACE;IACJ,GACAN;IAEFL,mBACE;QACEO,MAAMJ;QACNK,OAAO;QACPC,SAAS;QACTC,QAAQ;QACRC,aACE;IACJ,GACAN;AAEJ"}
1
+ {"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/order-zones.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n definePluginZone,\n registerPluginZone,\n} from '@aglyn/aglyn/plugin-manager/plugin-zones'\nimport { BUNDLE_ID } from '../../constants/bundle-common'\n\n/**\n * The zones the order dialog hosts (AGL-3611): `orderDetail`, beside the\n * order's actions, and `orderFulfillment`, inside the Fulfill items panel;\n * and `localDeliveryRow`, in a delivery's row of the Pickup & delivery queue\n * (AGL-3695).\n *\n * Declared here because zones are declared by the plugin that hosts them (the\n * product zones are the precedent). A widget from another plugin — a shipping\n * plugin's \"Buy label\" — restates the props it reads rather than importing\n * this package. A widget proposes and never writes the order itself: the\n * shipment it records goes through `recordFulfillment`, which is this\n * plugin's own route with its role gate, its quantity check and its\n * transition rule.\n */\n\n/** One order line as a widget reads it. `lineItemId` is the line's index. */\nexport interface ConsoleOrderZoneLine {\n lineItemId: number\n productId: string\n variantId: string | null\n name: string\n variantLabel: string | null\n sku: string | null\n /** `physical`, `digital` or `service`; `null` on a line written before types. */\n productType: string | null\n quantity: number\n unitAmountCents: number\n fulfilledQuantity: number\n remainingQuantity: number\n /** Whether the line has to be shipped at all. */\n requiresShipping: boolean\n}\n\n/** An address on the order, as the buyer gave it. */\nexport interface ConsoleOrderZoneAddress {\n name: string | null\n line1: string | null\n line2: string | null\n city: string | null\n state: string | null\n postalCode: string | null\n country: string | null\n phone: string | null\n}\n\n/** One recorded shipment. */\nexport interface ConsoleOrderZoneFulfillment {\n id: string\n lines: ReadonlyArray<{ lineItemId: number; quantity: number }>\n carrier: string | null\n trackingNumber: string | null\n trackingUrl: string | null\n labelUrl: string | null\n status: 'active' | 'cancelled'\n atMs: number\n}\n\n/** The order a widget is handed. Money is integer cents in `currency`. */\nexport interface ConsoleOrderZoneOrder {\n id: string\n /** The human number, e.g. `#1042`. */\n number: string\n status: string\n channel: string\n /** ISO 4217, upper case. */\n currency: string\n customerEmail: string | null\n customerName: string | null\n shippingAddress: ConsoleOrderZoneAddress | null\n lines: readonly ConsoleOrderZoneLine[]\n fulfillments: readonly ConsoleOrderZoneFulfillment[]\n totals: {\n itemsCents: number\n shippingCents: number\n taxCents: number\n discountCents: number\n totalCents: number\n }\n /** Whether the order was paid in Stripe test mode. */\n testMode: boolean\n /**\n * How the buyer receives it (AGL-3624): `shipping`, `pickup` or\n * `local_delivery`. Optional, so a widget written before reads it as shipped.\n */\n fulfillmentMethod?: string\n /** The store's own delivery, on a `local_delivery` order (AGL-3695); `null` otherwise. */\n localDelivery?: ConsoleOrderZoneLocalDelivery | null\n}\n\n/**\n * A local delivery as a widget reads it (AGL-3695): where it stands, the\n * window the buyer booked, and the outside courier on it, if one was sent.\n */\nexport interface ConsoleOrderZoneLocalDelivery {\n /** `scheduled`, `out_for_delivery`, `delivered` or `failed`. */\n status: string\n windowStartMs: number | null\n windowEndMs: number | null\n windowLabel: string | null\n courier: {\n provider: string\n providerLabel: string\n deliveryRef: string\n state: string\n trackingUrl: string | null\n etaMs: number | null\n reason: string | null\n testMode: boolean\n updatedAtMs: number\n } | null\n}\n\n/**\n * What the `localDeliveryRow` zone hands each widget (AGL-3695): one local\n * delivery in the Pickup & delivery queue, beside the row's own step\n * buttons. A widget there is a compact control — a courier's \"Send a\n * courier\" — and moves nothing itself: the courier's progress comes back\n * through core's `core.local-delivery-records`.\n */\nexport interface ConsoleLocalDeliveryRowZoneProps {\n hostId: string\n orgId: string | undefined\n order: ConsoleOrderZoneOrder\n}\n\n/** A shipment a widget asks the dialog to record. */\nexport interface ConsoleFulfillmentRequest {\n /** The units shipped. Omitted, the shipment covers everything still to ship. */\n lineItems?: ReadonlyArray<{ lineItemId: number; quantity: number }>\n carrier: string\n trackingNumber: string\n /** An explicit https tracking link; derived from the carrier when absent. */\n trackingUrl?: string\n /** The label the widget bought, an https URL. */\n labelUrl?: string\n /** Whether the buyer is told. Defaults to true. */\n notify?: boolean\n /**\n * One attempt. A retry with the same key finds the shipment it recorded,\n * so a widget that lost a response can ask again without shipping twice.\n */\n idempotencyKey: string\n}\n\n/**\n * What the `orderDetail` zone hands each widget, in the order dialog beside\n * its actions. `recordFulfillment` resolves with the shipment recorded (or\n * found, on a retry) and throws with a message a person can act on when the\n * dialog's route refuses it: more units than are left, an order refunded in\n * another tab.\n */\nexport interface ConsoleOrderDetailZoneProps {\n hostId: string\n /** The org the page names; `undefined` where the host does not know it. */\n orgId: string | undefined\n order: ConsoleOrderZoneOrder\n recordFulfillment: (request: ConsoleFulfillmentRequest) => Promise<ConsoleOrderZoneFulfillment>\n}\n\n/** The tracking a widget fills into the Fulfill items panel. */\nexport interface ConsoleFulfillmentTracking {\n carrier: string\n trackingNumber: string\n trackingUrl?: string\n labelUrl?: string\n}\n\n/**\n * What the `orderFulfillment` zone hands each widget, inside the Fulfill\n * items panel: the units the merchant has picked, and `applyTracking`, which\n * fills the panel's carrier and tracking fields (a bought label's) for the\n * merchant to confirm with Fulfill. `recordFulfillment` is there for a widget\n * that records the shipment itself.\n */\nexport interface ConsoleOrderFulfillmentZoneProps extends ConsoleOrderDetailZoneProps {\n /** The units picked in the panel, lines with a zero count left out. */\n selection: ReadonlyArray<{ lineItemId: number; quantity: number }>\n applyTracking: (tracking: ConsoleFulfillmentTracking) => void\n}\n\nexport const ORDER_DETAIL_ZONE =\n definePluginZone<ConsoleOrderDetailZoneProps>('orderDetail')\n\nexport const ORDER_FULFILLMENT_ZONE =\n definePluginZone<ConsoleOrderFulfillmentZoneProps>('orderFulfillment')\n\nexport const LOCAL_DELIVERY_ROW_ZONE =\n definePluginZone<ConsoleLocalDeliveryRowZoneProps>('localDeliveryRow')\n\n/** Declares the two order zones, from the console registrar. */\nexport function registerCommerceOrderZones(): void {\n const owner = { pluginId: BUNDLE_ID }\n registerPluginZone(\n {\n zone: ORDER_DETAIL_ZONE,\n label: 'Order detail',\n surface: 'console',\n layout: 'bare',\n description:\n 'In the order dialog, above its actions. A widget here reads the order — lines, what is left to ship, the ship-to address — and records a shipment through `recordFulfillment`, the dialog’s own route with its quantity check.',\n },\n owner,\n )\n registerPluginZone(\n {\n zone: ORDER_FULFILLMENT_ZONE,\n label: 'Order fulfillment',\n surface: 'console',\n layout: 'bare',\n description:\n 'Inside the order dialog’s Fulfill items panel. A widget here reads the units picked and fills the carrier and tracking through `applyTracking` (a bought label’s), for the merchant to confirm with Fulfill.',\n },\n owner,\n )\n registerPluginZone(\n {\n zone: LOCAL_DELIVERY_ROW_ZONE,\n label: 'Local delivery row',\n surface: 'console',\n layout: 'bare',\n description:\n 'In a local delivery’s row of the Pickup & delivery queue, beside its step buttons. A widget here is a compact control that reads the order and its delivery — the window, the status and any courier on it — such as sending an outside courier.',\n },\n owner,\n )\n}\n"],"names":["definePluginZone","registerPluginZone","BUNDLE_ID","ORDER_DETAIL_ZONE","ORDER_FULFILLMENT_ZONE","LOCAL_DELIVERY_ROW_ZONE","registerCommerceOrderZones","owner","pluginId","zone","label","surface","layout","description"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,gBAAgB,EAChBC,kBAAkB,QACb,2CAA0C;AACjD,SAASC,SAAS,QAAQ,mCAA+B;AAsLzD,OAAO,MAAMC,oBACXH,iBAA8C,eAAc;AAE9D,OAAO,MAAMI,yBACXJ,iBAAmD,oBAAmB;AAExE,OAAO,MAAMK,0BACXL,iBAAmD,oBAAmB;AAExE,8DAA8D,GAC9D,OAAO,SAASM;IACd,MAAMC,QAAQ;QAAEC,UAAUN;IAAU;IACpCD,mBACE;QACEQ,MAAMN;QACNO,OAAO;QACPC,SAAS;QACTC,QAAQ;QACRC,aACE;IACJ,GACAN;IAEFN,mBACE;QACEQ,MAAML;QACNM,OAAO;QACPC,SAAS;QACTC,QAAQ;QACRC,aACE;IACJ,GACAN;IAEFN,mBACE;QACEQ,MAAMJ;QACNK,OAAO;QACPC,SAAS;QACTC,QAAQ;QACRC,aACE;IACJ,GACAN;AAEJ"}
@@ -25,7 +25,10 @@ import { collection, doc, limit, orderBy, query, where } from "firebase/firestor
25
25
  import { useMemo, useState } from "react";
26
26
  import { useFirestore, useFirestoreCollection, useFirestoreDoc, usePagedCollection } from "@aglyn/tenant-feature-instance";
27
27
  import { ListPagination } from "@aglyn/shared-ui-jsx/components/list-pagination.component";
28
+ import { useConsoleWidgetSlot } from "@aglyn/aglyn/app-utils/console-widget-slot-context";
28
29
  import OrderDetailDialog from "./order-detail-dialog.component.js";
30
+ import { consoleOrderZoneOrder } from "./order-fulfillment-panel.component.js";
31
+ import { LOCAL_DELIVERY_ROW_ZONE } from "./order-zones.js";
29
32
  import { nextLocalFulfillmentSteps, useLocalFulfillmentStep } from "./order-local-fulfillment-panel.component.js";
30
33
  /**
31
34
  * The pickup and local delivery queue (AGL-3624): what to prepare, what is
@@ -46,6 +49,9 @@ import { nextLocalFulfillmentSteps, useLocalFulfillmentStep } from "./order-loca
46
49
  const [locationId, setLocationId] = useState('');
47
50
  const [open, setOpen] = useState(null);
48
51
  const { run, busy } = useLocalFulfillmentStep(hostId);
52
+ // The `localDeliveryRow` zone (AGL-3695): a courier plugin's "Send a
53
+ // courier" beside a delivery's own step buttons.
54
+ const WidgetSlot = useConsoleWidgetSlot();
49
55
  const { data: locationDocs } = useFirestoreCollection(()=>query(collection(firestore, 'hosts', hostId, 'locations'), limit(25)), [
50
56
  firestore,
51
57
  hostId
@@ -89,7 +95,9 @@ import { nextLocalFulfillmentSteps, useLocalFulfillmentStep } from "./order-loca
89
95
  return /*#__PURE__*/ _jsxs(CardDisplay, {
90
96
  header: 'Pickup & delivery',
91
97
  help: pluginDocsHelp('commerce', {
92
- anchor: '#pickup-and-local-delivery'
98
+ anchor: '#pickup-and-local-delivery',
99
+ title: 'Pickup & delivery queue',
100
+ excerpt: 'The orders waiting to be picked up or driven out, oldest first — ' + 'mark each one ready, collected or delivered as it happens.'
93
101
  }),
94
102
  HeaderProps: {
95
103
  action: locations.length > 1 ? /*#__PURE__*/ _jsxs(TextField, {
@@ -190,6 +198,12 @@ import { nextLocalFulfillmentSteps, useLocalFulfillmentStep } from "./order-loca
190
198
  onClick: ()=>void run(order.$id, entry.step),
191
199
  children: entry.label
192
200
  }, entry.step)),
201
+ WidgetSlot && order.fulfillmentMethod === 'local_delivery' ? /*#__PURE__*/ _jsx(WidgetSlot, {
202
+ slot: LOCAL_DELIVERY_ROW_ZONE.id,
203
+ hostId: hostId,
204
+ orgId: undefined,
205
+ order: consoleOrderZoneOrder(order, order.$id)
206
+ }) : null,
193
207
  /*#__PURE__*/ _jsx(Button, {
194
208
  size: "small",
195
209
  onClick: ()=>setOpen(order),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/pickup-delivery-queue-card.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n'use client'\n\nimport * as CommerceModel from '../../model'\nimport {\n LOCAL_FULFILLMENT_QUEUE_TABS,\n localFulfillmentQueueQuery,\n} from '../../constants/local-fulfillment-list-query'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport {\n Button,\n MenuItem,\n Stack,\n Tab,\n Tabs,\n TextField,\n Typography,\n} from '@mui/material'\nimport { collection, doc, limit, orderBy, query, where } from 'firebase/firestore'\nimport { useMemo, useState } from 'react'\nimport {\n useFirestore,\n useFirestoreCollection,\n useFirestoreDoc,\n usePagedCollection,\n} from '@aglyn/tenant-feature-instance'\nimport { ListPagination } from '@aglyn/shared-ui-jsx/components/list-pagination.component'\nimport OrderDetailDialog from './order-detail-dialog.component'\nimport { nextLocalFulfillmentSteps, useLocalFulfillmentStep } from './order-local-fulfillment-panel.component'\n\nexport interface PickupDeliveryQueueCardProps {\n hostId: string\n}\n\n/**\n * The pickup and local delivery queue (AGL-3624): what to prepare, what is\n * waiting at the counter, and what the store's driver takes out, per\n * location, soonest first — each tab ONE Firestore query on the fields every\n * pickup and delivery writer stamps (`constants/local-fulfillment-list-query`),\n * which the native Aglyn app runs too. A row's next step is one click; the\n * order opens for anything more.\n *\n * Draws nothing for a store with no pickup location and no local delivery\n * switched on, so a store that only ships never sees it.\n */\nexport function PickupDeliveryQueueCard(props: PickupDeliveryQueueCardProps) {\n const { hostId } = props\n const firestore = useFirestore()\n const [tab, setTab] = useState<CommerceModel.OrderFulfillmentKey>('pickup_preparing')\n const [locationId, setLocationId] = useState('')\n const [open, setOpen] = useState<(CommerceModel.HostOrder & { $id: string }) | null>(null)\n const { run, busy } = useLocalFulfillmentStep(hostId)\n\n const { data: locationDocs } = useFirestoreCollection<any>(\n () => query(collection(firestore, 'hosts', hostId, 'locations'), limit(25)),\n [firestore, hostId],\n { idField: '$id' },\n )\n const { data: settings } = useFirestoreDoc<any>(\n () => doc(firestore, 'hosts', hostId, 'settings', 'store'),\n [firestore, hostId],\n )\n const pickupOn = (locationDocs ?? []).some(\n (location: any) => CommerceModel.normalizePickupSettings(location?.pickup).enabled,\n )\n const deliveryOn = Boolean(\n CommerceModel.normalizeLocalDeliverySettings(settings?.localDelivery).enabled,\n )\n const tabs = LOCAL_FULFILLMENT_QUEUE_TABS.filter((entry) =>\n entry.method === 'pickup' ? pickupOn : deliveryOn,\n )\n const active = tabs.some((entry) => entry.key === tab) ? tab : (tabs[0]?.key ?? tab)\n const plan = useMemo(() => localFulfillmentQueueQuery(active, locationId || null), [active, locationId])\n const anyOn = tabs.length > 0\n // Paged like every list of something that grows: one tab's query, a page\n // at a time (the native app pages it by `plan.limit`).\n const {\n rows,\n status,\n page,\n setPage,\n pageSize,\n setPageSize,\n hasMore,\n } = usePagedCollection<any>(\n (pageLimit) =>\n anyOn\n ? query(\n collection(firestore, 'hosts', hostId, 'orders'),\n ...plan.where.map((clause) => where(clause.field, clause.op, clause.value as never)),\n orderBy(plan.orderBy.field, plan.orderBy.direction),\n limit(pageLimit),\n )\n : null,\n [firestore, hostId, active, locationId, anyOn],\n { idField: '$id' },\n )\n\n if (!tabs.length) return null\n const orders = (rows ?? []).map((row: any) => ({\n ...CommerceModel.liftLegacyOrder(row),\n $id: String(row.$id),\n })) as Array<CommerceModel.HostOrder & { $id: string }>\n const locations = [...(locationDocs ?? [])].sort((a: any, b: any) =>\n String(a.name ?? '').localeCompare(String(b.name ?? '')),\n )\n\n return (\n <CardDisplay\n header={'Pickup & delivery'}\n help={pluginDocsHelp('commerce', { anchor: '#pickup-and-local-delivery' })}\n HeaderProps={{\n action:\n locations.length > 1 ? (\n <TextField\n select\n label=\"Location\"\n value={locationId}\n onChange={(event) => setLocationId(event.target.value)}\n size=\"small\"\n sx={{ minWidth: 160 }}\n >\n <MenuItem value=\"\">{'All locations'}</MenuItem>\n {locations.map((location: any) => (\n <MenuItem key={location.$id} value={location.$id}>\n {location.name}\n </MenuItem>\n ))}\n </TextField>\n ) : null,\n }}\n contentGutterX\n contentGutterY\n >\n <Tabs\n value={active}\n onChange={(_event, value) => setTab(value)}\n variant=\"scrollable\"\n allowScrollButtonsMobile\n >\n {tabs.map((entry) => (\n <Tab key={entry.key} value={entry.key} label={entry.label} />\n ))}\n </Tabs>\n <Stack spacing={1} sx={{ pt: 1.5 }}>\n {status === 'loading' ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Loading…'}\n </Typography>\n ) : orders.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Nothing here right now.'}\n </Typography>\n ) : (\n orders.map((order) => {\n const units = (order.lineItems ?? []).reduce((sum, line) => sum + (Number(line.quantity) || 0), 0)\n const when =\n order.fulfillmentMethod === 'local_delivery'\n ? (order.localDelivery?.windowLabel ?? '')\n : order.createdAtMs\n ? `Ordered ${new Date(order.createdAtMs).toLocaleString()}`\n : ''\n const where =\n order.fulfillmentMethod === 'pickup'\n ? (order.pickup?.locationName ?? '')\n : [order.shippingAddress?.line1, order.localDelivery?.postalCode].filter(Boolean).join(', ')\n return (\n <Stack\n key={order.$id}\n direction={{ xs: 'column', sm: 'row' }}\n spacing={1}\n sx={{ alignItems: { sm: 'center' } }}\n >\n <Stack sx={{ flex: 1, minWidth: 0 }}>\n <Typography variant=\"body2\" noWrap>\n {`${CommerceModel.formatOrderNumber(order, order.$id)} · ${\n order.customerName || order.customerEmail || 'Guest buyer'\n } · ${units} item${units === 1 ? '' : 's'}`}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {[when, where].filter(Boolean).join(' · ')}\n </Typography>\n </Stack>\n {nextLocalFulfillmentSteps(order)\n .filter((entry) => entry.primary)\n .map((entry) => (\n <Button\n key={entry.step}\n size=\"small\"\n variant=\"outlined\"\n disabled={busy}\n onClick={() => void run(order.$id, entry.step)}\n >\n {entry.label}\n </Button>\n ))}\n <Button size=\"small\" onClick={() => setOpen(order)}>\n {'Open'}\n </Button>\n </Stack>\n )\n })\n )}\n <ListPagination\n page={page}\n pageSize={pageSize}\n rowCount={orders.length}\n hasMore={hasMore}\n onPageChange={setPage}\n onPageSizeChange={setPageSize}\n />\n </Stack>\n {open ? <OrderDetailDialog hostId={hostId} order={open} onClose={() => setOpen(null)} /> : null}\n </CardDisplay>\n )\n}\nPickupDeliveryQueueCard.displayName = 'PickupDeliveryQueueCard'\n\nexport default PickupDeliveryQueueCard\n"],"names":["CommerceModel","LOCAL_FULFILLMENT_QUEUE_TABS","localFulfillmentQueueQuery","CardDisplay","pluginDocsHelp","Button","MenuItem","Stack","Tab","Tabs","TextField","Typography","collection","doc","limit","orderBy","query","where","useMemo","useState","useFirestore","useFirestoreCollection","useFirestoreDoc","usePagedCollection","ListPagination","OrderDetailDialog","nextLocalFulfillmentSteps","useLocalFulfillmentStep","PickupDeliveryQueueCard","props","tabs","hostId","firestore","tab","setTab","locationId","setLocationId","open","setOpen","run","busy","data","locationDocs","idField","settings","pickupOn","some","location","normalizePickupSettings","pickup","enabled","deliveryOn","Boolean","normalizeLocalDeliverySettings","localDelivery","filter","entry","method","active","key","plan","anyOn","length","rows","status","page","setPage","pageSize","setPageSize","hasMore","pageLimit","map","clause","field","op","value","direction","orders","row","liftLegacyOrder","$id","String","locations","sort","a","b","name","localeCompare","header","help","anchor","HeaderProps","action","select","label","onChange","event","target","size","sx","minWidth","contentGutterX","contentGutterY","_event","variant","allowScrollButtonsMobile","spacing","pt","color","order","units","lineItems","reduce","sum","line","Number","quantity","when","fulfillmentMethod","windowLabel","createdAtMs","Date","toLocaleString","locationName","shippingAddress","line1","postalCode","join","xs","sm","alignItems","flex","noWrap","formatOrderNumber","customerName","customerEmail","primary","disabled","onClick","step","rowCount","onPageChange","onPageSizeChange","onClose","displayName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/pickup-delivery-queue-card.component.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n'use client'\n\nimport * as CommerceModel from '../../model'\nimport {\n LOCAL_FULFILLMENT_QUEUE_TABS,\n localFulfillmentQueueQuery,\n} from '../../constants/local-fulfillment-list-query'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport {\n Button,\n MenuItem,\n Stack,\n Tab,\n Tabs,\n TextField,\n Typography,\n} from '@mui/material'\nimport { collection, doc, limit, orderBy, query, where } from 'firebase/firestore'\nimport { useMemo, useState } from 'react'\nimport {\n useFirestore,\n useFirestoreCollection,\n useFirestoreDoc,\n usePagedCollection,\n} from '@aglyn/tenant-feature-instance'\nimport { ListPagination } from '@aglyn/shared-ui-jsx/components/list-pagination.component'\nimport { useConsoleWidgetSlot } from '@aglyn/aglyn/app-utils/console-widget-slot-context'\nimport OrderDetailDialog from './order-detail-dialog.component'\nimport { consoleOrderZoneOrder } from './order-fulfillment-panel.component'\nimport { LOCAL_DELIVERY_ROW_ZONE } from './order-zones'\nimport { nextLocalFulfillmentSteps, useLocalFulfillmentStep } from './order-local-fulfillment-panel.component'\n\nexport interface PickupDeliveryQueueCardProps {\n hostId: string\n}\n\n/**\n * The pickup and local delivery queue (AGL-3624): what to prepare, what is\n * waiting at the counter, and what the store's driver takes out, per\n * location, soonest first — each tab ONE Firestore query on the fields every\n * pickup and delivery writer stamps (`constants/local-fulfillment-list-query`),\n * which the native Aglyn app runs too. A row's next step is one click; the\n * order opens for anything more.\n *\n * Draws nothing for a store with no pickup location and no local delivery\n * switched on, so a store that only ships never sees it.\n */\nexport function PickupDeliveryQueueCard(props: PickupDeliveryQueueCardProps) {\n const { hostId } = props\n const firestore = useFirestore()\n const [tab, setTab] = useState<CommerceModel.OrderFulfillmentKey>('pickup_preparing')\n const [locationId, setLocationId] = useState('')\n const [open, setOpen] = useState<(CommerceModel.HostOrder & { $id: string }) | null>(null)\n const { run, busy } = useLocalFulfillmentStep(hostId)\n // The `localDeliveryRow` zone (AGL-3695): a courier plugin's \"Send a\n // courier\" beside a delivery's own step buttons.\n const WidgetSlot = useConsoleWidgetSlot()\n\n const { data: locationDocs } = useFirestoreCollection<any>(\n () => query(collection(firestore, 'hosts', hostId, 'locations'), limit(25)),\n [firestore, hostId],\n { idField: '$id' },\n )\n const { data: settings } = useFirestoreDoc<any>(\n () => doc(firestore, 'hosts', hostId, 'settings', 'store'),\n [firestore, hostId],\n )\n const pickupOn = (locationDocs ?? []).some(\n (location: any) => CommerceModel.normalizePickupSettings(location?.pickup).enabled,\n )\n const deliveryOn = Boolean(\n CommerceModel.normalizeLocalDeliverySettings(settings?.localDelivery).enabled,\n )\n const tabs = LOCAL_FULFILLMENT_QUEUE_TABS.filter((entry) =>\n entry.method === 'pickup' ? pickupOn : deliveryOn,\n )\n const active = tabs.some((entry) => entry.key === tab) ? tab : (tabs[0]?.key ?? tab)\n const plan = useMemo(() => localFulfillmentQueueQuery(active, locationId || null), [active, locationId])\n const anyOn = tabs.length > 0\n // Paged like every list of something that grows: one tab's query, a page\n // at a time (the native app pages it by `plan.limit`).\n const {\n rows,\n status,\n page,\n setPage,\n pageSize,\n setPageSize,\n hasMore,\n } = usePagedCollection<any>(\n (pageLimit) =>\n anyOn\n ? query(\n collection(firestore, 'hosts', hostId, 'orders'),\n ...plan.where.map((clause) => where(clause.field, clause.op, clause.value as never)),\n orderBy(plan.orderBy.field, plan.orderBy.direction),\n limit(pageLimit),\n )\n : null,\n [firestore, hostId, active, locationId, anyOn],\n { idField: '$id' },\n )\n\n if (!tabs.length) return null\n const orders = (rows ?? []).map((row: any) => ({\n ...CommerceModel.liftLegacyOrder(row),\n $id: String(row.$id),\n })) as Array<CommerceModel.HostOrder & { $id: string }>\n const locations = [...(locationDocs ?? [])].sort((a: any, b: any) =>\n String(a.name ?? '').localeCompare(String(b.name ?? '')),\n )\n\n return (\n <CardDisplay\n header={'Pickup & delivery'}\n help={pluginDocsHelp('commerce', {\n anchor: '#pickup-and-local-delivery',\n title: 'Pickup & delivery queue',\n excerpt:\n 'The orders waiting to be picked up or driven out, oldest first — ' +\n 'mark each one ready, collected or delivered as it happens.',\n })}\n HeaderProps={{\n action:\n locations.length > 1 ? (\n <TextField\n select\n label=\"Location\"\n value={locationId}\n onChange={(event) => setLocationId(event.target.value)}\n size=\"small\"\n sx={{ minWidth: 160 }}\n >\n <MenuItem value=\"\">{'All locations'}</MenuItem>\n {locations.map((location: any) => (\n <MenuItem key={location.$id} value={location.$id}>\n {location.name}\n </MenuItem>\n ))}\n </TextField>\n ) : null,\n }}\n contentGutterX\n contentGutterY\n >\n <Tabs\n value={active}\n onChange={(_event, value) => setTab(value)}\n variant=\"scrollable\"\n allowScrollButtonsMobile\n >\n {tabs.map((entry) => (\n <Tab key={entry.key} value={entry.key} label={entry.label} />\n ))}\n </Tabs>\n <Stack spacing={1} sx={{ pt: 1.5 }}>\n {status === 'loading' ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Loading…'}\n </Typography>\n ) : orders.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Nothing here right now.'}\n </Typography>\n ) : (\n orders.map((order) => {\n const units = (order.lineItems ?? []).reduce((sum, line) => sum + (Number(line.quantity) || 0), 0)\n const when =\n order.fulfillmentMethod === 'local_delivery'\n ? (order.localDelivery?.windowLabel ?? '')\n : order.createdAtMs\n ? `Ordered ${new Date(order.createdAtMs).toLocaleString()}`\n : ''\n const where =\n order.fulfillmentMethod === 'pickup'\n ? (order.pickup?.locationName ?? '')\n : [order.shippingAddress?.line1, order.localDelivery?.postalCode].filter(Boolean).join(', ')\n return (\n <Stack\n key={order.$id}\n direction={{ xs: 'column', sm: 'row' }}\n spacing={1}\n sx={{ alignItems: { sm: 'center' } }}\n >\n <Stack sx={{ flex: 1, minWidth: 0 }}>\n <Typography variant=\"body2\" noWrap>\n {`${CommerceModel.formatOrderNumber(order, order.$id)} · ${\n order.customerName || order.customerEmail || 'Guest buyer'\n } · ${units} item${units === 1 ? '' : 's'}`}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {[when, where].filter(Boolean).join(' · ')}\n </Typography>\n </Stack>\n {nextLocalFulfillmentSteps(order)\n .filter((entry) => entry.primary)\n .map((entry) => (\n <Button\n key={entry.step}\n size=\"small\"\n variant=\"outlined\"\n disabled={busy}\n onClick={() => void run(order.$id, entry.step)}\n >\n {entry.label}\n </Button>\n ))}\n {WidgetSlot && order.fulfillmentMethod === 'local_delivery' ? (\n <WidgetSlot\n slot={LOCAL_DELIVERY_ROW_ZONE.id}\n hostId={hostId}\n orgId={undefined}\n order={consoleOrderZoneOrder(order, order.$id)}\n />\n ) : null}\n <Button size=\"small\" onClick={() => setOpen(order)}>\n {'Open'}\n </Button>\n </Stack>\n )\n })\n )}\n <ListPagination\n page={page}\n pageSize={pageSize}\n rowCount={orders.length}\n hasMore={hasMore}\n onPageChange={setPage}\n onPageSizeChange={setPageSize}\n />\n </Stack>\n {open ? <OrderDetailDialog hostId={hostId} order={open} onClose={() => setOpen(null)} /> : null}\n </CardDisplay>\n )\n}\nPickupDeliveryQueueCard.displayName = 'PickupDeliveryQueueCard'\n\nexport default PickupDeliveryQueueCard\n"],"names":["CommerceModel","LOCAL_FULFILLMENT_QUEUE_TABS","localFulfillmentQueueQuery","CardDisplay","pluginDocsHelp","Button","MenuItem","Stack","Tab","Tabs","TextField","Typography","collection","doc","limit","orderBy","query","where","useMemo","useState","useFirestore","useFirestoreCollection","useFirestoreDoc","usePagedCollection","ListPagination","useConsoleWidgetSlot","OrderDetailDialog","consoleOrderZoneOrder","LOCAL_DELIVERY_ROW_ZONE","nextLocalFulfillmentSteps","useLocalFulfillmentStep","PickupDeliveryQueueCard","props","tabs","hostId","firestore","tab","setTab","locationId","setLocationId","open","setOpen","run","busy","WidgetSlot","data","locationDocs","idField","settings","pickupOn","some","location","normalizePickupSettings","pickup","enabled","deliveryOn","Boolean","normalizeLocalDeliverySettings","localDelivery","filter","entry","method","active","key","plan","anyOn","length","rows","status","page","setPage","pageSize","setPageSize","hasMore","pageLimit","map","clause","field","op","value","direction","orders","row","liftLegacyOrder","$id","String","locations","sort","a","b","name","localeCompare","header","help","anchor","title","excerpt","HeaderProps","action","select","label","onChange","event","target","size","sx","minWidth","contentGutterX","contentGutterY","_event","variant","allowScrollButtonsMobile","spacing","pt","color","order","units","lineItems","reduce","sum","line","Number","quantity","when","fulfillmentMethod","windowLabel","createdAtMs","Date","toLocaleString","locationName","shippingAddress","line1","postalCode","join","xs","sm","alignItems","flex","noWrap","formatOrderNumber","customerName","customerEmail","primary","disabled","onClick","step","slot","id","orgId","undefined","rowCount","onPageChange","onPageSizeChange","onClose","displayName"],"mappings":"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"}
@@ -932,8 +932,9 @@ export function PosConsolePage({ hostId }) {
932
932
  ref: fill.ref,
933
933
  sx: {
934
934
  display: 'flex',
935
- // From under the console's header, nav and page title to the
936
- // bottom of the window, not a whole window tall below them.
935
+ // From under the console's header, nav and page title down to
936
+ // where the page's padding and footer begin, so the whole page fits
937
+ // the window (AGL-3679, AGL-3710).
937
938
  height: fill.height,
938
939
  overflow: 'hidden'
939
940
  },