@aglyn/plugins-commerce 1.0.0-beta.288 → 1.0.0-beta.289

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +2 -2
  2. package/package.json +13 -13
  3. package/src/lib/components/commerce-console-page.js +29 -2
  4. package/src/lib/components/commerce-console-page.js.map +1 -1
  5. package/src/lib/components/console/commerce-analytics-card.component.js +4 -2
  6. package/src/lib/components/console/commerce-analytics-card.component.js.map +1 -1
  7. package/src/lib/components/console/host-orders-card.component.js +5 -1
  8. package/src/lib/components/console/host-orders-card.component.js.map +1 -1
  9. package/src/lib/components/console/host-quotes-card.component.d.ts +34 -0
  10. package/src/lib/components/console/host-quotes-card.component.js +247 -0
  11. package/src/lib/components/console/host-quotes-card.component.js.map +1 -0
  12. package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js +33 -28
  13. package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js.map +1 -1
  14. package/src/lib/components/console/quote-editor-dialog.component.d.ts +45 -0
  15. package/src/lib/components/console/quote-editor-dialog.component.js +1266 -0
  16. package/src/lib/components/console/quote-editor-dialog.component.js.map +1 -0
  17. package/src/lib/components/console/quote-pay-link.component.d.ts +38 -0
  18. package/src/lib/components/console/quote-pay-link.component.js +213 -0
  19. package/src/lib/components/console/quote-pay-link.component.js.map +1 -0
  20. package/src/lib/components/console/quote-settings-card.component.d.ts +29 -0
  21. package/src/lib/components/console/quote-settings-card.component.js +121 -0
  22. package/src/lib/components/console/quote-settings-card.component.js.map +1 -0
  23. package/src/lib/components/console/tax-settings-card.component.js +4 -1
  24. package/src/lib/components/console/tax-settings-card.component.js.map +1 -1
  25. package/src/lib/components/quote-page-body.d.ts +33 -0
  26. package/src/lib/components/quote-page-body.js +696 -0
  27. package/src/lib/components/quote-page-body.js.map +1 -0
  28. package/src/lib/components/quote-page.d.ts +29 -0
  29. package/src/lib/components/quote-page.js +96 -0
  30. package/src/lib/components/quote-page.js.map +1 -0
  31. package/src/lib/components/storefront-payment-element.d.ts +7 -1
  32. package/src/lib/components/storefront-payment-element.js +8 -3
  33. package/src/lib/components/storefront-payment-element.js.map +1 -1
  34. package/src/lib/constants/orders-list-query.js +6 -1
  35. package/src/lib/constants/orders-list-query.js.map +1 -1
  36. package/src/lib/constants/quote-page.d.ts +30 -0
  37. package/src/lib/constants/quote-page.js +35 -0
  38. package/src/lib/constants/quote-page.js.map +1 -0
  39. package/src/lib/model/commerce-orders.d.ts +25 -2
  40. package/src/lib/model/commerce-orders.js +10 -1
  41. package/src/lib/model/commerce-orders.js.map +1 -1
  42. package/src/lib/model/commerce-quote-pay.d.ts +229 -0
  43. package/src/lib/model/commerce-quote-pay.js +393 -0
  44. package/src/lib/model/commerce-quote-pay.js.map +1 -0
  45. package/src/lib/model/commerce-quotes.d.ts +279 -0
  46. package/src/lib/model/commerce-quotes.js +522 -0
  47. package/src/lib/model/commerce-quotes.js.map +1 -0
  48. package/src/lib/model/index.d.ts +2 -0
  49. package/src/lib/model/index.js +2 -0
  50. package/src/lib/model/index.js.map +1 -1
  51. package/src/lib/model/plugin-permissions.d.ts +1 -1
  52. package/src/lib/model/plugin-permissions.js +20 -0
  53. package/src/lib/model/plugin-permissions.js.map +1 -1
  54. package/src/lib/server/api-v1/orders-and-products.js +6 -2
  55. package/src/lib/server/api-v1/orders-and-products.js.map +1 -1
  56. package/src/lib/server/billing-webhook.js +127 -52
  57. package/src/lib/server/billing-webhook.js.map +1 -1
  58. package/src/lib/server/checkout-session-expiry.d.ts +36 -0
  59. package/src/lib/server/checkout-session-expiry.js +63 -0
  60. package/src/lib/server/checkout-session-expiry.js.map +1 -0
  61. package/src/lib/server/draft-order.js +16 -8
  62. package/src/lib/server/draft-order.js.map +1 -1
  63. package/src/lib/server/person-eraser.d.ts +7 -0
  64. package/src/lib/server/person-eraser.js +24 -2
  65. package/src/lib/server/person-eraser.js.map +1 -1
  66. package/src/lib/server/pos-return.js +3 -1
  67. package/src/lib/server/pos-return.js.map +1 -1
  68. package/src/lib/server/quote-link-token.d.ts +39 -0
  69. package/src/lib/server/quote-link-token.js +97 -0
  70. package/src/lib/server/quote-link-token.js.map +1 -0
  71. package/src/lib/server/quote-pay.d.ts +83 -0
  72. package/src/lib/server/quote-pay.js +606 -0
  73. package/src/lib/server/quote-pay.js.map +1 -0
  74. package/src/lib/server/quote.d.ts +49 -0
  75. package/src/lib/server/quote.js +513 -0
  76. package/src/lib/server/quote.js.map +1 -0
  77. package/src/lib/server/related.js +2 -0
  78. package/src/lib/server/related.js.map +1 -1
  79. package/src/lib/server/site-page-resolver.d.ts +2 -0
  80. package/src/lib/server/site-page-resolver.js +75 -0
  81. package/src/lib/server/site-page-resolver.js.map +1 -1
  82. package/src/lib/server.js +14 -0
  83. package/src/lib/server.js.map +1 -1
  84. package/src/lib/site.js +6 -0
  85. package/src/lib/site.js.map +1 -1
  86. package/src/lib/transfer/tracking.server.js +6 -0
  87. package/src/lib/transfer/tracking.server.js.map +1 -1
