@aglyn/plugins-commerce 1.0.0-beta.290 → 1.0.0-beta.292

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 (183) hide show
  1. package/README.md +4 -2
  2. package/package.json +13 -13
  3. package/src/lib/components/cart-fulfillment.d.ts +3 -0
  4. package/src/lib/components/cart-fulfillment.js.map +1 -1
  5. package/src/lib/components/cart.js +14 -4
  6. package/src/lib/components/cart.js.map +1 -1
  7. package/src/lib/components/commerce-console-page.js +2 -1
  8. package/src/lib/components/commerce-console-page.js.map +1 -1
  9. package/src/lib/components/console/host-orders-card.component.d.ts +6 -0
  10. package/src/lib/components/console/host-orders-card.component.js +3 -2
  11. package/src/lib/components/console/host-orders-card.component.js.map +1 -1
  12. package/src/lib/components/console/invoice-send.component.d.ts +44 -0
  13. package/src/lib/components/console/invoice-send.component.js +237 -0
  14. package/src/lib/components/console/invoice-send.component.js.map +1 -0
  15. package/src/lib/components/console/order-detail-dialog.component.d.ts +5 -0
  16. package/src/lib/components/console/order-detail-dialog.component.js +9 -2
  17. package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
  18. package/src/lib/components/console/order-invoice.component.d.ts +9 -0
  19. package/src/lib/components/console/order-invoice.component.js +27 -2
  20. package/src/lib/components/console/order-invoice.component.js.map +1 -1
  21. package/src/lib/components/console/pos/pos-item-dialog.component.js +3 -2
  22. package/src/lib/components/console/pos/pos-item-dialog.component.js.map +1 -1
  23. package/src/lib/components/console/pos-kiosk-page.component.js +2 -1
  24. package/src/lib/components/console/pos-kiosk-page.component.js.map +1 -1
  25. package/src/lib/components/console/pos-page.component.js +1 -1
  26. package/src/lib/components/console/pos-page.component.js.map +1 -1
  27. package/src/lib/components/console/product-add-ons-fields.component.d.ts +41 -0
  28. package/src/lib/components/console/product-add-ons-fields.component.js +356 -0
  29. package/src/lib/components/console/product-add-ons-fields.component.js.map +1 -0
  30. package/src/lib/components/console/product-editor-dialog.component.js +31 -5
  31. package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
  32. package/src/lib/components/console/product-register-fields.component.d.ts +4 -5
  33. package/src/lib/components/console/product-register-fields.component.js +8 -197
  34. package/src/lib/components/console/product-register-fields.component.js.map +1 -1
  35. package/src/lib/components/console/products-hub-zone.component.js +6 -0
  36. package/src/lib/components/console/products-hub-zone.component.js.map +1 -1
  37. package/src/lib/components/console/quote-editor-dialog.component.d.ts +29 -0
  38. package/src/lib/components/console/quote-editor-dialog.component.js +102 -4
  39. package/src/lib/components/console/quote-editor-dialog.component.js.map +1 -1
  40. package/src/lib/components/console/quote-pay-link.component.d.ts +8 -1
  41. package/src/lib/components/console/quote-pay-link.component.js +29 -3
  42. package/src/lib/components/console/quote-pay-link.component.js.map +1 -1
  43. package/src/lib/components/console/quote-proofs.component.d.ts +11 -0
  44. package/src/lib/components/console/quote-proofs.component.js +68 -0
  45. package/src/lib/components/console/quote-proofs.component.js.map +1 -1
  46. package/src/lib/components/console/quote-send.component.d.ts +42 -0
  47. package/src/lib/components/console/quote-send.component.js +304 -0
  48. package/src/lib/components/console/quote-send.component.js.map +1 -0
  49. package/src/lib/components/console/quote-start.component.d.ts +45 -0
  50. package/src/lib/components/console/quote-start.component.js +182 -0
  51. package/src/lib/components/console/quote-start.component.js.map +1 -0
  52. package/src/lib/components/product-add-ons.d.ts +28 -0
  53. package/src/lib/components/product-add-ons.js +136 -0
  54. package/src/lib/components/product-add-ons.js.map +1 -0
  55. package/src/lib/components/product-detail.d.ts +16 -0
  56. package/src/lib/components/product-detail.js +112 -19
  57. package/src/lib/components/product-detail.js.map +1 -1
  58. package/src/lib/components/product-grid.d.ts +8 -2
  59. package/src/lib/components/product-grid.js +6 -1
  60. package/src/lib/components/product-grid.js.map +1 -1
  61. package/src/lib/components/product-options-field-body.d.ts +44 -0
  62. package/src/lib/components/product-options-field-body.js +260 -0
  63. package/src/lib/components/product-options-field-body.js.map +1 -0
  64. package/src/lib/components/product-options-field.d.ts +32 -0
  65. package/src/lib/components/product-options-field.js +128 -0
  66. package/src/lib/components/product-options-field.js.map +1 -0
  67. package/src/lib/components/quote-page-body.js +39 -20
  68. package/src/lib/components/quote-page-body.js.map +1 -1
  69. package/src/lib/model/commerce-cart.d.ts +15 -3
  70. package/src/lib/model/commerce-cart.js +10 -3
  71. package/src/lib/model/commerce-cart.js.map +1 -1
  72. package/src/lib/model/commerce-invoices.d.ts +139 -0
  73. package/src/lib/model/commerce-invoices.js +343 -0
  74. package/src/lib/model/commerce-invoices.js.map +1 -0
  75. package/src/lib/model/commerce-orders.d.ts +35 -5
  76. package/src/lib/model/commerce-orders.js +3 -0
  77. package/src/lib/model/commerce-orders.js.map +1 -1
  78. package/src/lib/model/commerce-pos-kiosk.d.ts +1 -1
  79. package/src/lib/model/commerce-pos-kiosk.js +3 -2
  80. package/src/lib/model/commerce-pos-kiosk.js.map +1 -1
  81. package/src/lib/model/commerce-product-field.d.ts +23 -0
  82. package/src/lib/model/commerce-product-field.js +26 -0
  83. package/src/lib/model/commerce-product-field.js.map +1 -0
  84. package/src/lib/model/commerce-quote-email.d.ts +81 -0
  85. package/src/lib/model/commerce-quote-email.js +170 -0
  86. package/src/lib/model/commerce-quote-email.js.map +1 -0
  87. package/src/lib/model/commerce-quote-pay.d.ts +49 -6
  88. package/src/lib/model/commerce-quote-pay.js +69 -36
  89. package/src/lib/model/commerce-quote-pay.js.map +1 -1
  90. package/src/lib/model/commerce-quote-request.d.ts +93 -0
  91. package/src/lib/model/commerce-quote-request.js +207 -0
  92. package/src/lib/model/commerce-quote-request.js.map +1 -0
  93. package/src/lib/model/commerce-quotes.d.ts +81 -0
  94. package/src/lib/model/commerce-quotes.js +1 -1
  95. package/src/lib/model/commerce-quotes.js.map +1 -1
  96. package/src/lib/model/commerce.d.ts +18 -0
  97. package/src/lib/model/commerce.js +26 -0
  98. package/src/lib/model/commerce.js.map +1 -1
  99. package/src/lib/model/index.d.ts +3 -0
  100. package/src/lib/model/index.js +3 -0
  101. package/src/lib/model/index.js.map +1 -1
  102. package/src/lib/model/product-modifiers.d.ts +74 -4
  103. package/src/lib/model/product-modifiers.js +131 -10
  104. package/src/lib/model/product-modifiers.js.map +1 -1
  105. package/src/lib/plugin.js +19 -0
  106. package/src/lib/plugin.js.map +1 -1
  107. package/src/lib/server/billing-webhook.js +164 -98
  108. package/src/lib/server/billing-webhook.js.map +1 -1
  109. package/src/lib/server/cart-checkout.js +14 -2
  110. package/src/lib/server/cart-checkout.js.map +1 -1
  111. package/src/lib/server/cart.d.ts +5 -0
  112. package/src/lib/server/cart.js +41 -4
  113. package/src/lib/server/cart.js.map +1 -1
  114. package/src/lib/server/catalog.d.ts +6 -0
  115. package/src/lib/server/catalog.js +2 -0
  116. package/src/lib/server/catalog.js.map +1 -1
  117. package/src/lib/server/checkout-extras.js +3 -1
  118. package/src/lib/server/checkout-extras.js.map +1 -1
  119. package/src/lib/server/checkout.js +28 -3
  120. package/src/lib/server/checkout.js.map +1 -1
  121. package/src/lib/server/commerce-pdf.d.ts +5 -1
  122. package/src/lib/server/commerce-pdf.js +37 -10
  123. package/src/lib/server/commerce-pdf.js.map +1 -1
  124. package/src/lib/server/draft-order.js +23 -3
  125. package/src/lib/server/draft-order.js.map +1 -1
  126. package/src/lib/server/invoice-email.d.ts +76 -0
  127. package/src/lib/server/invoice-email.js +183 -0
  128. package/src/lib/server/invoice-email.js.map +1 -0
  129. package/src/lib/server/local-fulfillment.js +5 -1
  130. package/src/lib/server/local-fulfillment.js.map +1 -1
  131. package/src/lib/server/order-invoice-send.d.ts +43 -0
  132. package/src/lib/server/order-invoice-send.js +218 -0
  133. package/src/lib/server/order-invoice-send.js.map +1 -0
  134. package/src/lib/server/order-status.d.ts +11 -0
  135. package/src/lib/server/order-status.js +44 -8
  136. package/src/lib/server/order-status.js.map +1 -1
  137. package/src/lib/server/person-eraser.d.ts +3 -2
  138. package/src/lib/server/person-eraser.js +25 -6
  139. package/src/lib/server/person-eraser.js.map +1 -1
  140. package/src/lib/server/pos-offline-sync.js +1 -1
  141. package/src/lib/server/pos-offline-sync.js.map +1 -1
  142. package/src/lib/server/pos-order.js +1 -1
  143. package/src/lib/server/pos-order.js.map +1 -1
  144. package/src/lib/server/product.d.ts +26 -0
  145. package/src/lib/server/product.js +18 -0
  146. package/src/lib/server/product.js.map +1 -1
  147. package/src/lib/server/products-write.js +5 -2
  148. package/src/lib/server/products-write.js.map +1 -1
  149. package/src/lib/server/quote-email.d.ts +85 -0
  150. package/src/lib/server/quote-email.js +211 -0
  151. package/src/lib/server/quote-email.js.map +1 -0
  152. package/src/lib/server/quote-link-token.d.ts +11 -0
  153. package/src/lib/server/quote-link-token.js +21 -0
  154. package/src/lib/server/quote-link-token.js.map +1 -1
  155. package/src/lib/server/quote-pay.d.ts +8 -3
  156. package/src/lib/server/quote-pay.js +105 -43
  157. package/src/lib/server/quote-pay.js.map +1 -1
  158. package/src/lib/server/quote.d.ts +11 -0
  159. package/src/lib/server/quote.js +309 -12
  160. package/src/lib/server/quote.js.map +1 -1
  161. package/src/lib/server/site-page-resolver.js +2 -1
  162. package/src/lib/server/site-page-resolver.js.map +1 -1
  163. package/src/lib/server.js +5 -0
  164. package/src/lib/server.js.map +1 -1
  165. package/src/lib/site.js +8 -0
  166. package/src/lib/site.js.map +1 -1
  167. package/src/lib/tenant-emails.js +243 -0
  168. package/src/lib/tenant-emails.js.map +1 -1
  169. package/src/lib/utils/add-to-cart.d.ts +8 -0
  170. package/src/lib/utils/add-to-cart.js +10 -2
  171. package/src/lib/utils/add-to-cart.js.map +1 -1
  172. package/src/lib/utils/commerce-document-pdf.d.ts +5 -0
  173. package/src/lib/utils/commerce-document-pdf.js +6 -1
  174. package/src/lib/utils/commerce-document-pdf.js.map +1 -1
  175. package/src/lib/utils/invoice-email-content.d.ts +45 -0
  176. package/src/lib/utils/invoice-email-content.js +126 -0
  177. package/src/lib/utils/invoice-email-content.js.map +1 -0
  178. package/src/lib/utils/order-invoice.d.ts +1 -1
  179. package/src/lib/utils/order-invoice.js +14 -6
  180. package/src/lib/utils/order-invoice.js.map +1 -1
  181. package/src/lib/utils/quote-email-content.d.ts +63 -0
  182. package/src/lib/utils/quote-email-content.js +157 -0
  183. package/src/lib/utils/quote-email-content.js.map +1 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/components/commerce-console-page.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 type { ConsolePluginPageProps } from '@aglyn/aglyn'\nimport { GridItems } from '@aglyn/shared-ui-jsx'\nimport { HubSections } from '@aglyn/shared-ui-next'\nimport { lazy, Suspense, type ReactNode } from 'react'\nimport { Stack } from '@mui/material'\nimport {\n COMMERCE_SETTINGS_PAGE_ZONES,\n type CommerceConsoleSectionId,\n type CommerceSettingsSectionId,\n} from './commerce-console-sections'\nimport CatalogOrganizationCard from './console/catalog-organization-card.component'\nimport CommerceAnalyticsCard from './console/commerce-analytics-card.component'\nimport CustomerNotificationsCard from './console/customer-notifications-card.component'\nimport DiscountsCard from './console/discounts-card.component'\nimport GiftCardsCard from './console/gift-cards-card.component'\nimport HostCouponsCard from './console/host-coupons-card.component'\nimport HostOrdersCard from './console/host-orders-card.component'\nimport HostQuotesCard from './console/host-quotes-card.component'\nimport LocationsCard from './console/locations-card.component'\nimport LocalDeliverySettingsCard from './console/local-delivery-settings-card.component'\nimport PickupDeliveryQueueCard from './console/pickup-delivery-queue-card.component'\nimport MemberPostsCard from './console/member-posts-card.component'\nimport OrderWebhooksCard from './console/order-webhooks-card.component'\nimport PaymentsSettingsCard from './console/payments-settings-card.component'\nimport PosCheckInsCard from './console/pos-ops/pos-check-ins-card.component'\nimport PosDayTotalsCard from './console/pos-ops/pos-day-totals-card.component'\nimport PosShiftHistoryCard from './console/pos-ops/pos-shift-history-card.component'\nimport PosStaffPinsCard from './console/pos-ops/pos-staff-pins-card.component'\nimport PaymentMethodsCard from './console/payment-methods-card.component'\nimport ProductsHubCard from './console/products-hub-card.component'\nimport QuoteSettingsCard from './console/quote-settings-card.component'\nimport RecoveryQueueCard from './console/recovery-queue-card.component'\nimport RegistersCard from './console/registers-card.component'\nimport RegisterHardwareCards from './console/register-hardware-card.component'\nimport PosDevicesCard from './console/pos-devices-card.component'\nimport PosHardwareCard from './console/pos-hardware-card.component'\n\n/**\n * Card readers the workspace bought in person, waiting to be set up\n * (AGL-4038): its own chunk, drawn only while there is one.\n */\nconst PosHardwareWaitingCard = lazy(() => import('./console/pos-hardware-waiting-card.component'))\nimport { holdsPosPermission, posPermissionRefusal } from '../model/plugin-permissions'\nimport ReservationsCard from './console/reservations-card.component'\nimport ReturnSettingsCard from './console/return-settings-card.component'\nimport ReturnsCard from './console/returns-card.component'\nimport ReviewsModerationCard from './console/reviews-moderation-card.component'\nimport ReviewSettingsCard from './console/review-settings-card.component'\nimport ShippingSettingsCard from './console/shipping-settings-card.component'\nimport ShipStationCard from './console/shipstation-card.component'\nimport ShippingEasyCard from './console/shippingeasy-card.component'\nimport StockMovementsCard from './console/stock-movements-card.component'\nimport StoreSettingsCard from './console/store-settings-card.component'\nimport StorefrontTaxSummaryCard from './console/storefront-tax-summary-card.component'\nimport SuppliersCard from './console/suppliers-card.component'\nimport TaxSettingsCard from './console/tax-settings-card.component'\nimport { COMMERCE_PROMOTIONS_ZONE } from './console/store-zones'\nimport { useConsoleWidgetSlot } from '@aglyn/aglyn/app-utils/console-widget-slot-context'\n\n/**\n * A settings page's zone (AGL-3612, AGL-3713): other plugins' settings for\n * the store — label settings, carrier accounts, a tax service — under the\n * page's own cards. One zone per page, from `COMMERCE_SETTINGS_PAGE_ZONES`;\n * Integrations draws `commerceSettings`, where a widget naming no page lands.\n */\nfunction CommerceSettingsZone(props: {\n hostId: string\n page: CommerceSettingsSectionId\n}) {\n const WidgetSlot = useConsoleWidgetSlot()\n return WidgetSlot ? (\n <WidgetSlot\n slot={COMMERCE_SETTINGS_PAGE_ZONES[props.page]}\n hostId={props.hostId}\n orgId={undefined}\n />\n ) : null\n}\n\n/** One settings page: its cards in order, then its zone (AGL-3713). */\nfunction settingsPage(\n page: CommerceSettingsSectionId,\n hostId: string,\n cards: readonly ReactNode[],\n): ReactNode {\n return (\n <GridItems\n spacing={3}\n items={[\n ...cards.map((children) => ({ size: { xs: 12 }, children })),\n {\n size: { xs: 12 },\n children: <CommerceSettingsZone hostId={hostId} page={page} />,\n },\n ]}\n />\n )\n}\n\n/**\n * The `commercePromotions` zone (AGL-3640): other plugins' programs beside\n * the store's own money-off surfaces — a rewards program first.\n */\nfunction CommercePromotionsZone(props: { hostId: string }) {\n const WidgetSlot = useConsoleWidgetSlot()\n return WidgetSlot ? (\n <WidgetSlot slot={COMMERCE_PROMOTIONS_ZONE.id} hostId={props.hostId} orgId={undefined} />\n ) : null\n}\n\n/**\n * The body of one commerce section, built only when that section is the one\n * being read (AGL-2501).\n *\n * A function rather than a map of nodes on purpose: a `Record<id, ReactNode>`\n * would CONSTRUCT every section every render, and each card opens its Firestore\n * listens on mount — which is the entire cost this page exists to stop paying.\n * Only the returned branch is ever built.\n */\nfunction sectionBody(\n section: CommerceConsoleSectionId,\n hostId: string,\n canManagePos: boolean,\n /** The register's finer keys this page's cards ask (AGL-4047). */\n pos: { canSetUpDevices: boolean; canBuyHardware: boolean; canCashDrawer: boolean } = {\n canSetUpDevices: canManagePos,\n canBuyHardware: canManagePos,\n canCashDrawer: canManagePos,\n },\n /** The reservation keys this site decides for the member (AGL-4047). */\n reservations: { canManage: boolean; canWalkIn: boolean } = { canManage: true, canWalkIn: true },\n /** \"Create and edit quotes\" and \"Send quotes and invoices to customers\" on this site (AGL-4093, AGL-4094). */\n quotes: { canEdit: boolean; canSend: boolean } = { canEdit: true, canSend: true },\n): ReactNode {\n switch (section) {\n case 'catalog':\n return (\n <GridItems\n spacing={3}\n items={[\n { size: { xs: 12 }, children: <ProductsHubCard hostId={hostId} /> },\n {\n size: { xs: 12 },\n children: <CatalogOrganizationCard hostId={hostId} />,\n },\n // The ledger every stock writer fills and nothing displayed\n // (AGL-2341). Directly under the catalog, because the question\n // it answers — \"why does this count disagree with the shelf\" —\n // is asked while looking at the count.\n {\n size: { xs: 12 },\n children: <StockMovementsCard hostId={hostId} />,\n },\n { size: { xs: 12 }, children: <MemberPostsCard hostId={hostId} /> },\n ]}\n />\n )\n case 'orders':\n return (\n <GridItems\n spacing={3}\n items={[\n { size: { xs: 12 }, children: <HostOrdersCard hostId={hostId} /> },\n // Prices put to a customer before they buy (AGL-4093), beside the\n // orders they become once paid.\n {\n size: { xs: 12 },\n children: <HostQuotesCard hostId={hostId} canEdit={quotes.canEdit} canSend={quotes.canSend} />,\n },\n // What to prepare, hand over and drive out (AGL-3624). Renders\n // nothing for a store with no pickup and no local delivery.\n {\n size: { xs: 12 },\n children: <PickupDeliveryQueueCard hostId={hostId} />,\n },\n // The two queues that feed orders rather than record them\n // (AGL-2227): checkouts that stalled and shoppers waiting on\n // stock. Beneath the orders list because both are pre-order.\n {\n size: { xs: 12 },\n children: <RecoveryQueueCard hostId={hostId} />,\n },\n // One day's or one event's totals across every register, shift\n // and cashier (AGL-4037), above the shifts it adds up.\n {\n size: { xs: 12 },\n children: <PosDayTotalsCard hostId={hostId} canManagePos={canManagePos} />,\n },\n // Who is due at the window and who checked in (AGL-4043), beside\n // the day's totals.\n {\n size: { xs: 12 },\n children: <PosCheckInsCard hostId={hostId} canManagePos={canManagePos} />,\n },\n {\n size: { xs: 12 },\n children: <PosShiftHistoryCard hostId={hostId} />,\n },\n ]}\n />\n )\n case 'returns':\n // Returns (AGL-3611); `?return={id}` opens one on arrival.\n return <ReturnsCard hostId={hostId} />\n case 'promotions':\n return (\n <GridItems\n spacing={3}\n items={[\n { size: { xs: 12 }, children: <DiscountsCard hostId={hostId} /> },\n { size: { xs: 12 }, children: <HostCouponsCard hostId={hostId} /> },\n // Store credit lives with the other money-off surfaces\n // (AGL-2226) — it had no console anywhere before this.\n { size: { xs: 12 }, children: <GiftCardsCard hostId={hostId} /> },\n {\n size: { xs: 12 },\n children: <ReviewsModerationCard hostId={hostId} />,\n },\n // Who may review, and the review-request email (AGL-3736),\n // beside the queue those reviews land in.\n {\n size: { xs: 12 },\n children: <ReviewSettingsCard hostId={hostId} />,\n },\n {\n size: { xs: 12 },\n children: <CommercePromotionsZone hostId={hostId} />,\n },\n ]}\n />\n )\n case 'reservations':\n return (\n <ReservationsCard\n hostId={hostId}\n canManage={reservations.canManage}\n canWalkIn={reservations.canWalkIn}\n />\n )\n /*\n * The store's settings, a page each (AGL-3713). They were one `settings`\n * section — every card below in one column — and its old address opens\n * Payments (`COMMERCE_RETIRED_SECTIONS`). Each page is its cards, then\n * the zone where other plugins' cards for that page land.\n */\n case 'payments':\n return settingsPage(section, hostId, [\n <PaymentsSettingsCard key=\"payments\" hostId={hostId} />,\n // What shoppers may pay with (AGL-3629), beside the account the\n // money lands in.\n <PaymentMethodsCard key=\"methods\" hostId={hostId} />,\n ])\n case 'checkout':\n return settingsPage(section, hostId, [\n <StoreSettingsCard key=\"store\" hostId={hostId} />,\n // Whether buyers may ask for a return online (AGL-3611): the store's\n // policy, beside the terms and guest-checkout rules above it.\n <ReturnSettingsCard key=\"returns\" hostId={hostId} />,\n // What a new quote starts with (AGL-4093).\n <QuoteSettingsCard key=\"quotes\" hostId={hostId} />,\n ])\n case 'taxes':\n return settingsPage(section, hostId, [\n <TaxSettingsCard key=\"tax\" hostId={hostId} />,\n ])\n case 'shipping':\n return settingsPage(section, hostId, [\n <ShippingSettingsCard key=\"shipping\" hostId={hostId} />,\n // Where parcels ship from, and pickup, per location.\n <LocationsCard key=\"locations\" hostId={hostId} />,\n // The store's own delivery (AGL-3624); pickup is per location, on\n // the Inventory locations card above.\n <LocalDeliverySettingsCard key=\"local\" hostId={hostId} />,\n <SuppliersCard key=\"suppliers\" hostId={hostId} />,\n <ShipStationCard key=\"shipstation\" hostId={hostId} />,\n // ShippingEasy, with the merchant's own keys (AGL-3633).\n <ShippingEasyCard key=\"shippingeasy\" hostId={hostId} />,\n ])\n case 'notifications':\n return settingsPage(section, hostId, [\n <CustomerNotificationsCard key=\"customers\" hostId={hostId} />,\n // The store's own endpoints for order events (AGL-3611). Renders\n // nothing for a person who may not manage them.\n <OrderWebhooksCard key=\"webhooks\" hostId={hostId} />,\n ])\n case 'pos':\n return settingsPage(section, hostId, [\n // A reader bought in person waits at the top until it is set up\n // (AGL-4038), in the registers' own grid cell so an empty one\n // leaves no gap.\n <Stack key=\"registers\" spacing={3}>\n <Suspense fallback={null}>\n <PosHardwareWaitingCard\n hostId={hostId}\n {...(pos.canSetUpDevices ? {} : { devicesBlockedReason: posPermissionRefusal('posDevices') })}\n />\n </Suspense>\n <RegistersCard hostId={hostId} />\n </Stack>,\n <PosStaffPinsCard key=\"pins\" hostId={hostId} />,\n // A register's printers, cash drawer and status (AGL-3619), one card\n // per register, after the list that names them.\n <RegisterHardwareCards\n key=\"hardware\"\n hostId={hostId}\n blocked={{\n ...(pos.canSetUpDevices ? {} : { devices: posPermissionRefusal('posDevices') }),\n ...(pos.canCashDrawer ? {} : { drawer: posPermissionRefusal('posCashDrawer') }),\n }}\n />,\n <PosDevicesCard\n key=\"devices\"\n hostId={hostId}\n canManagePos={canManagePos}\n canSetUpDevices={pos.canSetUpDevices}\n />,\n // Card readers bought from the platform (AGL-4038), after the card\n // that registers them. Draws nothing until the deployment opens the\n // shop.\n <PosHardwareCard\n key=\"hardware-shop\"\n hostId={hostId}\n canManagePos={canManagePos}\n canBuyHardware={pos.canBuyHardware}\n />,\n ])\n case 'channels':\n case 'integrations':\n // Other plugins' cards only; the rail leaves either page out while\n // its zone has nothing to draw (`onlyWithZones`).\n return settingsPage(section, hostId, [])\n case 'analytics':\n return (\n // Two cards since AGL-2440. The tax summary lives here rather\n // than on the Taxes settings page because that page CONFIGURES tax and\n // this REPORTS what was collected — a merchant reading a figure\n // they may file from should not be one field away from changing\n // the rate that produced it.\n <GridItems\n spacing={3}\n items={[\n {\n size: { xs: 12 },\n children: <CommerceAnalyticsCard hostId={hostId} />,\n },\n {\n size: { xs: 12 },\n children: <StorefrontTaxSummaryCard hostId={hostId} />,\n },\n ]}\n />\n )\n default:\n return null\n }\n}\n\n/**\n * Commerce console page (AGL-395): the Products management surface, owned by\n * the commerce plugin and rendered by the shell's generic plugin route. The\n * product editor's media browser is supplied by the shell's\n * ConsoleMediaPickerProvider (the media library is org/session coupled and\n * stays in the app).\n *\n * ## Sections are ROUTES (AGL-2501)\n *\n * The sections hold thirty-two Firestore listens between them, and a tab\n * strip mounts every panel: opening Catalog also subscribed the orders,\n * promotions, reservations, settings and analytics cards. The `limit()` on\n * those queries is the bill — several ask for 500, and one load reached a\n * ceiling of ~4,460 documents to render one tab.\n *\n * `HubTabs lazy` bought that back as a flag somebody has to remember. A URL\n * per section makes it structural instead: the page builds one section's body\n * and the others do not exist to subscribe. Three things come with it that the\n * tab version faked — a section is linkable, the back button walks sections,\n * and which one is open is a fact about the URL rather than state kept in sync\n * with it. `commerce-console-read-cost.spec.tsx` meters it at the Firestore\n * boundary and refuses a section that listens before it is opened.\n *\n * The shell resolves the section, gates it and hands back the rail's hrefs;\n * this page only has to say what each section contains.\n */\nexport function CommerceConsolePage(props: ConsolePluginPageProps) {\n const { hostId, section, sections, basePath, permissions } = props\n /*\n * The register's own gate, for the devices card's Pair display (AGL-3712):\n * `managePos` — what the server's `mayWorkRegister` asks. The key decides,\n * not the site role (AGL-4047). The server stays the enforcement point.\n */\n const canManagePos = permissions?.managePos === true\n // The register's finer keys (AGL-4047), each following `managePos` unless a\n // role or the member sets it — what the devices and hardware routes ask.\n // Buying hardware stands on its own: the Hardware card is this page's for a\n // member who holds it without the register.\n const pos = {\n canSetUpDevices: canManagePos && holdsPosPermission(permissions, 'posDevices'),\n canBuyHardware: holdsPosPermission(permissions, 'posBuyHardware'),\n canCashDrawer: canManagePos && holdsPosPermission(permissions, 'posCashDrawer'),\n }\n // The reservation keys (AGL-4047), whose preset is the member's role on\n // this site; the shell decides them for the site in view. A map that does\n // not carry one (a shell that predates them) leaves the card as it was:\n // the rules and the routes decide.\n const reservations = {\n canManage: permissions?.['commerce.reservations'] !== false,\n canWalkIn: permissions?.['commerce.walkIns'] !== false,\n }\n // \"Create and edit quotes\" (AGL-4093), read the same way; the quote route\n // decides.\n const quotes = {\n canEdit: permissions?.['commerce.quotes'] !== false,\n canSend: permissions?.['commerce.quotes.send'] !== false,\n }\n\n /*\n * Nothing, deliberately, while the redirect is in flight.\n *\n * Rendering the default section here instead would issue that section's\n * listens on a URL that is about to be replaced — paying for Catalog on\n * every arrival at `/products`, which is every click of the nav tab.\n */\n if (!section || !sections?.length || !basePath) return null\n\n return (\n <HubSections sections={sections}>\n {sectionBody(section as CommerceConsoleSectionId, hostId, canManagePos, pos, reservations, quotes)}\n </HubSections>\n )\n}\nCommerceConsolePage.displayName = 'CommerceConsolePage'\n\nexport default CommerceConsolePage\n"],"names":["GridItems","HubSections","lazy","Suspense","Stack","COMMERCE_SETTINGS_PAGE_ZONES","CatalogOrganizationCard","CommerceAnalyticsCard","CustomerNotificationsCard","DiscountsCard","GiftCardsCard","HostCouponsCard","HostOrdersCard","HostQuotesCard","LocationsCard","LocalDeliverySettingsCard","PickupDeliveryQueueCard","MemberPostsCard","OrderWebhooksCard","PaymentsSettingsCard","PosCheckInsCard","PosDayTotalsCard","PosShiftHistoryCard","PosStaffPinsCard","PaymentMethodsCard","ProductsHubCard","QuoteSettingsCard","RecoveryQueueCard","RegistersCard","RegisterHardwareCards","PosDevicesCard","PosHardwareCard","PosHardwareWaitingCard","holdsPosPermission","posPermissionRefusal","ReservationsCard","ReturnSettingsCard","ReturnsCard","ReviewsModerationCard","ReviewSettingsCard","ShippingSettingsCard","ShipStationCard","ShippingEasyCard","StockMovementsCard","StoreSettingsCard","StorefrontTaxSummaryCard","SuppliersCard","TaxSettingsCard","COMMERCE_PROMOTIONS_ZONE","useConsoleWidgetSlot","CommerceSettingsZone","props","WidgetSlot","slot","page","hostId","orgId","undefined","settingsPage","cards","spacing","items","map","children","size","xs","CommercePromotionsZone","id","sectionBody","section","canManagePos","pos","canSetUpDevices","canBuyHardware","canCashDrawer","reservations","canManage","canWalkIn","quotes","canEdit","canSend","fallback","devicesBlockedReason","blocked","devices","drawer","CommerceConsolePage","sections","basePath","permissions","managePos","length","displayName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/components/commerce-console-page.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 type { ConsolePluginPageProps } from '@aglyn/aglyn'\nimport { GridItems } from '@aglyn/shared-ui-jsx'\nimport { HubSections } from '@aglyn/shared-ui-next'\nimport { lazy, Suspense, type ReactNode } from 'react'\nimport { Stack } from '@mui/material'\nimport {\n COMMERCE_SETTINGS_PAGE_ZONES,\n type CommerceConsoleSectionId,\n type CommerceSettingsSectionId,\n} from './commerce-console-sections'\nimport CatalogOrganizationCard from './console/catalog-organization-card.component'\nimport CommerceAnalyticsCard from './console/commerce-analytics-card.component'\nimport CustomerNotificationsCard from './console/customer-notifications-card.component'\nimport DiscountsCard from './console/discounts-card.component'\nimport GiftCardsCard from './console/gift-cards-card.component'\nimport HostCouponsCard from './console/host-coupons-card.component'\nimport HostOrdersCard from './console/host-orders-card.component'\nimport HostQuotesCard from './console/host-quotes-card.component'\nimport LocationsCard from './console/locations-card.component'\nimport LocalDeliverySettingsCard from './console/local-delivery-settings-card.component'\nimport PickupDeliveryQueueCard from './console/pickup-delivery-queue-card.component'\nimport MemberPostsCard from './console/member-posts-card.component'\nimport OrderWebhooksCard from './console/order-webhooks-card.component'\nimport PaymentsSettingsCard from './console/payments-settings-card.component'\nimport PosCheckInsCard from './console/pos-ops/pos-check-ins-card.component'\nimport PosDayTotalsCard from './console/pos-ops/pos-day-totals-card.component'\nimport PosShiftHistoryCard from './console/pos-ops/pos-shift-history-card.component'\nimport PosStaffPinsCard from './console/pos-ops/pos-staff-pins-card.component'\nimport PaymentMethodsCard from './console/payment-methods-card.component'\nimport ProductsHubCard from './console/products-hub-card.component'\nimport QuoteSettingsCard from './console/quote-settings-card.component'\nimport RecoveryQueueCard from './console/recovery-queue-card.component'\nimport RegistersCard from './console/registers-card.component'\nimport RegisterHardwareCards from './console/register-hardware-card.component'\nimport PosDevicesCard from './console/pos-devices-card.component'\nimport PosHardwareCard from './console/pos-hardware-card.component'\n\n/**\n * Card readers the workspace bought in person, waiting to be set up\n * (AGL-4038): its own chunk, drawn only while there is one.\n */\nconst PosHardwareWaitingCard = lazy(() => import('./console/pos-hardware-waiting-card.component'))\nimport { holdsPosPermission, posPermissionRefusal } from '../model/plugin-permissions'\nimport ReservationsCard from './console/reservations-card.component'\nimport ReturnSettingsCard from './console/return-settings-card.component'\nimport ReturnsCard from './console/returns-card.component'\nimport ReviewsModerationCard from './console/reviews-moderation-card.component'\nimport ReviewSettingsCard from './console/review-settings-card.component'\nimport ShippingSettingsCard from './console/shipping-settings-card.component'\nimport ShipStationCard from './console/shipstation-card.component'\nimport ShippingEasyCard from './console/shippingeasy-card.component'\nimport StockMovementsCard from './console/stock-movements-card.component'\nimport StoreSettingsCard from './console/store-settings-card.component'\nimport StorefrontTaxSummaryCard from './console/storefront-tax-summary-card.component'\nimport SuppliersCard from './console/suppliers-card.component'\nimport TaxSettingsCard from './console/tax-settings-card.component'\nimport { COMMERCE_PROMOTIONS_ZONE } from './console/store-zones'\nimport { useConsoleWidgetSlot } from '@aglyn/aglyn/app-utils/console-widget-slot-context'\n\n/**\n * A settings page's zone (AGL-3612, AGL-3713): other plugins' settings for\n * the store — label settings, carrier accounts, a tax service — under the\n * page's own cards. One zone per page, from `COMMERCE_SETTINGS_PAGE_ZONES`;\n * Integrations draws `commerceSettings`, where a widget naming no page lands.\n */\nfunction CommerceSettingsZone(props: {\n hostId: string\n page: CommerceSettingsSectionId\n}) {\n const WidgetSlot = useConsoleWidgetSlot()\n return WidgetSlot ? (\n <WidgetSlot\n slot={COMMERCE_SETTINGS_PAGE_ZONES[props.page]}\n hostId={props.hostId}\n orgId={undefined}\n />\n ) : null\n}\n\n/** One settings page: its cards in order, then its zone (AGL-3713). */\nfunction settingsPage(\n page: CommerceSettingsSectionId,\n hostId: string,\n cards: readonly ReactNode[],\n): ReactNode {\n return (\n <GridItems\n spacing={3}\n items={[\n ...cards.map((children) => ({ size: { xs: 12 }, children })),\n {\n size: { xs: 12 },\n children: <CommerceSettingsZone hostId={hostId} page={page} />,\n },\n ]}\n />\n )\n}\n\n/**\n * The `commercePromotions` zone (AGL-3640): other plugins' programs beside\n * the store's own money-off surfaces — a rewards program first.\n */\nfunction CommercePromotionsZone(props: { hostId: string }) {\n const WidgetSlot = useConsoleWidgetSlot()\n return WidgetSlot ? (\n <WidgetSlot slot={COMMERCE_PROMOTIONS_ZONE.id} hostId={props.hostId} orgId={undefined} />\n ) : null\n}\n\n/**\n * The body of one commerce section, built only when that section is the one\n * being read (AGL-2501).\n *\n * A function rather than a map of nodes on purpose: a `Record<id, ReactNode>`\n * would CONSTRUCT every section every render, and each card opens its Firestore\n * listens on mount — which is the entire cost this page exists to stop paying.\n * Only the returned branch is ever built.\n */\nfunction sectionBody(\n section: CommerceConsoleSectionId,\n hostId: string,\n canManagePos: boolean,\n /** The register's finer keys this page's cards ask (AGL-4047). */\n pos: { canSetUpDevices: boolean; canBuyHardware: boolean; canCashDrawer: boolean } = {\n canSetUpDevices: canManagePos,\n canBuyHardware: canManagePos,\n canCashDrawer: canManagePos,\n },\n /** The reservation keys this site decides for the member (AGL-4047). */\n reservations: { canManage: boolean; canWalkIn: boolean } = { canManage: true, canWalkIn: true },\n /** \"Create and edit quotes\" and \"Send quotes and invoices to customers\" on this site (AGL-4093, AGL-4094). */\n quotes: { canEdit: boolean; canSend: boolean } = { canEdit: true, canSend: true },\n): ReactNode {\n switch (section) {\n case 'catalog':\n return (\n <GridItems\n spacing={3}\n items={[\n { size: { xs: 12 }, children: <ProductsHubCard hostId={hostId} /> },\n {\n size: { xs: 12 },\n children: <CatalogOrganizationCard hostId={hostId} />,\n },\n // The ledger every stock writer fills and nothing displayed\n // (AGL-2341). Directly under the catalog, because the question\n // it answers — \"why does this count disagree with the shelf\" —\n // is asked while looking at the count.\n {\n size: { xs: 12 },\n children: <StockMovementsCard hostId={hostId} />,\n },\n { size: { xs: 12 }, children: <MemberPostsCard hostId={hostId} /> },\n ]}\n />\n )\n case 'orders':\n return (\n <GridItems\n spacing={3}\n items={[\n { size: { xs: 12 }, children: <HostOrdersCard hostId={hostId} canSendInvoices={quotes.canSend} /> },\n // Prices put to a customer before they buy (AGL-4093), beside the\n // orders they become once paid.\n {\n size: { xs: 12 },\n children: <HostQuotesCard hostId={hostId} canEdit={quotes.canEdit} canSend={quotes.canSend} />,\n },\n // What to prepare, hand over and drive out (AGL-3624). Renders\n // nothing for a store with no pickup and no local delivery.\n {\n size: { xs: 12 },\n children: <PickupDeliveryQueueCard hostId={hostId} />,\n },\n // The two queues that feed orders rather than record them\n // (AGL-2227): checkouts that stalled and shoppers waiting on\n // stock. Beneath the orders list because both are pre-order.\n {\n size: { xs: 12 },\n children: <RecoveryQueueCard hostId={hostId} />,\n },\n // One day's or one event's totals across every register, shift\n // and cashier (AGL-4037), above the shifts it adds up.\n {\n size: { xs: 12 },\n children: <PosDayTotalsCard hostId={hostId} canManagePos={canManagePos} />,\n },\n // Who is due at the window and who checked in (AGL-4043), beside\n // the day's totals.\n {\n size: { xs: 12 },\n children: <PosCheckInsCard hostId={hostId} canManagePos={canManagePos} />,\n },\n {\n size: { xs: 12 },\n children: <PosShiftHistoryCard hostId={hostId} />,\n },\n ]}\n />\n )\n case 'returns':\n // Returns (AGL-3611); `?return={id}` opens one on arrival.\n return <ReturnsCard hostId={hostId} />\n case 'promotions':\n return (\n <GridItems\n spacing={3}\n items={[\n { size: { xs: 12 }, children: <DiscountsCard hostId={hostId} /> },\n { size: { xs: 12 }, children: <HostCouponsCard hostId={hostId} /> },\n // Store credit lives with the other money-off surfaces\n // (AGL-2226) — it had no console anywhere before this.\n { size: { xs: 12 }, children: <GiftCardsCard hostId={hostId} /> },\n {\n size: { xs: 12 },\n children: <ReviewsModerationCard hostId={hostId} />,\n },\n // Who may review, and the review-request email (AGL-3736),\n // beside the queue those reviews land in.\n {\n size: { xs: 12 },\n children: <ReviewSettingsCard hostId={hostId} />,\n },\n {\n size: { xs: 12 },\n children: <CommercePromotionsZone hostId={hostId} />,\n },\n ]}\n />\n )\n case 'reservations':\n return (\n <ReservationsCard\n hostId={hostId}\n canManage={reservations.canManage}\n canWalkIn={reservations.canWalkIn}\n />\n )\n /*\n * The store's settings, a page each (AGL-3713). They were one `settings`\n * section — every card below in one column — and its old address opens\n * Payments (`COMMERCE_RETIRED_SECTIONS`). Each page is its cards, then\n * the zone where other plugins' cards for that page land.\n */\n case 'payments':\n return settingsPage(section, hostId, [\n <PaymentsSettingsCard key=\"payments\" hostId={hostId} />,\n // What shoppers may pay with (AGL-3629), beside the account the\n // money lands in.\n <PaymentMethodsCard key=\"methods\" hostId={hostId} />,\n ])\n case 'checkout':\n return settingsPage(section, hostId, [\n <StoreSettingsCard key=\"store\" hostId={hostId} />,\n // Whether buyers may ask for a return online (AGL-3611): the store's\n // policy, beside the terms and guest-checkout rules above it.\n <ReturnSettingsCard key=\"returns\" hostId={hostId} />,\n // What a new quote starts with (AGL-4093).\n <QuoteSettingsCard key=\"quotes\" hostId={hostId} />,\n ])\n case 'taxes':\n return settingsPage(section, hostId, [\n <TaxSettingsCard key=\"tax\" hostId={hostId} />,\n ])\n case 'shipping':\n return settingsPage(section, hostId, [\n <ShippingSettingsCard key=\"shipping\" hostId={hostId} />,\n // Where parcels ship from, and pickup, per location.\n <LocationsCard key=\"locations\" hostId={hostId} />,\n // The store's own delivery (AGL-3624); pickup is per location, on\n // the Inventory locations card above.\n <LocalDeliverySettingsCard key=\"local\" hostId={hostId} />,\n <SuppliersCard key=\"suppliers\" hostId={hostId} />,\n <ShipStationCard key=\"shipstation\" hostId={hostId} />,\n // ShippingEasy, with the merchant's own keys (AGL-3633).\n <ShippingEasyCard key=\"shippingeasy\" hostId={hostId} />,\n ])\n case 'notifications':\n return settingsPage(section, hostId, [\n <CustomerNotificationsCard key=\"customers\" hostId={hostId} />,\n // The store's own endpoints for order events (AGL-3611). Renders\n // nothing for a person who may not manage them.\n <OrderWebhooksCard key=\"webhooks\" hostId={hostId} />,\n ])\n case 'pos':\n return settingsPage(section, hostId, [\n // A reader bought in person waits at the top until it is set up\n // (AGL-4038), in the registers' own grid cell so an empty one\n // leaves no gap.\n <Stack key=\"registers\" spacing={3}>\n <Suspense fallback={null}>\n <PosHardwareWaitingCard\n hostId={hostId}\n {...(pos.canSetUpDevices ? {} : { devicesBlockedReason: posPermissionRefusal('posDevices') })}\n />\n </Suspense>\n <RegistersCard hostId={hostId} />\n </Stack>,\n <PosStaffPinsCard key=\"pins\" hostId={hostId} />,\n // A register's printers, cash drawer and status (AGL-3619), one card\n // per register, after the list that names them.\n <RegisterHardwareCards\n key=\"hardware\"\n hostId={hostId}\n blocked={{\n ...(pos.canSetUpDevices ? {} : { devices: posPermissionRefusal('posDevices') }),\n ...(pos.canCashDrawer ? {} : { drawer: posPermissionRefusal('posCashDrawer') }),\n }}\n />,\n <PosDevicesCard\n key=\"devices\"\n hostId={hostId}\n canManagePos={canManagePos}\n canSetUpDevices={pos.canSetUpDevices}\n />,\n // Card readers bought from the platform (AGL-4038), after the card\n // that registers them. Draws nothing until the deployment opens the\n // shop.\n <PosHardwareCard\n key=\"hardware-shop\"\n hostId={hostId}\n canManagePos={canManagePos}\n canBuyHardware={pos.canBuyHardware}\n />,\n ])\n case 'channels':\n case 'integrations':\n // Other plugins' cards only; the rail leaves either page out while\n // its zone has nothing to draw (`onlyWithZones`).\n return settingsPage(section, hostId, [])\n case 'analytics':\n return (\n // Two cards since AGL-2440. The tax summary lives here rather\n // than on the Taxes settings page because that page CONFIGURES tax and\n // this REPORTS what was collected — a merchant reading a figure\n // they may file from should not be one field away from changing\n // the rate that produced it.\n <GridItems\n spacing={3}\n items={[\n {\n size: { xs: 12 },\n children: <CommerceAnalyticsCard hostId={hostId} />,\n },\n {\n size: { xs: 12 },\n children: <StorefrontTaxSummaryCard hostId={hostId} />,\n },\n ]}\n />\n )\n default:\n return null\n }\n}\n\n/**\n * Commerce console page (AGL-395): the Products management surface, owned by\n * the commerce plugin and rendered by the shell's generic plugin route. The\n * product editor's media browser is supplied by the shell's\n * ConsoleMediaPickerProvider (the media library is org/session coupled and\n * stays in the app).\n *\n * ## Sections are ROUTES (AGL-2501)\n *\n * The sections hold thirty-two Firestore listens between them, and a tab\n * strip mounts every panel: opening Catalog also subscribed the orders,\n * promotions, reservations, settings and analytics cards. The `limit()` on\n * those queries is the bill — several ask for 500, and one load reached a\n * ceiling of ~4,460 documents to render one tab.\n *\n * `HubTabs lazy` bought that back as a flag somebody has to remember. A URL\n * per section makes it structural instead: the page builds one section's body\n * and the others do not exist to subscribe. Three things come with it that the\n * tab version faked — a section is linkable, the back button walks sections,\n * and which one is open is a fact about the URL rather than state kept in sync\n * with it. `commerce-console-read-cost.spec.tsx` meters it at the Firestore\n * boundary and refuses a section that listens before it is opened.\n *\n * The shell resolves the section, gates it and hands back the rail's hrefs;\n * this page only has to say what each section contains.\n */\nexport function CommerceConsolePage(props: ConsolePluginPageProps) {\n const { hostId, section, sections, basePath, permissions } = props\n /*\n * The register's own gate, for the devices card's Pair display (AGL-3712):\n * `managePos` — what the server's `mayWorkRegister` asks. The key decides,\n * not the site role (AGL-4047). The server stays the enforcement point.\n */\n const canManagePos = permissions?.managePos === true\n // The register's finer keys (AGL-4047), each following `managePos` unless a\n // role or the member sets it — what the devices and hardware routes ask.\n // Buying hardware stands on its own: the Hardware card is this page's for a\n // member who holds it without the register.\n const pos = {\n canSetUpDevices: canManagePos && holdsPosPermission(permissions, 'posDevices'),\n canBuyHardware: holdsPosPermission(permissions, 'posBuyHardware'),\n canCashDrawer: canManagePos && holdsPosPermission(permissions, 'posCashDrawer'),\n }\n // The reservation keys (AGL-4047), whose preset is the member's role on\n // this site; the shell decides them for the site in view. A map that does\n // not carry one (a shell that predates them) leaves the card as it was:\n // the rules and the routes decide.\n const reservations = {\n canManage: permissions?.['commerce.reservations'] !== false,\n canWalkIn: permissions?.['commerce.walkIns'] !== false,\n }\n // \"Create and edit quotes\" (AGL-4093), read the same way; the quote route\n // decides.\n const quotes = {\n canEdit: permissions?.['commerce.quotes'] !== false,\n canSend: permissions?.['commerce.quotes.send'] !== false,\n }\n\n /*\n * Nothing, deliberately, while the redirect is in flight.\n *\n * Rendering the default section here instead would issue that section's\n * listens on a URL that is about to be replaced — paying for Catalog on\n * every arrival at `/products`, which is every click of the nav tab.\n */\n if (!section || !sections?.length || !basePath) return null\n\n return (\n <HubSections sections={sections}>\n {sectionBody(section as CommerceConsoleSectionId, hostId, canManagePos, pos, reservations, quotes)}\n </HubSections>\n )\n}\nCommerceConsolePage.displayName = 'CommerceConsolePage'\n\nexport default CommerceConsolePage\n"],"names":["GridItems","HubSections","lazy","Suspense","Stack","COMMERCE_SETTINGS_PAGE_ZONES","CatalogOrganizationCard","CommerceAnalyticsCard","CustomerNotificationsCard","DiscountsCard","GiftCardsCard","HostCouponsCard","HostOrdersCard","HostQuotesCard","LocationsCard","LocalDeliverySettingsCard","PickupDeliveryQueueCard","MemberPostsCard","OrderWebhooksCard","PaymentsSettingsCard","PosCheckInsCard","PosDayTotalsCard","PosShiftHistoryCard","PosStaffPinsCard","PaymentMethodsCard","ProductsHubCard","QuoteSettingsCard","RecoveryQueueCard","RegistersCard","RegisterHardwareCards","PosDevicesCard","PosHardwareCard","PosHardwareWaitingCard","holdsPosPermission","posPermissionRefusal","ReservationsCard","ReturnSettingsCard","ReturnsCard","ReviewsModerationCard","ReviewSettingsCard","ShippingSettingsCard","ShipStationCard","ShippingEasyCard","StockMovementsCard","StoreSettingsCard","StorefrontTaxSummaryCard","SuppliersCard","TaxSettingsCard","COMMERCE_PROMOTIONS_ZONE","useConsoleWidgetSlot","CommerceSettingsZone","props","WidgetSlot","slot","page","hostId","orgId","undefined","settingsPage","cards","spacing","items","map","children","size","xs","CommercePromotionsZone","id","sectionBody","section","canManagePos","pos","canSetUpDevices","canBuyHardware","canCashDrawer","reservations","canManage","canWalkIn","quotes","canEdit","canSend","canSendInvoices","fallback","devicesBlockedReason","blocked","devices","drawer","CommerceConsolePage","sections","basePath","permissions","managePos","length","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAGA,SAASA,SAAS,QAAQ,uBAAsB;AAChD,SAASC,WAAW,QAAQ,wBAAuB;AACnD,SAASC,IAAI,EAAEC,QAAQ,QAAwB,QAAO;AACtD,SAASC,KAAK,QAAQ,gBAAe;AACrC,SACEC,4BAA4B,QAGvB,iCAA6B;AACpC,OAAOC,6BAA6B,mDAA+C;AACnF,OAAOC,2BAA2B,iDAA6C;AAC/E,OAAOC,+BAA+B,qDAAiD;AACvF,OAAOC,mBAAmB,wCAAoC;AAC9D,OAAOC,mBAAmB,yCAAqC;AAC/D,OAAOC,qBAAqB,2CAAuC;AACnE,OAAOC,oBAAoB,0CAAsC;AACjE,OAAOC,oBAAoB,0CAAsC;AACjE,OAAOC,mBAAmB,wCAAoC;AAC9D,OAAOC,+BAA+B,sDAAkD;AACxF,OAAOC,6BAA6B,oDAAgD;AACpF,OAAOC,qBAAqB,2CAAuC;AACnE,OAAOC,uBAAuB,6CAAyC;AACvE,OAAOC,0BAA0B,gDAA4C;AAC7E,OAAOC,qBAAqB,oDAAgD;AAC5E,OAAOC,sBAAsB,qDAAiD;AAC9E,OAAOC,yBAAyB,wDAAoD;AACpF,OAAOC,sBAAsB,qDAAiD;AAC9E,OAAOC,wBAAwB,8CAA0C;AACzE,OAAOC,qBAAqB,2CAAuC;AACnE,OAAOC,uBAAuB,6CAAyC;AACvE,OAAOC,uBAAuB,6CAAyC;AACvE,OAAOC,mBAAmB,wCAAoC;AAC9D,OAAOC,2BAA2B,gDAA4C;AAC9E,OAAOC,oBAAoB,0CAAsC;AACjE,OAAOC,qBAAqB,2CAAuC;AAEnE;;;CAGC,GACD,MAAMC,uCAAyB9B,KAAK,IAAM,MAAM,CAAC;AACjD,SAAS+B,kBAAkB,EAAEC,oBAAoB,QAAQ,iCAA6B;AACtF,OAAOC,sBAAsB,2CAAuC;AACpE,OAAOC,wBAAwB,8CAA0C;AACzE,OAAOC,iBAAiB,sCAAkC;AAC1D,OAAOC,2BAA2B,iDAA6C;AAC/E,OAAOC,wBAAwB,8CAA0C;AACzE,OAAOC,0BAA0B,gDAA4C;AAC7E,OAAOC,qBAAqB,0CAAsC;AAClE,OAAOC,sBAAsB,2CAAuC;AACpE,OAAOC,wBAAwB,8CAA0C;AACzE,OAAOC,uBAAuB,6CAAyC;AACvE,OAAOC,8BAA8B,qDAAiD;AACtF,OAAOC,mBAAmB,wCAAoC;AAC9D,OAAOC,qBAAqB,2CAAuC;AACnE,SAASC,wBAAwB,QAAQ,2BAAuB;AAChE,SAASC,oBAAoB,QAAQ,qDAAoD;AAEzF;;;;;CAKC,GACD,SAASC,qBAAqBC,KAG7B;IACC,MAAMC,aAAaH;IACnB,OAAOG,2BACL,KAACA;QACCC,MAAMhD,4BAA4B,CAAC8C,MAAMG,IAAI,CAAC;QAC9CC,QAAQJ,MAAMI,MAAM;QACpBC,OAAOC;SAEP;AACN;AAEA,qEAAqE,GACrE,SAASC,aACPJ,IAA+B,EAC/BC,MAAc,EACdI,KAA2B;IAE3B,qBACE,KAAC3D;QACC4D,SAAS;QACTC,OAAO;eACFF,MAAMG,GAAG,CAAC,CAACC,WAAc,CAAA;oBAAEC,MAAM;wBAAEC,IAAI;oBAAG;oBAAGF;gBAAS,CAAA;YACzD;gBACEC,MAAM;oBAAEC,IAAI;gBAAG;gBACfF,wBAAU,KAACb;oBAAqBK,QAAQA;oBAAQD,MAAMA;;YACxD;SACD;;AAGP;AAEA;;;CAGC,GACD,SAASY,uBAAuBf,KAAyB;IACvD,MAAMC,aAAaH;IACnB,OAAOG,2BACL,KAACA;QAAWC,MAAML,yBAAyBmB,EAAE;QAAEZ,QAAQJ,MAAMI,MAAM;QAAEC,OAAOC;SAC1E;AACN;AAEA;;;;;;;;CAQC,GACD,SAASW,YACPC,OAAiC,EACjCd,MAAc,EACde,YAAqB,EACrB,gEAAgE,GAChEC,MAAqF;IACnFC,iBAAiBF;IACjBG,gBAAgBH;IAChBI,eAAeJ;AACjB,CAAC,EACD,sEAAsE,GACtEK,eAA2D;IAAEC,WAAW;IAAMC,WAAW;AAAK,CAAC,EAC/F,4GAA4G,GAC5GC,SAAiD;IAAEC,SAAS;IAAMC,SAAS;AAAK,CAAC;IAEjF,OAAQX;QACN,KAAK;YACH,qBACE,KAACrE;gBACC4D,SAAS;gBACTC,OAAO;oBACL;wBAAEG,MAAM;4BAAEC,IAAI;wBAAG;wBAAGF,wBAAU,KAACtC;4BAAgB8B,QAAQA;;oBAAW;oBAClE;wBACES,MAAM;4BAAEC,IAAI;wBAAG;wBACfF,wBAAU,KAACzD;4BAAwBiD,QAAQA;;oBAC7C;oBACA,4DAA4D;oBAC5D,+DAA+D;oBAC/D,+DAA+D;oBAC/D,uCAAuC;oBACvC;wBACES,MAAM;4BAAEC,IAAI;wBAAG;wBACfF,wBAAU,KAACpB;4BAAmBY,QAAQA;;oBACxC;oBACA;wBAAES,MAAM;4BAAEC,IAAI;wBAAG;wBAAGF,wBAAU,KAAC9C;4BAAgBsC,QAAQA;;oBAAW;iBACnE;;QAGP,KAAK;YACH,qBACE,KAACvD;gBACC4D,SAAS;gBACTC,OAAO;oBACL;wBAAEG,MAAM;4BAAEC,IAAI;wBAAG;wBAAGF,wBAAU,KAACnD;4BAAe2C,QAAQA;4BAAQ0B,iBAAiBH,OAAOE,OAAO;;oBAAK;oBAClG,kEAAkE;oBAClE,gCAAgC;oBAChC;wBACEhB,MAAM;4BAAEC,IAAI;wBAAG;wBACfF,wBAAU,KAAClD;4BAAe0C,QAAQA;4BAAQwB,SAASD,OAAOC,OAAO;4BAAEC,SAASF,OAAOE,OAAO;;oBAC5F;oBACA,+DAA+D;oBAC/D,4DAA4D;oBAC5D;wBACEhB,MAAM;4BAAEC,IAAI;wBAAG;wBACfF,wBAAU,KAAC/C;4BAAwBuC,QAAQA;;oBAC7C;oBACA,0DAA0D;oBAC1D,6DAA6D;oBAC7D,6DAA6D;oBAC7D;wBACES,MAAM;4BAAEC,IAAI;wBAAG;wBACfF,wBAAU,KAACpC;4BAAkB4B,QAAQA;;oBACvC;oBACA,+DAA+D;oBAC/D,uDAAuD;oBACvD;wBACES,MAAM;4BAAEC,IAAI;wBAAG;wBACfF,wBAAU,KAAC1C;4BAAiBkC,QAAQA;4BAAQe,cAAcA;;oBAC5D;oBACA,iEAAiE;oBACjE,oBAAoB;oBACpB;wBACEN,MAAM;4BAAEC,IAAI;wBAAG;wBACfF,wBAAU,KAAC3C;4BAAgBmC,QAAQA;4BAAQe,cAAcA;;oBAC3D;oBACA;wBACEN,MAAM;4BAAEC,IAAI;wBAAG;wBACfF,wBAAU,KAACzC;4BAAoBiC,QAAQA;;oBACzC;iBACD;;QAGP,KAAK;YACH,2DAA2D;YAC3D,qBAAO,KAAClB;gBAAYkB,QAAQA;;QAC9B,KAAK;YACH,qBACE,KAACvD;gBACC4D,SAAS;gBACTC,OAAO;oBACL;wBAAEG,MAAM;4BAAEC,IAAI;wBAAG;wBAAGF,wBAAU,KAACtD;4BAAc8C,QAAQA;;oBAAW;oBAChE;wBAAES,MAAM;4BAAEC,IAAI;wBAAG;wBAAGF,wBAAU,KAACpD;4BAAgB4C,QAAQA;;oBAAW;oBAClE,uDAAuD;oBACvD,uDAAuD;oBACvD;wBAAES,MAAM;4BAAEC,IAAI;wBAAG;wBAAGF,wBAAU,KAACrD;4BAAc6C,QAAQA;;oBAAW;oBAChE;wBACES,MAAM;4BAAEC,IAAI;wBAAG;wBACfF,wBAAU,KAACzB;4BAAsBiB,QAAQA;;oBAC3C;oBACA,2DAA2D;oBAC3D,0CAA0C;oBAC1C;wBACES,MAAM;4BAAEC,IAAI;wBAAG;wBACfF,wBAAU,KAACxB;4BAAmBgB,QAAQA;;oBACxC;oBACA;wBACES,MAAM;4BAAEC,IAAI;wBAAG;wBACfF,wBAAU,KAACG;4BAAuBX,QAAQA;;oBAC5C;iBACD;;QAGP,KAAK;YACH,qBACE,KAACpB;gBACCoB,QAAQA;gBACRqB,WAAWD,aAAaC,SAAS;gBACjCC,WAAWF,aAAaE,SAAS;;QAGvC;;;;;KAKC,GACD,KAAK;YACH,OAAOnB,aAAaW,SAASd,QAAQ;8BACnC,KAACpC;oBAAoCoC,QAAQA;mBAAnB;gBAC1B,gEAAgE;gBAChE,kBAAkB;8BAClB,KAAC/B;oBAAiC+B,QAAQA;mBAAlB;aACzB;QACH,KAAK;YACH,OAAOG,aAAaW,SAASd,QAAQ;8BACnC,KAACX;oBAA8BW,QAAQA;mBAAhB;gBACvB,qEAAqE;gBACrE,8DAA8D;8BAC9D,KAACnB;oBAAiCmB,QAAQA;mBAAlB;gBACxB,2CAA2C;8BAC3C,KAAC7B;oBAA+B6B,QAAQA;mBAAjB;aACxB;QACH,KAAK;YACH,OAAOG,aAAaW,SAASd,QAAQ;8BACnC,KAACR;oBAA0BQ,QAAQA;mBAAd;aACtB;QACH,KAAK;YACH,OAAOG,aAAaW,SAASd,QAAQ;8BACnC,KAACf;oBAAoCe,QAAQA;mBAAnB;gBAC1B,qDAAqD;8BACrD,KAACzC;oBAA8ByC,QAAQA;mBAApB;gBACnB,kEAAkE;gBAClE,sCAAsC;8BACtC,KAACxC;oBAAsCwC,QAAQA;mBAAhB;8BAC/B,KAACT;oBAA8BS,QAAQA;mBAApB;8BACnB,KAACd;oBAAkCc,QAAQA;mBAAtB;gBACrB,yDAAyD;8BACzD,KAACb;oBAAoCa,QAAQA;mBAAvB;aACvB;QACH,KAAK;YACH,OAAOG,aAAaW,SAASd,QAAQ;8BACnC,KAAC/C;oBAA0C+C,QAAQA;mBAApB;gBAC/B,iEAAiE;gBACjE,gDAAgD;8BAChD,KAACrC;oBAAiCqC,QAAQA;mBAAnB;aACxB;QACH,KAAK;YACH,OAAOG,aAAaW,SAASd,QAAQ;gBACnC,gEAAgE;gBAChE,8DAA8D;gBAC9D,iBAAiB;8BACjB,MAACnD;oBAAsBwD,SAAS;;sCAC9B,KAACzD;4BAAS+E,UAAU;sCAClB,cAAA,KAAClD;gCACCuB,QAAQA;+BACHgB,IAAIC,eAAe,GAAG,CAAC,IAAI;gCAAEW,sBAAsBjD,qBAAqB;4BAAc;;sCAG/F,KAACN;4BAAc2B,QAAQA;;;mBAPd;8BASX,KAAChC;oBAA4BgC,QAAQA;mBAAf;gBACtB,qEAAqE;gBACrE,gDAAgD;8BAChD,KAAC1B;oBAEC0B,QAAQA;oBACR6B,SAAS,aACHb,IAAIC,eAAe,GAAG,CAAC,IAAI;wBAAEa,SAASnD,qBAAqB;oBAAc,GACzEqC,IAAIG,aAAa,GAAG,CAAC,IAAI;wBAAEY,QAAQpD,qBAAqB;oBAAiB;mBAJ3E;8BAON,KAACJ;oBAECyB,QAAQA;oBACRe,cAAcA;oBACdE,iBAAiBD,IAAIC,eAAe;mBAHhC;gBAKN,mEAAmE;gBACnE,oEAAoE;gBACpE,QAAQ;8BACR,KAACzC;oBAECwB,QAAQA;oBACRe,cAAcA;oBACdG,gBAAgBF,IAAIE,cAAc;mBAH9B;aAKP;QACH,KAAK;QACL,KAAK;YACH,mEAAmE;YACnE,kDAAkD;YAClD,OAAOf,aAAaW,SAASd,QAAQ,EAAE;QACzC,KAAK;YACH,OACE,8DAA8D;YAC9D,uEAAuE;YACvE,gEAAgE;YAChE,gEAAgE;YAChE,6BAA6B;0BAC7B,KAACvD;gBACC4D,SAAS;gBACTC,OAAO;oBACL;wBACEG,MAAM;4BAAEC,IAAI;wBAAG;wBACfF,wBAAU,KAACxD;4BAAsBgD,QAAQA;;oBAC3C;oBACA;wBACES,MAAM;4BAAEC,IAAI;wBAAG;wBACfF,wBAAU,KAAClB;4BAAyBU,QAAQA;;oBAC9C;iBACD;;QAGP;YACE,OAAO;IACX;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;CAyBC,GACD,OAAO,SAASgC,oBAAoBpC,KAA6B;IAC/D,MAAM,EAAEI,MAAM,EAAEc,OAAO,EAAEmB,QAAQ,EAAEC,QAAQ,EAAEC,WAAW,EAAE,GAAGvC;IAC7D;;;;GAIC,GACD,MAAMmB,eAAeoB,CAAAA,+BAAAA,YAAaC,SAAS,MAAK;IAChD,4EAA4E;IAC5E,yEAAyE;IACzE,4EAA4E;IAC5E,4CAA4C;IAC5C,MAAMpB,MAAM;QACVC,iBAAiBF,gBAAgBrC,mBAAmByD,aAAa;QACjEjB,gBAAgBxC,mBAAmByD,aAAa;QAChDhB,eAAeJ,gBAAgBrC,mBAAmByD,aAAa;IACjE;IACA,wEAAwE;IACxE,0EAA0E;IAC1E,wEAAwE;IACxE,mCAAmC;IACnC,MAAMf,eAAe;QACnBC,WAAWc,CAAAA,+BAAAA,WAAa,CAAC,wBAAwB,MAAK;QACtDb,WAAWa,CAAAA,+BAAAA,WAAa,CAAC,mBAAmB,MAAK;IACnD;IACA,0EAA0E;IAC1E,WAAW;IACX,MAAMZ,SAAS;QACbC,SAASW,CAAAA,+BAAAA,WAAa,CAAC,kBAAkB,MAAK;QAC9CV,SAASU,CAAAA,+BAAAA,WAAa,CAAC,uBAAuB,MAAK;IACrD;IAEA;;;;;;GAMC,GACD,IAAI,CAACrB,WAAW,EAACmB,4BAAAA,SAAUI,MAAM,KAAI,CAACH,UAAU,OAAO;IAEvD,qBACE,KAACxF;QAAYuF,UAAUA;kBACpBpB,YAAYC,SAAqCd,QAAQe,cAAcC,KAAKI,cAAcG;;AAGjG;AACAS,oBAAoBM,WAAW,GAAG;AAElC,eAAeN,oBAAmB"}
@@ -16,6 +16,12 @@
16
16
  */
17
17
  export interface HostOrdersCardProps {
18
18
  hostId: string;
19
+ /**
20
+ * Holds "Send quotes and invoices to customers" (`commerce.quotes.send`),
21
+ * which the order dialog's Send invoice asks (AGL-4099). Absent reads as
22
+ * held: the route decides.
23
+ */
24
+ canSendInvoices?: boolean;
19
25
  }
20
26
  /**
21
27
  * Orders console (AGL-287): filterable list over webhook-written order
@@ -98,7 +98,7 @@ const ORDER_PAGE_SORT_HEADERS = {
98
98
  */ export function HostOrdersCard(props) {
99
99
  var _ref, _loadedOrders_find, _payments_href, _payments_reason, _ref1, _ref2, _ref3, _ref4, _ref5, _payments_reason1;
100
100
  var _draft_shipCountries, _draft_shipCountries1, _draft_shipPostal;
101
- const { hostId } = props;
101
+ const { hostId, canSendInvoices } = props;
102
102
  const firestore = useFirestore();
103
103
  const ordersRef = useMemo(()=>collection(firestore, 'hosts', hostId, 'orders'), [
104
104
  firestore,
@@ -869,7 +869,8 @@ const ORDER_PAGE_SORT_HEADERS = {
869
869
  selectedOrder ? /*#__PURE__*/ _jsx(OrderDetailDialog, {
870
870
  hostId: hostId,
871
871
  order: selectedOrder,
872
- onClose: ()=>setSelectedId(null)
872
+ onClose: ()=>setSelectedId(null),
873
+ canSendInvoices: canSendInvoices
873
874
  }) : null,
874
875
  /*#__PURE__*/ _jsxs(Dialog, {
875
876
  open: Boolean(draft),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/host-orders-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 { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport ListFilterChips from '@aglyn/shared-ui-jsx/components/list-filter-chips.component'\nimport { ListPagination } from '@aglyn/shared-ui-jsx/components/list-pagination.component'\nimport {\n ListQueryNotices,\n listQueryRefusals,\n} from '@aglyn/shared-ui-jsx/components/list-query-notices.component'\nimport { ListTable } from '@aglyn/shared-ui-jsx/components/list-table.component'\nimport { hiddenFilterVisibility } from '@aglyn/shared-ui-jsx/const/list-filter'\nimport type { ListQuerySort } from '@aglyn/shared-ui-jsx/const/list-query-plan'\nimport { useListColumnSort } from '@aglyn/shared-ui-jsx/hooks/use-list-column-sort'\nimport {\n type ListFilterClause,\n listFilterGridColumns,\n upsertListFilterClause,\n} from '@aglyn/shared-ui-jsx/const/list-grid-filter'\nimport { useListGridFilter } from '@aglyn/shared-ui-jsx/hooks/use-list-grid-filter'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { checkEntitlement, pluginDocsHelp } from '@aglyn/aglyn'\nimport { ORDERS_CUSTOMER_PARAM, ORDERS_ORDER_PARAM } from '../../model/commerce-record-routes'\nimport {\n Alert,\n AlertTitle,\n Button,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n MenuItem,\n Stack,\n TextField,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport type { GridColDef } from '@mui/x-data-grid'\nimport {\n collection,\n doc,\n getDoc,\n limit,\n orderBy,\n query,\n where,\n} from 'firebase/firestore'\nimport { useSearchParams } from 'next/navigation'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport {\n ceilingedWindow,\n collectionCeiling,\n useFirestore,\n useMerchantPayments,\n useOrgPlan,\n useUser,\n} from '@aglyn/tenant-feature-instance'\nimport { BlockedControl } from '@aglyn/shared-ui-jsx/components/blocked-control.component'\nimport { PrerequisiteNotice } from '@aglyn/shared-ui-jsx/components/prerequisite-notice.component'\nimport { useFirestoreCollection } from '@aglyn/tenant-feature-instance'\nimport { useListQuery } from '@aglyn/tenant-feature-instance/hooks/use-list-query'\nimport { useTransferLauncher } from '@aglyn/aglyn/app-utils/transfer-launcher-context'\nimport { commerceListFilter } from '../../transfer/list-filter'\nimport { COMMERCE_ORDERS_TRANSFER } from '../../transfer/transfer-keys'\nimport OrderShippingActions from './order-shipping-actions.component'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\n\nimport {\n OPEN_DISPUTE_CLAUSE,\n ORDER_CHANNEL_OPTIONS,\n ORDER_LIST_COLUMN_SORTS,\n ORDER_DISPUTE_OPTIONS,\n ORDER_LIST_FIELDS,\n ORDER_LIST_HEADERS,\n ORDER_LIST_QUERY,\n ORDER_LIST_SELECT_FIELDS,\n ORDER_STATUS_OPTIONS,\n ordersCustomerClause,\n} from '../../constants/orders-list-query'\nimport CommerceStatTile from './commerce-stat-tile.component'\nimport { bulkFulfillOrders, BULK_FULFILLABLE_STATUSES, describeBulkFulfill } from './bulk-fulfill'\nimport { ORDERS_BULK_ZONE } from './store-zones'\nimport { useConsoleWidgetSlot } from '@aglyn/aglyn/app-utils/console-widget-slot-context'\nimport OrderDetailDialog, {\n DISPUTE_COLOR,\n} from './order-detail-dialog.component'\n\n/**\n * The products the card reads to NAME a legacy row and the CSV, to offer the\n * Product filter's choices and to fill the draft dialog's picker. A picker's\n * reach, not the list's: the orders themselves are paged by their query and\n * the Product filter asks it for any product id, named here or not.\n */\nconst PRODUCT_NAME_WINDOW = 100\n\n/**\n * How many open disputes the banner reads. Its own query, `disputeKey ==\n * 'open'`, so a deadline is raised whatever the list is filtered to and\n * however deep in the store the order sits; a store past this many open\n * cases is told \"more than\".\n */\nconst OPEN_DISPUTE_CEILING = 50\n\n/**\n * The money tiles read the last sixty days (thirty, and the thirty before it)\n * on their own bounded query. They are analytics over a period, not a filter\n * over the list, and share the analytics card's bound.\n */\nconst STATS_WINDOW_MS = 60 * 24 * 60 * 60 * 1000\nconst STATS_ORDER_CEILING = 500\n\n/** The columns the grid draws; every other declared field is a hidden filter column. */\nconst ORDER_VISIBLE_COLUMNS = [\n 'orderLabel',\n 'customerEmail',\n 'channelKey',\n 'statusKey',\n 'createdAtMs',\n]\nconst ORDER_HIDDEN_COLUMNS = hiddenFilterVisibility(\n ORDER_LIST_FIELDS,\n ORDER_VISIBLE_COLUMNS,\n)\n\nexport interface HostOrdersCardProps {\n hostId: string\n}\n\n/** Total is computed from the refunds, so it sorts the page on screen (AGL-3680). */\nconst ORDER_PAGE_SORTS = {\n netCents: (row: { netCents: number }) => row.netCents,\n}\nconst ORDER_PAGE_SORT_HEADERS = { netCents: 'Total' }\n\n/**\n * Orders console (AGL-287): filterable list over webhook-written order\n * docs with a detail dialog (timeline, fulfill, refund, cancel, notes,\n * packing slip) and draft orders that send the buyer a payment link.\n *\n * ## Every filter and the search are on the query (AGL-3321)\n *\n * The list used to read the newest two hundred orders and match its Filters\n * panel and search over them, so a Status filter on a busy store answered\n * \"none\" about every order past the two hundredth. Now each clause and the\n * search word are predicates on ONE Firestore query (`ORDER_LIST_QUERY`),\n * over the fields every writer stamps (`orderListFields`), and the footer\n * pages that query's answer. A combination one query cannot hold is refused\n * by name above the grid and never applied to some rows only.\n */\nexport function HostOrdersCard(props: HostOrdersCardProps) {\n const { hostId } = props\n const firestore = useFirestore()\n const ordersRef = useMemo(\n () => collection(firestore, 'hosts', hostId, 'orders'),\n [firestore, hostId],\n )\n const { data: productDocs } = useFirestoreCollection<any>(\n () =>\n collectionCeiling(\n collection(firestore, 'hosts', hostId, 'products'),\n PRODUCT_NAME_WINDOW,\n ),\n [firestore, hostId],\n { idField: '$id' },\n )\n const productWindow = useMemo(\n () => ceilingedWindow<any>(productDocs ?? undefined, PRODUCT_NAME_WINDOW),\n [productDocs],\n )\n const productNames = useMemo(() => {\n const map: Record<string, string> = {}\n for (const product of productWindow.rows) {\n map[product.$id] = product.name ?? product.$id\n }\n return map\n }, [productWindow])\n\n /**\n * The money tiles are the `commerceAnalytics` surface (AGL-1938,\n * AGL-2056), and this is the third place they appear. Rendering them\n * ungated here would undo both of those passes and hand a Starter org\n * the Pro figures one tab away from the upgrade prompt that refuses\n * them. The TABLE below is not gated — a list of your own orders is not\n * a paid feature.\n */\n const { org, ready: orgReady } = useOrgPlan(hostId)\n // A draft order's link is a Stripe payment page, so it needs the store's\n // Stripe account; the dialog says so before Create rather than after.\n const payments = useMerchantPayments(hostId)\n const showStats =\n orgReady && checkEntitlement(org as never, 'commerceAnalytics')\n\n /*\n * The grid's clauses (AGL-96, AGL-3317), held here so two things outside\n * the grid can set one: the CRM's contact page links with the buyer's\n * address to answer \"what has this customer ordered\" (AGL-2622) — a whole\n * address is that buyer, a domain every buyer at a company\n * (`ordersCustomerClause`) — and the dispute banner's \"Show them\".\n */\n const searchParams = useSearchParams()\n const [clauses, setClauses] = useState<ListFilterClause[]>(() => {\n const customer = ordersCustomerClause(\n searchParams?.get(ORDERS_CUSTOMER_PARAM) ?? '',\n )\n return customer ? [customer] : []\n })\n const gridFilter = useListGridFilter({\n clauses,\n onChange: setClauses,\n selectFields: ORDER_LIST_SELECT_FIELDS,\n })\n const filtering =\n clauses.length > 0 || gridFilter.searchWords.some((word) => word.trim())\n /*\n * Every header sorts (AGL-3680). Date, Order, Customer, Channel and Status\n * are the query's order over every order (`ORDER_LIST_COLUMN_SORTS`);\n * Total is computed from the refunds, so it sorts the page on screen.\n * Newest first until a header is clicked. A header order other than Date\n * holds only with no filter or search on — the plan falls back to newest\n * first and `ListQueryNotices` says so.\n */\n const [askedSort, setAskedSort] = useState<ListQuerySort | null>(\n ORDER_LIST_COLUMN_SORTS[0],\n )\n\n /*\n * The open disputes, on their OWN query (AGL-1796). Raised whatever the\n * list is filtered to — a merchant filtered to \"delivered\" still has a\n * deadline running on a `paid` order, and the evidence window is days —\n * and however far back the order is. Asked before the list so the list's\n * plan is the one a spec reads last.\n */\n const {\n rows: disputedRows,\n hasMore: moreDisputes,\n } = useListQuery<any>({\n collection: ordersRef,\n declaration: ORDER_LIST_QUERY,\n request: { clauses: [OPEN_DISPUTE_CLAUSE] },\n deps: [firestore, hostId],\n idField: '$id',\n pageSize: OPEN_DISPUTE_CEILING,\n // A dispute that closes leaves this query; confirm it before believing it.\n confirmDisappearances: true,\n })\n\n /*\n * THE LIST: every clause and the search word on one query, newest first,\n * paged by the footer. A status, a dispute or a paid draft's address can\n * move an order out of the filtered query mid-session, so a disappearance\n * is confirmed against the server before it is believed (AGL-1196).\n */\n const {\n rows: orders,\n data: loadedOrders,\n hasMore,\n page,\n setPage,\n pageSize,\n setPageSize,\n plan,\n status: listStatus,\n } = useListQuery<any>({\n collection: ordersRef,\n declaration: ORDER_LIST_QUERY,\n request: { clauses, search: gridFilter.searchWords, sort: askedSort },\n deps: [firestore, hostId],\n idField: '$id',\n confirmDisappearances: true,\n })\n\n const [selectedId, setSelectedId] = useState<string | null>(null)\n // Rows ticked for a bulk act (AGL-3611); the row click still opens one.\n const [checkedIds, setCheckedIds] = useState<string[]>([])\n const [bulkBusy, setBulkBusy] = useState(false)\n const WidgetSlot = useConsoleWidgetSlot()\n /*\n * An order named in the URL opens in its dialog on arrival (AGL-2622). A\n * contact's timeline names the order that made the person a customer,\n * and the address it links to is this list with `?order={id}`. The list\n * shows one page, and an order from last year is not on it, so the\n * document is read once by id and held beside the page for the dialog; an\n * order that IS loaded is found there first and the read is skipped. Once\n * per id — the ref keeps a re-render from reopening a dialog the merchant\n * has since closed — and the landing read is judged against the ref\n * rather than an effect cleanup, because the `setSelectedId` above\n * re-renders before the read lands and a cleanup keyed on any dep would\n * cancel the answer to the question just asked.\n */\n const seededOrderId = searchParams?.get(ORDERS_ORDER_PARAM) ?? null\n const [seededOrder, setSeededOrder] = useState<any | null>(null)\n const seededOpened = useRef<string | null>(null)\n useEffect(() => {\n if (!seededOrderId || seededOpened.current === seededOrderId) return\n if (listStatus === 'loading') return\n seededOpened.current = seededOrderId\n setSelectedId(seededOrderId)\n if (loadedOrders.some((order: any) => order.$id === seededOrderId)) return\n void getDoc(doc(firestore, 'hosts', hostId, 'orders', seededOrderId))\n .then((snapshot) => {\n if (seededOpened.current !== snapshot.id || !snapshot.exists()) return\n setSeededOrder({ ...snapshot.data(), $id: snapshot.id })\n })\n .catch(() => undefined)\n }, [seededOrderId, loadedOrders, listStatus, firestore, hostId])\n const [draft, setDraft] = useState<{\n productId: string\n variantId: string\n quantity: string\n email: string\n /** Destination the merchant declared, once they have been asked. */\n shipTo?: string\n /**\n * Revealed only when the server refuses for want of a destination\n * (AGL-1792). A merchant whose rates are the same everywhere — or who\n * configured none — is never asked and never sees this field.\n */\n shipCountries?: string[]\n /** The postal code, once live carrier rates ask for one (AGL-3612). */\n shipPostal?: string\n askPostal?: boolean\n busy?: boolean\n } | null>(null)\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n /**\n * Each order on the page with the values the grid DRAWS. What it filters\n * by is on the query; this is presentation only. `liftLegacyOrder` names\n * a status and channel on a row that predates them, and the item name\n * reads the line items first (AGL-1747): the flat `productId` is written\n * only by the two buy-now Stripe paths.\n */\n const orderRows = useMemo(\n () =>\n orders\n // An unpaid quote is not an order (AGL-4093). It carries no\n // `createdAtMs`, so the default order and every filter leave it out;\n // the unfiltered Order, Channel and Status header sorts are the only\n // queries that can reach one, and this keeps it off those pages too.\n .filter((order: any) => !CommerceModel.isUnpaidQuote(order))\n .map((order: any) => {\n const lifted = CommerceModel.liftLegacyOrder(order)\n return {\n ...order,\n orderLabel: CommerceModel.formatOrderNumber(lifted, order.$id),\n itemName:\n lifted.lineItems?.[0]?.name ??\n productNames[order.productId] ??\n order.productId ??\n '',\n statusKey: lifted.status,\n channelKey: lifted.channel ?? 'online',\n netCents: CommerceModel.orderNetCents(lifted),\n disputeBadge: CommerceModel.describeOrderDispute(lifted),\n }\n }),\n [orders, productNames],\n )\n const columnSort = useListColumnSort({\n sorts: ORDER_LIST_COLUMN_SORTS,\n defaultSort: ORDER_LIST_COLUMN_SORTS[0],\n sort: askedSort,\n onSortChange: setAskedSort,\n orderBy: plan.orderBy,\n rows: orderRows,\n pageSorts: ORDER_PAGE_SORTS,\n headers: ORDER_PAGE_SORT_HEADERS,\n })\n const productOptions = useMemo(\n () =>\n productWindow.rows.map((product: any) => ({\n value: String(product.$id),\n label: String(product.name ?? product.$id),\n })),\n [productWindow],\n )\n const filterOptions = useMemo(\n () => ({\n statusKey: ORDER_STATUS_OPTIONS,\n channelKey: ORDER_CHANNEL_OPTIONS,\n productIds: productOptions,\n disputeKey: ORDER_DISPUTE_OPTIONS,\n }),\n [productOptions],\n )\n const refused = useMemo(\n () =>\n listQueryRefusals(plan.refused, {\n fields: ORDER_LIST_FIELDS,\n headers: ORDER_LIST_HEADERS,\n options: filterOptions,\n }),\n [plan, filterOptions],\n )\n const showingOpenDisputes = clauses.some(\n (clause) =>\n clause.field === OPEN_DISPUTE_CLAUSE.field &&\n clause.op === OPEN_DISPUTE_CLAUSE.op &&\n clause.value === OPEN_DISPUTE_CLAUSE.value,\n )\n\n const openDisputes = useMemo(\n () =>\n CommerceModel.summariseOpenDisputes(\n disputedRows.map((order: any) => CommerceModel.liftLegacyOrder(order)),\n ),\n [disputedRows],\n )\n\n /*\n * 30-day money summary with the prior 30 days behind it (AGL-2136).\n * ANALYTICS, NOT A FILTER: the tiles describe a period, not the list, so\n * they keep their own bounded read — sixty days by `createdAtMs`, the\n * newest `STATS_ORDER_CEILING` of them, read only when the tiles show.\n * Range and order are the same field, so it needs no composite.\n */\n const statsSince = useMemo(() => Date.now() - STATS_WINDOW_MS, [])\n const { data: statsDocs } = useFirestoreCollection<any>(\n () =>\n showStats\n ? query(\n ordersRef,\n where('createdAtMs', '>=', statsSince),\n orderBy('createdAtMs', 'desc'),\n limit(STATS_ORDER_CEILING + 1),\n )\n : null,\n [firestore, hostId, showStats, statsSince],\n { idField: '$id' },\n )\n const statsWindow = useMemo(\n () => ceilingedWindow<any>(statsDocs ?? undefined, STATS_ORDER_CEILING),\n [statsDocs],\n )\n const summary = useMemo(\n () =>\n CommerceModel.summarizeOrderWindow(statsWindow.rows, { nowMs: Date.now() }),\n [statsWindow],\n )\n\n /**\n * Export (AGL-3531) opens the console's export dialog on the\n * `commerce.orders` resource: the fields the person picks, for what the\n * QUERY matches — every clause and the search the grid is showing, not the\n * page on screen — read and streamed on the server however many orders\n * match. Orders are exported only; there is no Import.\n */\n const transfer = useTransferLauncher()\n const openExport = useCallback(() => {\n transfer?.openExport({\n resource: COMMERCE_ORDERS_TRANSFER,\n scope: 'host',\n hostId,\n ...(filtering\n ? {\n filter: {\n label: 'the orders the list’s filters and search find',\n value: commerceListFilter(plan),\n },\n }\n : {}),\n })\n }, [transfer, hostId, filtering, plan])\n\n /**\n * Idempotency key for ONE draft attempt (AGL-1697).\n *\n * Minted lazily on the first create click, NOT per call — two clicks (or a\n * click retried after a lost response) must present ONE key so the server\n * replays the original payment link instead of minting a second order.\n * Retired whenever a content field changes: an edited draft is a different\n * order, and replaying the old one against it would hand the merchant a\n * link priced for fields they no longer see. Answering the shipping-country\n * ask also retires it, which is safe — that refusal is served before the\n * server takes the claim, so the first key was never spent.\n */\n const draftAttemptKey = useRef('')\n useEffect(() => {\n draftAttemptKey.current = ''\n }, [\n draft?.productId,\n draft?.variantId,\n draft?.quantity,\n draft?.email,\n draft?.shipTo,\n draft?.shipPostal,\n ])\n\n const handleDraftCreate = useCallback(async () => {\n if (!draft?.productId) return\n setDraft((prev) => (prev ? { ...prev, busy: true } : prev))\n try {\n if (!draftAttemptKey.current) {\n draftAttemptKey.current =\n globalThis.crypto?.randomUUID?.() ??\n `${Date.now()}-${Math.random().toString(36).slice(2)}`\n }\n const response = await authorizedFetch(\n user,\n '/api/commerce/draft-order',\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n // Stable across a retry of THIS attempt (AGL-1697), so a\n // double-click cannot mint two live payment links.\n 'Idempotency-Key': draftAttemptKey.current,\n },\n body: JSON.stringify({\n hostId,\n productId: draft.productId,\n variantId: draft.variantId || undefined,\n quantity: Number(draft.quantity) || 1,\n email: draft.email || undefined,\n // A request, never an instruction: the server resolves the\n // rates for this country AND restricts the payment link's\n // collectable addresses to it, so declaring one cannot buy a\n // cheaper zone's rate than the address the buyer then enters\n // (AGL-1721).\n ...(draft.shipTo ? { shippingCountry: draft.shipTo } : {}),\n ...(draft.shipPostal?.trim() ? { shippingPostalCode: draft.shipPostal.trim() } : {}),\n }),\n },\n )\n const payload = await response.json()\n if (!response.ok) {\n // The merchant's rates differ by destination, so the server will not\n // price this order until it knows one (AGL-1792). Reveal the field and\n // let them answer; a store whose rates are the same everywhere, or\n // which configured none, never sends this and never shows it.\n if (payload?.needsShippingCountry) {\n setDraft((prev) =>\n prev\n ? {\n ...prev,\n shipCountries: (\n payload.shippingCountries as string[] | undefined\n )?.length\n ? (payload.shippingCountries as string[])\n : [...CommerceModel.CHECKOUT_SHIPPING_COUNTRIES],\n ...(payload?.needsShippingPostalCode ? { askPostal: true } : {}),\n }\n : prev,\n )\n }\n return void enqueueSnackbar(payload?.error ?? 'Draft order failed', {\n variant: 'error',\n allowDuplicate: true,\n })\n }\n await navigator.clipboard.writeText(payload.url).catch(() => undefined)\n enqueueSnackbar('Draft created — payment link copied', {\n variant: 'success',\n persist: false,\n })\n setDraft(null)\n } finally {\n setDraft((prev) => (prev ? { ...prev, busy: false } : prev))\n }\n }, [draft, user, hostId, enqueueSnackbar])\n\n /*\n * Bulk \"Mark as fulfilled\" (AGL-3611): one route call per ticked order, so\n * each gets its own transition check. Only paid and partially fulfilled\n * rows count; the button says how many.\n */\n const checkedOrders = useMemo(\n () => orderRows.filter((row: any) => checkedIds.includes(String(row.$id))),\n [orderRows, checkedIds],\n )\n const fulfillableCount = checkedOrders.filter((row: any) =>\n BULK_FULFILLABLE_STATUSES.includes(String(row.status)),\n ).length\n const handleBulkFulfill = useCallback(async () => {\n if (!checkedOrders.length) return\n setBulkBusy(true)\n try {\n const batchKey =\n globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`\n const result = await bulkFulfillOrders(user, hostId, checkedOrders as any[], batchKey)\n enqueueSnackbar(describeBulkFulfill(result), {\n variant: result.unknown.length ? 'error' : result.refused.length ? 'warning' : 'success',\n allowDuplicate: true,\n })\n if (!result.unknown.length) setCheckedIds([])\n } finally {\n setBulkBusy(false)\n }\n }, [checkedOrders, user, hostId, enqueueSnackbar])\n\n const selectedOrder =\n loadedOrders.find((order: any) => order.$id === selectedId) ??\n (seededOrder && seededOrder.$id === selectedId ? seededOrder : null)\n\n /**\n * Shared by the two triggers (AGL-1805) so the empty state and the toolbar\n * cannot drift into opening the dialog with different starting fields.\n */\n const openDraft = useCallback(\n () => setDraft({ productId: '', variantId: '', quantity: '1', email: '' }),\n [],\n )\n\n /** What the draft dialog can actually offer. */\n const selectableProducts = useMemo(\n () => productWindow.rows.filter((product: any) => !product.deletedAt),\n [productWindow],\n )\n\n /*\n * The six columns `/product/commerce` advertises, in the order the mockup\n * shows them — every fact scannable on its own, Channel included.\n */\n const orderColumns = useMemo<GridColDef[]>(\n () => [\n {\n field: 'orderLabel',\n headerName: 'Order',\n flex: 1,\n minWidth: 160,\n renderCell: ({ row }: any) => {\n const extraItems = Math.max(0, (row.lineItems?.length ?? 0) - 1)\n return (\n <Stack sx={{ minWidth: 0 }}>\n <Typography variant=\"body2\" noWrap>\n {row.orderLabel}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {extraItems ? `${row.itemName} +${extraItems} more` : row.itemName}\n </Typography>\n </Stack>\n )\n },\n },\n {\n field: 'customerEmail',\n headerName: 'Customer',\n flex: 1,\n minWidth: 180,\n renderCell: ({ row }: any) => (\n <Typography variant=\"body2\" noWrap>\n {row.customerEmail || '—'}\n </Typography>\n ),\n },\n {\n field: 'channelKey',\n headerName: 'Channel',\n width: 120,\n renderCell: ({ row }: any) => (\n <Typography variant=\"body2\">\n {CommerceModel.orderChannelLabel(row.channelKey)}\n </Typography>\n ),\n },\n {\n field: 'netCents',\n headerName: 'Total',\n type: 'number',\n width: 150,\n align: 'right',\n headerAlign: 'right',\n renderCell: ({ row }: any) => (\n <Stack sx={{ alignItems: 'flex-end', minWidth: 0, width: 1 }}>\n <Typography variant=\"body2\">\n {`$${(row.netCents / 100).toFixed(2)}`}\n </Typography>\n {row.refundedCents ? (\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {`$${((row.totals?.totalCents ?? row.amountCents ?? 0) / 100).toFixed(2)} less refunds`}\n </Typography>\n ) : null}\n </Stack>\n ),\n },\n {\n field: 'statusKey',\n headerName: 'Status',\n width: 230,\n renderCell: ({ row }: any) => {\n // A lost chargeback leaves `status: 'refunded'` (AGL-1787), so the\n // status pill cannot tell the two apart either — which is why the\n // dispute chip sits beside it rather than being folded into it.\n const dispute: ReturnType<typeof CommerceModel.describeOrderDispute> =\n row.disputeBadge\n return (\n <Stack sx={{ minWidth: 0 }}>\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Chip\n label={\n CommerceModel.ORDER_STATUS_LABELS[\n row.statusKey as CommerceModel.OrderStatus\n ] ?? row.statusKey\n }\n size=\"small\"\n color={\n CommerceModel.ORDER_STATUS_COLOR[\n row.statusKey as CommerceModel.OrderStatus\n ] ?? 'default'\n }\n variant=\"outlined\"\n />\n {dispute ? (\n <Tooltip title={dispute.detail}>\n <Chip\n label={dispute.label}\n size=\"small\"\n color={DISPUTE_COLOR[dispute.tone]}\n variant=\"filled\"\n />\n </Tooltip>\n ) : null}\n </Stack>\n {/*\n The deadline on the row itself, while the case is open — the\n one fact on this screen that expires.\n */}\n {dispute?.evidenceDaysLeft !== undefined ? (\n <Typography\n variant=\"caption\"\n component=\"div\"\n color={dispute.evidenceDaysLeft < 0 ? 'error' : 'warning.main'}\n >\n {dispute.evidenceDaysLeft < 0\n ? 'Evidence deadline passed'\n : `Evidence due in ${dispute.evidenceDaysLeft} day${\n dispute.evidenceDaysLeft === 1 ? '' : 's'\n }`}\n </Typography>\n ) : null}\n </Stack>\n )\n },\n },\n {\n field: 'createdAtMs',\n headerName: 'Date',\n width: 130,\n renderCell: ({ row }: any) => {\n const createdAt =\n row.createdAt?.toDate?.() ??\n (row.createdAtMs ? new Date(row.createdAtMs) : null)\n return (\n <Stack sx={{ minWidth: 0 }}>\n <Typography variant=\"body2\" noWrap>\n {createdAt ? createdAt.toLocaleDateString() : '—'}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {createdAt ? createdAt.toLocaleTimeString() : ''}\n </Typography>\n </Stack>\n )\n },\n },\n ],\n [],\n )\n\n\n const columns = useMemo(\n () =>\n listFilterGridColumns(\n orderColumns,\n ORDER_LIST_FIELDS,\n filterOptions,\n ORDER_LIST_HEADERS,\n ),\n [orderColumns, filterOptions],\n )\n\n /*\n * The store is empty only when an UNFILTERED first page came back empty; a\n * filter or search that matches nothing keeps the grid, its chips and its\n * panel, so the reader can take the filter back off.\n */\n const empty =\n listStatus === 'success' &&\n !filtering &&\n askedSort === ORDER_LIST_COLUMN_SORTS[0] &&\n page === 0 &&\n orders.length === 0\n\n return (\n <CardDisplay\n header={'Orders'}\n // Shipping actions live in the card header (AGL-3613): the orders\n // still to ship for a label tool, and its tracking numbers back.\n HeaderProps={{ action: <OrderShippingActions hostId={hostId} /> }}\n help={pluginDocsHelp('commerce', {\n anchor: '#orders-screen',\n excerpt:\n 'Every order with its channel, status and net total. A refunded ' +\n 'order shows what is left, with the gross beneath it.',\n })}\n contentGutterX\n contentGutterY\n >\n {empty ? (\n /*\n * An invitation, not a report (AGL-1805). The \"Draft order\" button\n * used to live in the other arm of this ternary, so the one state a\n * draft order exists for — no sales yet, invoice the customer you\n * already have — was the only state that could not reach it, and\n * every other route into the dialog needs an order to exist first.\n *\n * The filters stay behind deliberately: they belong to a list with\n * rows in it. Export orders likewise — a header-only file is not\n * something a merchant on day one is looking for.\n */\n <Stack spacing={1} sx={{ alignItems: 'flex-start' }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {\n 'No orders yet. Storefront sales, POS sales and draft orders ' +\n 'all appear here as they come in.'\n }\n </Typography>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {\n 'Selling to someone directly? Draft their order and send them ' +\n 'a payment link.'\n }\n </Typography>\n <Button\n size=\"small\"\n variant=\"contained\"\n color=\"primary\"\n onClick={openDraft}\n >\n {'Draft order'}\n </Button>\n </Stack>\n ) : (\n <Stack spacing={1}>\n {showStats ? (\n <Stack\n useFlexGap\n direction=\"row\"\n spacing={3}\n sx={{ flexWrap: 'wrap', rowGap: 1 }}\n >\n <CommerceStatTile\n label=\"Revenue · 30d\"\n value={`$${(summary.revenueCents / 100).toFixed(2)}`}\n deltaPct={summary.revenueDeltaPct}\n deltaCaption=\"vs the previous 30 days\"\n />\n <CommerceStatTile\n label=\"Orders · 30d\"\n value={String(summary.orders)}\n deltaPct={summary.ordersDeltaPct}\n deltaCaption=\"vs the previous 30 days\"\n />\n <CommerceStatTile\n label=\"Avg order value\"\n value={`$${(summary.aovCents / 100).toFixed(2)}`}\n deltaPct={summary.aovDeltaPct}\n deltaCaption=\"vs the previous 30 days\"\n />\n </Stack>\n ) : null}\n {showStats && statsWindow.truncated ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`Figures count the ${STATS_ORDER_CEILING} most recent orders of the last 60 days.`}\n </Typography>\n ) : null}\n {openDisputes.count > 0 ? (\n <Alert\n severity={openDisputes.overdue ? 'error' : 'warning'}\n action={\n showingOpenDisputes ? undefined : (\n <Button\n size=\"small\"\n color=\"inherit\"\n onClick={() =>\n setClauses(\n upsertListFilterClause(\n clauses,\n OPEN_DISPUTE_CLAUSE.field,\n OPEN_DISPUTE_CLAUSE,\n ),\n )\n }\n >\n {'Show them'}\n </Button>\n )\n }\n >\n <AlertTitle>\n {moreDisputes\n ? `More than ${OPEN_DISPUTE_CEILING} charges are disputed with the shopper’s bank`\n : openDisputes.count === 1\n ? 'A shopper has disputed a charge with their bank'\n : `${openDisputes.count} charges are disputed with the shopper’s bank`}\n </AlertTitle>\n {openDisputes.soonestDaysLeft === undefined\n ? 'Answer in the Stripe dashboard while the case is open — an unanswered dispute is decided for the shopper.'\n : openDisputes.soonestDaysLeft < 0\n ? 'The evidence deadline has passed on at least one of these. Stripe decides an unanswered dispute for the shopper.'\n : `Evidence is due to Stripe in ${openDisputes.soonestDaysLeft} day${\n openDisputes.soonestDaysLeft === 1 ? '' : 's'\n } on the tightest of these. An unanswered dispute is decided for the shopper.`}\n </Alert>\n ) : null}\n {/*\n The buttons stay beside the grid: Export orders writes every order\n the query matches, with the fields the person picks, which the grid's\n own export — one page — cannot.\n */}\n <Stack\n direction=\"row\"\n spacing={1}\n useFlexGap\n sx={{ alignItems: 'center', justifyContent: 'flex-end', flexWrap: 'wrap' }}\n >\n {checkedIds.length ? (\n <Button\n size=\"small\"\n variant=\"outlined\"\n disabled={bulkBusy || fulfillableCount === 0}\n onClick={handleBulkFulfill}\n >\n {`Mark as fulfilled (${fulfillableCount})`}\n </Button>\n ) : null}\n {/* Other plugins' bulk actions on the ticked orders (AGL-3612). */}\n {checkedIds.length && WidgetSlot ? (\n <WidgetSlot\n slot={ORDERS_BULK_ZONE.id}\n hostId={hostId}\n orgId={undefined}\n selectedOrderIds={checkedIds}\n storeName=\"\"\n />\n ) : null}\n {/* Only for whom the route takes it (AGL-3554). */}\n {transfer?.can('export', { resource: COMMERCE_ORDERS_TRANSFER, scope: 'host', hostId }) ? (\n <Button size=\"small\" onClick={openExport}>\n {'Export orders'}\n </Button>\n ) : null}\n <Button\n size=\"small\"\n variant=\"contained\"\n color=\"primary\"\n onClick={openDraft}\n >\n {'Draft order'}\n </Button>\n </Stack>\n <ListFilterChips\n fields={ORDER_LIST_FIELDS}\n headers={ORDER_LIST_HEADERS}\n clauses={clauses}\n onChange={setClauses}\n options={filterOptions}\n />\n <ListQueryNotices\n refused={refused}\n notices={[...plan.notices, ...columnSort.notices]}\n />\n <ListTable\n aria-label=\"Orders\"\n rows={columnSort.rows}\n columns={columns}\n onOpen={(id) => setSelectedId(id)}\n selectable={{ selected: checkedIds, onChange: setCheckedIds }}\n loading={listStatus === 'loading'}\n /*\n * The grid must NOT also filter, search or sort on its own: the\n * query answers the filters and the search, and every header\n * order is the query's or the page's (`columnSort`).\n */\n filterMode=\"server\"\n filterModel={gridFilter.filterModel}\n onFilterModelChange={gridFilter.onFilterModelChange}\n quickFilter\n columnSort={columnSort}\n // `ListPagination` below pages the query.\n hideFooter\n initialState={{\n columns: { columnVisibilityModel: ORDER_HIDDEN_COLUMNS },\n }}\n noRowsLabel=\"No orders match these filters\"\n />\n <ListPagination\n page={page}\n pageSize={pageSize}\n rowCount={orderRows.length}\n hasMore={hasMore}\n onPageChange={setPage}\n onPageSizeChange={setPageSize}\n />\n </Stack>\n )}\n {selectedOrder ? (\n <OrderDetailDialog\n hostId={hostId}\n order={selectedOrder}\n onClose={() => setSelectedId(null)}\n />\n ) : null}\n <Dialog\n open={Boolean(draft)}\n onClose={() => setDraft(null)}\n maxWidth=\"xs\"\n fullWidth\n >\n <DialogTitle>{'Draft order'}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n {payments.blocked ? (\n <PrerequisiteNotice href={payments.href ?? undefined} actionLabel=\"Open Payments\">\n {`${payments.reason ?? ''} The buyer pays a draft order on a Stripe payment page.`}\n </PrerequisiteNotice>\n ) : null}\n <TextField\n label=\"Product\"\n value={draft?.productId ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev\n ? { ...prev, productId: event.target.value, variantId: '' }\n : prev,\n )\n }\n size=\"small\"\n select\n sx={{ mt: 1 }}\n /*\n * The second dead end behind the first (AGL-1805): a store with\n * no orders may have no products either, and a draft order is\n * composed from one — so \"Create & copy link\" stays disabled. Say\n * why, rather than opening an empty menu onto nothing.\n */\n helperText={\n selectableProducts.length === 0\n ? 'Add a product to this store first — a draft order is built from one.'\n : undefined\n }\n >\n {selectableProducts.map((product: any) => (\n <MenuItem key={product.$id} value={product.$id}>\n {product.name ?? product.$id}\n </MenuItem>\n ))}\n </TextField>\n {(() => {\n const product = productWindow.rows.find(\n (item: any) => item.$id === draft?.productId,\n )\n const variants = product\n ? CommerceModel.liftLegacyProduct(product).variants\n : []\n return variants.length > 1 ? (\n <TextField\n label=\"Variant\"\n value={draft?.variantId ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev ? { ...prev, variantId: event.target.value } : prev,\n )\n }\n size=\"small\"\n select\n >\n {variants.map((variant) => (\n <MenuItem key={variant.id} value={variant.id}>\n {`${Object.values(variant.options ?? {}).join(' / ') || 'Default'} — $${variant.priceUsd}`}\n </MenuItem>\n ))}\n </TextField>\n ) : null\n })()}\n <TextField\n label=\"Quantity\"\n value={draft?.quantity ?? '1'}\n onChange={(event) =>\n setDraft((prev) =>\n prev\n ? {\n ...prev,\n quantity: event.target.value.replace(/[^0-9]/g, ''),\n }\n : prev,\n )\n }\n size=\"small\"\n slotProps={{ htmlInput: { inputMode: 'numeric' } }}\n />\n <TextField\n label=\"Buyer email (optional)\"\n value={draft?.email ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev ? { ...prev, email: event.target.value } : prev,\n )\n }\n size=\"small\"\n />\n {draft?.shipCountries?.length ? (\n <TextField\n label=\"Ships to\"\n value={draft?.shipTo ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev ? { ...prev, shipTo: event.target.value } : prev,\n )\n }\n size=\"small\"\n select\n helperText={\n 'This store’s shipping rates differ by destination, so the ' +\n 'payment link has to be priced for one.'\n }\n >\n {draft.shipCountries.map((code) => (\n <MenuItem key={code} value={code}>\n {CommerceModel.CHECKOUT_SHIPPING_COUNTRY_NAMES[code] ?? code}\n </MenuItem>\n ))}\n </TextField>\n ) : null}\n {draft?.askPostal ? (\n <TextField\n label=\"Postal code\"\n value={draft?.shipPostal ?? ''}\n onChange={(event) =>\n setDraft((prev) => (prev ? { ...prev, shipPostal: event.target.value } : prev))\n }\n size=\"small\"\n helperText=\"This store prices shipping by carrier, which needs the postal code.\"\n />\n ) : null}\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setDraft(null)}>{'Cancel'}</Button>\n <BlockedControl blocked={payments.blocked} reason={payments.reason ?? ''}>\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={\n !draft?.productId ||\n draft?.busy ||\n // Once asked, the answer is required: retrying without one is\n // refused again, so the button would only look broken.\n Boolean(draft?.shipCountries?.length && !draft?.shipTo) ||\n Boolean(draft?.askPostal && !draft?.shipPostal?.trim())\n }\n onClick={handleDraftCreate}\n >\n {'Create & copy link'}\n </Button>\n </BlockedControl>\n </DialogActions>\n </Dialog>\n </CardDisplay>\n )\n}\nHostOrdersCard.displayName = 'HostOrdersCard'\n\nexport default HostOrdersCard\n"],"names":["CommerceModel","CardDisplay","ListFilterChips","ListPagination","ListQueryNotices","listQueryRefusals","ListTable","hiddenFilterVisibility","useListColumnSort","listFilterGridColumns","upsertListFilterClause","useListGridFilter","useSnackbar","checkEntitlement","pluginDocsHelp","ORDERS_CUSTOMER_PARAM","ORDERS_ORDER_PARAM","Alert","AlertTitle","Button","Chip","Dialog","DialogActions","DialogContent","DialogTitle","MenuItem","Stack","TextField","Tooltip","Typography","collection","doc","getDoc","limit","orderBy","query","where","useSearchParams","useCallback","useEffect","useMemo","useRef","useState","ceilingedWindow","collectionCeiling","useFirestore","useMerchantPayments","useOrgPlan","useUser","BlockedControl","PrerequisiteNotice","useFirestoreCollection","useListQuery","useTransferLauncher","commerceListFilter","COMMERCE_ORDERS_TRANSFER","OrderShippingActions","authorizedFetch","OPEN_DISPUTE_CLAUSE","ORDER_CHANNEL_OPTIONS","ORDER_LIST_COLUMN_SORTS","ORDER_DISPUTE_OPTIONS","ORDER_LIST_FIELDS","ORDER_LIST_HEADERS","ORDER_LIST_QUERY","ORDER_LIST_SELECT_FIELDS","ORDER_STATUS_OPTIONS","ordersCustomerClause","CommerceStatTile","bulkFulfillOrders","BULK_FULFILLABLE_STATUSES","describeBulkFulfill","ORDERS_BULK_ZONE","useConsoleWidgetSlot","OrderDetailDialog","DISPUTE_COLOR","PRODUCT_NAME_WINDOW","OPEN_DISPUTE_CEILING","STATS_WINDOW_MS","STATS_ORDER_CEILING","ORDER_VISIBLE_COLUMNS","ORDER_HIDDEN_COLUMNS","ORDER_PAGE_SORTS","netCents","row","ORDER_PAGE_SORT_HEADERS","HostOrdersCard","props","loadedOrders","payments","draft","hostId","firestore","ordersRef","data","productDocs","idField","productWindow","undefined","productNames","map","product","rows","$id","name","org","ready","orgReady","showStats","searchParams","clauses","setClauses","customer","get","gridFilter","onChange","selectFields","filtering","length","searchWords","some","word","trim","askedSort","setAskedSort","disputedRows","hasMore","moreDisputes","declaration","request","deps","pageSize","confirmDisappearances","orders","page","setPage","setPageSize","plan","status","listStatus","search","sort","selectedId","setSelectedId","checkedIds","setCheckedIds","bulkBusy","setBulkBusy","WidgetSlot","seededOrderId","seededOrder","setSeededOrder","seededOpened","current","order","then","snapshot","id","exists","catch","setDraft","user","enqueueSnackbar","orderRows","filter","isUnpaidQuote","lifted","liftLegacyOrder","orderLabel","formatOrderNumber","itemName","lineItems","productId","statusKey","channelKey","channel","orderNetCents","disputeBadge","describeOrderDispute","columnSort","sorts","defaultSort","onSortChange","pageSorts","headers","productOptions","value","String","label","filterOptions","productIds","disputeKey","refused","fields","options","showingOpenDisputes","clause","field","op","openDisputes","summariseOpenDisputes","statsSince","Date","now","statsDocs","statsWindow","summary","summarizeOrderWindow","nowMs","transfer","openExport","resource","scope","draftAttemptKey","variantId","quantity","email","shipTo","shipPostal","handleDraftCreate","prev","busy","globalThis","crypto","randomUUID","Math","random","toString","slice","response","method","body","JSON","stringify","Number","shippingCountry","shippingPostalCode","payload","json","ok","needsShippingCountry","shipCountries","shippingCountries","CHECKOUT_SHIPPING_COUNTRIES","needsShippingPostalCode","askPostal","error","variant","allowDuplicate","navigator","clipboard","writeText","url","persist","checkedOrders","includes","fulfillableCount","handleBulkFulfill","batchKey","result","unknown","selectedOrder","find","openDraft","selectableProducts","deletedAt","orderColumns","headerName","flex","minWidth","renderCell","extraItems","max","sx","noWrap","color","customerEmail","width","orderChannelLabel","type","align","headerAlign","alignItems","toFixed","refundedCents","totals","totalCents","amountCents","dispute","direction","spacing","ORDER_STATUS_LABELS","size","ORDER_STATUS_COLOR","title","detail","tone","evidenceDaysLeft","component","createdAt","toDate","createdAtMs","toLocaleDateString","toLocaleTimeString","columns","empty","header","HeaderProps","action","help","anchor","excerpt","contentGutterX","contentGutterY","onClick","useFlexGap","flexWrap","rowGap","revenueCents","deltaPct","revenueDeltaPct","deltaCaption","ordersDeltaPct","aovCents","aovDeltaPct","truncated","count","severity","overdue","soonestDaysLeft","justifyContent","disabled","slot","orgId","selectedOrderIds","storeName","can","notices","aria-label","onOpen","selectable","selected","loading","filterMode","filterModel","onFilterModelChange","quickFilter","hideFooter","initialState","columnVisibilityModel","noRowsLabel","rowCount","onPageChange","onPageSizeChange","onClose","open","Boolean","maxWidth","fullWidth","display","flexDirection","gap","blocked","href","actionLabel","reason","event","target","select","mt","helperText","item","variants","liftLegacyProduct","Object","values","join","priceUsd","replace","slotProps","htmlInput","inputMode","code","CHECKOUT_SHIPPING_COUNTRY_NAMES","displayName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/host-orders-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 { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport ListFilterChips from '@aglyn/shared-ui-jsx/components/list-filter-chips.component'\nimport { ListPagination } from '@aglyn/shared-ui-jsx/components/list-pagination.component'\nimport {\n ListQueryNotices,\n listQueryRefusals,\n} from '@aglyn/shared-ui-jsx/components/list-query-notices.component'\nimport { ListTable } from '@aglyn/shared-ui-jsx/components/list-table.component'\nimport { hiddenFilterVisibility } from '@aglyn/shared-ui-jsx/const/list-filter'\nimport type { ListQuerySort } from '@aglyn/shared-ui-jsx/const/list-query-plan'\nimport { useListColumnSort } from '@aglyn/shared-ui-jsx/hooks/use-list-column-sort'\nimport {\n type ListFilterClause,\n listFilterGridColumns,\n upsertListFilterClause,\n} from '@aglyn/shared-ui-jsx/const/list-grid-filter'\nimport { useListGridFilter } from '@aglyn/shared-ui-jsx/hooks/use-list-grid-filter'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { checkEntitlement, pluginDocsHelp } from '@aglyn/aglyn'\nimport { ORDERS_CUSTOMER_PARAM, ORDERS_ORDER_PARAM } from '../../model/commerce-record-routes'\nimport {\n Alert,\n AlertTitle,\n Button,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n MenuItem,\n Stack,\n TextField,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport type { GridColDef } from '@mui/x-data-grid'\nimport {\n collection,\n doc,\n getDoc,\n limit,\n orderBy,\n query,\n where,\n} from 'firebase/firestore'\nimport { useSearchParams } from 'next/navigation'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport {\n ceilingedWindow,\n collectionCeiling,\n useFirestore,\n useMerchantPayments,\n useOrgPlan,\n useUser,\n} from '@aglyn/tenant-feature-instance'\nimport { BlockedControl } from '@aglyn/shared-ui-jsx/components/blocked-control.component'\nimport { PrerequisiteNotice } from '@aglyn/shared-ui-jsx/components/prerequisite-notice.component'\nimport { useFirestoreCollection } from '@aglyn/tenant-feature-instance'\nimport { useListQuery } from '@aglyn/tenant-feature-instance/hooks/use-list-query'\nimport { useTransferLauncher } from '@aglyn/aglyn/app-utils/transfer-launcher-context'\nimport { commerceListFilter } from '../../transfer/list-filter'\nimport { COMMERCE_ORDERS_TRANSFER } from '../../transfer/transfer-keys'\nimport OrderShippingActions from './order-shipping-actions.component'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\n\nimport {\n OPEN_DISPUTE_CLAUSE,\n ORDER_CHANNEL_OPTIONS,\n ORDER_LIST_COLUMN_SORTS,\n ORDER_DISPUTE_OPTIONS,\n ORDER_LIST_FIELDS,\n ORDER_LIST_HEADERS,\n ORDER_LIST_QUERY,\n ORDER_LIST_SELECT_FIELDS,\n ORDER_STATUS_OPTIONS,\n ordersCustomerClause,\n} from '../../constants/orders-list-query'\nimport CommerceStatTile from './commerce-stat-tile.component'\nimport { bulkFulfillOrders, BULK_FULFILLABLE_STATUSES, describeBulkFulfill } from './bulk-fulfill'\nimport { ORDERS_BULK_ZONE } from './store-zones'\nimport { useConsoleWidgetSlot } from '@aglyn/aglyn/app-utils/console-widget-slot-context'\nimport OrderDetailDialog, {\n DISPUTE_COLOR,\n} from './order-detail-dialog.component'\n\n/**\n * The products the card reads to NAME a legacy row and the CSV, to offer the\n * Product filter's choices and to fill the draft dialog's picker. A picker's\n * reach, not the list's: the orders themselves are paged by their query and\n * the Product filter asks it for any product id, named here or not.\n */\nconst PRODUCT_NAME_WINDOW = 100\n\n/**\n * How many open disputes the banner reads. Its own query, `disputeKey ==\n * 'open'`, so a deadline is raised whatever the list is filtered to and\n * however deep in the store the order sits; a store past this many open\n * cases is told \"more than\".\n */\nconst OPEN_DISPUTE_CEILING = 50\n\n/**\n * The money tiles read the last sixty days (thirty, and the thirty before it)\n * on their own bounded query. They are analytics over a period, not a filter\n * over the list, and share the analytics card's bound.\n */\nconst STATS_WINDOW_MS = 60 * 24 * 60 * 60 * 1000\nconst STATS_ORDER_CEILING = 500\n\n/** The columns the grid draws; every other declared field is a hidden filter column. */\nconst ORDER_VISIBLE_COLUMNS = [\n 'orderLabel',\n 'customerEmail',\n 'channelKey',\n 'statusKey',\n 'createdAtMs',\n]\nconst ORDER_HIDDEN_COLUMNS = hiddenFilterVisibility(\n ORDER_LIST_FIELDS,\n ORDER_VISIBLE_COLUMNS,\n)\n\nexport interface HostOrdersCardProps {\n hostId: string\n /**\n * Holds \"Send quotes and invoices to customers\" (`commerce.quotes.send`),\n * which the order dialog's Send invoice asks (AGL-4099). Absent reads as\n * held: the route decides.\n */\n canSendInvoices?: boolean\n}\n\n/** Total is computed from the refunds, so it sorts the page on screen (AGL-3680). */\nconst ORDER_PAGE_SORTS = {\n netCents: (row: { netCents: number }) => row.netCents,\n}\nconst ORDER_PAGE_SORT_HEADERS = { netCents: 'Total' }\n\n/**\n * Orders console (AGL-287): filterable list over webhook-written order\n * docs with a detail dialog (timeline, fulfill, refund, cancel, notes,\n * packing slip) and draft orders that send the buyer a payment link.\n *\n * ## Every filter and the search are on the query (AGL-3321)\n *\n * The list used to read the newest two hundred orders and match its Filters\n * panel and search over them, so a Status filter on a busy store answered\n * \"none\" about every order past the two hundredth. Now each clause and the\n * search word are predicates on ONE Firestore query (`ORDER_LIST_QUERY`),\n * over the fields every writer stamps (`orderListFields`), and the footer\n * pages that query's answer. A combination one query cannot hold is refused\n * by name above the grid and never applied to some rows only.\n */\nexport function HostOrdersCard(props: HostOrdersCardProps) {\n const { hostId, canSendInvoices } = props\n const firestore = useFirestore()\n const ordersRef = useMemo(\n () => collection(firestore, 'hosts', hostId, 'orders'),\n [firestore, hostId],\n )\n const { data: productDocs } = useFirestoreCollection<any>(\n () =>\n collectionCeiling(\n collection(firestore, 'hosts', hostId, 'products'),\n PRODUCT_NAME_WINDOW,\n ),\n [firestore, hostId],\n { idField: '$id' },\n )\n const productWindow = useMemo(\n () => ceilingedWindow<any>(productDocs ?? undefined, PRODUCT_NAME_WINDOW),\n [productDocs],\n )\n const productNames = useMemo(() => {\n const map: Record<string, string> = {}\n for (const product of productWindow.rows) {\n map[product.$id] = product.name ?? product.$id\n }\n return map\n }, [productWindow])\n\n /**\n * The money tiles are the `commerceAnalytics` surface (AGL-1938,\n * AGL-2056), and this is the third place they appear. Rendering them\n * ungated here would undo both of those passes and hand a Starter org\n * the Pro figures one tab away from the upgrade prompt that refuses\n * them. The TABLE below is not gated — a list of your own orders is not\n * a paid feature.\n */\n const { org, ready: orgReady } = useOrgPlan(hostId)\n // A draft order's link is a Stripe payment page, so it needs the store's\n // Stripe account; the dialog says so before Create rather than after.\n const payments = useMerchantPayments(hostId)\n const showStats =\n orgReady && checkEntitlement(org as never, 'commerceAnalytics')\n\n /*\n * The grid's clauses (AGL-96, AGL-3317), held here so two things outside\n * the grid can set one: the CRM's contact page links with the buyer's\n * address to answer \"what has this customer ordered\" (AGL-2622) — a whole\n * address is that buyer, a domain every buyer at a company\n * (`ordersCustomerClause`) — and the dispute banner's \"Show them\".\n */\n const searchParams = useSearchParams()\n const [clauses, setClauses] = useState<ListFilterClause[]>(() => {\n const customer = ordersCustomerClause(\n searchParams?.get(ORDERS_CUSTOMER_PARAM) ?? '',\n )\n return customer ? [customer] : []\n })\n const gridFilter = useListGridFilter({\n clauses,\n onChange: setClauses,\n selectFields: ORDER_LIST_SELECT_FIELDS,\n })\n const filtering =\n clauses.length > 0 || gridFilter.searchWords.some((word) => word.trim())\n /*\n * Every header sorts (AGL-3680). Date, Order, Customer, Channel and Status\n * are the query's order over every order (`ORDER_LIST_COLUMN_SORTS`);\n * Total is computed from the refunds, so it sorts the page on screen.\n * Newest first until a header is clicked. A header order other than Date\n * holds only with no filter or search on — the plan falls back to newest\n * first and `ListQueryNotices` says so.\n */\n const [askedSort, setAskedSort] = useState<ListQuerySort | null>(\n ORDER_LIST_COLUMN_SORTS[0],\n )\n\n /*\n * The open disputes, on their OWN query (AGL-1796). Raised whatever the\n * list is filtered to — a merchant filtered to \"delivered\" still has a\n * deadline running on a `paid` order, and the evidence window is days —\n * and however far back the order is. Asked before the list so the list's\n * plan is the one a spec reads last.\n */\n const {\n rows: disputedRows,\n hasMore: moreDisputes,\n } = useListQuery<any>({\n collection: ordersRef,\n declaration: ORDER_LIST_QUERY,\n request: { clauses: [OPEN_DISPUTE_CLAUSE] },\n deps: [firestore, hostId],\n idField: '$id',\n pageSize: OPEN_DISPUTE_CEILING,\n // A dispute that closes leaves this query; confirm it before believing it.\n confirmDisappearances: true,\n })\n\n /*\n * THE LIST: every clause and the search word on one query, newest first,\n * paged by the footer. A status, a dispute or a paid draft's address can\n * move an order out of the filtered query mid-session, so a disappearance\n * is confirmed against the server before it is believed (AGL-1196).\n */\n const {\n rows: orders,\n data: loadedOrders,\n hasMore,\n page,\n setPage,\n pageSize,\n setPageSize,\n plan,\n status: listStatus,\n } = useListQuery<any>({\n collection: ordersRef,\n declaration: ORDER_LIST_QUERY,\n request: { clauses, search: gridFilter.searchWords, sort: askedSort },\n deps: [firestore, hostId],\n idField: '$id',\n confirmDisappearances: true,\n })\n\n const [selectedId, setSelectedId] = useState<string | null>(null)\n // Rows ticked for a bulk act (AGL-3611); the row click still opens one.\n const [checkedIds, setCheckedIds] = useState<string[]>([])\n const [bulkBusy, setBulkBusy] = useState(false)\n const WidgetSlot = useConsoleWidgetSlot()\n /*\n * An order named in the URL opens in its dialog on arrival (AGL-2622). A\n * contact's timeline names the order that made the person a customer,\n * and the address it links to is this list with `?order={id}`. The list\n * shows one page, and an order from last year is not on it, so the\n * document is read once by id and held beside the page for the dialog; an\n * order that IS loaded is found there first and the read is skipped. Once\n * per id — the ref keeps a re-render from reopening a dialog the merchant\n * has since closed — and the landing read is judged against the ref\n * rather than an effect cleanup, because the `setSelectedId` above\n * re-renders before the read lands and a cleanup keyed on any dep would\n * cancel the answer to the question just asked.\n */\n const seededOrderId = searchParams?.get(ORDERS_ORDER_PARAM) ?? null\n const [seededOrder, setSeededOrder] = useState<any | null>(null)\n const seededOpened = useRef<string | null>(null)\n useEffect(() => {\n if (!seededOrderId || seededOpened.current === seededOrderId) return\n if (listStatus === 'loading') return\n seededOpened.current = seededOrderId\n setSelectedId(seededOrderId)\n if (loadedOrders.some((order: any) => order.$id === seededOrderId)) return\n void getDoc(doc(firestore, 'hosts', hostId, 'orders', seededOrderId))\n .then((snapshot) => {\n if (seededOpened.current !== snapshot.id || !snapshot.exists()) return\n setSeededOrder({ ...snapshot.data(), $id: snapshot.id })\n })\n .catch(() => undefined)\n }, [seededOrderId, loadedOrders, listStatus, firestore, hostId])\n const [draft, setDraft] = useState<{\n productId: string\n variantId: string\n quantity: string\n email: string\n /** Destination the merchant declared, once they have been asked. */\n shipTo?: string\n /**\n * Revealed only when the server refuses for want of a destination\n * (AGL-1792). A merchant whose rates are the same everywhere — or who\n * configured none — is never asked and never sees this field.\n */\n shipCountries?: string[]\n /** The postal code, once live carrier rates ask for one (AGL-3612). */\n shipPostal?: string\n askPostal?: boolean\n busy?: boolean\n } | null>(null)\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n /**\n * Each order on the page with the values the grid DRAWS. What it filters\n * by is on the query; this is presentation only. `liftLegacyOrder` names\n * a status and channel on a row that predates them, and the item name\n * reads the line items first (AGL-1747): the flat `productId` is written\n * only by the two buy-now Stripe paths.\n */\n const orderRows = useMemo(\n () =>\n orders\n // An unpaid quote is not an order (AGL-4093). It carries no\n // `createdAtMs`, so the default order and every filter leave it out;\n // the unfiltered Order, Channel and Status header sorts are the only\n // queries that can reach one, and this keeps it off those pages too.\n .filter((order: any) => !CommerceModel.isUnpaidQuote(order))\n .map((order: any) => {\n const lifted = CommerceModel.liftLegacyOrder(order)\n return {\n ...order,\n orderLabel: CommerceModel.formatOrderNumber(lifted, order.$id),\n itemName:\n lifted.lineItems?.[0]?.name ??\n productNames[order.productId] ??\n order.productId ??\n '',\n statusKey: lifted.status,\n channelKey: lifted.channel ?? 'online',\n netCents: CommerceModel.orderNetCents(lifted),\n disputeBadge: CommerceModel.describeOrderDispute(lifted),\n }\n }),\n [orders, productNames],\n )\n const columnSort = useListColumnSort({\n sorts: ORDER_LIST_COLUMN_SORTS,\n defaultSort: ORDER_LIST_COLUMN_SORTS[0],\n sort: askedSort,\n onSortChange: setAskedSort,\n orderBy: plan.orderBy,\n rows: orderRows,\n pageSorts: ORDER_PAGE_SORTS,\n headers: ORDER_PAGE_SORT_HEADERS,\n })\n const productOptions = useMemo(\n () =>\n productWindow.rows.map((product: any) => ({\n value: String(product.$id),\n label: String(product.name ?? product.$id),\n })),\n [productWindow],\n )\n const filterOptions = useMemo(\n () => ({\n statusKey: ORDER_STATUS_OPTIONS,\n channelKey: ORDER_CHANNEL_OPTIONS,\n productIds: productOptions,\n disputeKey: ORDER_DISPUTE_OPTIONS,\n }),\n [productOptions],\n )\n const refused = useMemo(\n () =>\n listQueryRefusals(plan.refused, {\n fields: ORDER_LIST_FIELDS,\n headers: ORDER_LIST_HEADERS,\n options: filterOptions,\n }),\n [plan, filterOptions],\n )\n const showingOpenDisputes = clauses.some(\n (clause) =>\n clause.field === OPEN_DISPUTE_CLAUSE.field &&\n clause.op === OPEN_DISPUTE_CLAUSE.op &&\n clause.value === OPEN_DISPUTE_CLAUSE.value,\n )\n\n const openDisputes = useMemo(\n () =>\n CommerceModel.summariseOpenDisputes(\n disputedRows.map((order: any) => CommerceModel.liftLegacyOrder(order)),\n ),\n [disputedRows],\n )\n\n /*\n * 30-day money summary with the prior 30 days behind it (AGL-2136).\n * ANALYTICS, NOT A FILTER: the tiles describe a period, not the list, so\n * they keep their own bounded read — sixty days by `createdAtMs`, the\n * newest `STATS_ORDER_CEILING` of them, read only when the tiles show.\n * Range and order are the same field, so it needs no composite.\n */\n const statsSince = useMemo(() => Date.now() - STATS_WINDOW_MS, [])\n const { data: statsDocs } = useFirestoreCollection<any>(\n () =>\n showStats\n ? query(\n ordersRef,\n where('createdAtMs', '>=', statsSince),\n orderBy('createdAtMs', 'desc'),\n limit(STATS_ORDER_CEILING + 1),\n )\n : null,\n [firestore, hostId, showStats, statsSince],\n { idField: '$id' },\n )\n const statsWindow = useMemo(\n () => ceilingedWindow<any>(statsDocs ?? undefined, STATS_ORDER_CEILING),\n [statsDocs],\n )\n const summary = useMemo(\n () =>\n CommerceModel.summarizeOrderWindow(statsWindow.rows, { nowMs: Date.now() }),\n [statsWindow],\n )\n\n /**\n * Export (AGL-3531) opens the console's export dialog on the\n * `commerce.orders` resource: the fields the person picks, for what the\n * QUERY matches — every clause and the search the grid is showing, not the\n * page on screen — read and streamed on the server however many orders\n * match. Orders are exported only; there is no Import.\n */\n const transfer = useTransferLauncher()\n const openExport = useCallback(() => {\n transfer?.openExport({\n resource: COMMERCE_ORDERS_TRANSFER,\n scope: 'host',\n hostId,\n ...(filtering\n ? {\n filter: {\n label: 'the orders the list’s filters and search find',\n value: commerceListFilter(plan),\n },\n }\n : {}),\n })\n }, [transfer, hostId, filtering, plan])\n\n /**\n * Idempotency key for ONE draft attempt (AGL-1697).\n *\n * Minted lazily on the first create click, NOT per call — two clicks (or a\n * click retried after a lost response) must present ONE key so the server\n * replays the original payment link instead of minting a second order.\n * Retired whenever a content field changes: an edited draft is a different\n * order, and replaying the old one against it would hand the merchant a\n * link priced for fields they no longer see. Answering the shipping-country\n * ask also retires it, which is safe — that refusal is served before the\n * server takes the claim, so the first key was never spent.\n */\n const draftAttemptKey = useRef('')\n useEffect(() => {\n draftAttemptKey.current = ''\n }, [\n draft?.productId,\n draft?.variantId,\n draft?.quantity,\n draft?.email,\n draft?.shipTo,\n draft?.shipPostal,\n ])\n\n const handleDraftCreate = useCallback(async () => {\n if (!draft?.productId) return\n setDraft((prev) => (prev ? { ...prev, busy: true } : prev))\n try {\n if (!draftAttemptKey.current) {\n draftAttemptKey.current =\n globalThis.crypto?.randomUUID?.() ??\n `${Date.now()}-${Math.random().toString(36).slice(2)}`\n }\n const response = await authorizedFetch(\n user,\n '/api/commerce/draft-order',\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n // Stable across a retry of THIS attempt (AGL-1697), so a\n // double-click cannot mint two live payment links.\n 'Idempotency-Key': draftAttemptKey.current,\n },\n body: JSON.stringify({\n hostId,\n productId: draft.productId,\n variantId: draft.variantId || undefined,\n quantity: Number(draft.quantity) || 1,\n email: draft.email || undefined,\n // A request, never an instruction: the server resolves the\n // rates for this country AND restricts the payment link's\n // collectable addresses to it, so declaring one cannot buy a\n // cheaper zone's rate than the address the buyer then enters\n // (AGL-1721).\n ...(draft.shipTo ? { shippingCountry: draft.shipTo } : {}),\n ...(draft.shipPostal?.trim() ? { shippingPostalCode: draft.shipPostal.trim() } : {}),\n }),\n },\n )\n const payload = await response.json()\n if (!response.ok) {\n // The merchant's rates differ by destination, so the server will not\n // price this order until it knows one (AGL-1792). Reveal the field and\n // let them answer; a store whose rates are the same everywhere, or\n // which configured none, never sends this and never shows it.\n if (payload?.needsShippingCountry) {\n setDraft((prev) =>\n prev\n ? {\n ...prev,\n shipCountries: (\n payload.shippingCountries as string[] | undefined\n )?.length\n ? (payload.shippingCountries as string[])\n : [...CommerceModel.CHECKOUT_SHIPPING_COUNTRIES],\n ...(payload?.needsShippingPostalCode ? { askPostal: true } : {}),\n }\n : prev,\n )\n }\n return void enqueueSnackbar(payload?.error ?? 'Draft order failed', {\n variant: 'error',\n allowDuplicate: true,\n })\n }\n await navigator.clipboard.writeText(payload.url).catch(() => undefined)\n enqueueSnackbar('Draft created — payment link copied', {\n variant: 'success',\n persist: false,\n })\n setDraft(null)\n } finally {\n setDraft((prev) => (prev ? { ...prev, busy: false } : prev))\n }\n }, [draft, user, hostId, enqueueSnackbar])\n\n /*\n * Bulk \"Mark as fulfilled\" (AGL-3611): one route call per ticked order, so\n * each gets its own transition check. Only paid and partially fulfilled\n * rows count; the button says how many.\n */\n const checkedOrders = useMemo(\n () => orderRows.filter((row: any) => checkedIds.includes(String(row.$id))),\n [orderRows, checkedIds],\n )\n const fulfillableCount = checkedOrders.filter((row: any) =>\n BULK_FULFILLABLE_STATUSES.includes(String(row.status)),\n ).length\n const handleBulkFulfill = useCallback(async () => {\n if (!checkedOrders.length) return\n setBulkBusy(true)\n try {\n const batchKey =\n globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`\n const result = await bulkFulfillOrders(user, hostId, checkedOrders as any[], batchKey)\n enqueueSnackbar(describeBulkFulfill(result), {\n variant: result.unknown.length ? 'error' : result.refused.length ? 'warning' : 'success',\n allowDuplicate: true,\n })\n if (!result.unknown.length) setCheckedIds([])\n } finally {\n setBulkBusy(false)\n }\n }, [checkedOrders, user, hostId, enqueueSnackbar])\n\n const selectedOrder =\n loadedOrders.find((order: any) => order.$id === selectedId) ??\n (seededOrder && seededOrder.$id === selectedId ? seededOrder : null)\n\n /**\n * Shared by the two triggers (AGL-1805) so the empty state and the toolbar\n * cannot drift into opening the dialog with different starting fields.\n */\n const openDraft = useCallback(\n () => setDraft({ productId: '', variantId: '', quantity: '1', email: '' }),\n [],\n )\n\n /** What the draft dialog can actually offer. */\n const selectableProducts = useMemo(\n () => productWindow.rows.filter((product: any) => !product.deletedAt),\n [productWindow],\n )\n\n /*\n * The six columns `/product/commerce` advertises, in the order the mockup\n * shows them — every fact scannable on its own, Channel included.\n */\n const orderColumns = useMemo<GridColDef[]>(\n () => [\n {\n field: 'orderLabel',\n headerName: 'Order',\n flex: 1,\n minWidth: 160,\n renderCell: ({ row }: any) => {\n const extraItems = Math.max(0, (row.lineItems?.length ?? 0) - 1)\n return (\n <Stack sx={{ minWidth: 0 }}>\n <Typography variant=\"body2\" noWrap>\n {row.orderLabel}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {extraItems ? `${row.itemName} +${extraItems} more` : row.itemName}\n </Typography>\n </Stack>\n )\n },\n },\n {\n field: 'customerEmail',\n headerName: 'Customer',\n flex: 1,\n minWidth: 180,\n renderCell: ({ row }: any) => (\n <Typography variant=\"body2\" noWrap>\n {row.customerEmail || '—'}\n </Typography>\n ),\n },\n {\n field: 'channelKey',\n headerName: 'Channel',\n width: 120,\n renderCell: ({ row }: any) => (\n <Typography variant=\"body2\">\n {CommerceModel.orderChannelLabel(row.channelKey)}\n </Typography>\n ),\n },\n {\n field: 'netCents',\n headerName: 'Total',\n type: 'number',\n width: 150,\n align: 'right',\n headerAlign: 'right',\n renderCell: ({ row }: any) => (\n <Stack sx={{ alignItems: 'flex-end', minWidth: 0, width: 1 }}>\n <Typography variant=\"body2\">\n {`$${(row.netCents / 100).toFixed(2)}`}\n </Typography>\n {row.refundedCents ? (\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {`$${((row.totals?.totalCents ?? row.amountCents ?? 0) / 100).toFixed(2)} less refunds`}\n </Typography>\n ) : null}\n </Stack>\n ),\n },\n {\n field: 'statusKey',\n headerName: 'Status',\n width: 230,\n renderCell: ({ row }: any) => {\n // A lost chargeback leaves `status: 'refunded'` (AGL-1787), so the\n // status pill cannot tell the two apart either — which is why the\n // dispute chip sits beside it rather than being folded into it.\n const dispute: ReturnType<typeof CommerceModel.describeOrderDispute> =\n row.disputeBadge\n return (\n <Stack sx={{ minWidth: 0 }}>\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n <Chip\n label={\n CommerceModel.ORDER_STATUS_LABELS[\n row.statusKey as CommerceModel.OrderStatus\n ] ?? row.statusKey\n }\n size=\"small\"\n color={\n CommerceModel.ORDER_STATUS_COLOR[\n row.statusKey as CommerceModel.OrderStatus\n ] ?? 'default'\n }\n variant=\"outlined\"\n />\n {dispute ? (\n <Tooltip title={dispute.detail}>\n <Chip\n label={dispute.label}\n size=\"small\"\n color={DISPUTE_COLOR[dispute.tone]}\n variant=\"filled\"\n />\n </Tooltip>\n ) : null}\n </Stack>\n {/*\n The deadline on the row itself, while the case is open — the\n one fact on this screen that expires.\n */}\n {dispute?.evidenceDaysLeft !== undefined ? (\n <Typography\n variant=\"caption\"\n component=\"div\"\n color={dispute.evidenceDaysLeft < 0 ? 'error' : 'warning.main'}\n >\n {dispute.evidenceDaysLeft < 0\n ? 'Evidence deadline passed'\n : `Evidence due in ${dispute.evidenceDaysLeft} day${\n dispute.evidenceDaysLeft === 1 ? '' : 's'\n }`}\n </Typography>\n ) : null}\n </Stack>\n )\n },\n },\n {\n field: 'createdAtMs',\n headerName: 'Date',\n width: 130,\n renderCell: ({ row }: any) => {\n const createdAt =\n row.createdAt?.toDate?.() ??\n (row.createdAtMs ? new Date(row.createdAtMs) : null)\n return (\n <Stack sx={{ minWidth: 0 }}>\n <Typography variant=\"body2\" noWrap>\n {createdAt ? createdAt.toLocaleDateString() : '—'}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {createdAt ? createdAt.toLocaleTimeString() : ''}\n </Typography>\n </Stack>\n )\n },\n },\n ],\n [],\n )\n\n\n const columns = useMemo(\n () =>\n listFilterGridColumns(\n orderColumns,\n ORDER_LIST_FIELDS,\n filterOptions,\n ORDER_LIST_HEADERS,\n ),\n [orderColumns, filterOptions],\n )\n\n /*\n * The store is empty only when an UNFILTERED first page came back empty; a\n * filter or search that matches nothing keeps the grid, its chips and its\n * panel, so the reader can take the filter back off.\n */\n const empty =\n listStatus === 'success' &&\n !filtering &&\n askedSort === ORDER_LIST_COLUMN_SORTS[0] &&\n page === 0 &&\n orders.length === 0\n\n return (\n <CardDisplay\n header={'Orders'}\n // Shipping actions live in the card header (AGL-3613): the orders\n // still to ship for a label tool, and its tracking numbers back.\n HeaderProps={{ action: <OrderShippingActions hostId={hostId} /> }}\n help={pluginDocsHelp('commerce', {\n anchor: '#orders-screen',\n excerpt:\n 'Every order with its channel, status and net total. A refunded ' +\n 'order shows what is left, with the gross beneath it.',\n })}\n contentGutterX\n contentGutterY\n >\n {empty ? (\n /*\n * An invitation, not a report (AGL-1805). The \"Draft order\" button\n * used to live in the other arm of this ternary, so the one state a\n * draft order exists for — no sales yet, invoice the customer you\n * already have — was the only state that could not reach it, and\n * every other route into the dialog needs an order to exist first.\n *\n * The filters stay behind deliberately: they belong to a list with\n * rows in it. Export orders likewise — a header-only file is not\n * something a merchant on day one is looking for.\n */\n <Stack spacing={1} sx={{ alignItems: 'flex-start' }}>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {\n 'No orders yet. Storefront sales, POS sales and draft orders ' +\n 'all appear here as they come in.'\n }\n </Typography>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {\n 'Selling to someone directly? Draft their order and send them ' +\n 'a payment link.'\n }\n </Typography>\n <Button\n size=\"small\"\n variant=\"contained\"\n color=\"primary\"\n onClick={openDraft}\n >\n {'Draft order'}\n </Button>\n </Stack>\n ) : (\n <Stack spacing={1}>\n {showStats ? (\n <Stack\n useFlexGap\n direction=\"row\"\n spacing={3}\n sx={{ flexWrap: 'wrap', rowGap: 1 }}\n >\n <CommerceStatTile\n label=\"Revenue · 30d\"\n value={`$${(summary.revenueCents / 100).toFixed(2)}`}\n deltaPct={summary.revenueDeltaPct}\n deltaCaption=\"vs the previous 30 days\"\n />\n <CommerceStatTile\n label=\"Orders · 30d\"\n value={String(summary.orders)}\n deltaPct={summary.ordersDeltaPct}\n deltaCaption=\"vs the previous 30 days\"\n />\n <CommerceStatTile\n label=\"Avg order value\"\n value={`$${(summary.aovCents / 100).toFixed(2)}`}\n deltaPct={summary.aovDeltaPct}\n deltaCaption=\"vs the previous 30 days\"\n />\n </Stack>\n ) : null}\n {showStats && statsWindow.truncated ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`Figures count the ${STATS_ORDER_CEILING} most recent orders of the last 60 days.`}\n </Typography>\n ) : null}\n {openDisputes.count > 0 ? (\n <Alert\n severity={openDisputes.overdue ? 'error' : 'warning'}\n action={\n showingOpenDisputes ? undefined : (\n <Button\n size=\"small\"\n color=\"inherit\"\n onClick={() =>\n setClauses(\n upsertListFilterClause(\n clauses,\n OPEN_DISPUTE_CLAUSE.field,\n OPEN_DISPUTE_CLAUSE,\n ),\n )\n }\n >\n {'Show them'}\n </Button>\n )\n }\n >\n <AlertTitle>\n {moreDisputes\n ? `More than ${OPEN_DISPUTE_CEILING} charges are disputed with the shopper’s bank`\n : openDisputes.count === 1\n ? 'A shopper has disputed a charge with their bank'\n : `${openDisputes.count} charges are disputed with the shopper’s bank`}\n </AlertTitle>\n {openDisputes.soonestDaysLeft === undefined\n ? 'Answer in the Stripe dashboard while the case is open — an unanswered dispute is decided for the shopper.'\n : openDisputes.soonestDaysLeft < 0\n ? 'The evidence deadline has passed on at least one of these. Stripe decides an unanswered dispute for the shopper.'\n : `Evidence is due to Stripe in ${openDisputes.soonestDaysLeft} day${\n openDisputes.soonestDaysLeft === 1 ? '' : 's'\n } on the tightest of these. An unanswered dispute is decided for the shopper.`}\n </Alert>\n ) : null}\n {/*\n The buttons stay beside the grid: Export orders writes every order\n the query matches, with the fields the person picks, which the grid's\n own export — one page — cannot.\n */}\n <Stack\n direction=\"row\"\n spacing={1}\n useFlexGap\n sx={{ alignItems: 'center', justifyContent: 'flex-end', flexWrap: 'wrap' }}\n >\n {checkedIds.length ? (\n <Button\n size=\"small\"\n variant=\"outlined\"\n disabled={bulkBusy || fulfillableCount === 0}\n onClick={handleBulkFulfill}\n >\n {`Mark as fulfilled (${fulfillableCount})`}\n </Button>\n ) : null}\n {/* Other plugins' bulk actions on the ticked orders (AGL-3612). */}\n {checkedIds.length && WidgetSlot ? (\n <WidgetSlot\n slot={ORDERS_BULK_ZONE.id}\n hostId={hostId}\n orgId={undefined}\n selectedOrderIds={checkedIds}\n storeName=\"\"\n />\n ) : null}\n {/* Only for whom the route takes it (AGL-3554). */}\n {transfer?.can('export', { resource: COMMERCE_ORDERS_TRANSFER, scope: 'host', hostId }) ? (\n <Button size=\"small\" onClick={openExport}>\n {'Export orders'}\n </Button>\n ) : null}\n <Button\n size=\"small\"\n variant=\"contained\"\n color=\"primary\"\n onClick={openDraft}\n >\n {'Draft order'}\n </Button>\n </Stack>\n <ListFilterChips\n fields={ORDER_LIST_FIELDS}\n headers={ORDER_LIST_HEADERS}\n clauses={clauses}\n onChange={setClauses}\n options={filterOptions}\n />\n <ListQueryNotices\n refused={refused}\n notices={[...plan.notices, ...columnSort.notices]}\n />\n <ListTable\n aria-label=\"Orders\"\n rows={columnSort.rows}\n columns={columns}\n onOpen={(id) => setSelectedId(id)}\n selectable={{ selected: checkedIds, onChange: setCheckedIds }}\n loading={listStatus === 'loading'}\n /*\n * The grid must NOT also filter, search or sort on its own: the\n * query answers the filters and the search, and every header\n * order is the query's or the page's (`columnSort`).\n */\n filterMode=\"server\"\n filterModel={gridFilter.filterModel}\n onFilterModelChange={gridFilter.onFilterModelChange}\n quickFilter\n columnSort={columnSort}\n // `ListPagination` below pages the query.\n hideFooter\n initialState={{\n columns: { columnVisibilityModel: ORDER_HIDDEN_COLUMNS },\n }}\n noRowsLabel=\"No orders match these filters\"\n />\n <ListPagination\n page={page}\n pageSize={pageSize}\n rowCount={orderRows.length}\n hasMore={hasMore}\n onPageChange={setPage}\n onPageSizeChange={setPageSize}\n />\n </Stack>\n )}\n {selectedOrder ? (\n <OrderDetailDialog\n hostId={hostId}\n order={selectedOrder}\n onClose={() => setSelectedId(null)}\n canSendInvoices={canSendInvoices}\n />\n ) : null}\n <Dialog\n open={Boolean(draft)}\n onClose={() => setDraft(null)}\n maxWidth=\"xs\"\n fullWidth\n >\n <DialogTitle>{'Draft order'}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n {payments.blocked ? (\n <PrerequisiteNotice href={payments.href ?? undefined} actionLabel=\"Open Payments\">\n {`${payments.reason ?? ''} The buyer pays a draft order on a Stripe payment page.`}\n </PrerequisiteNotice>\n ) : null}\n <TextField\n label=\"Product\"\n value={draft?.productId ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev\n ? { ...prev, productId: event.target.value, variantId: '' }\n : prev,\n )\n }\n size=\"small\"\n select\n sx={{ mt: 1 }}\n /*\n * The second dead end behind the first (AGL-1805): a store with\n * no orders may have no products either, and a draft order is\n * composed from one — so \"Create & copy link\" stays disabled. Say\n * why, rather than opening an empty menu onto nothing.\n */\n helperText={\n selectableProducts.length === 0\n ? 'Add a product to this store first — a draft order is built from one.'\n : undefined\n }\n >\n {selectableProducts.map((product: any) => (\n <MenuItem key={product.$id} value={product.$id}>\n {product.name ?? product.$id}\n </MenuItem>\n ))}\n </TextField>\n {(() => {\n const product = productWindow.rows.find(\n (item: any) => item.$id === draft?.productId,\n )\n const variants = product\n ? CommerceModel.liftLegacyProduct(product).variants\n : []\n return variants.length > 1 ? (\n <TextField\n label=\"Variant\"\n value={draft?.variantId ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev ? { ...prev, variantId: event.target.value } : prev,\n )\n }\n size=\"small\"\n select\n >\n {variants.map((variant) => (\n <MenuItem key={variant.id} value={variant.id}>\n {`${Object.values(variant.options ?? {}).join(' / ') || 'Default'} — $${variant.priceUsd}`}\n </MenuItem>\n ))}\n </TextField>\n ) : null\n })()}\n <TextField\n label=\"Quantity\"\n value={draft?.quantity ?? '1'}\n onChange={(event) =>\n setDraft((prev) =>\n prev\n ? {\n ...prev,\n quantity: event.target.value.replace(/[^0-9]/g, ''),\n }\n : prev,\n )\n }\n size=\"small\"\n slotProps={{ htmlInput: { inputMode: 'numeric' } }}\n />\n <TextField\n label=\"Buyer email (optional)\"\n value={draft?.email ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev ? { ...prev, email: event.target.value } : prev,\n )\n }\n size=\"small\"\n />\n {draft?.shipCountries?.length ? (\n <TextField\n label=\"Ships to\"\n value={draft?.shipTo ?? ''}\n onChange={(event) =>\n setDraft((prev) =>\n prev ? { ...prev, shipTo: event.target.value } : prev,\n )\n }\n size=\"small\"\n select\n helperText={\n 'This store’s shipping rates differ by destination, so the ' +\n 'payment link has to be priced for one.'\n }\n >\n {draft.shipCountries.map((code) => (\n <MenuItem key={code} value={code}>\n {CommerceModel.CHECKOUT_SHIPPING_COUNTRY_NAMES[code] ?? code}\n </MenuItem>\n ))}\n </TextField>\n ) : null}\n {draft?.askPostal ? (\n <TextField\n label=\"Postal code\"\n value={draft?.shipPostal ?? ''}\n onChange={(event) =>\n setDraft((prev) => (prev ? { ...prev, shipPostal: event.target.value } : prev))\n }\n size=\"small\"\n helperText=\"This store prices shipping by carrier, which needs the postal code.\"\n />\n ) : null}\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setDraft(null)}>{'Cancel'}</Button>\n <BlockedControl blocked={payments.blocked} reason={payments.reason ?? ''}>\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={\n !draft?.productId ||\n draft?.busy ||\n // Once asked, the answer is required: retrying without one is\n // refused again, so the button would only look broken.\n Boolean(draft?.shipCountries?.length && !draft?.shipTo) ||\n Boolean(draft?.askPostal && !draft?.shipPostal?.trim())\n }\n onClick={handleDraftCreate}\n >\n {'Create & copy link'}\n </Button>\n </BlockedControl>\n </DialogActions>\n </Dialog>\n </CardDisplay>\n )\n}\nHostOrdersCard.displayName = 'HostOrdersCard'\n\nexport default HostOrdersCard\n"],"names":["CommerceModel","CardDisplay","ListFilterChips","ListPagination","ListQueryNotices","listQueryRefusals","ListTable","hiddenFilterVisibility","useListColumnSort","listFilterGridColumns","upsertListFilterClause","useListGridFilter","useSnackbar","checkEntitlement","pluginDocsHelp","ORDERS_CUSTOMER_PARAM","ORDERS_ORDER_PARAM","Alert","AlertTitle","Button","Chip","Dialog","DialogActions","DialogContent","DialogTitle","MenuItem","Stack","TextField","Tooltip","Typography","collection","doc","getDoc","limit","orderBy","query","where","useSearchParams","useCallback","useEffect","useMemo","useRef","useState","ceilingedWindow","collectionCeiling","useFirestore","useMerchantPayments","useOrgPlan","useUser","BlockedControl","PrerequisiteNotice","useFirestoreCollection","useListQuery","useTransferLauncher","commerceListFilter","COMMERCE_ORDERS_TRANSFER","OrderShippingActions","authorizedFetch","OPEN_DISPUTE_CLAUSE","ORDER_CHANNEL_OPTIONS","ORDER_LIST_COLUMN_SORTS","ORDER_DISPUTE_OPTIONS","ORDER_LIST_FIELDS","ORDER_LIST_HEADERS","ORDER_LIST_QUERY","ORDER_LIST_SELECT_FIELDS","ORDER_STATUS_OPTIONS","ordersCustomerClause","CommerceStatTile","bulkFulfillOrders","BULK_FULFILLABLE_STATUSES","describeBulkFulfill","ORDERS_BULK_ZONE","useConsoleWidgetSlot","OrderDetailDialog","DISPUTE_COLOR","PRODUCT_NAME_WINDOW","OPEN_DISPUTE_CEILING","STATS_WINDOW_MS","STATS_ORDER_CEILING","ORDER_VISIBLE_COLUMNS","ORDER_HIDDEN_COLUMNS","ORDER_PAGE_SORTS","netCents","row","ORDER_PAGE_SORT_HEADERS","HostOrdersCard","props","loadedOrders","payments","draft","hostId","canSendInvoices","firestore","ordersRef","data","productDocs","idField","productWindow","undefined","productNames","map","product","rows","$id","name","org","ready","orgReady","showStats","searchParams","clauses","setClauses","customer","get","gridFilter","onChange","selectFields","filtering","length","searchWords","some","word","trim","askedSort","setAskedSort","disputedRows","hasMore","moreDisputes","declaration","request","deps","pageSize","confirmDisappearances","orders","page","setPage","setPageSize","plan","status","listStatus","search","sort","selectedId","setSelectedId","checkedIds","setCheckedIds","bulkBusy","setBulkBusy","WidgetSlot","seededOrderId","seededOrder","setSeededOrder","seededOpened","current","order","then","snapshot","id","exists","catch","setDraft","user","enqueueSnackbar","orderRows","filter","isUnpaidQuote","lifted","liftLegacyOrder","orderLabel","formatOrderNumber","itemName","lineItems","productId","statusKey","channelKey","channel","orderNetCents","disputeBadge","describeOrderDispute","columnSort","sorts","defaultSort","onSortChange","pageSorts","headers","productOptions","value","String","label","filterOptions","productIds","disputeKey","refused","fields","options","showingOpenDisputes","clause","field","op","openDisputes","summariseOpenDisputes","statsSince","Date","now","statsDocs","statsWindow","summary","summarizeOrderWindow","nowMs","transfer","openExport","resource","scope","draftAttemptKey","variantId","quantity","email","shipTo","shipPostal","handleDraftCreate","prev","busy","globalThis","crypto","randomUUID","Math","random","toString","slice","response","method","body","JSON","stringify","Number","shippingCountry","shippingPostalCode","payload","json","ok","needsShippingCountry","shipCountries","shippingCountries","CHECKOUT_SHIPPING_COUNTRIES","needsShippingPostalCode","askPostal","error","variant","allowDuplicate","navigator","clipboard","writeText","url","persist","checkedOrders","includes","fulfillableCount","handleBulkFulfill","batchKey","result","unknown","selectedOrder","find","openDraft","selectableProducts","deletedAt","orderColumns","headerName","flex","minWidth","renderCell","extraItems","max","sx","noWrap","color","customerEmail","width","orderChannelLabel","type","align","headerAlign","alignItems","toFixed","refundedCents","totals","totalCents","amountCents","dispute","direction","spacing","ORDER_STATUS_LABELS","size","ORDER_STATUS_COLOR","title","detail","tone","evidenceDaysLeft","component","createdAt","toDate","createdAtMs","toLocaleDateString","toLocaleTimeString","columns","empty","header","HeaderProps","action","help","anchor","excerpt","contentGutterX","contentGutterY","onClick","useFlexGap","flexWrap","rowGap","revenueCents","deltaPct","revenueDeltaPct","deltaCaption","ordersDeltaPct","aovCents","aovDeltaPct","truncated","count","severity","overdue","soonestDaysLeft","justifyContent","disabled","slot","orgId","selectedOrderIds","storeName","can","notices","aria-label","onOpen","selectable","selected","loading","filterMode","filterModel","onFilterModelChange","quickFilter","hideFooter","initialState","columnVisibilityModel","noRowsLabel","rowCount","onPageChange","onPageSizeChange","onClose","open","Boolean","maxWidth","fullWidth","display","flexDirection","gap","blocked","href","actionLabel","reason","event","target","select","mt","helperText","item","variants","liftLegacyProduct","Object","values","join","priceUsd","replace","slotProps","htmlInput","inputMode","code","CHECKOUT_SHIPPING_COUNTRY_NAMES","displayName"],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import * as CommerceModel from '../../model';
18
+ /**
19
+ * The order's (or the quote's) last invoice email, as the console says it:
20
+ * `Invoice sent Oct 29, 2026, 3:04 PM to jordan@example.com.` Null when none
21
+ * was sent.
22
+ */
23
+ export declare function invoiceSentLine(order: Pick<CommerceModel.HostOrder, 'invoiceSends'>): string | null;
24
+ export interface InvoiceSendDialogProps {
25
+ open: boolean;
26
+ onClose: () => void;
27
+ hostId: string;
28
+ orderId: string;
29
+ order: CommerceModel.HostOrder;
30
+ }
31
+ /**
32
+ * Send invoice (AGL-4099), for an order or a quote: a short form (To,
33
+ * Subject, Message) that emails the invoice in the site's look with the
34
+ * invoice PDF attached. Unpaid, the email carries a Pay button to the order's
35
+ * lasting pay link on the business's site; paid, it is the customer's record.
36
+ * A quote's invoice lands in the quote's conversation, and an order's in its
37
+ * own. The site's name and contact email are read once when the form opens,
38
+ * so the dialog that offers it listens to nothing more.
39
+ */
40
+ export declare function InvoiceSendDialog(props: InvoiceSendDialogProps): import("react").JSX.Element;
41
+ export declare namespace InvoiceSendDialog {
42
+ var displayName: string;
43
+ }
44
+ export default InvoiceSendDialog;