@aglyn/plugins-commerce 1.0.0-beta.259 → 1.0.0-beta.260
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +13 -13
- package/src/lib/components/console/host-orders-card.component.js +24 -10
- package/src/lib/components/console/host-orders-card.component.js.map +1 -1
- package/src/lib/components/console/payments-settings-card.component.js +16 -7
- package/src/lib/components/console/payments-settings-card.component.js.map +1 -1
- package/src/lib/components/console/pos/pos-tender-panel.component.js +67 -33
- package/src/lib/components/console/pos/pos-tender-panel.component.js.map +1 -1
- package/src/lib/components/console/product-editor-dialog.component.js +4 -0
- package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
- package/src/lib/components/console/reservations-card.component.js +12 -2
- package/src/lib/components/console/reservations-card.component.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aglyn/plugins-commerce",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.260",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://aglyn.com",
|
|
6
6
|
"repository": {
|
|
@@ -25,18 +25,18 @@
|
|
|
25
25
|
"./package.json": "./package.json"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@aglyn/aglyn": "1.0.0-beta.
|
|
29
|
-
"@aglyn/shared-data-mdi": "1.0.0-beta.
|
|
30
|
-
"@aglyn/shared-ui-jsx": "1.0.0-beta.
|
|
31
|
-
"@aglyn/shared-ui-next": "1.0.0-beta.
|
|
32
|
-
"@aglyn/shared-ui-snackstack": "1.0.0-beta.
|
|
33
|
-
"@aglyn/shared-util-email": "1.0.0-beta.
|
|
34
|
-
"@aglyn/shared-util-http": "1.0.0-beta.
|
|
35
|
-
"@aglyn/shared-util-timestamp": "1.0.0-beta.
|
|
36
|
-
"@aglyn/shared-util-tools": "1.0.0-beta.
|
|
37
|
-
"@aglyn/tenant-data-admin": "1.0.0-beta.
|
|
38
|
-
"@aglyn/tenant-feature-instance": "1.0.0-beta.
|
|
39
|
-
"@aglyn/tenant-runtime": "1.0.0-beta.
|
|
28
|
+
"@aglyn/aglyn": "1.0.0-beta.260",
|
|
29
|
+
"@aglyn/shared-data-mdi": "1.0.0-beta.260",
|
|
30
|
+
"@aglyn/shared-ui-jsx": "1.0.0-beta.260",
|
|
31
|
+
"@aglyn/shared-ui-next": "1.0.0-beta.260",
|
|
32
|
+
"@aglyn/shared-ui-snackstack": "1.0.0-beta.260",
|
|
33
|
+
"@aglyn/shared-util-email": "1.0.0-beta.260",
|
|
34
|
+
"@aglyn/shared-util-http": "1.0.0-beta.260",
|
|
35
|
+
"@aglyn/shared-util-timestamp": "1.0.0-beta.260",
|
|
36
|
+
"@aglyn/shared-util-tools": "1.0.0-beta.260",
|
|
37
|
+
"@aglyn/tenant-data-admin": "1.0.0-beta.260",
|
|
38
|
+
"@aglyn/tenant-feature-instance": "1.0.0-beta.260",
|
|
39
|
+
"@aglyn/tenant-runtime": "1.0.0-beta.260",
|
|
40
40
|
"@stripe/react-stripe-js": "^6.12.0",
|
|
41
41
|
"@stripe/stripe-js": "^9.17.0",
|
|
42
42
|
"@swc/helpers": "0.5.23",
|
|
@@ -33,7 +33,9 @@ import { Alert, AlertTitle, Button, Chip, Dialog, DialogActions, DialogContent,
|
|
|
33
33
|
import { collection, doc, getDoc, limit, orderBy, query, where } from "firebase/firestore";
|
|
34
34
|
import { useSearchParams } from "next/navigation";
|
|
35
35
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
36
|
-
import { ceilingedWindow, collectionCeiling, useFirestore, useOrgPlan, useUser } from "@aglyn/tenant-feature-instance";
|
|
36
|
+
import { ceilingedWindow, collectionCeiling, useFirestore, useMerchantPayments, useOrgPlan, useUser } from "@aglyn/tenant-feature-instance";
|
|
37
|
+
import { BlockedControl } from "@aglyn/shared-ui-jsx/components/blocked-control.component";
|
|
38
|
+
import { PrerequisiteNotice } from "@aglyn/shared-ui-jsx/components/prerequisite-notice.component";
|
|
37
39
|
import { useFirestoreCollection } from "@aglyn/tenant-feature-instance";
|
|
38
40
|
import { useListQuery } from "@aglyn/tenant-feature-instance/hooks/use-list-query";
|
|
39
41
|
import { useTransferLauncher } from "@aglyn/aglyn/app-utils/transfer-launcher-context";
|
|
@@ -94,7 +96,7 @@ const ORDER_PAGE_SORT_HEADERS = {
|
|
|
94
96
|
* pages that query's answer. A combination one query cannot hold is refused
|
|
95
97
|
* by name above the grid and never applied to some rows only.
|
|
96
98
|
*/ export function HostOrdersCard(props) {
|
|
97
|
-
var _ref, _loadedOrders_find, _ref1, _ref2, _ref3, _ref4, _ref5;
|
|
99
|
+
var _ref, _loadedOrders_find, _payments_href, _payments_reason, _ref1, _ref2, _ref3, _ref4, _ref5, _payments_reason1;
|
|
98
100
|
var _draft_shipCountries, _draft_shipCountries1, _draft_shipPostal;
|
|
99
101
|
const { hostId } = props;
|
|
100
102
|
const firestore = useFirestore();
|
|
@@ -129,6 +131,9 @@ const ORDER_PAGE_SORT_HEADERS = {
|
|
|
129
131
|
* them. The TABLE below is not gated — a list of your own orders is not
|
|
130
132
|
* a paid feature.
|
|
131
133
|
*/ const { org, ready: orgReady } = useOrgPlan(hostId);
|
|
134
|
+
// A draft order's link is a Stripe payment page, so it needs the store's
|
|
135
|
+
// Stripe account; the dialog says so before Create rather than after.
|
|
136
|
+
const payments = useMerchantPayments(hostId);
|
|
132
137
|
const showStats = orgReady && checkEntitlement(org, 'commerceAnalytics');
|
|
133
138
|
/*
|
|
134
139
|
* The grid's clauses (AGL-96, AGL-3317), held here so two things outside
|
|
@@ -878,6 +883,11 @@ const ORDER_PAGE_SORT_HEADERS = {
|
|
|
878
883
|
gap: 2
|
|
879
884
|
},
|
|
880
885
|
children: [
|
|
886
|
+
payments.blocked ? /*#__PURE__*/ _jsx(PrerequisiteNotice, {
|
|
887
|
+
href: (_payments_href = payments.href) != null ? _payments_href : undefined,
|
|
888
|
+
actionLabel: "Open Payments",
|
|
889
|
+
children: `${(_payments_reason = payments.reason) != null ? _payments_reason : ''} The buyer pays a draft order on a Stripe payment page.`
|
|
890
|
+
}) : null,
|
|
881
891
|
/*#__PURE__*/ _jsx(TextField, {
|
|
882
892
|
label: "Product",
|
|
883
893
|
value: (_ref1 = draft == null ? void 0 : draft.productId) != null ? _ref1 : '',
|
|
@@ -980,14 +990,18 @@ const ORDER_PAGE_SORT_HEADERS = {
|
|
|
980
990
|
onClick: ()=>setDraft(null),
|
|
981
991
|
children: 'Cancel'
|
|
982
992
|
}),
|
|
983
|
-
/*#__PURE__*/ _jsx(
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
993
|
+
/*#__PURE__*/ _jsx(BlockedControl, {
|
|
994
|
+
blocked: payments.blocked,
|
|
995
|
+
reason: (_payments_reason1 = payments.reason) != null ? _payments_reason1 : '',
|
|
996
|
+
children: /*#__PURE__*/ _jsx(Button, {
|
|
997
|
+
variant: "contained",
|
|
998
|
+
color: "primary",
|
|
999
|
+
disabled: !(draft == null ? void 0 : draft.productId) || (draft == null ? void 0 : draft.busy) || // Once asked, the answer is required: retrying without one is
|
|
1000
|
+
// refused again, so the button would only look broken.
|
|
1001
|
+
Boolean((draft == null ? void 0 : (_draft_shipCountries1 = draft.shipCountries) == null ? void 0 : _draft_shipCountries1.length) && !(draft == null ? void 0 : draft.shipTo)) || Boolean((draft == null ? void 0 : draft.askPostal) && !(draft == null ? void 0 : (_draft_shipPostal = draft.shipPostal) == null ? void 0 : _draft_shipPostal.trim())),
|
|
1002
|
+
onClick: handleDraftCreate,
|
|
1003
|
+
children: 'Create & copy link'
|
|
1004
|
+
})
|
|
991
1005
|
})
|
|
992
1006
|
]
|
|
993
1007
|
})
|
|
@@ -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 useOrgPlan,\n useUser,\n} from '@aglyn/tenant-feature-instance'\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 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.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 <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 <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 </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","useOrgPlan","useUser","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","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","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","filter","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","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\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.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","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","filter","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":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;AAEA,YAAYA,mBAAmB,uBAAa;AAC5C,SAASC,WAAW,QAAQ,uBAAsB;AAClD,OAAOC,qBAAqB,8DAA6D;AACzF,SAASC,cAAc,QAAQ,4DAA2D;AAC1F,SACEC,gBAAgB,EAChBC,iBAAiB,QACZ,+DAA8D;AACrE,SAASC,SAAS,QAAQ,uDAAsD;AAChF,SAASC,sBAAsB,QAAQ,yCAAwC;AAE/E,SAASC,iBAAiB,QAAQ,kDAAiD;AACnF,SAEEC,qBAAqB,EACrBC,sBAAsB,QACjB,8CAA6C;AACpD,SAASC,iBAAiB,QAAQ,kDAAiD;AACnF,SAASC,WAAW,QAAQ,8BAA6B;AACzD,SAASC,gBAAgB,EAAEC,cAAc,QAAQ,eAAc;AAC/D,SAASC,qBAAqB,EAAEC,kBAAkB,QAAQ,wCAAoC;AAC9F,SACEC,KAAK,EACLC,UAAU,EACVC,MAAM,EACNC,IAAI,EACJC,MAAM,EACNC,aAAa,EACbC,aAAa,EACbC,WAAW,EACXC,QAAQ,EACRC,KAAK,EACLC,SAAS,EACTC,OAAO,EACPC,UAAU,QACL,gBAAe;AAEtB,SACEC,UAAU,EACVC,GAAG,EACHC,MAAM,EACNC,KAAK,EACLC,OAAO,EACPC,KAAK,EACLC,KAAK,QACA,qBAAoB;AAC3B,SAASC,eAAe,QAAQ,kBAAiB;AACjD,SAASC,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,QAAO;AACzE,SACEC,eAAe,EACfC,iBAAiB,EACjBC,YAAY,EACZC,mBAAmB,EACnBC,UAAU,EACVC,OAAO,QACF,iCAAgC;AACvC,SAASC,cAAc,QAAQ,4DAA2D;AAC1F,SAASC,kBAAkB,QAAQ,gEAA+D;AAClG,SAASC,sBAAsB,QAAQ,iCAAgC;AACvE,SAASC,YAAY,QAAQ,sDAAqD;AAClF,SAASC,mBAAmB,QAAQ,mDAAkD;AACtF,SAASC,kBAAkB,QAAQ,gCAA4B;AAC/D,SAASC,wBAAwB,QAAQ,kCAA8B;AACvE,OAAOC,0BAA0B,wCAAoC;AACrE,SAASC,eAAe,QAAQ,2CAA0C;AAE1E,SACEC,mBAAmB,EACnBC,qBAAqB,EACrBC,uBAAuB,EACvBC,qBAAqB,EACrBC,iBAAiB,EACjBC,kBAAkB,EAClBC,gBAAgB,EAChBC,wBAAwB,EACxBC,oBAAoB,EACpBC,oBAAoB,QACf,uCAAmC;AAC1C,OAAOC,sBAAsB,oCAAgC;AAC7D,SAASC,iBAAiB,EAAEC,yBAAyB,EAAEC,mBAAmB,QAAQ,oBAAgB;AAClG,SAASC,gBAAgB,QAAQ,mBAAe;AAChD,SAASC,oBAAoB,QAAQ,qDAAoD;AACzF,OAAOC,qBACLC,aAAa,QACR,qCAAiC;AAExC;;;;;CAKC,GACD,MAAMC,sBAAsB;AAE5B;;;;;CAKC,GACD,MAAMC,uBAAuB;AAE7B;;;;CAIC,GACD,MAAMC,kBAAkB,KAAK,KAAK,KAAK,KAAK;AAC5C,MAAMC,sBAAsB;AAE5B,sFAAsF,GACtF,MAAMC,wBAAwB;IAC5B;IACA;IACA;IACA;IACA;CACD;AACD,MAAMC,uBAAuB1E,uBAC3BuD,mBACAkB;AAOF,mFAAmF,GACnF,MAAME,mBAAmB;IACvBC,UAAU,CAACC,MAA8BA,IAAID,QAAQ;AACvD;AACA,MAAME,0BAA0B;IAAEF,UAAU;AAAQ;AAEpD;;;;;;;;;;;;;;CAcC,GACD,OAAO,SAASG,eAAeC,KAA0B;cAobrDC,oBAoakCC,gBACpBA,qDA4H2CA;QArClDC,sBA8CaA,uBACqBA;IA99B3C,MAAM,EAAEC,MAAM,EAAE,GAAGJ;IACnB,MAAMK,YAAY/C;IAClB,MAAMgD,YAAYrD,QAChB,IAAMV,WAAW8D,WAAW,SAASD,QAAQ,WAC7C;QAACC;QAAWD;KAAO;IAErB,MAAM,EAAEG,MAAMC,WAAW,EAAE,GAAG5C,uBAC5B,IACEP,kBACEd,WAAW8D,WAAW,SAASD,QAAQ,aACvCf,sBAEJ;QAACgB;QAAWD;KAAO,EACnB;QAAEK,SAAS;IAAM;IAEnB,MAAMC,gBAAgBzD,QACpB,IAAMG,gBAAqBoD,sBAAAA,cAAeG,WAAWtB,sBACrD;QAACmB;KAAY;IAEf,MAAMI,eAAe3D,QAAQ;QAC3B,MAAM4D,MAA8B,CAAC;QACrC,KAAK,MAAMC,WAAWJ,cAAcK,IAAI,CAAE;gBACrBD;YAAnBD,GAAG,CAACC,QAAQE,GAAG,CAAC,IAAGF,gBAAAA,QAAQG,IAAI,YAAZH,gBAAgBA,QAAQE,GAAG;QAChD;QACA,OAAOH;IACT,GAAG;QAACH;KAAc;IAElB;;;;;;;GAOC,GACD,MAAM,EAAEQ,GAAG,EAAEC,OAAOC,QAAQ,EAAE,GAAG5D,WAAW4C;IAC5C,yEAAyE;IACzE,sEAAsE;IACtE,MAAMF,WAAW3C,oBAAoB6C;IACrC,MAAMiB,YACJD,YAAY9F,iBAAiB4F,KAAc;IAE7C;;;;;;GAMC,GACD,MAAMI,eAAexE;IACrB,MAAM,CAACyE,SAASC,WAAW,GAAGrE,SAA6B;;QACzD,MAAMsE,WAAW7C,6BACf0C,gCAAAA,aAAcI,GAAG,CAAClG,yCAA0B;QAE9C,OAAOiG,WAAW;YAACA;SAAS,GAAG,EAAE;IACnC;IACA,MAAME,aAAavG,kBAAkB;QACnCmG;QACAK,UAAUJ;QACVK,cAAcnD;IAChB;IACA,MAAMoD,YACJP,QAAQQ,MAAM,GAAG,KAAKJ,WAAWK,WAAW,CAACC,IAAI,CAAC,CAACC,OAASA,KAAKC,IAAI;IACvE;;;;;;;GAOC,GACD,MAAM,CAACC,WAAWC,aAAa,GAAGlF,SAChCkB,uBAAuB,CAAC,EAAE;IAG5B;;;;;;GAMC,GACD,MAAM,EACJ0C,MAAMuB,YAAY,EAClBC,SAASC,YAAY,EACtB,GAAG3E,aAAkB;QACpBtB,YAAY+D;QACZmC,aAAahE;QACbiE,SAAS;YAAEnB,SAAS;gBAACpD;aAAoB;QAAC;QAC1CwE,MAAM;YAACtC;YAAWD;SAAO;QACzBK,SAAS;QACTmC,UAAUtD;QACV,2EAA2E;QAC3EuD,uBAAuB;IACzB;IAEA;;;;;GAKC,GACD,MAAM,EACJ9B,MAAM+B,MAAM,EACZvC,MAAMN,YAAY,EAClBsC,OAAO,EACPQ,IAAI,EACJC,OAAO,EACPJ,QAAQ,EACRK,WAAW,EACXC,IAAI,EACJC,QAAQC,UAAU,EACnB,GAAGvF,aAAkB;QACpBtB,YAAY+D;QACZmC,aAAahE;QACbiE,SAAS;YAAEnB;YAAS8B,QAAQ1B,WAAWK,WAAW;YAAEsB,MAAMlB;QAAU;QACpEO,MAAM;YAACtC;YAAWD;SAAO;QACzBK,SAAS;QACToC,uBAAuB;IACzB;IAEA,MAAM,CAACU,YAAYC,cAAc,GAAGrG,SAAwB;IAC5D,wEAAwE;IACxE,MAAM,CAACsG,YAAYC,cAAc,GAAGvG,SAAmB,EAAE;IACzD,MAAM,CAACwG,UAAUC,YAAY,GAAGzG,SAAS;IACzC,MAAM0G,aAAa3E;IACnB;;;;;;;;;;;;GAYC,GACD,MAAM4E,wBAAgBxC,gCAAAA,aAAcI,GAAG,CAACjG,sCAAuB;IAC/D,MAAM,CAACsI,aAAaC,eAAe,GAAG7G,SAAqB;IAC3D,MAAM8G,eAAe/G,OAAsB;IAC3CF,UAAU;QACR,IAAI,CAAC8G,iBAAiBG,aAAaC,OAAO,KAAKJ,eAAe;QAC9D,IAAIV,eAAe,WAAW;QAC9Ba,aAAaC,OAAO,GAAGJ;QACvBN,cAAcM;QACd,IAAI7D,aAAagC,IAAI,CAAC,CAACkC,QAAeA,MAAMnD,GAAG,KAAK8C,gBAAgB;QACpE,KAAKrH,OAAOD,IAAI6D,WAAW,SAASD,QAAQ,UAAU0D,gBACnDM,IAAI,CAAC,CAACC;YACL,IAAIJ,aAAaC,OAAO,KAAKG,SAASC,EAAE,IAAI,CAACD,SAASE,MAAM,IAAI;YAChEP,eAAe,aAAKK,SAAS9D,IAAI;gBAAIS,KAAKqD,SAASC,EAAE;;QACvD,GACCE,KAAK,CAAC,IAAM7D;IACjB,GAAG;QAACmD;QAAe7D;QAAcmD;QAAY/C;QAAWD;KAAO;IAC/D,MAAM,CAACD,OAAOsE,SAAS,GAAGtH,SAiBhB;IACV,MAAM,EAAEoD,MAAMmE,IAAI,EAAE,GAAGjH;IACvB,MAAM,EAAEkH,eAAe,EAAE,GAAGtJ;IAC5B;;;;;;GAMC,GACD,MAAMuJ,YAAY3H,QAChB,IACE6F,OAAOjC,GAAG,CAAC,CAACsD;gBAMNU,MAAAA,cAKUA;gBALVA,oBAAAA;YALJ,MAAMA,SAASpK,cAAcqK,eAAe,CAACX;YAC7C,OAAO,aACFA;gBACHY,YAAYtK,cAAcuK,iBAAiB,CAACH,QAAQV,MAAMnD,GAAG;gBAC7DiE,QAAQ,GACNJ,QAAAA,kBAAAA,oBAAAA,OAAOK,SAAS,sBAAhBL,qBAAAA,iBAAkB,CAAC,EAAE,qBAArBA,mBAAuB5D,IAAI,oBAC3BL,YAAY,CAACuD,MAAMgB,SAAS,CAAC,YAD7BN,QAEAV,MAAMgB,SAAS,YAFfN,OAGA;gBACFO,WAAWP,OAAO1B,MAAM;gBACxBkC,UAAU,GAAER,kBAAAA,OAAOS,OAAO,YAAdT,kBAAkB;gBAC9BjF,UAAUnF,cAAc8K,aAAa,CAACV;gBACtCW,cAAc/K,cAAcgL,oBAAoB,CAACZ;;QAErD,IACF;QAAC/B;QAAQlC;KAAa;IAExB,MAAM8E,aAAazK,kBAAkB;QACnC0K,OAAOtH;QACPuH,aAAavH,uBAAuB,CAAC,EAAE;QACvCiF,MAAMlB;QACNyD,cAAcxD;QACd1F,SAASuG,KAAKvG,OAAO;QACrBoE,MAAM6D;QACNkB,WAAWnG;QACXoG,SAASjG;IACX;IACA,MAAMkG,iBAAiB/I,QACrB,IACEyD,cAAcK,IAAI,CAACF,GAAG,CAAC,CAACC;gBAERA;mBAF0B;gBACxCmF,OAAOC,OAAOpF,QAAQE,GAAG;gBACzBmF,OAAOD,QAAOpF,gBAAAA,QAAQG,IAAI,YAAZH,gBAAgBA,QAAQE,GAAG;YAC3C;YACF;QAACN;KAAc;IAEjB,MAAM0F,gBAAgBnJ,QACpB,IAAO,CAAA;YACLmI,WAAWzG;YACX0G,YAAYjH;YACZiI,YAAYL;YACZM,YAAYhI;QACd,CAAA,GACA;QAAC0H;KAAe;IAElB,MAAMO,UAAUtJ,QACd,IACEnC,kBAAkBoI,KAAKqD,OAAO,EAAE;YAC9BC,QAAQjI;YACRwH,SAASvH;YACTiI,SAASL;QACX,IACF;QAAClD;QAAMkD;KAAc;IAEvB,MAAMM,sBAAsBnF,QAAQU,IAAI,CACtC,CAAC0E,SACCA,OAAOC,KAAK,KAAKzI,oBAAoByI,KAAK,IAC1CD,OAAOE,EAAE,KAAK1I,oBAAoB0I,EAAE,IACpCF,OAAOV,KAAK,KAAK9H,oBAAoB8H,KAAK;IAG9C,MAAMa,eAAe7J,QACnB,IACExC,cAAcsM,qBAAqB,CACjCzE,aAAazB,GAAG,CAAC,CAACsD,QAAe1J,cAAcqK,eAAe,CAACX,UAEnE;QAAC7B;KAAa;IAGhB;;;;;;GAMC,GACD,MAAM0E,aAAa/J,QAAQ,IAAMgK,KAAKC,GAAG,KAAK3H,iBAAiB,EAAE;IACjE,MAAM,EAAEgB,MAAM4G,SAAS,EAAE,GAAGvJ,uBAC1B,IACEyD,YACIzE,MACE0D,WACAzD,MAAM,eAAe,MAAMmK,aAC3BrK,QAAQ,eAAe,SACvBD,MAAM8C,sBAAsB,MAE9B,MACN;QAACa;QAAWD;QAAQiB;QAAW2F;KAAW,EAC1C;QAAEvG,SAAS;IAAM;IAEnB,MAAM2G,cAAcnK,QAClB,IAAMG,gBAAqB+J,oBAAAA,YAAaxG,WAAWnB,sBACnD;QAAC2H;KAAU;IAEb,MAAME,UAAUpK,QACd,IACExC,cAAc6M,oBAAoB,CAACF,YAAYrG,IAAI,EAAE;YAAEwG,OAAON,KAAKC,GAAG;QAAG,IAC3E;QAACE;KAAY;IAGf;;;;;;GAMC,GACD,MAAMI,WAAW1J;IACjB,MAAM2J,aAAa1K,YAAY;QAC7ByK,4BAAAA,SAAUC,UAAU,CAAC;YACnBC,UAAU1J;YACV2J,OAAO;YACPvH;WACI0B,YACA;YACE8F,QAAQ;gBACNzB,OAAO;gBACPF,OAAOlI,mBAAmBmF;YAC5B;QACF,IACA,CAAC;IAET,GAAG;QAACsE;QAAUpH;QAAQ0B;QAAWoB;KAAK;IAEtC;;;;;;;;;;;GAWC,GACD,MAAM2E,kBAAkB3K,OAAO;IAC/BF,UAAU;QACR6K,gBAAgB3D,OAAO,GAAG;IAC5B,GAAG;QACD/D,yBAAAA,MAAOgF,SAAS;QAChBhF,yBAAAA,MAAO2H,SAAS;QAChB3H,yBAAAA,MAAO4H,QAAQ;QACf5H,yBAAAA,MAAO6H,KAAK;QACZ7H,yBAAAA,MAAO8H,MAAM;QACb9H,yBAAAA,MAAO+H,UAAU;KAClB;IAED,MAAMC,oBAAoBpL,YAAY;QACpC,IAAI,EAACoD,yBAAAA,MAAOgF,SAAS,GAAE;QACvBV,SAAS,CAAC2D,OAAUA,OAAO,aAAKA;gBAAMC,MAAM;iBAASD;QACrD,IAAI;gBA6BQjI;YA5BV,IAAI,CAAC0H,gBAAgB3D,OAAO,EAAE;;oBAE1BoE,+BAAAA;gBADFT,gBAAgB3D,OAAO,YACrBoE,qBAAAA,WAAWC,MAAM,sBAAjBD,gCAAAA,mBAAmBE,UAAU,qBAA7BF,mCAAAA,sCACA,GAAGrB,KAAKC,GAAG,GAAG,CAAC,EAAEuB,KAAKC,MAAM,GAAGC,QAAQ,CAAC,IAAIC,KAAK,CAAC,IAAI;YAC1D;YACA,MAAMC,WAAW,MAAM3K,gBACrBwG,MACA,6BACA;gBACEoE,QAAQ;gBACR/C,SAAS;oBACP,gBAAgB;oBAChB,yDAAyD;oBACzD,mDAAmD;oBACnD,mBAAmB8B,gBAAgB3D,OAAO;gBAC5C;gBACA6E,MAAMC,KAAKC,SAAS,CAAC;oBACnB7I;oBACA+E,WAAWhF,MAAMgF,SAAS;oBAC1B2C,WAAW3H,MAAM2H,SAAS,IAAInH;oBAC9BoH,UAAUmB,OAAO/I,MAAM4H,QAAQ,KAAK;oBACpCC,OAAO7H,MAAM6H,KAAK,IAAIrH;mBAMlBR,MAAM8H,MAAM,GAAG;oBAAEkB,iBAAiBhJ,MAAM8H,MAAM;gBAAC,IAAI,CAAC,GACpD9H,EAAAA,oBAAAA,MAAM+H,UAAU,qBAAhB/H,kBAAkBgC,IAAI,MAAK;oBAAEiH,oBAAoBjJ,MAAM+H,UAAU,CAAC/F,IAAI;gBAAG,IAAI,CAAC;YAEtF;YAEF,MAAMkH,UAAU,MAAMR,SAASS,IAAI;YACnC,IAAI,CAACT,SAASU,EAAE,EAAE;;gBAChB,qEAAqE;gBACrE,uEAAuE;gBACvE,mEAAmE;gBACnE,8DAA8D;gBAC9D,IAAIF,2BAAAA,QAASG,oBAAoB,EAAE;oBACjC/E,SAAS,CAAC2D;4BAKAiB;+BAJRjB,OACI,aACKA;4BACHqB,eAAe,EACbJ,6BAAAA,QAAQK,iBAAiB,qBADZ,AACbL,2BACCtH,MAAM,IACJsH,QAAQK,iBAAiB,GAC1B;mCAAIjP,cAAckP,2BAA2B;6BAAC;2BAC9CN,CAAAA,2BAAAA,QAASO,uBAAuB,IAAG;4BAAEC,WAAW;wBAAK,IAAI,CAAC,KAEhEzB;;gBAER;gBACA,OAAO,KAAKzD,yBAAgB0E,2BAAAA,QAASS,KAAK,oBAAI,sBAAsB;oBAClEC,SAAS;oBACTC,gBAAgB;gBAClB;YACF;YACA,MAAMC,UAAUC,SAAS,CAACC,SAAS,CAACd,QAAQe,GAAG,EAAE5F,KAAK,CAAC,IAAM7D;YAC7DgE,gBAAgB,uCAAuC;gBACrDoF,SAAS;gBACTM,SAAS;YACX;YACA5F,SAAS;QACX,SAAU;YACRA,SAAS,CAAC2D,OAAUA,OAAO,aAAKA;oBAAMC,MAAM;qBAAUD;QACxD;IACF,GAAG;QAACjI;QAAOuE;QAAMtE;QAAQuE;KAAgB;IAEzC;;;;GAIC,GACD,MAAM2F,gBAAgBrN,QACpB,IAAM2H,UAAUgD,MAAM,CAAC,CAAC/H,MAAa4D,WAAW8G,QAAQ,CAACrE,OAAOrG,IAAImB,GAAG,KACvE;QAAC4D;QAAWnB;KAAW;IAEzB,MAAM+G,mBAAmBF,cAAc1C,MAAM,CAAC,CAAC/H,MAC7Cd,0BAA0BwL,QAAQ,CAACrE,OAAOrG,IAAIsD,MAAM,IACpDpB,MAAM;IACR,MAAM0I,oBAAoB1N,YAAY;QACpC,IAAI,CAACuN,cAAcvI,MAAM,EAAE;QAC3B6B,YAAY;QACZ,IAAI;;gBAEA0E,+BAAAA;YADF,MAAMoC,oBACJpC,qBAAAA,WAAWC,MAAM,sBAAjBD,gCAAAA,mBAAmBE,UAAU,qBAA7BF,mCAAAA,sCAAqC,GAAGrB,KAAKC,GAAG,GAAG,CAAC,EAAEuB,KAAKC,MAAM,GAAGC,QAAQ,CAAC,IAAIC,KAAK,CAAC,IAAI;YAC7F,MAAM+B,SAAS,MAAM7L,kBAAkB4F,MAAMtE,QAAQkK,eAAwBI;YAC7E/F,gBAAgB3F,oBAAoB2L,SAAS;gBAC3CZ,SAASY,OAAOC,OAAO,CAAC7I,MAAM,GAAG,UAAU4I,OAAOpE,OAAO,CAACxE,MAAM,GAAG,YAAY;gBAC/EiI,gBAAgB;YAClB;YACA,IAAI,CAACW,OAAOC,OAAO,CAAC7I,MAAM,EAAE2B,cAAc,EAAE;QAC9C,SAAU;YACRE,YAAY;QACd;IACF,GAAG;QAAC0G;QAAe5F;QAAMtE;QAAQuE;KAAgB;IAEjD,MAAMkG,iBACJ5K,qBAAAA,aAAa6K,IAAI,CAAC,CAAC3G,QAAeA,MAAMnD,GAAG,KAAKuC,uBAAhDtD,qBACC8D,eAAeA,YAAY/C,GAAG,KAAKuC,aAAaQ,cAAc;IAEjE;;;GAGC,GACD,MAAMgH,YAAYhO,YAChB,IAAM0H,SAAS;YAAEU,WAAW;YAAI2C,WAAW;YAAIC,UAAU;YAAKC,OAAO;QAAG,IACxE,EAAE;IAGJ,8CAA8C,GAC9C,MAAMgD,qBAAqB/N,QACzB,IAAMyD,cAAcK,IAAI,CAAC6G,MAAM,CAAC,CAAC9G,UAAiB,CAACA,QAAQmK,SAAS,GACpE;QAACvK;KAAc;IAGjB;;;GAGC,GACD,MAAMwK,eAAejO,QACnB,IAAM;YACJ;gBACE2J,OAAO;gBACPuE,YAAY;gBACZC,MAAM;gBACNC,UAAU;gBACVC,YAAY,CAAC,EAAEzL,GAAG,EAAO;;wBACSA;oBAAhC,MAAM0L,aAAa9C,KAAK+C,GAAG,CAAC,GAAG,UAAC3L,iBAAAA,IAAIqF,SAAS,qBAAbrF,eAAekC,MAAM,mBAAI,KAAK;oBAC9D,qBACE,MAAC5F;wBAAMsP,IAAI;4BAAEJ,UAAU;wBAAE;;0CACvB,KAAC/O;gCAAWyN,SAAQ;gCAAQ2B,MAAM;0CAC/B7L,IAAIkF,UAAU;;0CAEjB,KAACzI;gCAAWyN,SAAQ;gCAAU4B,OAAM;gCAAiBD,MAAM;0CACxDH,aAAa,GAAG1L,IAAIoF,QAAQ,CAAC,EAAE,EAAEsG,WAAW,KAAK,CAAC,GAAG1L,IAAIoF,QAAQ;;;;gBAI1E;YACF;YACA;gBACE2B,OAAO;gBACPuE,YAAY;gBACZC,MAAM;gBACNC,UAAU;gBACVC,YAAY,CAAC,EAAEzL,GAAG,EAAO,iBACvB,KAACvD;wBAAWyN,SAAQ;wBAAQ2B,MAAM;kCAC/B7L,IAAI+L,aAAa,IAAI;;YAG5B;YACA;gBACEhF,OAAO;gBACPuE,YAAY;gBACZU,OAAO;gBACPP,YAAY,CAAC,EAAEzL,GAAG,EAAO,iBACvB,KAACvD;wBAAWyN,SAAQ;kCACjBtP,cAAcqR,iBAAiB,CAACjM,IAAIwF,UAAU;;YAGrD;YACA;gBACEuB,OAAO;gBACPuE,YAAY;gBACZY,MAAM;gBACNF,OAAO;gBACPG,OAAO;gBACPC,aAAa;gBACbX,YAAY,CAAC,EAAEzL,GAAG,EAAO;wBAOVA;wBAAAA;yCANb,MAAC1D;wBAAMsP,IAAI;4BAAES,YAAY;4BAAYb,UAAU;4BAAGQ,OAAO;wBAAE;;0CACzD,KAACvP;gCAAWyN,SAAQ;0CACjB,CAAC,CAAC,EAAE,AAAClK,CAAAA,IAAID,QAAQ,GAAG,GAAE,EAAGuM,OAAO,CAAC,IAAI;;4BAEvCtM,IAAIuM,aAAa,iBAChB,KAAC9P;gCAAWyN,SAAQ;gCAAU4B,OAAM;gCAAiBD,MAAM;0CACxD,CAAC,CAAC,EAAE,AAAC,CAAA,EAAC7L,iBAAAA,cAAAA,IAAIwM,MAAM,qBAAVxM,YAAYyM,UAAU,oBAAIzM,IAAI0M,WAAW,YAAzC1M,OAA6C,KAAK,GAAE,EAAGsM,OAAO,CAAC,GAAG,aAAa,CAAC;iCAEvF;;;;YAGV;YACA;gBACEvF,OAAO;gBACPuE,YAAY;gBACZU,OAAO;gBACPP,YAAY,CAAC,EAAEzL,GAAG,EAAO;wBAWbpF,kDAMAA;oBAhBV,mEAAmE;oBACnE,kEAAkE;oBAClE,gEAAgE;oBAChE,MAAM+R,UACJ3M,IAAI2F,YAAY;oBAClB,qBACE,MAACrJ;wBAAMsP,IAAI;4BAAEJ,UAAU;wBAAE;;0CACvB,MAAClP;gCAAMsQ,WAAU;gCAAMC,SAAS;gCAAKjB,IAAI;oCAAES,YAAY;gCAAS;;kDAC9D,KAACrQ;wCACCsK,KAAK,GACH1L,mDAAAA,cAAckS,mBAAmB,CAC/B9M,IAAIuF,SAAS,CACd,YAFD3K,mDAEKoF,IAAIuF,SAAS;wCAEpBwH,MAAK;wCACLjB,KAAK,GACHlR,kDAAAA,cAAcoS,kBAAkB,CAC9BhN,IAAIuF,SAAS,CACd,YAFD3K,kDAEK;wCAEPsP,SAAQ;;oCAETyC,wBACC,KAACnQ;wCAAQyQ,OAAON,QAAQO,MAAM;kDAC5B,cAAA,KAAClR;4CACCsK,OAAOqG,QAAQrG,KAAK;4CACpByG,MAAK;4CACLjB,OAAOvM,aAAa,CAACoN,QAAQQ,IAAI,CAAC;4CAClCjD,SAAQ;;yCAGV;;;4BAMLyC,CAAAA,2BAAAA,QAASS,gBAAgB,MAAKtM,0BAC7B,KAACrE;gCACCyN,SAAQ;gCACRmD,WAAU;gCACVvB,OAAOa,QAAQS,gBAAgB,GAAG,IAAI,UAAU;0CAE/CT,QAAQS,gBAAgB,GAAG,IACxB,6BACA,CAAC,gBAAgB,EAAET,QAAQS,gBAAgB,CAAC,IAAI,EAC9CT,QAAQS,gBAAgB,KAAK,IAAI,KAAK,KACtC;iCAEN;;;gBAGV;YACF;YACA;gBACErG,OAAO;gBACPuE,YAAY;gBACZU,OAAO;gBACPP,YAAY,CAAC,EAAEzL,GAAG,EAAO;;wBAErBA,uBAAAA;oBADF,MAAMsN,qBACJtN,iBAAAA,IAAIsN,SAAS,sBAAbtN,wBAAAA,eAAeuN,MAAM,qBAArBvN,2BAAAA,kCACCA,IAAIwN,WAAW,GAAG,IAAIpG,KAAKpH,IAAIwN,WAAW,IAAI;oBACjD,qBACE,MAAClR;wBAAMsP,IAAI;4BAAEJ,UAAU;wBAAE;;0CACvB,KAAC/O;gCAAWyN,SAAQ;gCAAQ2B,MAAM;0CAC/ByB,YAAYA,UAAUG,kBAAkB,KAAK;;0CAEhD,KAAChR;gCAAWyN,SAAQ;gCAAU4B,OAAM;gCAAiBD,MAAM;0CACxDyB,YAAYA,UAAUI,kBAAkB,KAAK;;;;gBAItD;YACF;SACD,EACD,EAAE;IAIJ,MAAMC,UAAUvQ,QACd,IACE/B,sBACEgQ,cACA3M,mBACA6H,eACA5H,qBAEJ;QAAC0M;QAAc9E;KAAc;IAG/B;;;;GAIC,GACD,MAAMqH,QACJrK,eAAe,aACf,CAACtB,aACDM,cAAc/D,uBAAuB,CAAC,EAAE,IACxC0E,SAAS,KACTD,OAAOf,MAAM,KAAK;IAEpB,qBACE,MAACrH;QACCgT,QAAQ;QACR,kEAAkE;QAClE,iEAAiE;QACjEC,aAAa;YAAEC,sBAAQ,KAAC3P;gBAAqBmC,QAAQA;;QAAW;QAChEyN,MAAMtS,eAAe,YAAY;YAC/BuS,QAAQ;YACRC,SACE,oEACA;QACJ;QACAC,cAAc;QACdC,cAAc;;YAEbR,QACC;;;;;;;;;;SAUC,iBACD,MAACtR;gBAAMuQ,SAAS;gBAAGjB,IAAI;oBAAES,YAAY;gBAAa;;kCAChD,KAAC5P;wBAAWyN,SAAQ;wBAAQ4B,OAAM;kCAE9B,iEACA;;kCAGJ,KAACrP;wBAAWyN,SAAQ;wBAAQ4B,OAAM;kCAE9B,kEACA;;kCAGJ,KAAC/P;wBACCgR,MAAK;wBACL7C,SAAQ;wBACR4B,OAAM;wBACNuC,SAASnD;kCAER;;;+BAIL,MAAC5O;gBAAMuQ,SAAS;;oBACbrL,0BACC,MAAClF;wBACCgS,UAAU;wBACV1B,WAAU;wBACVC,SAAS;wBACTjB,IAAI;4BAAE2C,UAAU;4BAAQC,QAAQ;wBAAE;;0CAElC,KAACxP;gCACCsH,OAAM;gCACNF,OAAO,CAAC,CAAC,EAAE,AAACoB,CAAAA,QAAQiH,YAAY,GAAG,GAAE,EAAGnC,OAAO,CAAC,IAAI;gCACpDoC,UAAUlH,QAAQmH,eAAe;gCACjCC,cAAa;;0CAEf,KAAC5P;gCACCsH,OAAM;gCACNF,OAAOC,OAAOmB,QAAQvE,MAAM;gCAC5ByL,UAAUlH,QAAQqH,cAAc;gCAChCD,cAAa;;0CAEf,KAAC5P;gCACCsH,OAAM;gCACNF,OAAO,CAAC,CAAC,EAAE,AAACoB,CAAAA,QAAQsH,QAAQ,GAAG,GAAE,EAAGxC,OAAO,CAAC,IAAI;gCAChDoC,UAAUlH,QAAQuH,WAAW;gCAC7BH,cAAa;;;yBAGf;oBACHpN,aAAa+F,YAAYyH,SAAS,iBACjC,KAACvS;wBAAWyN,SAAQ;wBAAU4B,OAAM;kCACjC,CAAC,kBAAkB,EAAEnM,oBAAoB,wCAAwC,CAAC;yBAEnF;oBACHsH,aAAagI,KAAK,GAAG,kBACpB,MAACpT;wBACCqT,UAAUjI,aAAakI,OAAO,GAAG,UAAU;wBAC3CpB,QACElH,sBAAsB/F,0BACpB,KAAC/E;4BACCgR,MAAK;4BACLjB,OAAM;4BACNuC,SAAS,IACP1M,WACErG,uBACEoG,SACApD,oBAAoByI,KAAK,EACzBzI;sCAKL;;;0CAKP,KAACxC;0CACE6G,eACG,CAAC,UAAU,EAAElD,qBAAqB,6CAA6C,CAAC,GAChFwH,aAAagI,KAAK,KAAK,IACrB,oDACA,GAAGhI,aAAagI,KAAK,CAAC,6CAA6C,CAAC;;4BAE3EhI,aAAamI,eAAe,KAAKtO,YAC9B,8GACAmG,aAAamI,eAAe,GAAG,IAC7B,qHACA,CAAC,6BAA6B,EAAEnI,aAAamI,eAAe,CAAC,IAAI,EAC/DnI,aAAamI,eAAe,KAAK,IAAI,KAAK,IAC3C,4EAA4E,CAAC;;yBAEpF;kCAMJ,MAAC9S;wBACCsQ,WAAU;wBACVC,SAAS;wBACTyB,UAAU;wBACV1C,IAAI;4BAAES,YAAY;4BAAUgD,gBAAgB;4BAAYd,UAAU;wBAAO;;4BAExE3K,WAAW1B,MAAM,iBAChB,KAACnG;gCACCgR,MAAK;gCACL7C,SAAQ;gCACRoF,UAAUxL,YAAY6G,qBAAqB;gCAC3C0D,SAASzD;0CAER,CAAC,mBAAmB,EAAED,iBAAiB,CAAC,CAAC;iCAE1C;4BAEH/G,WAAW1B,MAAM,IAAI8B,2BACpB,KAACA;gCACCuL,MAAMnQ,iBAAiBqF,EAAE;gCACzBlE,QAAQA;gCACRiP,OAAO1O;gCACP2O,kBAAkB7L;gCAClB8L,WAAU;iCAEV;4BAEH/H,CAAAA,4BAAAA,SAAUgI,GAAG,CAAC,UAAU;gCAAE9H,UAAU1J;gCAA0B2J,OAAO;gCAAQvH;4BAAO,oBACnF,KAACxE;gCAAOgR,MAAK;gCAAQsB,SAASzG;0CAC3B;iCAED;0CACJ,KAAC7L;gCACCgR,MAAK;gCACL7C,SAAQ;gCACR4B,OAAM;gCACNuC,SAASnD;0CAER;;;;kCAGL,KAACpQ;wBACC6L,QAAQjI;wBACRwH,SAASvH;wBACT+C,SAASA;wBACTK,UAAUJ;wBACViF,SAASL;;kCAEX,KAACvL;wBACC0L,SAASA;wBACTkJ,SAAS;+BAAIvM,KAAKuM,OAAO;+BAAK/J,WAAW+J,OAAO;yBAAC;;kCAEnD,KAAC1U;wBACC2U,cAAW;wBACX3O,MAAM2E,WAAW3E,IAAI;wBACrByM,SAASA;wBACTmC,QAAQ,CAACrL,KAAOd,cAAcc;wBAC9BsL,YAAY;4BAAEC,UAAUpM;4BAAY7B,UAAU8B;wBAAc;wBAC5DoM,SAAS1M,eAAe;wBACxB;;;;aAIC,GACD2M,YAAW;wBACXC,aAAarO,WAAWqO,WAAW;wBACnCC,qBAAqBtO,WAAWsO,mBAAmB;wBACnDC,WAAW;wBACXxK,YAAYA;wBACZ,0CAA0C;wBAC1CyK,UAAU;wBACVC,cAAc;4BACZ5C,SAAS;gCAAE6C,uBAAuB3Q;4BAAqB;wBACzD;wBACA4Q,aAAY;;kCAEd,KAAC1V;wBACCmI,MAAMA;wBACNH,UAAUA;wBACV2N,UAAU3L,UAAU7C,MAAM;wBAC1BQ,SAASA;wBACTiO,cAAcxN;wBACdyN,kBAAkBxN;;;;YAIvB4H,8BACC,KAAC1L;gBACCiB,QAAQA;gBACR+D,OAAO0G;gBACP6F,SAAS,IAAMlN,cAAc;iBAE7B;0BACJ,MAAC1H;gBACC6U,MAAMC,QAAQzQ;gBACduQ,SAAS,IAAMjM,SAAS;gBACxBoM,UAAS;gBACTC,SAAS;;kCAET,KAAC7U;kCAAa;;kCACd,MAACD;wBAAcyP,IAAI;4BAAEsF,SAAS;4BAAQC,eAAe;4BAAUC,KAAK;wBAAE;;4BACnE/Q,SAASgR,OAAO,iBACf,KAACvT;gCAAmBwT,IAAI,GAAEjR,iBAAAA,SAASiR,IAAI,YAAbjR,iBAAiBS;gCAAWyQ,aAAY;0CAC/D,IAAGlR,mBAAAA,SAASmR,MAAM,YAAfnR,mBAAmB,GAAG,uDAAuD,CAAC;iCAElF;0CACJ,KAAC9D;gCACC+J,OAAM;gCACNF,KAAK,WAAE9F,yBAAAA,MAAOgF,SAAS,oBAAI;gCAC3BvD,UAAU,CAAC0P,QACT7M,SAAS,CAAC2D,OACRA,OACI,aAAKA;4CAAMjD,WAAWmM,MAAMC,MAAM,CAACtL,KAAK;4CAAE6B,WAAW;6CACrDM;gCAGRwE,MAAK;gCACL4E,MAAM;gCACN/F,IAAI;oCAAEgG,IAAI;gCAAE;gCACZ;;;;;aAKC,GACDC,YACE1G,mBAAmBjJ,MAAM,KAAK,IAC1B,yEACApB;0CAGLqK,mBAAmBnK,GAAG,CAAC,CAACC;wCAEpBA;yDADH,KAAC5E;wCAA2B+J,OAAOnF,QAAQE,GAAG;mDAC3CF,gBAAAA,QAAQG,IAAI,YAAZH,gBAAgBA,QAAQE,GAAG;uCADfF,QAAQE,GAAG;;;4BAK5B,CAAA;;gCACA,MAAMF,UAAUJ,cAAcK,IAAI,CAAC+J,IAAI,CACrC,CAAC6G,OAAcA,KAAK3Q,GAAG,MAAKb,yBAAAA,MAAOgF,SAAS;gCAE9C,MAAMyM,WAAW9Q,UACbrG,cAAcoX,iBAAiB,CAAC/Q,SAAS8Q,QAAQ,GACjD,EAAE;gCACN,OAAOA,SAAS7P,MAAM,GAAG,kBACvB,KAAC3F;oCACC+J,OAAM;oCACNF,KAAK,UAAE9F,yBAAAA,MAAO2H,SAAS,mBAAI;oCAC3BlG,UAAU,CAAC0P,QACT7M,SAAS,CAAC2D,OACRA,OAAO,aAAKA;gDAAMN,WAAWwJ,MAAMC,MAAM,CAACtL,KAAK;iDAAKmC;oCAGxDwE,MAAK;oCACL4E,MAAM;8CAELI,SAAS/Q,GAAG,CAAC,CAACkJ;4CAEOA;6DADpB,KAAC7N;4CAA0B+J,OAAO8D,QAAQzF,EAAE;sDACzC,GAAGwN,OAAOC,MAAM,EAAChI,mBAAAA,QAAQtD,OAAO,YAAfsD,mBAAmB,CAAC,GAAGiI,IAAI,CAAC,UAAU,UAAU,IAAI,EAAEjI,QAAQkI,QAAQ,EAAE;2CAD7ElI,QAAQzF,EAAE;;qCAK3B;4BACN,CAAA;0CACA,KAAClI;gCACC+J,OAAM;gCACNF,KAAK,WAAE9F,yBAAAA,MAAO4H,QAAQ,oBAAI;gCAC1BnG,UAAU,CAAC0P,QACT7M,SAAS,CAAC2D,OACRA,OACI,aACKA;4CACHL,UAAUuJ,MAAMC,MAAM,CAACtL,KAAK,CAACiM,OAAO,CAAC,WAAW;6CAElD9J;gCAGRwE,MAAK;gCACLuF,WAAW;oCAAEC,WAAW;wCAAEC,WAAW;oCAAU;gCAAE;;0CAEnD,KAACjW;gCACC+J,OAAM;gCACNF,KAAK,WAAE9F,yBAAAA,MAAO6H,KAAK,oBAAI;gCACvBpG,UAAU,CAAC0P,QACT7M,SAAS,CAAC2D,OACRA,OAAO,aAAKA;4CAAMJ,OAAOsJ,MAAMC,MAAM,CAACtL,KAAK;6CAAKmC;gCAGpDwE,MAAK;;4BAENzM,CAAAA,0BAAAA,uBAAAA,MAAOsJ,aAAa,qBAApBtJ,qBAAsB4B,MAAM,kBAC3B,KAAC3F;gCACC+J,OAAM;gCACNF,KAAK,WAAE9F,yBAAAA,MAAO8H,MAAM,oBAAI;gCACxBrG,UAAU,CAAC0P,QACT7M,SAAS,CAAC2D,OACRA,OAAO,aAAKA;4CAAMH,QAAQqJ,MAAMC,MAAM,CAACtL,KAAK;6CAAKmC;gCAGrDwE,MAAK;gCACL4E,MAAM;gCACNE,YACE,+DACA;0CAGDvR,MAAMsJ,aAAa,CAAC5I,GAAG,CAAC,CAACyR;wCAErB7X;yDADH,KAACyB;wCAAoB+J,OAAOqM;mDACzB7X,sDAAAA,cAAc8X,+BAA+B,CAACD,KAAK,YAAnD7X,sDAAuD6X;uCAD3CA;;iCAKjB;4BACHnS,CAAAA,yBAAAA,MAAO0J,SAAS,kBACf,KAACzN;gCACC+J,OAAM;gCACNF,KAAK,WAAE9F,yBAAAA,MAAO+H,UAAU,oBAAI;gCAC5BtG,UAAU,CAAC0P,QACT7M,SAAS,CAAC2D,OAAUA,OAAO,aAAKA;4CAAMF,YAAYoJ,MAAMC,MAAM,CAACtL,KAAK;6CAAKmC;gCAE3EwE,MAAK;gCACL8E,YAAW;iCAEX;;;kCAEN,MAAC3V;;0CACC,KAACH;gCAAOsS,SAAS,IAAMzJ,SAAS;0CAAQ;;0CACxC,KAAC/G;gCAAewT,SAAShR,SAASgR,OAAO;gCAAEG,MAAM,GAAEnR,oBAAAA,SAASmR,MAAM,YAAfnR,oBAAmB;0CACpE,cAAA,KAACtE;oCACCmO,SAAQ;oCACR4B,OAAM;oCACNwD,UACE,EAAChP,yBAAAA,MAAOgF,SAAS,MACjBhF,yBAAAA,MAAOkI,IAAI,KACX,8DAA8D;oCAC9D,uDAAuD;oCACvDuI,QAAQzQ,CAAAA,0BAAAA,wBAAAA,MAAOsJ,aAAa,qBAApBtJ,sBAAsB4B,MAAM,KAAI,EAAC5B,yBAAAA,MAAO8H,MAAM,MACtD2I,QAAQzQ,CAAAA,yBAAAA,MAAO0J,SAAS,KAAI,EAAC1J,0BAAAA,oBAAAA,MAAO+H,UAAU,qBAAjB/H,kBAAmBgC,IAAI;oCAEtD+L,SAAS/F;8CAER;;;;;;;;;AAOf;AACApI,eAAeyS,WAAW,GAAG;AAE7B,eAAezS,eAAc"}
|
|
@@ -27,6 +27,8 @@ import { useFirestoreDoc } from "@aglyn/tenant-feature-instance";
|
|
|
27
27
|
import { useOrgPlan } from "@aglyn/tenant-feature-instance";
|
|
28
28
|
import { pluginDocsHelp } from "@aglyn/aglyn";
|
|
29
29
|
import { authorizedFetch } from "@aglyn/shared-util-http/authorized-token";
|
|
30
|
+
import { PrerequisiteNotice } from "@aglyn/shared-ui-jsx/components/prerequisite-notice.component";
|
|
31
|
+
import { useCommerceEntitlement } from "./entitlement-gate.component.js";
|
|
30
32
|
/**
|
|
31
33
|
* Merchant payments card (AGL-284): Stripe Connect Express onboarding
|
|
32
34
|
* status for the org owner + the plan's transaction-fee ladder so the
|
|
@@ -45,13 +47,19 @@ import { authorizedFetch } from "@aglyn/shared-util-http/authorized-token";
|
|
|
45
47
|
*/ const [dashboardUrl, setDashboardUrl] = useState(null);
|
|
46
48
|
const { org, ready: planReady } = useOrgPlan(hostId);
|
|
47
49
|
/** Bumped by Retry to re-subscribe the profile listen (AGL-1380). */ const [retryNonce, setRetryNonce] = useState(0);
|
|
48
|
-
const
|
|
50
|
+
const { upgradeHref } = useCommerceEntitlement(hostId, 'commerce');
|
|
51
|
+
/**
|
|
52
|
+
* The OWNER's profile: the Stripe account every money route charges
|
|
53
|
+
* against is the one on the workspace owner's profile. Reading the
|
|
54
|
+
* signed-in member's instead told an admin who is not the owner that a
|
|
55
|
+
* connected store was not set up.
|
|
56
|
+
*/ const ownerUid = typeof (org == null ? void 0 : org.ownerUid) === 'string' && org.ownerUid ? org.ownerUid : undefined;
|
|
49
57
|
const { data: profile, status: profileStatus } = useFirestoreDoc(// Held at null rather than addressed as `profiles/-pending-` — that
|
|
50
58
|
// sentinel issued a guaranteed-denied read on every pre-auth mount, and
|
|
51
59
|
// a denial lands in `status: 'error'`, which now means something.
|
|
52
|
-
()=>
|
|
60
|
+
()=>ownerUid ? doc(firestore, 'profiles', ownerUid) : null, [
|
|
53
61
|
firestore,
|
|
54
|
-
|
|
62
|
+
ownerUid,
|
|
55
63
|
retryNonce
|
|
56
64
|
]);
|
|
57
65
|
const isOwner = Boolean((org == null ? void 0 : org.ownerUid) && (user == null ? void 0 : user.uid) === org.ownerUid);
|
|
@@ -63,7 +71,7 @@ import { authorizedFetch } from "@aglyn/shared-util-http/authorized-token";
|
|
|
63
71
|
* is wrong in the direction that provokes action: the same falsy value
|
|
64
72
|
* turns the button into "Set up payments", which sends a merchant who is
|
|
65
73
|
* already taking money into Stripe onboarding.
|
|
66
|
-
*/ const stripeState = !
|
|
74
|
+
*/ const stripeState = !planReady || ownerUid && profileStatus === 'loading' ? 'pending' : profileStatus === 'error' ? 'error' : 'loaded';
|
|
67
75
|
/**
|
|
68
76
|
* WHICH STRIPE WORLD THE STORED ACCOUNT BELONGS TO (AGL-2471).
|
|
69
77
|
*
|
|
@@ -212,9 +220,10 @@ import { authorizedFetch } from "@aglyn/shared-util-http/authorized-token";
|
|
|
212
220
|
children: 'Checking your plan…'
|
|
213
221
|
}) : /*#__PURE__*/ _jsxs(_Fragment, {
|
|
214
222
|
children: [
|
|
215
|
-
!commerceEnabled ? /*#__PURE__*/ _jsx(
|
|
216
|
-
|
|
217
|
-
|
|
223
|
+
!commerceEnabled ? /*#__PURE__*/ _jsx(PrerequisiteNotice, {
|
|
224
|
+
href: upgradeHref,
|
|
225
|
+
actionLabel: "See plans",
|
|
226
|
+
children: 'Selling needs a paid plan. Choose one on Billing, then connect Stripe here.'
|
|
218
227
|
}) : null,
|
|
219
228
|
/*#__PURE__*/ _jsx(Typography, {
|
|
220
229
|
variant: "body2",
|