@@ -0,0 +1,247 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ 'use client';
17
+ import { _ as _extends } from "@swc/helpers/_/_extends";
18
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
+ import * as CommerceModel from "../../model/index.js";
20
+ import { posMoney } from "../../model/commerce-pos-ops.js";
21
+ import { commerceSitePermissionRefusal } from "../../model/plugin-permissions.js";
22
+ import { pluginDocsHelp } from "@aglyn/aglyn";
23
+ import { CardDisplay } from "@aglyn/shared-ui-jsx";
24
+ import { BlockedControl } from "@aglyn/shared-ui-jsx/components/blocked-control.component";
25
+ import { ListTable } from "@aglyn/shared-ui-jsx/components/list-table.component";
26
+ import { ceilingedWindow, collectionCeiling, useFirestore, useFirestoreCollection } from "@aglyn/tenant-feature-instance";
27
+ import { Button, Chip, Stack, Typography } from "@mui/material";
28
+ import { collection, limit, query, where } from "firebase/firestore";
29
+ import { useMemo, useState } from "react";
30
+ import QuoteEditorDialog from "./quote-editor-dialog.component.js";
31
+ /**
32
+ * How many quotes the list reads. The whole set is read and the grid sorts
33
+ * it by any column; a store past this many is told the list stops short.
34
+ */ const QUOTE_CEILING = 500;
35
+ /** The products the editor's picker offers. */ const PRODUCT_WINDOW = 200;
36
+ const REFUSAL = commerceSitePermissionRefusal('commerce.quotes');
37
+ /** One quote as its row draws and sorts it. */ function quoteListRow(quote) {
38
+ var _quote_lineItems, _ref, _ref1, _ref2;
39
+ var _quote_quote, _items_, _quote_totals, _quote_quote1;
40
+ const customer = (_quote_quote = quote.quote) == null ? void 0 : _quote_quote.customer;
41
+ const status = CommerceModel.quoteDisplayStatus(quote);
42
+ const items = (_quote_lineItems = quote.lineItems) != null ? _quote_lineItems : [];
43
+ return _extends({}, quote, {
44
+ customerLabel: (customer == null ? void 0 : customer.name) || (customer == null ? void 0 : customer.company) || (customer == null ? void 0 : customer.email) || '',
45
+ firstItem: (_ref = (_items_ = items[0]) == null ? void 0 : _items_.name) != null ? _ref : '',
46
+ moreItems: Math.max(0, items.length - 1),
47
+ statusKey: status.key,
48
+ statusLabel: status.label,
49
+ totalCents: Number((_ref1 = (_quote_totals = quote.totals) == null ? void 0 : _quote_totals.totalCents) != null ? _ref1 : 0),
50
+ updatedAtMs: Number((_ref2 = (_quote_quote1 = quote.quote) == null ? void 0 : _quote_quote1.updatedAtMs) != null ? _ref2 : 0)
51
+ });
52
+ }
53
+ /**
54
+ * Quotes (AGL-4093): prices put to a customer before they buy, beside the
55
+ * orders they become. A quote is an unpaid order on the `quote` channel, so
56
+ * this reads `hosts/{hostId}/orders` for that channel alone; the Orders list
57
+ * above never shows one until it is paid.
58
+ */ export function HostQuotesCard(props) {
59
+ var _quotes_rows_find;
60
+ const { hostId, canEdit, canSend } = props;
61
+ const firestore = useFirestore();
62
+ const { data: quoteDocs, status } = useFirestoreCollection(()=>query(collection(firestore, 'hosts', hostId, 'orders'), where('channel', '==', 'quote'), limit(QUOTE_CEILING + 1)), [
63
+ firestore,
64
+ hostId
65
+ ], {
66
+ idField: '$id'
67
+ });
68
+ const quotes = useMemo(()=>ceilingedWindow(quoteDocs != null ? quoteDocs : undefined, QUOTE_CEILING), [
69
+ quoteDocs
70
+ ]);
71
+ const rows = useMemo(()=>Array.from(quotes.rows, quoteListRow), [
72
+ quotes
73
+ ]);
74
+ const { data: productDocs } = useFirestoreCollection(()=>collectionCeiling(collection(firestore, 'hosts', hostId, 'products'), PRODUCT_WINDOW), [
75
+ firestore,
76
+ hostId
77
+ ], {
78
+ idField: '$id'
79
+ });
80
+ const products = useMemo(()=>ceilingedWindow(productDocs != null ? productDocs : undefined, PRODUCT_WINDOW).rows.filter((product)=>!product['deletedAt']), [
81
+ productDocs
82
+ ]);
83
+ /** The quote open in the editor: its id, or `new`. */ const [openId, setOpenId] = useState(null);
84
+ const openQuote = openId && openId !== 'new' ? (_quotes_rows_find = quotes.rows.find((row)=>row.$id === openId)) != null ? _quotes_rows_find : null : null;
85
+ const columns = useMemo(()=>[
86
+ {
87
+ field: 'number',
88
+ headerName: 'Quote',
89
+ flex: 1,
90
+ minWidth: 160,
91
+ renderCell: ({ row })=>/*#__PURE__*/ _jsxs(Stack, {
92
+ sx: {
93
+ minWidth: 0
94
+ },
95
+ children: [
96
+ /*#__PURE__*/ _jsx(Typography, {
97
+ variant: "body2",
98
+ noWrap: true,
99
+ children: CommerceModel.formatQuoteNumber(row, row.$id)
100
+ }),
101
+ /*#__PURE__*/ _jsx(Typography, {
102
+ variant: "caption",
103
+ color: "text.secondary",
104
+ noWrap: true,
105
+ children: row.moreItems ? `${row.firstItem} and more` : row.firstItem
106
+ })
107
+ ]
108
+ })
109
+ },
110
+ {
111
+ field: 'customerLabel',
112
+ headerName: 'Customer',
113
+ flex: 1,
114
+ minWidth: 160,
115
+ renderCell: ({ row })=>/*#__PURE__*/ _jsx(Typography, {
116
+ variant: "body2",
117
+ noWrap: true,
118
+ children: row.customerLabel || '—'
119
+ })
120
+ },
121
+ {
122
+ field: 'totalCents',
123
+ headerName: 'Total',
124
+ type: 'number',
125
+ width: 140,
126
+ align: 'right',
127
+ headerAlign: 'right',
128
+ renderCell: ({ row })=>{
129
+ var _row_quote_tax, _row_quote;
130
+ return /*#__PURE__*/ _jsxs(Stack, {
131
+ sx: {
132
+ alignItems: 'flex-end',
133
+ minWidth: 0,
134
+ width: 1
135
+ },
136
+ children: [
137
+ /*#__PURE__*/ _jsx(Typography, {
138
+ variant: "body2",
139
+ children: posMoney(row.totalCents)
140
+ }),
141
+ ((_row_quote = row.quote) == null ? void 0 : (_row_quote_tax = _row_quote.tax) == null ? void 0 : _row_quote_tax.kind) === 'at-payment' && CommerceModel.isUnpaidQuote(row) ? /*#__PURE__*/ _jsx(Typography, {
142
+ variant: "caption",
143
+ color: "text.secondary",
144
+ noWrap: true,
145
+ children: 'plus tax at payment'
146
+ }) : null
147
+ ]
148
+ });
149
+ }
150
+ },
151
+ {
152
+ field: 'statusLabel',
153
+ headerName: 'Status',
154
+ width: 180,
155
+ renderCell: ({ row })=>/*#__PURE__*/ _jsx(Chip, {
156
+ size: "small",
157
+ variant: "outlined",
158
+ label: row.statusLabel,
159
+ color: CommerceModel.QUOTE_STATUS_COLOR[row.statusKey]
160
+ })
161
+ },
162
+ {
163
+ field: 'updatedAtMs',
164
+ headerName: 'Updated',
165
+ type: 'number',
166
+ width: 140,
167
+ align: 'left',
168
+ headerAlign: 'left',
169
+ renderCell: ({ row })=>/*#__PURE__*/ _jsx(Typography, {
170
+ variant: "body2",
171
+ noWrap: true,
172
+ children: row.updatedAtMs ? new Date(row.updatedAtMs).toLocaleDateString() : '—'
173
+ })
174
+ }
175
+ ], []);
176
+ const empty = status === 'success' && rows.length === 0;
177
+ return /*#__PURE__*/ _jsxs(CardDisplay, {
178
+ header: 'Quotes',
179
+ subheader: 'Prices for a customer’s order before they buy',
180
+ help: pluginDocsHelp('quotes', {
181
+ anchor: '#make-a-quote',
182
+ title: 'Quotes',
183
+ excerpt: 'Put a price to a customer with your products, items typed for the job and anything ' + 'included. A quote becomes an order when it is paid.'
184
+ }),
185
+ HeaderProps: {
186
+ action: /*#__PURE__*/ _jsx(BlockedControl, {
187
+ blocked: !canEdit,
188
+ reason: REFUSAL,
189
+ children: /*#__PURE__*/ _jsx(Button, {
190
+ size: "small",
191
+ variant: "contained",
192
+ onClick: ()=>setOpenId('new'),
193
+ children: 'New quote'
194
+ })
195
+ })
196
+ },
197
+ contentGutterX: true,
198
+ contentGutterY: true,
199
+ children: [
200
+ empty ? /*#__PURE__*/ _jsx(Typography, {
201
+ variant: "body2",
202
+ color: "text.secondary",
203
+ children: 'No quotes yet. A quote prices a customer’s order before they buy: your products, ' + 'items typed for the job, and anything you include at no charge.'
204
+ }) : /*#__PURE__*/ _jsxs(Stack, {
205
+ spacing: 1,
206
+ children: [
207
+ quotes.truncated ? /*#__PURE__*/ _jsx(Typography, {
208
+ variant: "caption",
209
+ color: "text.secondary",
210
+ children: 'This store has more quotes than the list shows at once.'
211
+ }) : null,
212
+ /*#__PURE__*/ _jsx(ListTable, {
213
+ "aria-label": "Quotes",
214
+ rows: rows,
215
+ columns: columns,
216
+ loading: status === 'loading',
217
+ onOpen: (id)=>setOpenId(id),
218
+ quickFilter: true,
219
+ initialState: {
220
+ sorting: {
221
+ sortModel: [
222
+ {
223
+ field: 'updatedAtMs',
224
+ sort: 'desc'
225
+ }
226
+ ]
227
+ }
228
+ },
229
+ noRowsLabel: "No quotes match"
230
+ })
231
+ ]
232
+ }),
233
+ openId === 'new' || openQuote ? /*#__PURE__*/ _jsx(QuoteEditorDialog, {
234
+ hostId: hostId,
235
+ quote: openQuote,
236
+ products: products,
237
+ canEdit: canEdit,
238
+ canSend: canSend,
239
+ onClose: ()=>setOpenId(null)
240
+ }, openId) : null
241
+ ]
242
+ });
243
+ }
244
+ HostQuotesCard.displayName = 'HostQuotesCard';
245
+ export default HostQuotesCard;
246
+
247
+ //# sourceMappingURL=host-quotes-card.component.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/host-quotes-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 { posMoney } from '../../model/commerce-pos-ops'\nimport { commerceSitePermissionRefusal } from '../../model/plugin-permissions'\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { BlockedControl } from '@aglyn/shared-ui-jsx/components/blocked-control.component'\nimport { ListTable } from '@aglyn/shared-ui-jsx/components/list-table.component'\nimport {\n ceilingedWindow,\n collectionCeiling,\n useFirestore,\n useFirestoreCollection,\n} from '@aglyn/tenant-feature-instance'\nimport { Button, Chip, Stack, Typography } from '@mui/material'\nimport type { GridColDef } from '@mui/x-data-grid'\nimport { collection, limit, query, where } from 'firebase/firestore'\nimport { useMemo, useState } from 'react'\nimport QuoteEditorDialog, { type QuoteRow } from './quote-editor-dialog.component'\n\nexport interface HostQuotesCardProps {\n hostId: string\n /** Holds \"Create and edit quotes\" (`commerce.quotes`). */\n canEdit: boolean\n /** Holds \"Send quotes and invoices to customers\" (`commerce.quotes.send`). */\n canSend: boolean\n}\n\n/**\n * How many quotes the list reads. The whole set is read and the grid sorts\n * it by any column; a store past this many is told the list stops short.\n */\nconst QUOTE_CEILING = 500\n\n/** The products the editor's picker offers. */\nconst PRODUCT_WINDOW = 200\n\nconst REFUSAL = commerceSitePermissionRefusal('commerce.quotes')\n\ninterface QuoteListRow extends QuoteRow {\n customerLabel: string\n firstItem: string\n moreItems: number\n statusKey: ReturnType<typeof CommerceModel.quoteDisplayStatus>['key']\n statusLabel: string\n totalCents: number\n updatedAtMs: number\n}\n\n/** One quote as its row draws and sorts it. */\nfunction quoteListRow(quote: QuoteRow): QuoteListRow {\n const customer = quote.quote?.customer\n const status = CommerceModel.quoteDisplayStatus(quote)\n const items = quote.lineItems ?? []\n return {\n ...quote,\n customerLabel: customer?.name || customer?.company || customer?.email || '',\n firstItem: items[0]?.name ?? '',\n moreItems: Math.max(0, items.length - 1),\n statusKey: status.key,\n statusLabel: status.label,\n totalCents: Number(quote.totals?.totalCents ?? 0),\n updatedAtMs: Number(quote.quote?.updatedAtMs ?? 0),\n }\n}\n\n/**\n * Quotes (AGL-4093): prices put to a customer before they buy, beside the\n * orders they become. A quote is an unpaid order on the `quote` channel, so\n * this reads `hosts/{hostId}/orders` for that channel alone; the Orders list\n * above never shows one until it is paid.\n */\nexport function HostQuotesCard(props: HostQuotesCardProps) {\n const { hostId, canEdit, canSend } = props\n const firestore = useFirestore()\n const { data: quoteDocs, status } = useFirestoreCollection<QuoteRow>(\n () =>\n query(\n collection(firestore, 'hosts', hostId, 'orders'),\n where('channel', '==', 'quote'),\n limit(QUOTE_CEILING + 1),\n ),\n [firestore, hostId],\n { idField: '$id' },\n )\n const quotes = useMemo(() => ceilingedWindow<QuoteRow>(quoteDocs ?? undefined, QUOTE_CEILING), [quoteDocs])\n const rows = useMemo(() => Array.from(quotes.rows, quoteListRow), [quotes])\n\n const { data: productDocs } = useFirestoreCollection<Record<string, any>>(\n () => collectionCeiling(collection(firestore, 'hosts', hostId, 'products'), PRODUCT_WINDOW),\n [firestore, hostId],\n { idField: '$id' },\n )\n const products = useMemo(\n () => ceilingedWindow<Record<string, any>>(productDocs ?? undefined, PRODUCT_WINDOW).rows.filter((product) => !product['deletedAt']),\n [productDocs],\n )\n\n /** The quote open in the editor: its id, or `new`. */\n const [openId, setOpenId] = useState<string | null>(null)\n const openQuote = openId && openId !== 'new' ? (quotes.rows.find((row) => row.$id === openId) ?? null) : null\n\n const columns = useMemo<GridColDef[]>(\n () => [\n {\n field: 'number',\n headerName: 'Quote',\n flex: 1,\n minWidth: 160,\n renderCell: ({ row }: { row: QuoteListRow }) => (\n <Stack sx={{ minWidth: 0 }}>\n <Typography variant=\"body2\" noWrap>\n {CommerceModel.formatQuoteNumber(row, row.$id)}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {row.moreItems ? `${row.firstItem} and more` : row.firstItem}\n </Typography>\n </Stack>\n ),\n },\n {\n field: 'customerLabel',\n headerName: 'Customer',\n flex: 1,\n minWidth: 160,\n renderCell: ({ row }: { row: QuoteListRow }) => (\n <Typography variant=\"body2\" noWrap>\n {row.customerLabel || '—'}\n </Typography>\n ),\n },\n {\n field: 'totalCents',\n headerName: 'Total',\n type: 'number',\n width: 140,\n align: 'right',\n headerAlign: 'right',\n renderCell: ({ row }: { row: QuoteListRow }) => (\n <Stack sx={{ alignItems: 'flex-end', minWidth: 0, width: 1 }}>\n <Typography variant=\"body2\">{posMoney(row.totalCents)}</Typography>\n {row.quote?.tax?.kind === 'at-payment' && CommerceModel.isUnpaidQuote(row) ? (\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {'plus tax at payment'}\n </Typography>\n ) : null}\n </Stack>\n ),\n },\n {\n field: 'statusLabel',\n headerName: 'Status',\n width: 180,\n renderCell: ({ row }: { row: QuoteListRow }) => (\n <Chip\n size=\"small\"\n variant=\"outlined\"\n label={row.statusLabel}\n color={CommerceModel.QUOTE_STATUS_COLOR[row.statusKey]}\n />\n ),\n },\n {\n field: 'updatedAtMs',\n headerName: 'Updated',\n type: 'number',\n width: 140,\n align: 'left',\n headerAlign: 'left',\n renderCell: ({ row }: { row: QuoteListRow }) => (\n <Typography variant=\"body2\" noWrap>\n {row.updatedAtMs ? new Date(row.updatedAtMs).toLocaleDateString() : '—'}\n </Typography>\n ),\n },\n ],\n [],\n )\n\n const empty = status === 'success' && rows.length === 0\n\n return (\n <CardDisplay\n header={'Quotes'}\n subheader={'Prices for a customer’s order before they buy'}\n help={pluginDocsHelp('quotes', {\n anchor: '#make-a-quote',\n title: 'Quotes',\n excerpt:\n 'Put a price to a customer with your products, items typed for the job and anything ' +\n 'included. A quote becomes an order when it is paid.',\n })}\n HeaderProps={{\n action: (\n <BlockedControl blocked={!canEdit} reason={REFUSAL}>\n <Button size=\"small\" variant=\"contained\" onClick={() => setOpenId('new')}>\n {'New quote'}\n </Button>\n </BlockedControl>\n ),\n }}\n contentGutterX\n contentGutterY\n >\n {empty ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'No quotes yet. A quote prices a customer’s order before they buy: your products, ' +\n 'items typed for the job, and anything you include at no charge.'}\n </Typography>\n ) : (\n <Stack spacing={1}>\n {quotes.truncated ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'This store has more quotes than the list shows at once.'}\n </Typography>\n ) : null}\n <ListTable\n aria-label=\"Quotes\"\n rows={rows}\n columns={columns}\n loading={status === 'loading'}\n onOpen={(id) => setOpenId(id)}\n quickFilter\n initialState={{ sorting: { sortModel: [{ field: 'updatedAtMs', sort: 'desc' }] } }}\n noRowsLabel=\"No quotes match\"\n />\n </Stack>\n )}\n {/* A quote deleted while open closes its editor rather than turn it into a new one. */}\n {openId === 'new' || openQuote ? (\n <QuoteEditorDialog\n key={openId}\n hostId={hostId}\n quote={openQuote}\n products={products}\n canEdit={canEdit}\n canSend={canSend}\n onClose={() => setOpenId(null)}\n />\n ) : null}\n </CardDisplay>\n )\n}\nHostQuotesCard.displayName = 'HostQuotesCard'\n\nexport default HostQuotesCard\n"],"names":["CommerceModel","posMoney","commerceSitePermissionRefusal","pluginDocsHelp","CardDisplay","BlockedControl","ListTable","ceilingedWindow","collectionCeiling","useFirestore","useFirestoreCollection","Button","Chip","Stack","Typography","collection","limit","query","where","useMemo","useState","QuoteEditorDialog","QUOTE_CEILING","PRODUCT_WINDOW","REFUSAL","quoteListRow","quote","items","customer","status","quoteDisplayStatus","lineItems","customerLabel","name","company","email","firstItem","moreItems","Math","max","length","statusKey","key","statusLabel","label","totalCents","Number","totals","updatedAtMs","HostQuotesCard","props","quotes","hostId","canEdit","canSend","firestore","data","quoteDocs","idField","undefined","rows","Array","from","productDocs","products","filter","product","openId","setOpenId","openQuote","find","row","$id","columns","field","headerName","flex","minWidth","renderCell","sx","variant","noWrap","formatQuoteNumber","color","type","width","align","headerAlign","alignItems","tax","kind","isUnpaidQuote","size","QUOTE_STATUS_COLOR","Date","toLocaleDateString","empty","header","subheader","help","anchor","title","excerpt","HeaderProps","action","blocked","reason","onClick","contentGutterX","contentGutterY","spacing","truncated","aria-label","loading","onOpen","id","quickFilter","initialState","sorting","sortModel","sort","noRowsLabel","onClose","displayName"],"mappings":"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"}
@@ -165,6 +165,39 @@ function PosCheckInsBody(props) {
165
165
  minWidth: 150,
166
166
  valueGetter: (_value, row)=>row.customerName || row.customerEmail || ''
167
167
  },
168
+ {
169
+ // What a pass waiting at the window can still have done to it: a
170
+ // rain check, or one taken back; and a stay's guest count (AGL-4043).
171
+ // Not a value, so nothing to sort.
172
+ //
173
+ // Second, beside the name it acts on, rather than trailing. The grid
174
+ // has no column pinning, so a trailing column sat past the right edge
175
+ // of any window narrower than every column put together — on a
176
+ // laptop, and always on a phone — and the window could not see it.
177
+ field: 'rainCheckAction',
178
+ headerName: 'Actions',
179
+ minWidth: 150,
180
+ sortable: false,
181
+ filterable: false,
182
+ hideable: false,
183
+ disableColumnMenu: true,
184
+ renderCell: ({ row })=>row.source === 'reservation' && row.reservationId ? /*#__PURE__*/ _jsx(Button, {
185
+ size: "small",
186
+ disabled: !canManagePos,
187
+ onClick: ()=>setGuestsFor(row.reservationId),
188
+ children: 'Guests'
189
+ }) : row.source !== 'order' || row.status !== 'expected' ? null : row.rainCheck ? /*#__PURE__*/ _jsx(Button, {
190
+ size: "small",
191
+ disabled: !canManagePos,
192
+ onClick: ()=>void undoRainCheck(row),
193
+ children: 'Undo rain check'
194
+ }) : /*#__PURE__*/ _jsx(Button, {
195
+ size: "small",
196
+ disabled: !canManagePos || !todayKey,
197
+ onClick: ()=>setRainCheckRow(row),
198
+ children: 'Rain check'
199
+ })
200
+ },
168
201
  {
169
202
  field: 'itemName',
170
203
  headerName: 'Item',
@@ -225,34 +258,6 @@ function PosCheckInsBody(props) {
225
258
  headerName: 'Wristband',
226
259
  minWidth: 120,
227
260
  valueGetter: (_value, row)=>describeWristband(row.wristband)
228
- },
229
- {
230
- // What a pass waiting at the window can still have done to it: a
231
- // rain check, or one taken back; and a stay's guest count (AGL-4043).
232
- // Not a value, so nothing to sort.
233
- field: 'rainCheckAction',
234
- headerName: '',
235
- minWidth: 150,
236
- sortable: false,
237
- filterable: false,
238
- hideable: false,
239
- disableColumnMenu: true,
240
- renderCell: ({ row })=>row.source === 'reservation' && row.reservationId ? /*#__PURE__*/ _jsx(Button, {
241
- size: "small",
242
- disabled: !canManagePos,
243
- onClick: ()=>setGuestsFor(row.reservationId),
244
- children: 'Guests'
245
- }) : row.source !== 'order' || row.status !== 'expected' ? null : row.rainCheck ? /*#__PURE__*/ _jsx(Button, {
246
- size: "small",
247
- disabled: !canManagePos,
248
- onClick: ()=>void undoRainCheck(row),
249
- children: 'Undo rain check'
250
- }) : /*#__PURE__*/ _jsx(Button, {
251
- size: "small",
252
- disabled: !canManagePos || !todayKey,
253
- onClick: ()=>setRainCheckRow(row),
254
- children: 'Rain check'
255
- })
256
261
  }
257
262
  ], [
258
263
  list,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-ops/pos-check-ins-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'use client'\n\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { ListTable } from '@aglyn/shared-ui-jsx/components/list-table.component'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { useFirestore, useFirestoreCollection, useUser } from '@aglyn/tenant-feature-instance'\nimport { Alert, Button, Chip, Stack, ToggleButton, ToggleButtonGroup, Typography } from '@mui/material'\nimport type { GridColDef } from '@mui/x-data-grid'\nimport { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'\nimport { DatePicker } from '@mui/x-date-pickers/DatePicker'\nimport { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'\nimport type { Dayjs } from 'dayjs'\nimport { collection, documentId, limit, orderBy, query } from 'firebase/firestore'\nimport { lazy, Suspense, useCallback, useEffect, useMemo, useState } from 'react'\nimport { zonedDayKey } from '@aglyn/shared-util-timestamp/zoned-time'\nimport {\n checkInItemLabel,\n checkInRainCheckIsOpen,\n checkInStatusLabel,\n checkInTimeLabel,\n describeWristband,\n POS_CHECK_IN_ROUTE,\n rainCheckLabel,\n type CheckInDayTotals,\n type CheckInRow,\n} from '../../../model/commerce-check-in'\nimport { callPosOps } from './pos-ops-api'\nimport type { StayCheckInMode } from '../../../model/commerce-reservations'\nimport { PosRainCheckDialog } from './pos-rain-check-dialog.component'\nimport { escapeHtml } from '../../../utils/escape-html'\nimport CommerceStatTile from '../commerce-stat-tile.component'\nimport { EntitlementGatedCard } from '../entitlement-gate.component'\nimport { POS_RECEIPT_STYLES } from './pos-receipt'\nimport { printPosDocument } from './pos-shift-report.component'\n\n/*==========================================\n * TODAY'S CHECK-INS (AGL-4043): who is due at the window on a day, who is\n * checked in, by whom and with which wristband, from\n * `GET /api/commerce/pos-check-in`. The day is a whole, bounded list, so\n * the grid sorts it by any column itself.\n *=========================================*/\n\nexport interface PosCheckInsCardProps {\n hostId: string\n /** The viewer may work the register: what the route's gate asks. */\n canManagePos?: boolean\n}\n\n/** A stay's guest count (AGL-4043), loaded the first time it opens. */\nconst ReservationGuestsDialog = lazy(() => import('../reservation-guests-dialog.component'))\n\nconst HEADER = \"Today's check-ins\"\nconst HELP = pluginDocsHelp('posOperations', { anchor: '#check-in-at-the-window' })\nconst DAY_FORMAT = 'YYYY-MM-DD'\n\ninterface DayList {\n dayKey: string\n timeZone: string\n totals: CheckInDayTotals\n checkIns: CheckInRow[]\n truncated?: boolean\n /** How the store checks stays in (AGL-4043). */\n stayCheckIn?: StayCheckInMode\n}\n\n/** The quick control's choices, in the order the window reads them. */\nconst STAY_MODE_LABELS: ReadonlyArray<{ mode: StayCheckInMode; label: string }> = [\n { mode: 'resource', label: 'As each resource is set' },\n { mode: 'stay', label: 'One per stay' },\n { mode: 'guest', label: 'One per guest' },\n]\n\ntype Answer =\n | { state: 'idle' | 'loading' }\n | { state: 'ready'; list: DayList }\n | { state: 'error'; error: string }\n\n/** The day's list as a printable 80 mm document, like the day totals. */\nexport function posCheckInsDocument(list: DayList): string {\n const rows = list.checkIns\n .map(\n (row) =>\n `<div class=\"row\"><span>${escapeHtml(`${row.customerName || row.customerEmail || 'Customer'} · ${checkInItemLabel(row)}`)}</span>` +\n `<span>${escapeHtml(\n row.status === 'checked_in'\n ? [checkInTimeLabel(row.checkedInAtMs, list.timeZone), describeWristband(row.wristband)].filter(Boolean).join(' ')\n : checkInRainCheckIsOpen(row)\n ? 'Rain check'\n : '—',\n )}</span></div>`,\n )\n .join('')\n return (\n '<!doctype html><html><head><meta charset=\"utf-8\">' +\n `<title>CHECK-INS</title><style>${POS_RECEIPT_STYLES}</style></head><body>` +\n `<div class=\"receipt\"><div class=\"center\"><div class=\"title\">CHECK-INS</div>` +\n `<div class=\"muted\">${escapeHtml(list.dayKey)} · ${list.totals.checkedIn} of ${list.totals.expected} checked in</div></div>` +\n `<hr class=\"rule\">${rows}</div></body></html>`\n )\n}\n\nfunction PosCheckInsBody(props: PosCheckInsCardProps) {\n const { hostId, canManagePos = false } = props\n const { data: user } = useUser()\n const [day, setDay] = useState<Dayjs | null>(null)\n const [answer, setAnswer] = useState<Answer>({ state: 'idle' })\n const [exporting, setExporting] = useState(false)\n /** The pass a rain check is being given on (AGL-4043). */\n const [rainCheckRow, setRainCheckRow] = useState<CheckInRow | null>(null)\n const [actionError, setActionError] = useState('')\n /** The stay whose guests are being changed (AGL-4043). */\n const [guestsFor, setGuestsFor] = useState<string | null>(null)\n\n const url = useCallback(\n (format?: 'csv') => {\n const params = new URLSearchParams({ hostId })\n if (day?.isValid()) params.set('day', day.format(DAY_FORMAT))\n if (format) params.set('format', format)\n return `${POS_CHECK_IN_ROUTE}?${params.toString()}`\n },\n [hostId, day],\n )\n\n const load = useCallback(async () => {\n if (!user || !canManagePos) return\n setAnswer({ state: 'loading' })\n try {\n const response = await authorizedFetch(user as never, url(), { method: 'GET' })\n const body = (await response.json().catch(() => ({}))) as Partial<DayList> & { error?: string }\n setAnswer(\n response.ok && body.checkIns\n ? { state: 'ready', list: body as DayList }\n : { state: 'error', error: body.error || 'The check-ins could not be read.' },\n )\n } catch {\n setAnswer({ state: 'error', error: 'The check-ins could not be read. Check the connection.' })\n }\n }, [user, canManagePos, url])\n\n useEffect(() => {\n void load()\n }, [load])\n\n const list = answer.state === 'ready' ? answer.list : null\n const todayKey = list ? zonedDayKey(Date.now(), list.timeZone) : ''\n\n const [savingStayMode, setSavingStayMode] = useState(false)\n /** The store's quick control for stays: one check-in per stay or per guest (AGL-4043). */\n const setStayMode = useCallback(\n async (mode: StayCheckInMode) => {\n setActionError('')\n setSavingStayMode(true)\n const done = await callPosOps(user, 'pos-check-in', {\n hostId,\n action: 'stay_mode',\n mode,\n ...(day?.isValid() ? { day: day.format(DAY_FORMAT) } : {}),\n })\n setSavingStayMode(false)\n if (!done.ok) return setActionError(done.body.error ?? 'The setting could not be saved.')\n await load()\n },\n [user, hostId, day, load],\n )\n\n const undoRainCheck = useCallback(\n async (row: CheckInRow) => {\n setActionError('')\n const done = await callPosOps<{ checkIn?: CheckInRow }>(user, 'pos-check-in', {\n hostId,\n action: 'undo_rain_check',\n id: row.id,\n })\n if (!done.ok) return setActionError(done.body.error ?? 'The rain check could not be undone.')\n await load()\n },\n [user, hostId, load],\n )\n\n const columns = useMemo<GridColDef[]>(\n () => [\n {\n field: 'customerName',\n headerName: 'Name',\n flex: 1,\n minWidth: 150,\n valueGetter: (_value: unknown, row: CheckInRow) => row.customerName || row.customerEmail || '',\n },\n {\n field: 'itemName',\n headerName: 'Item',\n flex: 1,\n minWidth: 160,\n valueGetter: (_value: unknown, row: CheckInRow) => checkInItemLabel(row),\n },\n {\n field: 'orderLabel',\n headerName: 'Order',\n minWidth: 100,\n valueGetter: (_value: unknown, row: CheckInRow) => row.orderLabel ?? (row.source === 'reservation' ? 'Stay' : ''),\n },\n {\n field: 'status',\n headerName: 'Status',\n minWidth: 120,\n valueGetter: (_value: unknown, row: CheckInRow) => checkInStatusLabel(row),\n renderCell: ({ row }: { row: CheckInRow }) =>\n row.status === 'checked_in' ? (\n <Chip size=\"small\" color=\"success\" label=\"Checked in\" />\n ) : checkInRainCheckIsOpen(row) ? (\n <Chip size=\"small\" color=\"info\" variant=\"outlined\" label=\"Rain check\" />\n ) : (\n <Chip size=\"small\" variant=\"outlined\" label=\"Expected\" />\n ),\n },\n {\n field: 'rainCheck',\n headerName: 'Rain check',\n minWidth: 200,\n flex: 1,\n valueGetter: (_value: unknown, row: CheckInRow) => rainCheckLabel(row),\n },\n {\n field: 'checkedInAtMs',\n headerName: 'Checked in at',\n type: 'number',\n minWidth: 120,\n valueFormatter: (value: number | null) => (list ? checkInTimeLabel(value, list.timeZone) : ''),\n },\n { field: 'checkedInByName', headerName: 'By', minWidth: 120 },\n {\n field: 'wristband',\n headerName: 'Wristband',\n minWidth: 120,\n valueGetter: (_value: unknown, row: CheckInRow) => describeWristband(row.wristband),\n },\n {\n // What a pass waiting at the window can still have done to it: a\n // rain check, or one taken back; and a stay's guest count (AGL-4043).\n // Not a value, so nothing to sort.\n field: 'rainCheckAction',\n headerName: '',\n minWidth: 150,\n sortable: false,\n filterable: false,\n hideable: false,\n disableColumnMenu: true,\n renderCell: ({ row }: { row: CheckInRow }) =>\n row.source === 'reservation' && row.reservationId ? (\n <Button size=\"small\" disabled={!canManagePos} onClick={() => setGuestsFor(row.reservationId)}>\n {'Guests'}\n </Button>\n ) : row.source !== 'order' || row.status !== 'expected' ? null : row.rainCheck ? (\n <Button size=\"small\" disabled={!canManagePos} onClick={() => void undoRainCheck(row)}>\n {'Undo rain check'}\n </Button>\n ) : (\n <Button size=\"small\" disabled={!canManagePos || !todayKey} onClick={() => setRainCheckRow(row)}>\n {'Rain check'}\n </Button>\n ),\n },\n ],\n [list, canManagePos, todayKey, undoRainCheck],\n )\n const rows = useMemo(() => (list ? list.checkIns.map((row) => ({ ...row, $id: row.id })) : []), [list])\n\n const exportCsv = async () => {\n if (!user || !list) return\n setExporting(true)\n try {\n const response = await authorizedFetch(user as never, url('csv'), { method: 'GET' })\n if (!response.ok) {\n const body = (await response.json().catch(() => ({}))) as { error?: string }\n setAnswer({ state: 'error', error: body.error || 'The spreadsheet could not be made.' })\n return\n }\n const blob = new Blob([await response.text()], { type: 'text/csv;charset=utf-8' })\n const href = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = href\n link.download = `check-ins-${list.dayKey}.csv`\n link.click()\n window.setTimeout(() => URL.revokeObjectURL(href), 1000)\n } finally {\n setExporting(false)\n }\n }\n\n return (\n <CardDisplay\n header={HEADER}\n help={HELP}\n HeaderProps={{\n action: (\n <Stack direction=\"row\" spacing={1}>\n <Button size=\"small\" onClick={() => void load()} disabled={!canManagePos || answer.state === 'loading'}>\n {'Refresh'}\n </Button>\n <Button size=\"small\" onClick={() => void exportCsv()} disabled={!list || exporting}>\n {'Export CSV'}\n </Button>\n <Button size=\"small\" onClick={() => list && printPosDocument(posCheckInsDocument(list))} disabled={!list}>\n {'Print'}\n </Button>\n </Stack>\n ),\n }}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2.5}>\n {!canManagePos ? (\n <Alert severity=\"info\">\n {'Check-ins are for members who can use the register: a site admin or editor with the \"Use the point of sale\" permission.'}\n </Alert>\n ) : null}\n <LocalizationProvider dateAdapter={AdapterDayjs}>\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={1.5} sx={{ alignItems: { sm: 'center' } }}>\n <DatePicker\n label=\"Day\"\n value={day}\n onChange={setDay}\n disabled={!canManagePos}\n slotProps={{ textField: { size: 'small' } }}\n />\n <Button size=\"small\" disabled={!canManagePos || !day} onClick={() => setDay(null)}>\n {'Today'}\n </Button>\n </Stack>\n </LocalizationProvider>\n <Stack spacing={0.5}>\n <Typography variant=\"subtitle2\" component=\"h3\" id=\"stay-check-in-label\">\n {'Stays at check-in'}\n </Typography>\n <ToggleButtonGroup\n exclusive\n size=\"small\"\n aria-labelledby=\"stay-check-in-label\"\n value={list?.stayCheckIn ?? 'resource'}\n onChange={(_event, mode: StayCheckInMode | null) => {\n if (mode && mode !== list?.stayCheckIn) void setStayMode(mode)\n }}\n disabled={!canManagePos || !list || savingStayMode}\n sx={{ flexWrap: 'wrap' }}\n >\n {STAY_MODE_LABELS.map((choice) => (\n <ToggleButton key={choice.mode} value={choice.mode}>\n {choice.label}\n </ToggleButton>\n ))}\n </ToggleButtonGroup>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'One per guest gives each guest of a stay their own check-in and wristband, by the stay’s guest count.'}\n </Typography>\n </Stack>\n {answer.state === 'loading' ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Reading who is due…'}\n </Typography>\n ) : null}\n {answer.state === 'error' ? <Alert severity=\"warning\">{answer.error}</Alert> : null}\n {list ? (\n <>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`${list.dayKey} · ${list.timeZone} · passes and stays that need check-in`}\n </Typography>\n {list.truncated ? (\n <Alert severity=\"warning\">\n {'This day has more check-ins than one list reads; some are missing here.'}\n </Alert>\n ) : null}\n <Stack direction=\"row\" spacing={3} sx={{ flexWrap: 'wrap', rowGap: 1.5 }}>\n <CommerceStatTile label=\"Expected\" value={String(list.totals.expected)} />\n <CommerceStatTile label=\"Checked in\" value={String(list.totals.checkedIn)} />\n <CommerceStatTile label=\"Still to come\" value={String(list.totals.expected - list.totals.checkedIn)} />\n {list.totals.rainChecks ? (\n <CommerceStatTile label=\"Rain checks\" value={String(list.totals.rainChecks)} />\n ) : null}\n </Stack>\n {actionError ? <Alert severity=\"warning\">{actionError}</Alert> : null}\n <ListTable\n aria-label=\"Check-ins on this day\"\n rows={rows}\n columns={columns}\n noRowsLabel=\"Nobody is due to check in on this day\"\n />\n </>\n ) : null}\n </Stack>\n <PosRainCheckDialog\n row={rainCheckRow}\n hostId={hostId}\n todayKey={todayKey}\n onClose={() => setRainCheckRow(null)}\n onDone={() => {\n setRainCheckRow(null)\n void load()\n }}\n />\n {guestsFor ? (\n <Suspense fallback={null}>\n <ReservationGuestsDialog\n reservationId={guestsFor}\n hostId={hostId}\n onClose={() => setGuestsFor(null)}\n onDone={() => {\n setGuestsFor(null)\n void load()\n }}\n />\n </Suspense>\n ) : null}\n </CardDisplay>\n )\n}\n\n/**\n * Today's check-ins (AGL-4043): beside the day totals, for a store with a\n * register, on a plan with the point of sale.\n */\nexport function PosCheckInsCard(props: PosCheckInsCardProps) {\n const firestore = useFirestore()\n // Whether the store has a register at all, as the day totals ask it.\n const { data: registers, status } = useFirestoreCollection<any>(\n () =>\n query(collection(firestore, 'hosts', props.hostId, 'registers'), orderBy(documentId()), limit(1)),\n [firestore, props.hostId],\n { idField: '$id' },\n )\n if (status === 'success' && !registers?.length) return null\n return (\n <EntitlementGatedCard\n hostId={props.hostId}\n feature=\"pos\"\n header={HEADER}\n help={HELP}\n upsell={'Checking in passes, camping and stays at the window, with wristbands, comes with the point of sale.'}\n >\n <PosCheckInsBody {...props} />\n </EntitlementGatedCard>\n )\n}\n\nPosCheckInsCard.displayName = 'PosCheckInsCard'\n\nexport default PosCheckInsCard\n"],"names":["pluginDocsHelp","CardDisplay","ListTable","authorizedFetch","useFirestore","useFirestoreCollection","useUser","Alert","Button","Chip","Stack","ToggleButton","ToggleButtonGroup","Typography","AdapterDayjs","DatePicker","LocalizationProvider","collection","documentId","limit","orderBy","query","lazy","Suspense","useCallback","useEffect","useMemo","useState","zonedDayKey","checkInItemLabel","checkInRainCheckIsOpen","checkInStatusLabel","checkInTimeLabel","describeWristband","POS_CHECK_IN_ROUTE","rainCheckLabel","callPosOps","PosRainCheckDialog","escapeHtml","CommerceStatTile","EntitlementGatedCard","POS_RECEIPT_STYLES","printPosDocument","ReservationGuestsDialog","HEADER","HELP","anchor","DAY_FORMAT","STAY_MODE_LABELS","mode","label","posCheckInsDocument","list","rows","checkIns","map","row","customerName","customerEmail","status","checkedInAtMs","timeZone","wristband","filter","Boolean","join","dayKey","totals","checkedIn","expected","PosCheckInsBody","props","hostId","canManagePos","data","user","day","setDay","answer","setAnswer","state","exporting","setExporting","rainCheckRow","setRainCheckRow","actionError","setActionError","guestsFor","setGuestsFor","url","format","params","URLSearchParams","isValid","set","toString","load","response","method","body","json","catch","ok","error","todayKey","Date","now","savingStayMode","setSavingStayMode","setStayMode","done","action","undoRainCheck","id","columns","field","headerName","flex","minWidth","valueGetter","_value","orderLabel","source","renderCell","size","color","variant","type","valueFormatter","value","sortable","filterable","hideable","disableColumnMenu","reservationId","disabled","onClick","rainCheck","$id","exportCsv","blob","Blob","text","href","URL","createObjectURL","link","document","createElement","download","click","window","setTimeout","revokeObjectURL","header","help","HeaderProps","direction","spacing","contentGutterX","contentGutterY","severity","dateAdapter","xs","sm","sx","alignItems","onChange","slotProps","textField","component","exclusive","aria-labelledby","stayCheckIn","_event","flexWrap","choice","truncated","rowGap","String","rainChecks","aria-label","noRowsLabel","onClose","onDone","fallback","PosCheckInsCard","firestore","registers","idField","length","feature","upsell","displayName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../../../libs/plugins/commerce/src/lib/components/console/pos-ops/pos-check-ins-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'use client'\n\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { ListTable } from '@aglyn/shared-ui-jsx/components/list-table.component'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport { useFirestore, useFirestoreCollection, useUser } from '@aglyn/tenant-feature-instance'\nimport { Alert, Button, Chip, Stack, ToggleButton, ToggleButtonGroup, Typography } from '@mui/material'\nimport type { GridColDef } from '@mui/x-data-grid'\nimport { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'\nimport { DatePicker } from '@mui/x-date-pickers/DatePicker'\nimport { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'\nimport type { Dayjs } from 'dayjs'\nimport { collection, documentId, limit, orderBy, query } from 'firebase/firestore'\nimport { lazy, Suspense, useCallback, useEffect, useMemo, useState } from 'react'\nimport { zonedDayKey } from '@aglyn/shared-util-timestamp/zoned-time'\nimport {\n checkInItemLabel,\n checkInRainCheckIsOpen,\n checkInStatusLabel,\n checkInTimeLabel,\n describeWristband,\n POS_CHECK_IN_ROUTE,\n rainCheckLabel,\n type CheckInDayTotals,\n type CheckInRow,\n} from '../../../model/commerce-check-in'\nimport { callPosOps } from './pos-ops-api'\nimport type { StayCheckInMode } from '../../../model/commerce-reservations'\nimport { PosRainCheckDialog } from './pos-rain-check-dialog.component'\nimport { escapeHtml } from '../../../utils/escape-html'\nimport CommerceStatTile from '../commerce-stat-tile.component'\nimport { EntitlementGatedCard } from '../entitlement-gate.component'\nimport { POS_RECEIPT_STYLES } from './pos-receipt'\nimport { printPosDocument } from './pos-shift-report.component'\n\n/*==========================================\n * TODAY'S CHECK-INS (AGL-4043): who is due at the window on a day, who is\n * checked in, by whom and with which wristband, from\n * `GET /api/commerce/pos-check-in`. The day is a whole, bounded list, so\n * the grid sorts it by any column itself.\n *=========================================*/\n\nexport interface PosCheckInsCardProps {\n hostId: string\n /** The viewer may work the register: what the route's gate asks. */\n canManagePos?: boolean\n}\n\n/** A stay's guest count (AGL-4043), loaded the first time it opens. */\nconst ReservationGuestsDialog = lazy(() => import('../reservation-guests-dialog.component'))\n\nconst HEADER = \"Today's check-ins\"\nconst HELP = pluginDocsHelp('posOperations', { anchor: '#check-in-at-the-window' })\nconst DAY_FORMAT = 'YYYY-MM-DD'\n\ninterface DayList {\n dayKey: string\n timeZone: string\n totals: CheckInDayTotals\n checkIns: CheckInRow[]\n truncated?: boolean\n /** How the store checks stays in (AGL-4043). */\n stayCheckIn?: StayCheckInMode\n}\n\n/** The quick control's choices, in the order the window reads them. */\nconst STAY_MODE_LABELS: ReadonlyArray<{ mode: StayCheckInMode; label: string }> = [\n { mode: 'resource', label: 'As each resource is set' },\n { mode: 'stay', label: 'One per stay' },\n { mode: 'guest', label: 'One per guest' },\n]\n\ntype Answer =\n | { state: 'idle' | 'loading' }\n | { state: 'ready'; list: DayList }\n | { state: 'error'; error: string }\n\n/** The day's list as a printable 80 mm document, like the day totals. */\nexport function posCheckInsDocument(list: DayList): string {\n const rows = list.checkIns\n .map(\n (row) =>\n `<div class=\"row\"><span>${escapeHtml(`${row.customerName || row.customerEmail || 'Customer'} · ${checkInItemLabel(row)}`)}</span>` +\n `<span>${escapeHtml(\n row.status === 'checked_in'\n ? [checkInTimeLabel(row.checkedInAtMs, list.timeZone), describeWristband(row.wristband)].filter(Boolean).join(' ')\n : checkInRainCheckIsOpen(row)\n ? 'Rain check'\n : '—',\n )}</span></div>`,\n )\n .join('')\n return (\n '<!doctype html><html><head><meta charset=\"utf-8\">' +\n `<title>CHECK-INS</title><style>${POS_RECEIPT_STYLES}</style></head><body>` +\n `<div class=\"receipt\"><div class=\"center\"><div class=\"title\">CHECK-INS</div>` +\n `<div class=\"muted\">${escapeHtml(list.dayKey)} · ${list.totals.checkedIn} of ${list.totals.expected} checked in</div></div>` +\n `<hr class=\"rule\">${rows}</div></body></html>`\n )\n}\n\nfunction PosCheckInsBody(props: PosCheckInsCardProps) {\n const { hostId, canManagePos = false } = props\n const { data: user } = useUser()\n const [day, setDay] = useState<Dayjs | null>(null)\n const [answer, setAnswer] = useState<Answer>({ state: 'idle' })\n const [exporting, setExporting] = useState(false)\n /** The pass a rain check is being given on (AGL-4043). */\n const [rainCheckRow, setRainCheckRow] = useState<CheckInRow | null>(null)\n const [actionError, setActionError] = useState('')\n /** The stay whose guests are being changed (AGL-4043). */\n const [guestsFor, setGuestsFor] = useState<string | null>(null)\n\n const url = useCallback(\n (format?: 'csv') => {\n const params = new URLSearchParams({ hostId })\n if (day?.isValid()) params.set('day', day.format(DAY_FORMAT))\n if (format) params.set('format', format)\n return `${POS_CHECK_IN_ROUTE}?${params.toString()}`\n },\n [hostId, day],\n )\n\n const load = useCallback(async () => {\n if (!user || !canManagePos) return\n setAnswer({ state: 'loading' })\n try {\n const response = await authorizedFetch(user as never, url(), { method: 'GET' })\n const body = (await response.json().catch(() => ({}))) as Partial<DayList> & { error?: string }\n setAnswer(\n response.ok && body.checkIns\n ? { state: 'ready', list: body as DayList }\n : { state: 'error', error: body.error || 'The check-ins could not be read.' },\n )\n } catch {\n setAnswer({ state: 'error', error: 'The check-ins could not be read. Check the connection.' })\n }\n }, [user, canManagePos, url])\n\n useEffect(() => {\n void load()\n }, [load])\n\n const list = answer.state === 'ready' ? answer.list : null\n const todayKey = list ? zonedDayKey(Date.now(), list.timeZone) : ''\n\n const [savingStayMode, setSavingStayMode] = useState(false)\n /** The store's quick control for stays: one check-in per stay or per guest (AGL-4043). */\n const setStayMode = useCallback(\n async (mode: StayCheckInMode) => {\n setActionError('')\n setSavingStayMode(true)\n const done = await callPosOps(user, 'pos-check-in', {\n hostId,\n action: 'stay_mode',\n mode,\n ...(day?.isValid() ? { day: day.format(DAY_FORMAT) } : {}),\n })\n setSavingStayMode(false)\n if (!done.ok) return setActionError(done.body.error ?? 'The setting could not be saved.')\n await load()\n },\n [user, hostId, day, load],\n )\n\n const undoRainCheck = useCallback(\n async (row: CheckInRow) => {\n setActionError('')\n const done = await callPosOps<{ checkIn?: CheckInRow }>(user, 'pos-check-in', {\n hostId,\n action: 'undo_rain_check',\n id: row.id,\n })\n if (!done.ok) return setActionError(done.body.error ?? 'The rain check could not be undone.')\n await load()\n },\n [user, hostId, load],\n )\n\n const columns = useMemo<GridColDef[]>(\n () => [\n {\n field: 'customerName',\n headerName: 'Name',\n flex: 1,\n minWidth: 150,\n valueGetter: (_value: unknown, row: CheckInRow) => row.customerName || row.customerEmail || '',\n },\n {\n // What a pass waiting at the window can still have done to it: a\n // rain check, or one taken back; and a stay's guest count (AGL-4043).\n // Not a value, so nothing to sort.\n //\n // Second, beside the name it acts on, rather than trailing. The grid\n // has no column pinning, so a trailing column sat past the right edge\n // of any window narrower than every column put together — on a\n // laptop, and always on a phone — and the window could not see it.\n field: 'rainCheckAction',\n headerName: 'Actions',\n minWidth: 150,\n sortable: false,\n filterable: false,\n hideable: false,\n disableColumnMenu: true,\n renderCell: ({ row }: { row: CheckInRow }) =>\n row.source === 'reservation' && row.reservationId ? (\n <Button size=\"small\" disabled={!canManagePos} onClick={() => setGuestsFor(row.reservationId)}>\n {'Guests'}\n </Button>\n ) : row.source !== 'order' || row.status !== 'expected' ? null : row.rainCheck ? (\n <Button size=\"small\" disabled={!canManagePos} onClick={() => void undoRainCheck(row)}>\n {'Undo rain check'}\n </Button>\n ) : (\n <Button size=\"small\" disabled={!canManagePos || !todayKey} onClick={() => setRainCheckRow(row)}>\n {'Rain check'}\n </Button>\n ),\n },\n {\n field: 'itemName',\n headerName: 'Item',\n flex: 1,\n minWidth: 160,\n valueGetter: (_value: unknown, row: CheckInRow) => checkInItemLabel(row),\n },\n {\n field: 'orderLabel',\n headerName: 'Order',\n minWidth: 100,\n valueGetter: (_value: unknown, row: CheckInRow) => row.orderLabel ?? (row.source === 'reservation' ? 'Stay' : ''),\n },\n {\n field: 'status',\n headerName: 'Status',\n minWidth: 120,\n valueGetter: (_value: unknown, row: CheckInRow) => checkInStatusLabel(row),\n renderCell: ({ row }: { row: CheckInRow }) =>\n row.status === 'checked_in' ? (\n <Chip size=\"small\" color=\"success\" label=\"Checked in\" />\n ) : checkInRainCheckIsOpen(row) ? (\n <Chip size=\"small\" color=\"info\" variant=\"outlined\" label=\"Rain check\" />\n ) : (\n <Chip size=\"small\" variant=\"outlined\" label=\"Expected\" />\n ),\n },\n {\n field: 'rainCheck',\n headerName: 'Rain check',\n minWidth: 200,\n flex: 1,\n valueGetter: (_value: unknown, row: CheckInRow) => rainCheckLabel(row),\n },\n {\n field: 'checkedInAtMs',\n headerName: 'Checked in at',\n type: 'number',\n minWidth: 120,\n valueFormatter: (value: number | null) => (list ? checkInTimeLabel(value, list.timeZone) : ''),\n },\n { field: 'checkedInByName', headerName: 'By', minWidth: 120 },\n {\n field: 'wristband',\n headerName: 'Wristband',\n minWidth: 120,\n valueGetter: (_value: unknown, row: CheckInRow) => describeWristband(row.wristband),\n },\n ],\n [list, canManagePos, todayKey, undoRainCheck],\n )\n const rows = useMemo(() => (list ? list.checkIns.map((row) => ({ ...row, $id: row.id })) : []), [list])\n\n const exportCsv = async () => {\n if (!user || !list) return\n setExporting(true)\n try {\n const response = await authorizedFetch(user as never, url('csv'), { method: 'GET' })\n if (!response.ok) {\n const body = (await response.json().catch(() => ({}))) as { error?: string }\n setAnswer({ state: 'error', error: body.error || 'The spreadsheet could not be made.' })\n return\n }\n const blob = new Blob([await response.text()], { type: 'text/csv;charset=utf-8' })\n const href = URL.createObjectURL(blob)\n const link = document.createElement('a')\n link.href = href\n link.download = `check-ins-${list.dayKey}.csv`\n link.click()\n window.setTimeout(() => URL.revokeObjectURL(href), 1000)\n } finally {\n setExporting(false)\n }\n }\n\n return (\n <CardDisplay\n header={HEADER}\n help={HELP}\n HeaderProps={{\n action: (\n <Stack direction=\"row\" spacing={1}>\n <Button size=\"small\" onClick={() => void load()} disabled={!canManagePos || answer.state === 'loading'}>\n {'Refresh'}\n </Button>\n <Button size=\"small\" onClick={() => void exportCsv()} disabled={!list || exporting}>\n {'Export CSV'}\n </Button>\n <Button size=\"small\" onClick={() => list && printPosDocument(posCheckInsDocument(list))} disabled={!list}>\n {'Print'}\n </Button>\n </Stack>\n ),\n }}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={2.5}>\n {!canManagePos ? (\n <Alert severity=\"info\">\n {'Check-ins are for members who can use the register: a site admin or editor with the \"Use the point of sale\" permission.'}\n </Alert>\n ) : null}\n <LocalizationProvider dateAdapter={AdapterDayjs}>\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={1.5} sx={{ alignItems: { sm: 'center' } }}>\n <DatePicker\n label=\"Day\"\n value={day}\n onChange={setDay}\n disabled={!canManagePos}\n slotProps={{ textField: { size: 'small' } }}\n />\n <Button size=\"small\" disabled={!canManagePos || !day} onClick={() => setDay(null)}>\n {'Today'}\n </Button>\n </Stack>\n </LocalizationProvider>\n <Stack spacing={0.5}>\n <Typography variant=\"subtitle2\" component=\"h3\" id=\"stay-check-in-label\">\n {'Stays at check-in'}\n </Typography>\n <ToggleButtonGroup\n exclusive\n size=\"small\"\n aria-labelledby=\"stay-check-in-label\"\n value={list?.stayCheckIn ?? 'resource'}\n onChange={(_event, mode: StayCheckInMode | null) => {\n if (mode && mode !== list?.stayCheckIn) void setStayMode(mode)\n }}\n disabled={!canManagePos || !list || savingStayMode}\n sx={{ flexWrap: 'wrap' }}\n >\n {STAY_MODE_LABELS.map((choice) => (\n <ToggleButton key={choice.mode} value={choice.mode}>\n {choice.label}\n </ToggleButton>\n ))}\n </ToggleButtonGroup>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'One per guest gives each guest of a stay their own check-in and wristband, by the stay’s guest count.'}\n </Typography>\n </Stack>\n {answer.state === 'loading' ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Reading who is due…'}\n </Typography>\n ) : null}\n {answer.state === 'error' ? <Alert severity=\"warning\">{answer.error}</Alert> : null}\n {list ? (\n <>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {`${list.dayKey} · ${list.timeZone} · passes and stays that need check-in`}\n </Typography>\n {list.truncated ? (\n <Alert severity=\"warning\">\n {'This day has more check-ins than one list reads; some are missing here.'}\n </Alert>\n ) : null}\n <Stack direction=\"row\" spacing={3} sx={{ flexWrap: 'wrap', rowGap: 1.5 }}>\n <CommerceStatTile label=\"Expected\" value={String(list.totals.expected)} />\n <CommerceStatTile label=\"Checked in\" value={String(list.totals.checkedIn)} />\n <CommerceStatTile label=\"Still to come\" value={String(list.totals.expected - list.totals.checkedIn)} />\n {list.totals.rainChecks ? (\n <CommerceStatTile label=\"Rain checks\" value={String(list.totals.rainChecks)} />\n ) : null}\n </Stack>\n {actionError ? <Alert severity=\"warning\">{actionError}</Alert> : null}\n <ListTable\n aria-label=\"Check-ins on this day\"\n rows={rows}\n columns={columns}\n noRowsLabel=\"Nobody is due to check in on this day\"\n />\n </>\n ) : null}\n </Stack>\n <PosRainCheckDialog\n row={rainCheckRow}\n hostId={hostId}\n todayKey={todayKey}\n onClose={() => setRainCheckRow(null)}\n onDone={() => {\n setRainCheckRow(null)\n void load()\n }}\n />\n {guestsFor ? (\n <Suspense fallback={null}>\n <ReservationGuestsDialog\n reservationId={guestsFor}\n hostId={hostId}\n onClose={() => setGuestsFor(null)}\n onDone={() => {\n setGuestsFor(null)\n void load()\n }}\n />\n </Suspense>\n ) : null}\n </CardDisplay>\n )\n}\n\n/**\n * Today's check-ins (AGL-4043): beside the day totals, for a store with a\n * register, on a plan with the point of sale.\n */\nexport function PosCheckInsCard(props: PosCheckInsCardProps) {\n const firestore = useFirestore()\n // Whether the store has a register at all, as the day totals ask it.\n const { data: registers, status } = useFirestoreCollection<any>(\n () =>\n query(collection(firestore, 'hosts', props.hostId, 'registers'), orderBy(documentId()), limit(1)),\n [firestore, props.hostId],\n { idField: '$id' },\n )\n if (status === 'success' && !registers?.length) return null\n return (\n <EntitlementGatedCard\n hostId={props.hostId}\n feature=\"pos\"\n header={HEADER}\n help={HELP}\n upsell={'Checking in passes, camping and stays at the window, with wristbands, comes with the point of sale.'}\n >\n <PosCheckInsBody {...props} />\n </EntitlementGatedCard>\n )\n}\n\nPosCheckInsCard.displayName = 'PosCheckInsCard'\n\nexport default PosCheckInsCard\n"],"names":["pluginDocsHelp","CardDisplay","ListTable","authorizedFetch","useFirestore","useFirestoreCollection","useUser","Alert","Button","Chip","Stack","ToggleButton","ToggleButtonGroup","Typography","AdapterDayjs","DatePicker","LocalizationProvider","collection","documentId","limit","orderBy","query","lazy","Suspense","useCallback","useEffect","useMemo","useState","zonedDayKey","checkInItemLabel","checkInRainCheckIsOpen","checkInStatusLabel","checkInTimeLabel","describeWristband","POS_CHECK_IN_ROUTE","rainCheckLabel","callPosOps","PosRainCheckDialog","escapeHtml","CommerceStatTile","EntitlementGatedCard","POS_RECEIPT_STYLES","printPosDocument","ReservationGuestsDialog","HEADER","HELP","anchor","DAY_FORMAT","STAY_MODE_LABELS","mode","label","posCheckInsDocument","list","rows","checkIns","map","row","customerName","customerEmail","status","checkedInAtMs","timeZone","wristband","filter","Boolean","join","dayKey","totals","checkedIn","expected","PosCheckInsBody","props","hostId","canManagePos","data","user","day","setDay","answer","setAnswer","state","exporting","setExporting","rainCheckRow","setRainCheckRow","actionError","setActionError","guestsFor","setGuestsFor","url","format","params","URLSearchParams","isValid","set","toString","load","response","method","body","json","catch","ok","error","todayKey","Date","now","savingStayMode","setSavingStayMode","setStayMode","done","action","undoRainCheck","id","columns","field","headerName","flex","minWidth","valueGetter","_value","sortable","filterable","hideable","disableColumnMenu","renderCell","source","reservationId","size","disabled","onClick","rainCheck","orderLabel","color","variant","type","valueFormatter","value","$id","exportCsv","blob","Blob","text","href","URL","createObjectURL","link","document","createElement","download","click","window","setTimeout","revokeObjectURL","header","help","HeaderProps","direction","spacing","contentGutterX","contentGutterY","severity","dateAdapter","xs","sm","sx","alignItems","onChange","slotProps","textField","component","exclusive","aria-labelledby","stayCheckIn","_event","flexWrap","choice","truncated","rowGap","String","rainChecks","aria-label","noRowsLabel","onClose","onDone","fallback","PosCheckInsCard","firestore","registers","idField","length","feature","upsell","displayName"],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import * as CommerceModel from '../../model';
18
+ /** A quote as the list reads it: the order document and its id. */
19
+ export type QuoteRow = CommerceModel.HostOrder & {
20
+ $id: string;
21
+ };
22
+ export interface QuoteEditorDialogProps {
23
+ hostId: string;
24
+ /** The quote to edit, or `null` for a new one. */
25
+ quote: QuoteRow | null;
26
+ /** The store's products, for the product picker. */
27
+ products: readonly Record<string, any>[];
28
+ /** Holds "Create and edit quotes" (`commerce.quotes`). */
29
+ canEdit: boolean;
30
+ /** Holds "Send quotes and invoices to customers" (`commerce.quotes.send`). */
31
+ canSend: boolean;
32
+ onClose: () => void;
33
+ }
34
+ /**
35
+ * The quote editor (AGL-4093): who it is for, its lines (products with their
36
+ * options and add-ons, typed items, things included at no charge), discount,
37
+ * shipping, notes and terms, with the totals worked out as it is edited. The
38
+ * server prices and saves it; the totals here are the same function's answer
39
+ * over the same inputs, and a connected tax service's figure arrives on save.
40
+ */
41
+ export declare function QuoteEditorDialog(props: QuoteEditorDialogProps): import("react").JSX.Element;
42
+ export declare namespace QuoteEditorDialog {
43
+ var displayName: string;
44
+ }
45
+ export default QuoteEditorDialog;