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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/README.md +4 -2
  2. package/package.json +13 -13
  3. package/src/lib/components/cart-fulfillment.d.ts +3 -0
  4. package/src/lib/components/cart-fulfillment.js.map +1 -1
  5. package/src/lib/components/cart.js +14 -4
  6. package/src/lib/components/cart.js.map +1 -1
  7. package/src/lib/components/commerce-console-page.js +2 -1
  8. package/src/lib/components/commerce-console-page.js.map +1 -1
  9. package/src/lib/components/console/host-orders-card.component.d.ts +6 -0
  10. package/src/lib/components/console/host-orders-card.component.js +3 -2
  11. package/src/lib/components/console/host-orders-card.component.js.map +1 -1
  12. package/src/lib/components/console/invoice-send.component.d.ts +44 -0
  13. package/src/lib/components/console/invoice-send.component.js +237 -0
  14. package/src/lib/components/console/invoice-send.component.js.map +1 -0
  15. package/src/lib/components/console/order-detail-dialog.component.d.ts +5 -0
  16. package/src/lib/components/console/order-detail-dialog.component.js +9 -2
  17. package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
  18. package/src/lib/components/console/order-invoice.component.d.ts +9 -0
  19. package/src/lib/components/console/order-invoice.component.js +27 -2
  20. package/src/lib/components/console/order-invoice.component.js.map +1 -1
  21. package/src/lib/components/console/pos/pos-item-dialog.component.js +3 -2
  22. package/src/lib/components/console/pos/pos-item-dialog.component.js.map +1 -1
  23. package/src/lib/components/console/pos-kiosk-page.component.js +2 -1
  24. package/src/lib/components/console/pos-kiosk-page.component.js.map +1 -1
  25. package/src/lib/components/console/pos-page.component.js +1 -1
  26. package/src/lib/components/console/pos-page.component.js.map +1 -1
  27. package/src/lib/components/console/product-add-ons-fields.component.d.ts +41 -0
  28. package/src/lib/components/console/product-add-ons-fields.component.js +356 -0
  29. package/src/lib/components/console/product-add-ons-fields.component.js.map +1 -0
  30. package/src/lib/components/console/product-editor-dialog.component.js +31 -5
  31. package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
  32. package/src/lib/components/console/product-register-fields.component.d.ts +4 -5
  33. package/src/lib/components/console/product-register-fields.component.js +8 -197
  34. package/src/lib/components/console/product-register-fields.component.js.map +1 -1
  35. package/src/lib/components/console/products-hub-zone.component.js +6 -0
  36. package/src/lib/components/console/products-hub-zone.component.js.map +1 -1
  37. package/src/lib/components/console/quote-editor-dialog.component.d.ts +29 -0
  38. package/src/lib/components/console/quote-editor-dialog.component.js +102 -4
  39. package/src/lib/components/console/quote-editor-dialog.component.js.map +1 -1
  40. package/src/lib/components/console/quote-pay-link.component.d.ts +8 -1
  41. package/src/lib/components/console/quote-pay-link.component.js +29 -3
  42. package/src/lib/components/console/quote-pay-link.component.js.map +1 -1
  43. package/src/lib/components/console/quote-proofs.component.d.ts +11 -0
  44. package/src/lib/components/console/quote-proofs.component.js +68 -0
  45. package/src/lib/components/console/quote-proofs.component.js.map +1 -1
  46. package/src/lib/components/console/quote-send.component.d.ts +42 -0
  47. package/src/lib/components/console/quote-send.component.js +304 -0
  48. package/src/lib/components/console/quote-send.component.js.map +1 -0
  49. package/src/lib/components/console/quote-start.component.d.ts +45 -0
  50. package/src/lib/components/console/quote-start.component.js +182 -0
  51. package/src/lib/components/console/quote-start.component.js.map +1 -0
  52. package/src/lib/components/product-add-ons.d.ts +28 -0
  53. package/src/lib/components/product-add-ons.js +136 -0
  54. package/src/lib/components/product-add-ons.js.map +1 -0
  55. package/src/lib/components/product-detail.d.ts +16 -0
  56. package/src/lib/components/product-detail.js +112 -19
  57. package/src/lib/components/product-detail.js.map +1 -1
  58. package/src/lib/components/product-grid.d.ts +8 -2
  59. package/src/lib/components/product-grid.js +6 -1
  60. package/src/lib/components/product-grid.js.map +1 -1
  61. package/src/lib/components/product-options-field-body.d.ts +44 -0
  62. package/src/lib/components/product-options-field-body.js +260 -0
  63. package/src/lib/components/product-options-field-body.js.map +1 -0
  64. package/src/lib/components/product-options-field.d.ts +32 -0
  65. package/src/lib/components/product-options-field.js +128 -0
  66. package/src/lib/components/product-options-field.js.map +1 -0
  67. package/src/lib/components/quote-page-body.js +39 -20
  68. package/src/lib/components/quote-page-body.js.map +1 -1
  69. package/src/lib/model/commerce-cart.d.ts +15 -3
  70. package/src/lib/model/commerce-cart.js +10 -3
  71. package/src/lib/model/commerce-cart.js.map +1 -1
  72. package/src/lib/model/commerce-invoices.d.ts +139 -0
  73. package/src/lib/model/commerce-invoices.js +343 -0
  74. package/src/lib/model/commerce-invoices.js.map +1 -0
  75. package/src/lib/model/commerce-orders.d.ts +35 -5
  76. package/src/lib/model/commerce-orders.js +3 -0
  77. package/src/lib/model/commerce-orders.js.map +1 -1
  78. package/src/lib/model/commerce-pos-kiosk.d.ts +1 -1
  79. package/src/lib/model/commerce-pos-kiosk.js +3 -2
  80. package/src/lib/model/commerce-pos-kiosk.js.map +1 -1
  81. package/src/lib/model/commerce-product-field.d.ts +23 -0
  82. package/src/lib/model/commerce-product-field.js +26 -0
  83. package/src/lib/model/commerce-product-field.js.map +1 -0
  84. package/src/lib/model/commerce-quote-email.d.ts +81 -0
  85. package/src/lib/model/commerce-quote-email.js +170 -0
  86. package/src/lib/model/commerce-quote-email.js.map +1 -0
  87. package/src/lib/model/commerce-quote-pay.d.ts +49 -6
  88. package/src/lib/model/commerce-quote-pay.js +69 -36
  89. package/src/lib/model/commerce-quote-pay.js.map +1 -1
  90. package/src/lib/model/commerce-quote-request.d.ts +93 -0
  91. package/src/lib/model/commerce-quote-request.js +207 -0
  92. package/src/lib/model/commerce-quote-request.js.map +1 -0
  93. package/src/lib/model/commerce-quotes.d.ts +81 -0
  94. package/src/lib/model/commerce-quotes.js +1 -1
  95. package/src/lib/model/commerce-quotes.js.map +1 -1
  96. package/src/lib/model/commerce.d.ts +18 -0
  97. package/src/lib/model/commerce.js +26 -0
  98. package/src/lib/model/commerce.js.map +1 -1
  99. package/src/lib/model/index.d.ts +3 -0
  100. package/src/lib/model/index.js +3 -0
  101. package/src/lib/model/index.js.map +1 -1
  102. package/src/lib/model/product-modifiers.d.ts +74 -4
  103. package/src/lib/model/product-modifiers.js +131 -10
  104. package/src/lib/model/product-modifiers.js.map +1 -1
  105. package/src/lib/plugin.js +19 -0
  106. package/src/lib/plugin.js.map +1 -1
  107. package/src/lib/server/billing-webhook.js +164 -98
  108. package/src/lib/server/billing-webhook.js.map +1 -1
  109. package/src/lib/server/cart-checkout.js +14 -2
  110. package/src/lib/server/cart-checkout.js.map +1 -1
  111. package/src/lib/server/cart.d.ts +5 -0
  112. package/src/lib/server/cart.js +41 -4
  113. package/src/lib/server/cart.js.map +1 -1
  114. package/src/lib/server/catalog.d.ts +6 -0
  115. package/src/lib/server/catalog.js +2 -0
  116. package/src/lib/server/catalog.js.map +1 -1
  117. package/src/lib/server/checkout-extras.js +3 -1
  118. package/src/lib/server/checkout-extras.js.map +1 -1
  119. package/src/lib/server/checkout.js +28 -3
  120. package/src/lib/server/checkout.js.map +1 -1
  121. package/src/lib/server/commerce-pdf.d.ts +5 -1
  122. package/src/lib/server/commerce-pdf.js +37 -10
  123. package/src/lib/server/commerce-pdf.js.map +1 -1
  124. package/src/lib/server/draft-order.js +23 -3
  125. package/src/lib/server/draft-order.js.map +1 -1
  126. package/src/lib/server/invoice-email.d.ts +76 -0
  127. package/src/lib/server/invoice-email.js +183 -0
  128. package/src/lib/server/invoice-email.js.map +1 -0
  129. package/src/lib/server/local-fulfillment.js +5 -1
  130. package/src/lib/server/local-fulfillment.js.map +1 -1
  131. package/src/lib/server/order-invoice-send.d.ts +43 -0
  132. package/src/lib/server/order-invoice-send.js +218 -0
  133. package/src/lib/server/order-invoice-send.js.map +1 -0
  134. package/src/lib/server/order-status.d.ts +11 -0
  135. package/src/lib/server/order-status.js +44 -8
  136. package/src/lib/server/order-status.js.map +1 -1
  137. package/src/lib/server/person-eraser.d.ts +3 -2
  138. package/src/lib/server/person-eraser.js +25 -6
  139. package/src/lib/server/person-eraser.js.map +1 -1
  140. package/src/lib/server/pos-offline-sync.js +1 -1
  141. package/src/lib/server/pos-offline-sync.js.map +1 -1
  142. package/src/lib/server/pos-order.js +1 -1
  143. package/src/lib/server/pos-order.js.map +1 -1
  144. package/src/lib/server/product.d.ts +26 -0
  145. package/src/lib/server/product.js +18 -0
  146. package/src/lib/server/product.js.map +1 -1
  147. package/src/lib/server/products-write.js +5 -2
  148. package/src/lib/server/products-write.js.map +1 -1
  149. package/src/lib/server/quote-email.d.ts +85 -0
  150. package/src/lib/server/quote-email.js +211 -0
  151. package/src/lib/server/quote-email.js.map +1 -0
  152. package/src/lib/server/quote-link-token.d.ts +11 -0
  153. package/src/lib/server/quote-link-token.js +21 -0
  154. package/src/lib/server/quote-link-token.js.map +1 -1
  155. package/src/lib/server/quote-pay.d.ts +8 -3
  156. package/src/lib/server/quote-pay.js +105 -43
  157. package/src/lib/server/quote-pay.js.map +1 -1
  158. package/src/lib/server/quote.d.ts +11 -0
  159. package/src/lib/server/quote.js +309 -12
  160. package/src/lib/server/quote.js.map +1 -1
  161. package/src/lib/server/site-page-resolver.js +2 -1
  162. package/src/lib/server/site-page-resolver.js.map +1 -1
  163. package/src/lib/server.js +5 -0
  164. package/src/lib/server.js.map +1 -1
  165. package/src/lib/site.js +8 -0
  166. package/src/lib/site.js.map +1 -1
  167. package/src/lib/tenant-emails.js +243 -0
  168. package/src/lib/tenant-emails.js.map +1 -1
  169. package/src/lib/utils/add-to-cart.d.ts +8 -0
  170. package/src/lib/utils/add-to-cart.js +10 -2
  171. package/src/lib/utils/add-to-cart.js.map +1 -1
  172. package/src/lib/utils/commerce-document-pdf.d.ts +5 -0
  173. package/src/lib/utils/commerce-document-pdf.js +6 -1
  174. package/src/lib/utils/commerce-document-pdf.js.map +1 -1
  175. package/src/lib/utils/invoice-email-content.d.ts +45 -0
  176. package/src/lib/utils/invoice-email-content.js +126 -0
  177. package/src/lib/utils/invoice-email-content.js.map +1 -0
  178. package/src/lib/utils/order-invoice.d.ts +1 -1
  179. package/src/lib/utils/order-invoice.js +14 -6
  180. package/src/lib/utils/order-invoice.js.map +1 -1
  181. package/src/lib/utils/quote-email-content.d.ts +63 -0
  182. package/src/lib/utils/quote-email-content.js +157 -0
  183. package/src/lib/utils/quote-email-content.js.map +1 -0
@@ -29,7 +29,8 @@ import { doc } from "firebase/firestore";
29
29
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
30
30
  import { downloadCommercePdf } from "./commerce-pdf-download.js";
31
31
  import { QuotePayLinkSection } from "./quote-pay-link.component.js";
32
- import { QuoteProofsSection } from "./quote-proofs.component.js";
32
+ import { QuoteProofsSection, QuoteRequestFilesSection } from "./quote-proofs.component.js";
33
+ import { QuoteSendSection } from "./quote-send.component.js";
33
34
  const REFUSAL = commerceSitePermissionRefusal('commerce.quotes');
34
35
  const SEARCH_DEBOUNCE_MS = 250;
35
36
  const money = (cents)=>posMoney(cents);
@@ -114,6 +115,34 @@ function formFromQuote(quote, requireProofApproval) {
114
115
  requireProofApproval: section ? section.requireProofApproval === true : requireProofApproval
115
116
  };
116
117
  }
118
+ /** A new quote's form, filled in from where it was started (AGL-4098). */ function formFromStart(start, requireProofApproval) {
119
+ var _customer_record, _customer_name, _customer_company, _customer_email, _customer_phone;
120
+ const blank = formFromQuote(null, requireProofApproval);
121
+ const { customer, lines, notes } = start.prefill;
122
+ return _extends({}, blank, {
123
+ customer: {
124
+ record: (_customer_record = customer.record) != null ? _customer_record : null,
125
+ name: (_customer_name = customer.name) != null ? _customer_name : '',
126
+ company: (_customer_company = customer.company) != null ? _customer_company : '',
127
+ email: (_customer_email = customer.email) != null ? _customer_email : '',
128
+ phone: (_customer_phone = customer.phone) != null ? _customer_phone : ''
129
+ },
130
+ lines: lines.map((line)=>{
131
+ var _line_variantId, _line_modifiers, _line_description;
132
+ return {
133
+ key: nextLineKey(),
134
+ kind: 'catalog',
135
+ productId: line.productId,
136
+ variantId: (_line_variantId = line.variantId) != null ? _line_variantId : '',
137
+ quantity: String(line.quantity || 1),
138
+ modifiers: (_line_modifiers = line.modifiers) != null ? _line_modifiers : [],
139
+ description: (_line_description = line.description) != null ? _line_description : '',
140
+ included: line.included === true
141
+ };
142
+ }),
143
+ notes: notes != null ? notes : ''
144
+ });
145
+ }
117
146
  function lineRequest(line) {
118
147
  var _centsOf;
119
148
  const quantity = Number(line.quantity);
@@ -192,9 +221,10 @@ function addressBody(address) {
192
221
  * server prices and saves it; the totals here are the same function's answer
193
222
  * over the same inputs, and a connected tax service's figure arrives on save.
194
223
  */ export function QuoteEditorDialog(props) {
195
- var _centsOf, _ref, _ref1;
196
- var _quote_quote_tax, _quote_quote, _quote_quote1, _quote_quote2;
224
+ var _props_start, _centsOf, _ref, _start_files, _ref1;
225
+ var _quote_quote_tax, _quote_quote, _quote_quote1, _quote_quote2, _quote_quote3;
197
226
  const { hostId, quote, products, canEdit, canSend, onClose } = props;
227
+ const start = quote ? null : (_props_start = props.start) != null ? _props_start : null;
198
228
  const firestore = useFirestore();
199
229
  const { data: user } = useUser();
200
230
  const { enqueueSnackbar } = useSnackbar();
@@ -204,7 +234,7 @@ function addressBody(address) {
204
234
  hostId
205
235
  ]);
206
236
  const storeDefault = CommerceModel.quoteRequiresProofApprovalByDefault(store == null ? void 0 : store.quotes);
207
- const [form, setForm] = useState(()=>formFromQuote(quote, storeDefault));
237
+ const [form, setForm] = useState(()=>start ? formFromStart(start, storeDefault) : formFromQuote(quote, storeDefault));
208
238
  // The version this form was opened on. A change saved elsewhere while it is
209
239
  // open arrives on `quote`; the save still names this one, so the server
210
240
  // refuses rather than overwrite that change. A proof added or a revision
@@ -323,6 +353,8 @@ function addressBody(address) {
323
353
  }, quote ? {
324
354
  quoteId: quote.$id,
325
355
  baseUpdatedAtMs
356
+ } : {}, !quote && (start == null ? void 0 : start.from) ? {
357
+ from: start.from
326
358
  } : {}, {
327
359
  quote: quoteBody(_extends({}, form, {
328
360
  requireProofApproval
@@ -352,6 +384,7 @@ function addressBody(address) {
352
384
  quote,
353
385
  hostId,
354
386
  baseUpdatedAtMs,
387
+ start,
355
388
  form,
356
389
  requireProofApproval,
357
390
  enqueueSnackbar,
@@ -469,6 +502,13 @@ function addressBody(address) {
469
502
  severity: "success",
470
503
  children: (quote == null ? void 0 : (_quote_quote2 = quote.quote) == null ? void 0 : _quote_quote2.paidAtMs) ? `Paid ${new Date(quote.quote.paidAtMs).toLocaleDateString()}. It is an order now and can no longer be changed.` : 'This quote has been paid, so it is an order now and can no longer be changed.'
471
504
  }) : null,
505
+ quote ? /*#__PURE__*/ _jsx(QuoteSendSection, {
506
+ hostId: hostId,
507
+ quoteId: quote.$id,
508
+ quote: quote,
509
+ canSend: canSend,
510
+ edited: edited
511
+ }) : null,
472
512
  quote ? /*#__PURE__*/ _jsx(QuotePayLinkSection, {
473
513
  hostId: hostId,
474
514
  quoteId: quote.$id,
@@ -485,6 +525,17 @@ function addressBody(address) {
485
525
  if (updatedAtMs) setBaseUpdatedAtMs(updatedAtMs);
486
526
  }
487
527
  }) : null,
528
+ (start == null ? void 0 : start.request) ? /*#__PURE__*/ _jsx(QuoteStartedFromRequest, {
529
+ formName: start.request.formName,
530
+ receivedAtMs: start.request.receivedAtMs,
531
+ files: (_start_files = start.files) != null ? _start_files : [],
532
+ threaded: start.threaded === true
533
+ }) : null,
534
+ (quote == null ? void 0 : (_quote_quote3 = quote.quote) == null ? void 0 : _quote_quote3.request) ? /*#__PURE__*/ _jsx(QuoteRequestFilesSection, {
535
+ hostId: hostId,
536
+ quoteId: quote.$id,
537
+ quote: quote
538
+ }) : null,
488
539
  taxBasis.kind === 'none' && taxBasis.reason === 'undecided' ? /*#__PURE__*/ _jsx(PrerequisiteNotice, {
489
540
  href: taxesHref != null ? taxesHref : undefined,
490
541
  actionLabel: "Open Taxes",
@@ -781,6 +832,53 @@ function addressBody(address) {
781
832
  });
782
833
  }
783
834
  QuoteEditorDialog.displayName = 'QuoteEditorDialog';
835
+ /** A new quote's request (AGL-4098): which form sent it and when, its files by name, and its conversation. */ function QuoteStartedFromRequest(props) {
836
+ const { formName, receivedAtMs, files, threaded } = props;
837
+ const when = receivedAtMs ? ` on ${new Date(receivedAtMs).toLocaleString(undefined, {
838
+ dateStyle: 'medium',
839
+ timeStyle: 'short'
840
+ })}` : '';
841
+ return /*#__PURE__*/ _jsx(Alert, {
842
+ severity: "info",
843
+ children: /*#__PURE__*/ _jsxs(Stack, {
844
+ spacing: 1,
845
+ children: [
846
+ /*#__PURE__*/ _jsx(Typography, {
847
+ variant: "body2",
848
+ children: `From a request sent through “${formName}”${when}.`
849
+ }),
850
+ files.length ? /*#__PURE__*/ _jsxs(Stack, {
851
+ spacing: 0.5,
852
+ children: [
853
+ /*#__PURE__*/ _jsx(Typography, {
854
+ variant: "caption",
855
+ color: "text.secondary",
856
+ children: 'Their files, kept on the quote as the customer’s:'
857
+ }),
858
+ /*#__PURE__*/ _jsx(Stack, {
859
+ direction: "row",
860
+ spacing: 1,
861
+ useFlexGap: true,
862
+ sx: {
863
+ flexWrap: 'wrap'
864
+ },
865
+ children: files.map((file)=>/*#__PURE__*/ _jsx(Chip, {
866
+ size: "small",
867
+ variant: "outlined",
868
+ label: file.name
869
+ }, file.id))
870
+ })
871
+ ]
872
+ }) : null,
873
+ /*#__PURE__*/ _jsx(Typography, {
874
+ variant: "caption",
875
+ color: "text.secondary",
876
+ children: threaded ? 'When you email the quote, it replies to the confirmation they were sent, in the same conversation.' : 'They weren’t sent a confirmation, so the quote’s email starts the conversation.'
877
+ })
878
+ ]
879
+ })
880
+ });
881
+ }
784
882
  /** Who the quote is for: a person the workspace keeps, or details typed here. */ function QuoteCustomerSection(props) {
785
883
  const { hostId, form, disabled, onChange } = props;
786
884
  const { data: user } = useUser();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/quote-editor-dialog.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 { BlockedControl } from '@aglyn/shared-ui-jsx/components/blocked-control.component'\nimport { PrerequisiteNotice } from '@aglyn/shared-ui-jsx/components/prerequisite-notice.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport {\n useFirestore,\n useFirestoreDoc,\n useStoreSettingsHref,\n useUser,\n} from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Box,\n Button,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n Divider,\n FormControlLabel,\n List,\n ListItemButton,\n ListItemText,\n MenuItem,\n Paper,\n Stack,\n Switch,\n TextField,\n Typography,\n type Theme,\n} from '@mui/material'\nimport { doc } from 'firebase/firestore'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { downloadCommercePdf } from './commerce-pdf-download'\nimport { QuotePayLinkSection } from './quote-pay-link.component'\nimport { QuoteProofsSection } from './quote-proofs.component'\n\n/** A quote as the list reads it: the order document and its id. */\nexport type QuoteRow = CommerceModel.HostOrder & { $id: string }\n\nexport interface QuoteEditorDialogProps {\n hostId: string\n /** The quote to edit, or `null` for a new one. */\n quote: QuoteRow | null\n /** The store's products, for the product picker. */\n products: readonly Record<string, any>[]\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 onClose: () => void\n}\n\nconst REFUSAL = commerceSitePermissionRefusal('commerce.quotes')\nconst SEARCH_DEBOUNCE_MS = 250\n\nconst money = (cents: number): string => posMoney(cents)\n\n/** Field widths on a wide screen, from the theme's spacing; full width on a phone. */\nconst narrowField = (theme: Theme) => ({ maxWidth: { sm: theme.spacing(16) } })\nconst mediumField = (theme: Theme) => ({ minWidth: { sm: theme.spacing(20) }, maxWidth: { sm: theme.spacing(24) } })\n\n/** Dollars typed into a field, as whole cents, or `null` when it is not an amount. */\nfunction centsOf(text: string): number | null {\n const trimmed = text.trim()\n if (!trimmed) return 0\n if (!/^\\d+(\\.\\d{0,2})?$/.test(trimmed)) return null\n return Math.round(Number(trimmed) * 100)\n}\n\nconst dollarsOf = (cents: number | undefined): string =>\n cents ? (cents / 100).toFixed(2).replace(/\\.00$/, '') : ''\n\ntype AddressForm = Record<'name' | 'line1' | 'line2' | 'city' | 'state' | 'postalCode' | 'country', string>\n\nfunction addressForm(address: CommerceModel.OrderAddress | null | undefined): AddressForm {\n return {\n name: address?.name ?? '',\n line1: address?.line1 ?? '',\n line2: address?.line2 ?? '',\n city: address?.city ?? '',\n state: address?.state ?? '',\n postalCode: address?.postalCode ?? '',\n country: address?.country ?? '',\n }\n}\n\ntype LineForm =\n | {\n key: string\n kind: 'catalog'\n productId: string\n variantId: string\n quantity: string\n modifiers: CommerceModel.ModifierSelection[]\n description: string\n included: boolean\n }\n | {\n key: string\n kind: 'custom'\n name: string\n description: string\n sku: string\n price: string\n quantity: string\n ships: boolean\n included: boolean\n }\n\ninterface QuoteForm {\n lines: LineForm[]\n customer: { record: { kind: string; id: string } | null; name: string; company: string; email: string; phone: string }\n shipTo: AddressForm\n billTo: AddressForm\n discountKind: 'none' | 'amount' | 'percent'\n discountValue: string\n shipping: string\n notes: string\n terms: string\n requireProofApproval: boolean\n}\n\nlet lineSequence = 0\nconst nextLineKey = () => `line-${++lineSequence}`\n\nfunction formFromQuote(quote: QuoteRow | null, requireProofApproval: boolean): QuoteForm {\n const section = quote?.quote\n const discount = section?.discount ?? null\n return {\n lines: (quote?.lineItems ?? []).map((line): LineForm => {\n const request = CommerceModel.quoteLineRequestFromLine(line)\n return request.kind === 'custom'\n ? {\n key: nextLineKey(),\n kind: 'custom',\n name: request.name,\n description: request.description ?? '',\n sku: request.sku ?? '',\n price: dollarsOf(request.unitAmountCents),\n quantity: String(request.quantity),\n ships: request.ships !== false,\n included: request.included === true,\n }\n : {\n key: nextLineKey(),\n kind: 'catalog',\n productId: request.productId,\n variantId: request.variantId ?? '',\n quantity: String(request.quantity),\n modifiers: request.modifiers ?? [],\n description: request.description ?? '',\n included: request.included === true,\n }\n }),\n customer: {\n record: section?.customer?.record ?? null,\n name: section?.customer?.name ?? '',\n company: section?.customer?.company ?? '',\n email: section?.customer?.email ?? '',\n phone: section?.customer?.phone ?? '',\n },\n shipTo: addressForm(section?.shipTo),\n billTo: addressForm(section?.billTo),\n discountKind: discount?.kind ?? 'none',\n discountValue:\n discount?.kind === 'amount' ? dollarsOf(discount.amountCents) : discount?.kind === 'percent' ? String(discount.pct) : '',\n shipping: dollarsOf(section?.shipping?.amountCents),\n notes: section?.notes ?? '',\n terms: section?.terms ?? '',\n requireProofApproval: section ? section.requireProofApproval === true : requireProofApproval,\n }\n}\n\nfunction lineRequest(line: LineForm): CommerceModel.QuoteLineRequest {\n const quantity = Number(line.quantity)\n if (line.kind === 'catalog') {\n return {\n kind: 'catalog',\n productId: line.productId,\n ...(line.variantId ? { variantId: line.variantId } : {}),\n quantity,\n ...(line.modifiers.length ? { modifiers: line.modifiers } : {}),\n ...(line.included ? { included: true } : {}),\n ...(line.description.trim() ? { description: line.description.trim() } : {}),\n }\n }\n return {\n kind: 'custom',\n name: line.name.trim(),\n ...(line.description.trim() ? { description: line.description.trim() } : {}),\n ...(line.sku.trim() ? { sku: line.sku.trim() } : {}),\n unitAmountCents: line.included ? 0 : (centsOf(line.price) ?? Number.NaN),\n quantity,\n ships: line.ships,\n ...(line.included ? { included: true } : {}),\n }\n}\n\nfunction addressBody(address: AddressForm): Partial<AddressForm> | null {\n const entries = Object.entries(address).filter(([, value]) => value.trim())\n return entries.length ? Object.fromEntries(entries.map(([key, value]) => [key, value.trim()])) : null\n}\n\n/** What the server is sent: choices, never what a product costs. */\nfunction quoteBody(form: QuoteForm): Record<string, unknown> {\n const discountCents = centsOf(form.discountValue)\n return {\n lines: form.lines.map(lineRequest),\n customer: {\n ...(form.customer.record ? { record: form.customer.record } : {}),\n name: form.customer.name,\n company: form.customer.company,\n email: form.customer.email,\n phone: form.customer.phone,\n },\n shipTo: addressBody(form.shipTo),\n billTo: addressBody(form.billTo),\n discount:\n form.discountKind === 'amount'\n ? { kind: 'amount', amountCents: discountCents ?? Number.NaN }\n : form.discountKind === 'percent'\n ? { kind: 'percent', pct: Number(form.discountValue || 0) }\n : null,\n shipping: form.shipping.trim() ? { amountCents: centsOf(form.shipping) ?? Number.NaN } : null,\n notes: form.notes,\n terms: form.terms,\n requireProofApproval: form.requireProofApproval,\n }\n}\n\ninterface FoundCustomer {\n record: { kind: string; id: string }\n name: string\n company: string\n email: string | null\n phone: string | null\n}\n\n/**\n * The quote editor (AGL-4093): who it is for, its lines (products with their\n * options and add-ons, typed items, things included at no charge), discount,\n * shipping, notes and terms, with the totals worked out as it is edited. The\n * server prices and saves it; the totals here are the same function's answer\n * over the same inputs, and a connected tax service's figure arrives on save.\n */\nexport function QuoteEditorDialog(props: QuoteEditorDialogProps) {\n const { hostId, quote, products, canEdit, canSend, onClose } = props\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const taxesHref = useStoreSettingsHref(hostId, 'taxes')\n const { data: store } = useFirestoreDoc<any>(\n () => doc(firestore, 'hosts', hostId, 'settings', 'store'),\n [firestore, hostId],\n )\n const storeDefault = CommerceModel.quoteRequiresProofApprovalByDefault(store?.quotes)\n const [form, setForm] = useState<QuoteForm>(() => formFromQuote(quote, storeDefault))\n // The version this form was opened on. A change saved elsewhere while it is\n // open arrives on `quote`; the save still names this one, so the server\n // refuses rather than overwrite that change. A proof added or a revision\n // started here (AGL-4096) moves it, and the save names the new one.\n const [baseUpdatedAtMs, setBaseUpdatedAtMs] = useState(() => quote?.quote?.updatedAtMs)\n const [busy, setBusy] = useState(false)\n const [confirmingDelete, setConfirmingDelete] = useState(false)\n /** Whether anything has been changed since the dialog opened. */\n const [edited, setEdited] = useState(false)\n /** Whether the proof-approval switch was set by hand. */\n const [approvalSet, setApprovalSet] = useState(false)\n // A new quote starts with the store's default, which may arrive after the\n // dialog opens; a switch set by hand keeps its setting.\n const requireProofApproval = quote || approvalSet ? form.requireProofApproval : storeDefault\n\n const update = useCallback((patch: Partial<QuoteForm>) => {\n setEdited(true)\n if ('requireProofApproval' in patch) setApprovalSet(true)\n setForm((prev) => ({ ...prev, ...patch }))\n }, [])\n const updateLine = useCallback((key: string, patch: Partial<LineForm>) => {\n setEdited(true)\n setForm((prev) => ({\n ...prev,\n lines: prev.lines.map((line) => (line.key === key ? ({ ...line, ...patch } as LineForm) : line)),\n }))\n }, [])\n\n /*\n * One attempt per change (AGL-1697's rule): a retried Save presents the same\n * key and is answered from the first, an edited quote is a new attempt.\n */\n const attemptKey = useRef('')\n useEffect(() => {\n attemptKey.current = ''\n }, [form])\n\n const productsById = useMemo(\n () => new Map(products.map((product) => [String(product.$id), product])),\n [products],\n )\n\n /** Each line priced as the server will price it, or why it cannot be. */\n const priced = useMemo(\n () =>\n form.lines.map((line) => {\n const request = lineRequest(line)\n if (request.kind === 'custom') {\n if (!request.name) return { error: 'Name the item.' }\n if (!Number.isInteger(request.unitAmountCents)) return { error: 'Enter a price.' }\n if (!(request.quantity >= 1)) return { error: 'Enter a quantity.' }\n return { line: CommerceModel.priceQuoteCustomLine(request) }\n }\n if (!request.productId) return { error: 'Choose a product.' }\n if (!(request.quantity >= 1)) return { error: 'Enter a quantity.' }\n const answer = CommerceModel.priceQuoteCatalogLine(productsById.get(request.productId) as never, request)\n return 'error' in answer ? { error: answer.error } : { line: answer.line }\n }),\n [form.lines, productsById],\n )\n\n const discountCents = centsOf(form.discountValue)\n const discount: CommerceModel.QuoteDiscount | null =\n form.discountKind === 'amount' && discountCents\n ? { kind: 'amount', amountCents: discountCents }\n : form.discountKind === 'percent' && Number(form.discountValue) > 0\n ? { kind: 'percent', pct: Math.min(100, Number(form.discountValue)) }\n : null\n const shippingCents = centsOf(form.shipping) ?? 0\n const taxBasis = CommerceModel.quoteTaxBasisFromSettings(store?.tax, {\n country: form.shipTo.country.trim().toUpperCase(),\n state: form.shipTo.state.trim(),\n })\n const pricedLines = priced.flatMap((entry) => ('line' in entry && entry.line ? [entry.line] : []))\n const totals = CommerceModel.computeQuoteTotals({ lines: pricedLines, discount, shippingCents, tax: taxBasis })\n const problems = priced.some((entry) => 'error' in entry)\n const savedService = quote?.quote?.tax?.kind === 'service' ? quote.quote.tax : null\n\n const save = useCallback(async () => {\n setBusy(true)\n try {\n if (!attemptKey.current) {\n attemptKey.current = globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`\n }\n const response = await authorizedFetch(user, '/api/commerce/quote', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'Idempotency-Key': attemptKey.current },\n body: JSON.stringify({\n action: quote ? 'update' : 'create',\n hostId,\n ...(quote ? { quoteId: quote.$id, baseUpdatedAtMs } : {}),\n quote: quoteBody({ ...form, requireProofApproval }),\n }),\n })\n const payload = await response.json().catch(() => ({}))\n if (!response.ok) {\n return void enqueueSnackbar(payload?.error ?? 'The quote could not be saved', { variant: 'error', allowDuplicate: true })\n }\n enqueueSnackbar(`${CommerceModel.formatQuoteNumber({ number: payload.number ?? undefined }, payload.quoteId)} saved`, {\n variant: 'success',\n persist: false,\n })\n onClose()\n } finally {\n setBusy(false)\n }\n }, [user, quote, hostId, baseUpdatedAtMs, form, requireProofApproval, enqueueSnackbar, onClose])\n\n const remove = useCallback(async () => {\n if (!quote) return\n setBusy(true)\n try {\n const response = await authorizedFetch(user, '/api/commerce/quote', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'delete', hostId, quoteId: quote.$id }),\n })\n const payload = await response.json().catch(() => ({}))\n if (!response.ok) {\n return void enqueueSnackbar(payload?.error ?? 'The quote could not be deleted', { variant: 'error', allowDuplicate: true })\n }\n enqueueSnackbar(`${CommerceModel.formatQuoteNumber(quote, quote.$id)} deleted`, { variant: 'success', persist: false })\n setConfirmingDelete(false)\n onClose()\n } finally {\n setBusy(false)\n }\n }, [user, quote, hostId, enqueueSnackbar, onClose])\n\n const [downloading, setDownloading] = useState(false)\n const downloadPdf = useCallback(async () => {\n if (!quote) return\n setDownloading(true)\n try {\n const refused = await downloadCommercePdf(\n user,\n '/api/commerce/quote',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'pdf', hostId, quoteId: quote.$id }),\n },\n `quote-${quote.number ?? quote.$id.slice(-6)}.pdf`,\n )\n if (refused) enqueueSnackbar(refused, { variant: 'error', allowDuplicate: true })\n } finally {\n setDownloading(false)\n }\n }, [user, quote, hostId, enqueueSnackbar])\n\n const readOnly = !canEdit || busy\n const paid = quote ? !CommerceModel.isUnpaidQuote(quote) : false\n const title = quote ? CommerceModel.formatQuoteNumber(quote, quote.$id) : 'New quote'\n const status = quote ? CommerceModel.quoteDisplayStatus(quote) : null\n const deletable = Boolean(quote) && !paid && (quote?.quote?.stage ?? 'draft') === 'draft'\n\n return (\n <Dialog open onClose={busy ? undefined : onClose} maxWidth=\"md\" fullWidth scroll=\"paper\" aria-labelledby=\"quote-editor-title\">\n <DialogTitle id=\"quote-editor-title\">\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <span>{title}</span>\n {status ? (\n <Chip size=\"small\" variant=\"outlined\" label={status.label} color={CommerceModel.QUOTE_STATUS_COLOR[status.key]} />\n ) : null}\n </Stack>\n </DialogTitle>\n <DialogContent dividers>\n <Stack spacing={3}>\n {paid ? (\n <Alert severity=\"success\">\n {quote?.quote?.paidAtMs\n ? `Paid ${new Date(quote.quote.paidAtMs).toLocaleDateString()}. It is an order now and can no longer be changed.`\n : 'This quote has been paid, so it is an order now and can no longer be changed.'}\n </Alert>\n ) : null}\n {quote ? (\n <QuotePayLinkSection hostId={hostId} quoteId={quote.$id} quote={quote} canSend={canSend} edited={edited} />\n ) : null}\n {quote ? (\n <QuoteProofsSection\n hostId={hostId}\n quoteId={quote.$id}\n quote={quote}\n canEdit={canEdit}\n onEdited={(updatedAtMs) => {\n if (updatedAtMs) setBaseUpdatedAtMs(updatedAtMs)\n }}\n />\n ) : null}\n {taxBasis.kind === 'none' && taxBasis.reason === 'undecided' ? (\n <PrerequisiteNotice href={taxesHref ?? undefined} actionLabel=\"Open Taxes\">\n {'This store has not chosen how it handles sales tax, so this quote shows no tax. Choose it in Taxes.'}\n </PrerequisiteNotice>\n ) : null}\n\n <QuoteCustomerSection\n hostId={hostId}\n form={form}\n disabled={readOnly || paid}\n onChange={(customer) => update({ customer })}\n />\n\n <Stack spacing={1.5}>\n <Typography variant=\"subtitle2\">{'Items'}</Typography>\n {form.lines.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Add products from your catalog, or type an item that is made to order.'}\n </Typography>\n ) : null}\n {form.lines.map((line, index) => (\n <QuoteLineEditor\n key={line.key}\n line={line}\n priced={priced[index]}\n products={products}\n disabled={readOnly || paid}\n onChange={(patch) => updateLine(line.key, patch)}\n onRemove={() => update({ lines: form.lines.filter((entry) => entry.key !== line.key) })}\n />\n ))}\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ flexWrap: 'wrap' }}>\n <Button\n size=\"small\"\n disabled={readOnly || paid || products.length === 0}\n onClick={() =>\n update({\n lines: [\n ...form.lines,\n { key: nextLineKey(), kind: 'catalog', productId: '', variantId: '', quantity: '1', modifiers: [], description: '', included: false },\n ],\n })\n }\n >\n {'Add product'}\n </Button>\n <Button\n size=\"small\"\n disabled={readOnly || paid}\n onClick={() =>\n update({\n lines: [\n ...form.lines,\n { key: nextLineKey(), kind: 'custom', name: '', description: '', sku: '', price: '', quantity: '1', ships: true, included: false },\n ],\n })\n }\n >\n {'Add custom item'}\n </Button>\n </Stack>\n </Stack>\n\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <TextField\n label=\"Discount\"\n select\n size=\"small\"\n value={form.discountKind}\n disabled={readOnly || paid}\n onChange={(event) => update({ discountKind: event.target.value as QuoteForm['discountKind'] })}\n sx={mediumField}\n >\n <MenuItem value=\"none\">{'None'}</MenuItem>\n <MenuItem value=\"amount\">{'Amount off'}</MenuItem>\n <MenuItem value=\"percent\">{'Percent off'}</MenuItem>\n </TextField>\n {form.discountKind !== 'none' ? (\n <TextField\n label={form.discountKind === 'amount' ? 'Amount ($)' : 'Percent (%)'}\n size=\"small\"\n value={form.discountValue}\n disabled={readOnly || paid}\n onChange={(event) => update({ discountValue: event.target.value })}\n slotProps={{ htmlInput: { inputMode: 'decimal' } }}\n error={form.discountKind === 'amount' ? centsOf(form.discountValue) === null : !(Number(form.discountValue) >= 0 && Number(form.discountValue) <= 100)}\n />\n ) : null}\n <TextField\n label=\"Shipping ($)\"\n size=\"small\"\n value={form.shipping}\n disabled={readOnly || paid}\n onChange={(event) => update({ shipping: event.target.value })}\n slotProps={{ htmlInput: { inputMode: 'decimal' } }}\n error={centsOf(form.shipping) === null}\n helperText=\"Leave empty when nothing ships.\"\n />\n </Stack>\n\n <QuoteAddressFields\n label=\"Ship to\"\n value={form.shipTo}\n disabled={readOnly || paid}\n helperText=\"Where the order goes. Store tax rates use its state and country.\"\n onChange={(shipTo) => update({ shipTo })}\n />\n <QuoteAddressFields\n label=\"Bill to\"\n value={form.billTo}\n disabled={readOnly || paid}\n onChange={(billTo) => update({ billTo })}\n />\n\n <Stack spacing={2}>\n <TextField\n label=\"Notes for the customer\"\n multiline\n minRows={2}\n value={form.notes}\n disabled={readOnly || paid}\n onChange={(event) => update({ notes: event.target.value })}\n />\n <TextField\n label=\"Terms\"\n multiline\n minRows={2}\n value={form.terms}\n disabled={readOnly || paid}\n onChange={(event) => update({ terms: event.target.value })}\n />\n <FormControlLabel\n control={\n <Switch\n checked={requireProofApproval}\n disabled={readOnly || paid}\n onChange={(event) => update({ requireProofApproval: event.target.checked })}\n />\n }\n label=\"Customers approve the proof before they can pay\"\n />\n </Stack>\n\n <Divider />\n <QuoteTotalsSummary\n totals={totals}\n tax={taxBasis}\n savedService={edited ? null : savedService}\n savedTotals={edited ? null : (quote?.totals ?? null)}\n />\n </Stack>\n </DialogContent>\n <DialogActions sx={{ flexWrap: 'wrap', rowGap: 1 }}>\n {deletable ? (\n <BlockedControl blocked={!canEdit} reason={REFUSAL}>\n <Button color=\"error\" disabled={busy} onClick={() => setConfirmingDelete(true)} sx={{ mr: 'auto' }}>\n {'Delete'}\n </Button>\n </BlockedControl>\n ) : null}\n {quote ? (\n <BlockedControl\n blocked={!canEdit || edited}\n reason={edited ? 'Save your changes first: the PDF shows the quote as it was last saved.' : REFUSAL}\n >\n <Button disabled={busy || downloading} onClick={() => void downloadPdf()}>\n {downloading ? 'Making PDF…' : 'Download PDF'}\n </Button>\n </BlockedControl>\n ) : null}\n <Button onClick={onClose} disabled={busy}>\n {paid || !canEdit ? 'Close' : 'Cancel'}\n </Button>\n {paid ? null : (\n <BlockedControl blocked={!canEdit} reason={REFUSAL}>\n <Button\n variant=\"contained\"\n disabled={busy || form.lines.length === 0 || problems}\n onClick={() => void save()}\n >\n {quote ? 'Save' : 'Create quote'}\n </Button>\n </BlockedControl>\n )}\n </DialogActions>\n <Dialog open={confirmingDelete} onClose={() => setConfirmingDelete(false)} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{`Delete ${title}?`}</DialogTitle>\n <DialogContent>\n <DialogContentText>{'The quote and everything on it is removed. This can’t be undone.'}</DialogContentText>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setConfirmingDelete(false)} disabled={busy}>\n {'Cancel'}\n </Button>\n <Button color=\"error\" variant=\"contained\" disabled={busy} onClick={() => void remove()}>\n {'Delete'}\n </Button>\n </DialogActions>\n </Dialog>\n </Dialog>\n )\n}\nQuoteEditorDialog.displayName = 'QuoteEditorDialog'\n\n/** Who the quote is for: a person the workspace keeps, or details typed here. */\nfunction QuoteCustomerSection(props: {\n hostId: string\n form: QuoteForm\n disabled: boolean\n onChange: (customer: QuoteForm['customer']) => void\n}) {\n const { hostId, form, disabled, onChange } = props\n const { data: user } = useUser()\n const [text, setText] = useState('')\n const [found, setFound] = useState<FoundCustomer[]>([])\n const [available, setAvailable] = useState(true)\n const ticket = useRef(0)\n const customer = form.customer\n\n useEffect(() => {\n const typed = text.trim()\n if (typed.length < 2 || !user) {\n // Only when something is listed, so an effect that re-runs settles.\n setFound((prev) => (prev.length ? [] : prev))\n return\n }\n const mine = ++ticket.current\n const timer = window.setTimeout(() => {\n void authorizedFetch(user, '/api/commerce/quote', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'search-customers', hostId, text: typed }),\n })\n .then((response) => response.json().catch(() => ({})))\n .then((payload) => {\n if (mine !== ticket.current) return\n setAvailable(payload?.available !== false)\n setFound(Array.isArray(payload?.customers) ? payload.customers : [])\n })\n .catch(() => undefined)\n }, SEARCH_DEBOUNCE_MS)\n return () => window.clearTimeout(timer)\n }, [text, user, hostId])\n\n const pick = (person: FoundCustomer) => {\n onChange({\n record: person.record,\n name: person.name,\n company: person.company,\n email: person.email ?? '',\n phone: person.phone ?? '',\n })\n setText('')\n setFound([])\n }\n\n return (\n <Stack spacing={1.5}>\n <Typography variant=\"subtitle2\">{'Customer'}</Typography>\n {customer.record ? (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Chip\n color=\"primary\"\n variant=\"outlined\"\n label={customer.name || customer.email || 'Contact'}\n onDelete={disabled ? undefined : () => onChange({ ...customer, record: null })}\n />\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'From your contacts'}\n </Typography>\n </Stack>\n ) : available ? (\n <Box>\n <TextField\n size=\"small\"\n fullWidth\n label=\"Find a contact\"\n placeholder=\"Name, email or phone\"\n value={text}\n disabled={disabled}\n onChange={(event) => setText(event.target.value)}\n />\n {found.length ? (\n <Paper variant=\"outlined\" sx={{ mt: 0.5 }}>\n <List dense disablePadding>\n {found.map((person) => (\n <ListItemButton key={`${person.record.kind}:${person.record.id}`} onClick={() => pick(person)}>\n <ListItemText\n primary={person.name || person.email || 'Contact'}\n secondary={[person.company, person.email, person.phone].filter(Boolean).join(' · ')}\n />\n </ListItemButton>\n ))}\n </List>\n </Paper>\n ) : null}\n </Box>\n ) : null}\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <TextField size=\"small\" fullWidth label=\"Name\" value={customer.name} disabled={disabled} onChange={(event) => onChange({ ...customer, name: event.target.value })} />\n <TextField size=\"small\" fullWidth label=\"Company\" value={customer.company} disabled={disabled} onChange={(event) => onChange({ ...customer, company: event.target.value })} />\n </Stack>\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <TextField size=\"small\" fullWidth label=\"Email\" type=\"email\" value={customer.email} disabled={disabled} onChange={(event) => onChange({ ...customer, email: event.target.value })} />\n <TextField size=\"small\" fullWidth label=\"Phone\" value={customer.phone} disabled={disabled} onChange={(event) => onChange({ ...customer, phone: event.target.value })} />\n </Stack>\n </Stack>\n )\n}\n\n/** One address on the quote. */\nfunction QuoteAddressFields(props: {\n label: string\n value: AddressForm\n disabled: boolean\n helperText?: string\n onChange: (value: AddressForm) => void\n}) {\n const { label, value, disabled, helperText, onChange } = props\n const field = (key: keyof AddressForm, fieldLabel: string, extra: Record<string, unknown> = {}) => (\n <TextField\n size=\"small\"\n fullWidth\n label={fieldLabel}\n value={value[key]}\n disabled={disabled}\n onChange={(event) => onChange({ ...value, [key]: event.target.value })}\n {...extra}\n />\n )\n return (\n <Stack spacing={1.5}>\n <Typography variant=\"subtitle2\">{label}</Typography>\n {helperText ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {helperText}\n </Typography>\n ) : null}\n {field('name', 'Name')}\n {field('line1', 'Address')}\n {field('line2', 'Apartment, suite, unit')}\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n {field('city', 'City')}\n {field('state', 'State or region')}\n {field('postalCode', 'Postal code')}\n {field('country', 'Country code', { placeholder: 'US', slotProps: { htmlInput: { maxLength: 2 } } })}\n </Stack>\n </Stack>\n )\n}\n\n/** One line of the quote: a product with its options and add-ons, or a typed item. */\nfunction QuoteLineEditor(props: {\n line: LineForm\n priced: { line?: CommerceModel.PricedQuoteLine; error?: string } | undefined\n products: readonly Record<string, any>[]\n disabled: boolean\n onChange: (patch: Partial<LineForm>) => void\n onRemove: () => void\n}) {\n const { line, priced, products, disabled, onChange, onRemove } = props\n const product = line.kind === 'catalog' ? products.find((entry) => String(entry.$id) === line.productId) : undefined\n const lifted = product ? CommerceModel.liftLegacyProduct(product) : null\n const groups = lifted ? CommerceModel.productModifierGroups(lifted) : []\n const lineCents = priced?.line ? CommerceModel.quoteLineCents(priced.line) : 0\n\n return (\n <Paper variant=\"outlined\" sx={{ p: 2 }}>\n <Stack spacing={1.5}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'flex-start' }}>\n <Stack spacing={1.5} sx={{ flex: 1, minWidth: 0 }}>\n {line.kind === 'catalog' ? (\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <TextField\n label=\"Product\"\n select\n size=\"small\"\n fullWidth\n value={line.productId}\n disabled={disabled}\n onChange={(event) => onChange({ productId: event.target.value, variantId: '', modifiers: [] })}\n >\n {products.map((entry) => (\n <MenuItem key={String(entry.$id)} value={String(entry.$id)}>\n {String(entry.name ?? entry.$id)}\n </MenuItem>\n ))}\n </TextField>\n {lifted && lifted.variants.length > 1 ? (\n <TextField\n label=\"Option\"\n select\n size=\"small\"\n fullWidth\n value={line.variantId || lifted.variants[0]?.id || ''}\n disabled={disabled}\n onChange={(event) => onChange({ variantId: event.target.value })}\n >\n {lifted.variants.map((variant) => (\n <MenuItem key={variant.id} value={variant.id}>\n {Object.values(variant.options ?? {}).join(' / ') || 'Default'}\n </MenuItem>\n ))}\n </TextField>\n ) : null}\n </Stack>\n ) : (\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <TextField\n label=\"Item\"\n size=\"small\"\n fullWidth\n value={line.name}\n disabled={disabled}\n onChange={(event) => onChange({ name: event.target.value })}\n />\n <TextField\n label=\"SKU (optional)\"\n size=\"small\"\n value={line.sku}\n disabled={disabled}\n onChange={(event) => onChange({ sku: event.target.value })}\n />\n </Stack>\n )}\n {groups.map((group) => {\n const chosen = line.kind === 'catalog' ? line.modifiers.filter((pick) => pick.groupId === group.id).map((pick) => pick.optionId) : []\n return (\n <TextField\n key={group.id}\n label={CommerceModel.modifierGroupRequired(group) ? group.name : `${group.name} (optional)`}\n select\n size=\"small\"\n fullWidth\n value={group.max > 1 ? chosen : (chosen[0] ?? '')}\n disabled={disabled}\n slotProps={{ select: { multiple: group.max > 1 } }}\n onChange={(event) => {\n const raw = event.target.value as unknown\n const picked = (Array.isArray(raw) ? raw : raw ? [raw] : []).map(String)\n if (line.kind !== 'catalog') return\n onChange({\n modifiers: [\n ...line.modifiers.filter((pick) => pick.groupId !== group.id),\n ...picked.map((optionId) => ({ groupId: group.id, optionId })),\n ],\n })\n }}\n >\n {group.max > 1 ? null : <MenuItem value=\"\">{'None'}</MenuItem>}\n {group.options.map((option) => (\n <MenuItem key={option.id} value={option.id}>\n {option.priceCents ? `${option.name} (+${money(option.priceCents)})` : option.name}\n </MenuItem>\n ))}\n </TextField>\n )\n })}\n <TextField\n label=\"Description (optional)\"\n size=\"small\"\n fullWidth\n multiline\n value={line.description}\n disabled={disabled}\n onChange={(event) => onChange({ description: event.target.value })}\n />\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2} sx={{ alignItems: { sm: 'center' } }}>\n <TextField\n label=\"Quantity\"\n size=\"small\"\n value={line.quantity}\n disabled={disabled}\n onChange={(event) => onChange({ quantity: event.target.value.replace(/[^0-9]/g, '') })}\n slotProps={{ htmlInput: { inputMode: 'numeric' } }}\n sx={narrowField}\n />\n {line.kind === 'custom' ? (\n <TextField\n label=\"Unit price ($)\"\n size=\"small\"\n value={line.included ? '' : line.price}\n disabled={disabled || line.included}\n onChange={(event) => onChange({ price: event.target.value })}\n slotProps={{ htmlInput: { inputMode: 'decimal' } }}\n error={!line.included && centsOf(line.price) === null}\n sx={mediumField}\n />\n ) : null}\n {line.kind === 'custom' ? (\n <FormControlLabel\n control={<Switch checked={line.ships} disabled={disabled} onChange={(event) => onChange({ ships: event.target.checked })} />}\n label=\"Ships\"\n />\n ) : null}\n <FormControlLabel\n control={\n <Switch checked={line.included} disabled={disabled} onChange={(event) => onChange({ included: event.target.checked })} />\n }\n label=\"Included at no charge\"\n />\n </Stack>\n </Stack>\n <Stack sx={{ alignItems: 'flex-end', flexShrink: 0 }}>\n <Button size=\"small\" color=\"inherit\" disabled={disabled} onClick={onRemove}>\n {'Remove'}\n </Button>\n <Typography variant=\"body2\" sx={{ fontWeight: 'fontWeightMedium' }}>\n {line.included ? 'Included' : money(lineCents)}\n </Typography>\n {priced?.line && !line.included && priced.line.quantity > 1 ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`${money(priced.line.unitAmountCents)} each`}\n </Typography>\n ) : null}\n </Stack>\n </Stack>\n {priced?.error ? (\n <Typography variant=\"caption\" color=\"error\">\n {priced.error}\n </Typography>\n ) : null}\n </Stack>\n </Paper>\n )\n}\n\n/** The quote's totals, as the customer will read them. */\nfunction QuoteTotalsSummary(props: {\n totals: CommerceModel.QuoteTotals\n tax: CommerceModel.QuoteTaxBasis\n /** A saved quote's tax service answer, shown until the quote is edited. */\n savedService: CommerceModel.QuoteTaxBasis | null\n savedTotals: CommerceModel.OrderTotals | null\n}) {\n const { totals, tax, savedService, savedTotals } = props\n const shown = savedService && savedTotals ? { ...totals, ...savedTotals } : totals\n const taxLabel = CommerceModel.describeQuoteTax(savedService ?? tax)\n const row = (label: string, value: string, strong = false) => (\n <Stack direction=\"row\" sx={{ justifyContent: 'space-between' }}>\n <Typography variant={strong ? 'subtitle1' : 'body2'} color={strong ? 'text.primary' : 'text.secondary'}>\n {label}\n </Typography>\n <Typography variant={strong ? 'subtitle1' : 'body2'}>{value}</Typography>\n </Stack>\n )\n return (\n <Stack spacing={0.5} sx={(theme) => ({ alignSelf: { sm: 'flex-end' }, minWidth: { sm: theme.spacing(40) } })}>\n {row('Items', money(shown.itemsCents))}\n {shown.discountCents ? row('Discount', `−${money(shown.discountCents)}`) : null}\n {shown.shippingCents ? row('Shipping', money(shown.shippingCents)) : null}\n {tax.kind === 'at-payment' && !savedService ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {taxLabel}\n </Typography>\n ) : (\n row(taxLabel, money(shown.taxCents))\n )}\n {row(totals.taxAtPayment && !savedService ? 'Total before tax' : 'Total', money(shown.totalCents), true)}\n </Stack>\n )\n}\n\nexport default QuoteEditorDialog\n"],"names":["CommerceModel","posMoney","commerceSitePermissionRefusal","BlockedControl","PrerequisiteNotice","useSnackbar","authorizedFetch","useFirestore","useFirestoreDoc","useStoreSettingsHref","useUser","Alert","Box","Button","Chip","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","Divider","FormControlLabel","List","ListItemButton","ListItemText","MenuItem","Paper","Stack","Switch","TextField","Typography","doc","useCallback","useEffect","useMemo","useRef","useState","downloadCommercePdf","QuotePayLinkSection","QuoteProofsSection","REFUSAL","SEARCH_DEBOUNCE_MS","money","cents","narrowField","theme","maxWidth","sm","spacing","mediumField","minWidth","centsOf","text","trimmed","trim","test","Math","round","Number","dollarsOf","toFixed","replace","addressForm","address","name","line1","line2","city","state","postalCode","country","lineSequence","nextLineKey","formFromQuote","quote","requireProofApproval","section","discount","lines","lineItems","map","line","request","quoteLineRequestFromLine","kind","key","description","sku","price","unitAmountCents","quantity","String","ships","included","productId","variantId","modifiers","customer","record","company","email","phone","shipTo","billTo","discountKind","discountValue","amountCents","pct","shipping","notes","terms","lineRequest","length","NaN","addressBody","entries","Object","filter","value","fromEntries","quoteBody","form","discountCents","QuoteEditorDialog","props","hostId","products","canEdit","canSend","onClose","firestore","data","user","enqueueSnackbar","taxesHref","store","storeDefault","quoteRequiresProofApprovalByDefault","quotes","setForm","baseUpdatedAtMs","setBaseUpdatedAtMs","updatedAtMs","busy","setBusy","confirmingDelete","setConfirmingDelete","edited","setEdited","approvalSet","setApprovalSet","update","patch","prev","updateLine","attemptKey","current","productsById","Map","product","$id","priced","error","isInteger","priceQuoteCustomLine","answer","priceQuoteCatalogLine","get","min","shippingCents","taxBasis","quoteTaxBasisFromSettings","tax","toUpperCase","pricedLines","flatMap","entry","totals","computeQuoteTotals","problems","some","savedService","save","payload","globalThis","crypto","randomUUID","Date","now","random","toString","slice","response","method","headers","body","JSON","stringify","action","quoteId","json","catch","ok","variant","allowDuplicate","formatQuoteNumber","number","undefined","persist","remove","downloading","setDownloading","downloadPdf","refused","readOnly","paid","isUnpaidQuote","title","status","quoteDisplayStatus","deletable","Boolean","stage","open","fullWidth","scroll","aria-labelledby","id","direction","sx","alignItems","span","size","label","color","QUOTE_STATUS_COLOR","dividers","severity","paidAtMs","toLocaleDateString","onEdited","reason","href","actionLabel","QuoteCustomerSection","disabled","onChange","index","QuoteLineEditor","onRemove","useFlexGap","flexWrap","onClick","xs","select","event","target","slotProps","htmlInput","inputMode","helperText","QuoteAddressFields","multiline","minRows","control","checked","QuoteTotalsSummary","savedTotals","rowGap","blocked","mr","displayName","setText","found","setFound","available","setAvailable","ticket","typed","mine","timer","window","setTimeout","then","Array","isArray","customers","clearTimeout","pick","person","onDelete","placeholder","mt","dense","disablePadding","primary","secondary","join","type","field","fieldLabel","extra","maxLength","lifted","find","liftLegacyProduct","groups","productModifierGroups","lineCents","quoteLineCents","p","flex","variants","values","options","group","chosen","groupId","optionId","modifierGroupRequired","max","multiple","raw","picked","option","priceCents","flexShrink","fontWeight","shown","taxLabel","describeQuoteTax","row","strong","justifyContent","alignSelf","itemsCents","taxCents","taxAtPayment","totalCents"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../../libs/plugins/commerce/src/lib/components/console/quote-editor-dialog.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 { BlockedControl } from '@aglyn/shared-ui-jsx/components/blocked-control.component'\nimport { PrerequisiteNotice } from '@aglyn/shared-ui-jsx/components/prerequisite-notice.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { authorizedFetch } from '@aglyn/shared-util-http/authorized-token'\nimport {\n useFirestore,\n useFirestoreDoc,\n useStoreSettingsHref,\n useUser,\n} from '@aglyn/tenant-feature-instance'\nimport {\n Alert,\n Box,\n Button,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n Divider,\n FormControlLabel,\n List,\n ListItemButton,\n ListItemText,\n MenuItem,\n Paper,\n Stack,\n Switch,\n TextField,\n Typography,\n type Theme,\n} from '@mui/material'\nimport { doc } from 'firebase/firestore'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { downloadCommercePdf } from './commerce-pdf-download'\nimport { QuotePayLinkSection } from './quote-pay-link.component'\nimport { QuoteProofsSection, QuoteRequestFilesSection } from './quote-proofs.component'\nimport { QuoteSendSection } from './quote-send.component'\n\n/** A quote as the list reads it: the order document and its id. */\nexport type QuoteRow = CommerceModel.HostOrder & { $id: string }\n\nexport interface QuoteEditorDialogProps {\n hostId: string\n /** The quote to edit, or `null` for a new one. */\n quote: QuoteRow | null\n /** The store's products, for the product picker. */\n products: readonly Record<string, any>[]\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 * What a NEW quote opens with when it is started from a request or a\n * contact (AGL-4098). The editable fields are filled in; a request's own\n * parts (which request, its files, its conversation) are stamped by the\n * server from `from` when the quote is created, never from here.\n */\n start?: QuoteEditorStart | null\n onClose: () => void\n}\n\n/** A new quote's start: from a request (with what it carried) or from a contact. */\nexport interface QuoteEditorStart {\n /** The request it is started from, which the server reads again on create; null for a contact. */\n from: { kind: 'submission'; id: string } | null\n prefill: CommerceModel.QuoteStartPrefill\n /** The request, as the editor says where the quote came from. */\n request?: { formName: string; receivedAtMs: number | null } | null\n files?: ReadonlyArray<{ id: string; name: string; contentType: string; size: number }>\n /** Whether the request started an email conversation the quote's first email will reply into. */\n threaded?: boolean\n}\n\nconst REFUSAL = commerceSitePermissionRefusal('commerce.quotes')\nconst SEARCH_DEBOUNCE_MS = 250\n\nconst money = (cents: number): string => posMoney(cents)\n\n/** Field widths on a wide screen, from the theme's spacing; full width on a phone. */\nconst narrowField = (theme: Theme) => ({ maxWidth: { sm: theme.spacing(16) } })\nconst mediumField = (theme: Theme) => ({ minWidth: { sm: theme.spacing(20) }, maxWidth: { sm: theme.spacing(24) } })\n\n/** Dollars typed into a field, as whole cents, or `null` when it is not an amount. */\nfunction centsOf(text: string): number | null {\n const trimmed = text.trim()\n if (!trimmed) return 0\n if (!/^\\d+(\\.\\d{0,2})?$/.test(trimmed)) return null\n return Math.round(Number(trimmed) * 100)\n}\n\nconst dollarsOf = (cents: number | undefined): string =>\n cents ? (cents / 100).toFixed(2).replace(/\\.00$/, '') : ''\n\ntype AddressForm = Record<'name' | 'line1' | 'line2' | 'city' | 'state' | 'postalCode' | 'country', string>\n\nfunction addressForm(address: CommerceModel.OrderAddress | null | undefined): AddressForm {\n return {\n name: address?.name ?? '',\n line1: address?.line1 ?? '',\n line2: address?.line2 ?? '',\n city: address?.city ?? '',\n state: address?.state ?? '',\n postalCode: address?.postalCode ?? '',\n country: address?.country ?? '',\n }\n}\n\ntype LineForm =\n | {\n key: string\n kind: 'catalog'\n productId: string\n variantId: string\n quantity: string\n modifiers: CommerceModel.ModifierSelection[]\n description: string\n included: boolean\n }\n | {\n key: string\n kind: 'custom'\n name: string\n description: string\n sku: string\n price: string\n quantity: string\n ships: boolean\n included: boolean\n }\n\ninterface QuoteForm {\n lines: LineForm[]\n customer: { record: { kind: string; id: string } | null; name: string; company: string; email: string; phone: string }\n shipTo: AddressForm\n billTo: AddressForm\n discountKind: 'none' | 'amount' | 'percent'\n discountValue: string\n shipping: string\n notes: string\n terms: string\n requireProofApproval: boolean\n}\n\nlet lineSequence = 0\nconst nextLineKey = () => `line-${++lineSequence}`\n\nfunction formFromQuote(quote: QuoteRow | null, requireProofApproval: boolean): QuoteForm {\n const section = quote?.quote\n const discount = section?.discount ?? null\n return {\n lines: (quote?.lineItems ?? []).map((line): LineForm => {\n const request = CommerceModel.quoteLineRequestFromLine(line)\n return request.kind === 'custom'\n ? {\n key: nextLineKey(),\n kind: 'custom',\n name: request.name,\n description: request.description ?? '',\n sku: request.sku ?? '',\n price: dollarsOf(request.unitAmountCents),\n quantity: String(request.quantity),\n ships: request.ships !== false,\n included: request.included === true,\n }\n : {\n key: nextLineKey(),\n kind: 'catalog',\n productId: request.productId,\n variantId: request.variantId ?? '',\n quantity: String(request.quantity),\n modifiers: request.modifiers ?? [],\n description: request.description ?? '',\n included: request.included === true,\n }\n }),\n customer: {\n record: section?.customer?.record ?? null,\n name: section?.customer?.name ?? '',\n company: section?.customer?.company ?? '',\n email: section?.customer?.email ?? '',\n phone: section?.customer?.phone ?? '',\n },\n shipTo: addressForm(section?.shipTo),\n billTo: addressForm(section?.billTo),\n discountKind: discount?.kind ?? 'none',\n discountValue:\n discount?.kind === 'amount' ? dollarsOf(discount.amountCents) : discount?.kind === 'percent' ? String(discount.pct) : '',\n shipping: dollarsOf(section?.shipping?.amountCents),\n notes: section?.notes ?? '',\n terms: section?.terms ?? '',\n requireProofApproval: section ? section.requireProofApproval === true : requireProofApproval,\n }\n}\n\n/** A new quote's form, filled in from where it was started (AGL-4098). */\nfunction formFromStart(start: QuoteEditorStart, requireProofApproval: boolean): QuoteForm {\n const blank = formFromQuote(null, requireProofApproval)\n const { customer, lines, notes } = start.prefill\n return {\n ...blank,\n customer: {\n record: customer.record ?? null,\n name: customer.name ?? '',\n company: customer.company ?? '',\n email: customer.email ?? '',\n phone: customer.phone ?? '',\n },\n lines: lines.map(\n (line): LineForm => ({\n key: nextLineKey(),\n kind: 'catalog',\n productId: line.productId,\n variantId: line.variantId ?? '',\n quantity: String(line.quantity || 1),\n modifiers: line.modifiers ?? [],\n description: line.description ?? '',\n included: line.included === true,\n }),\n ),\n notes: notes ?? '',\n }\n}\n\nfunction lineRequest(line: LineForm): CommerceModel.QuoteLineRequest {\n const quantity = Number(line.quantity)\n if (line.kind === 'catalog') {\n return {\n kind: 'catalog',\n productId: line.productId,\n ...(line.variantId ? { variantId: line.variantId } : {}),\n quantity,\n ...(line.modifiers.length ? { modifiers: line.modifiers } : {}),\n ...(line.included ? { included: true } : {}),\n ...(line.description.trim() ? { description: line.description.trim() } : {}),\n }\n }\n return {\n kind: 'custom',\n name: line.name.trim(),\n ...(line.description.trim() ? { description: line.description.trim() } : {}),\n ...(line.sku.trim() ? { sku: line.sku.trim() } : {}),\n unitAmountCents: line.included ? 0 : (centsOf(line.price) ?? Number.NaN),\n quantity,\n ships: line.ships,\n ...(line.included ? { included: true } : {}),\n }\n}\n\nfunction addressBody(address: AddressForm): Partial<AddressForm> | null {\n const entries = Object.entries(address).filter(([, value]) => value.trim())\n return entries.length ? Object.fromEntries(entries.map(([key, value]) => [key, value.trim()])) : null\n}\n\n/** What the server is sent: choices, never what a product costs. */\nfunction quoteBody(form: QuoteForm): Record<string, unknown> {\n const discountCents = centsOf(form.discountValue)\n return {\n lines: form.lines.map(lineRequest),\n customer: {\n ...(form.customer.record ? { record: form.customer.record } : {}),\n name: form.customer.name,\n company: form.customer.company,\n email: form.customer.email,\n phone: form.customer.phone,\n },\n shipTo: addressBody(form.shipTo),\n billTo: addressBody(form.billTo),\n discount:\n form.discountKind === 'amount'\n ? { kind: 'amount', amountCents: discountCents ?? Number.NaN }\n : form.discountKind === 'percent'\n ? { kind: 'percent', pct: Number(form.discountValue || 0) }\n : null,\n shipping: form.shipping.trim() ? { amountCents: centsOf(form.shipping) ?? Number.NaN } : null,\n notes: form.notes,\n terms: form.terms,\n requireProofApproval: form.requireProofApproval,\n }\n}\n\ninterface FoundCustomer {\n record: { kind: string; id: string }\n name: string\n company: string\n email: string | null\n phone: string | null\n}\n\n/**\n * The quote editor (AGL-4093): who it is for, its lines (products with their\n * options and add-ons, typed items, things included at no charge), discount,\n * shipping, notes and terms, with the totals worked out as it is edited. The\n * server prices and saves it; the totals here are the same function's answer\n * over the same inputs, and a connected tax service's figure arrives on save.\n */\nexport function QuoteEditorDialog(props: QuoteEditorDialogProps) {\n const { hostId, quote, products, canEdit, canSend, onClose } = props\n const start = quote ? null : (props.start ?? null)\n const firestore = useFirestore()\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const taxesHref = useStoreSettingsHref(hostId, 'taxes')\n const { data: store } = useFirestoreDoc<any>(\n () => doc(firestore, 'hosts', hostId, 'settings', 'store'),\n [firestore, hostId],\n )\n const storeDefault = CommerceModel.quoteRequiresProofApprovalByDefault(store?.quotes)\n const [form, setForm] = useState<QuoteForm>(() =>\n start ? formFromStart(start, storeDefault) : formFromQuote(quote, storeDefault),\n )\n // The version this form was opened on. A change saved elsewhere while it is\n // open arrives on `quote`; the save still names this one, so the server\n // refuses rather than overwrite that change. A proof added or a revision\n // started here (AGL-4096) moves it, and the save names the new one.\n const [baseUpdatedAtMs, setBaseUpdatedAtMs] = useState(() => quote?.quote?.updatedAtMs)\n const [busy, setBusy] = useState(false)\n const [confirmingDelete, setConfirmingDelete] = useState(false)\n /** Whether anything has been changed since the dialog opened. */\n const [edited, setEdited] = useState(false)\n /** Whether the proof-approval switch was set by hand. */\n const [approvalSet, setApprovalSet] = useState(false)\n // A new quote starts with the store's default, which may arrive after the\n // dialog opens; a switch set by hand keeps its setting.\n const requireProofApproval = quote || approvalSet ? form.requireProofApproval : storeDefault\n\n const update = useCallback((patch: Partial<QuoteForm>) => {\n setEdited(true)\n if ('requireProofApproval' in patch) setApprovalSet(true)\n setForm((prev) => ({ ...prev, ...patch }))\n }, [])\n const updateLine = useCallback((key: string, patch: Partial<LineForm>) => {\n setEdited(true)\n setForm((prev) => ({\n ...prev,\n lines: prev.lines.map((line) => (line.key === key ? ({ ...line, ...patch } as LineForm) : line)),\n }))\n }, [])\n\n /*\n * One attempt per change (AGL-1697's rule): a retried Save presents the same\n * key and is answered from the first, an edited quote is a new attempt.\n */\n const attemptKey = useRef('')\n useEffect(() => {\n attemptKey.current = ''\n }, [form])\n\n const productsById = useMemo(\n () => new Map(products.map((product) => [String(product.$id), product])),\n [products],\n )\n\n /** Each line priced as the server will price it, or why it cannot be. */\n const priced = useMemo(\n () =>\n form.lines.map((line) => {\n const request = lineRequest(line)\n if (request.kind === 'custom') {\n if (!request.name) return { error: 'Name the item.' }\n if (!Number.isInteger(request.unitAmountCents)) return { error: 'Enter a price.' }\n if (!(request.quantity >= 1)) return { error: 'Enter a quantity.' }\n return { line: CommerceModel.priceQuoteCustomLine(request) }\n }\n if (!request.productId) return { error: 'Choose a product.' }\n if (!(request.quantity >= 1)) return { error: 'Enter a quantity.' }\n const answer = CommerceModel.priceQuoteCatalogLine(productsById.get(request.productId) as never, request)\n return 'error' in answer ? { error: answer.error } : { line: answer.line }\n }),\n [form.lines, productsById],\n )\n\n const discountCents = centsOf(form.discountValue)\n const discount: CommerceModel.QuoteDiscount | null =\n form.discountKind === 'amount' && discountCents\n ? { kind: 'amount', amountCents: discountCents }\n : form.discountKind === 'percent' && Number(form.discountValue) > 0\n ? { kind: 'percent', pct: Math.min(100, Number(form.discountValue)) }\n : null\n const shippingCents = centsOf(form.shipping) ?? 0\n const taxBasis = CommerceModel.quoteTaxBasisFromSettings(store?.tax, {\n country: form.shipTo.country.trim().toUpperCase(),\n state: form.shipTo.state.trim(),\n })\n const pricedLines = priced.flatMap((entry) => ('line' in entry && entry.line ? [entry.line] : []))\n const totals = CommerceModel.computeQuoteTotals({ lines: pricedLines, discount, shippingCents, tax: taxBasis })\n const problems = priced.some((entry) => 'error' in entry)\n const savedService = quote?.quote?.tax?.kind === 'service' ? quote.quote.tax : null\n\n const save = useCallback(async () => {\n setBusy(true)\n try {\n if (!attemptKey.current) {\n attemptKey.current = globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`\n }\n const response = await authorizedFetch(user, '/api/commerce/quote', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'Idempotency-Key': attemptKey.current },\n body: JSON.stringify({\n action: quote ? 'update' : 'create',\n hostId,\n ...(quote ? { quoteId: quote.$id, baseUpdatedAtMs } : {}),\n // A request's parts are read again by the server from here (AGL-4098).\n ...(!quote && start?.from ? { from: start.from } : {}),\n quote: quoteBody({ ...form, requireProofApproval }),\n }),\n })\n const payload = await response.json().catch(() => ({}))\n if (!response.ok) {\n return void enqueueSnackbar(payload?.error ?? 'The quote could not be saved', { variant: 'error', allowDuplicate: true })\n }\n enqueueSnackbar(`${CommerceModel.formatQuoteNumber({ number: payload.number ?? undefined }, payload.quoteId)} saved`, {\n variant: 'success',\n persist: false,\n })\n onClose()\n } finally {\n setBusy(false)\n }\n }, [user, quote, hostId, baseUpdatedAtMs, start, form, requireProofApproval, enqueueSnackbar, onClose])\n\n const remove = useCallback(async () => {\n if (!quote) return\n setBusy(true)\n try {\n const response = await authorizedFetch(user, '/api/commerce/quote', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'delete', hostId, quoteId: quote.$id }),\n })\n const payload = await response.json().catch(() => ({}))\n if (!response.ok) {\n return void enqueueSnackbar(payload?.error ?? 'The quote could not be deleted', { variant: 'error', allowDuplicate: true })\n }\n enqueueSnackbar(`${CommerceModel.formatQuoteNumber(quote, quote.$id)} deleted`, { variant: 'success', persist: false })\n setConfirmingDelete(false)\n onClose()\n } finally {\n setBusy(false)\n }\n }, [user, quote, hostId, enqueueSnackbar, onClose])\n\n const [downloading, setDownloading] = useState(false)\n const downloadPdf = useCallback(async () => {\n if (!quote) return\n setDownloading(true)\n try {\n const refused = await downloadCommercePdf(\n user,\n '/api/commerce/quote',\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'pdf', hostId, quoteId: quote.$id }),\n },\n `quote-${quote.number ?? quote.$id.slice(-6)}.pdf`,\n )\n if (refused) enqueueSnackbar(refused, { variant: 'error', allowDuplicate: true })\n } finally {\n setDownloading(false)\n }\n }, [user, quote, hostId, enqueueSnackbar])\n\n const readOnly = !canEdit || busy\n const paid = quote ? !CommerceModel.isUnpaidQuote(quote) : false\n const title = quote ? CommerceModel.formatQuoteNumber(quote, quote.$id) : 'New quote'\n const status = quote ? CommerceModel.quoteDisplayStatus(quote) : null\n const deletable = Boolean(quote) && !paid && (quote?.quote?.stage ?? 'draft') === 'draft'\n\n return (\n <Dialog open onClose={busy ? undefined : onClose} maxWidth=\"md\" fullWidth scroll=\"paper\" aria-labelledby=\"quote-editor-title\">\n <DialogTitle id=\"quote-editor-title\">\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <span>{title}</span>\n {status ? (\n <Chip size=\"small\" variant=\"outlined\" label={status.label} color={CommerceModel.QUOTE_STATUS_COLOR[status.key]} />\n ) : null}\n </Stack>\n </DialogTitle>\n <DialogContent dividers>\n <Stack spacing={3}>\n {paid ? (\n <Alert severity=\"success\">\n {quote?.quote?.paidAtMs\n ? `Paid ${new Date(quote.quote.paidAtMs).toLocaleDateString()}. It is an order now and can no longer be changed.`\n : 'This quote has been paid, so it is an order now and can no longer be changed.'}\n </Alert>\n ) : null}\n {quote ? (\n <QuoteSendSection hostId={hostId} quoteId={quote.$id} quote={quote} canSend={canSend} edited={edited} />\n ) : null}\n {quote ? (\n <QuotePayLinkSection hostId={hostId} quoteId={quote.$id} quote={quote} canSend={canSend} edited={edited} />\n ) : null}\n {quote ? (\n <QuoteProofsSection\n hostId={hostId}\n quoteId={quote.$id}\n quote={quote}\n canEdit={canEdit}\n onEdited={(updatedAtMs) => {\n if (updatedAtMs) setBaseUpdatedAtMs(updatedAtMs)\n }}\n />\n ) : null}\n {/* Where it came from (AGL-4098): the request, its files and its conversation. */}\n {start?.request ? (\n <QuoteStartedFromRequest\n formName={start.request.formName}\n receivedAtMs={start.request.receivedAtMs}\n files={start.files ?? []}\n threaded={start.threaded === true}\n />\n ) : null}\n {quote?.quote?.request ? (\n <QuoteRequestFilesSection hostId={hostId} quoteId={quote.$id} quote={quote} />\n ) : null}\n {taxBasis.kind === 'none' && taxBasis.reason === 'undecided' ? (\n <PrerequisiteNotice href={taxesHref ?? undefined} actionLabel=\"Open Taxes\">\n {'This store has not chosen how it handles sales tax, so this quote shows no tax. Choose it in Taxes.'}\n </PrerequisiteNotice>\n ) : null}\n\n <QuoteCustomerSection\n hostId={hostId}\n form={form}\n disabled={readOnly || paid}\n onChange={(customer) => update({ customer })}\n />\n\n <Stack spacing={1.5}>\n <Typography variant=\"subtitle2\">{'Items'}</Typography>\n {form.lines.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'Add products from your catalog, or type an item that is made to order.'}\n </Typography>\n ) : null}\n {form.lines.map((line, index) => (\n <QuoteLineEditor\n key={line.key}\n line={line}\n priced={priced[index]}\n products={products}\n disabled={readOnly || paid}\n onChange={(patch) => updateLine(line.key, patch)}\n onRemove={() => update({ lines: form.lines.filter((entry) => entry.key !== line.key) })}\n />\n ))}\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ flexWrap: 'wrap' }}>\n <Button\n size=\"small\"\n disabled={readOnly || paid || products.length === 0}\n onClick={() =>\n update({\n lines: [\n ...form.lines,\n { key: nextLineKey(), kind: 'catalog', productId: '', variantId: '', quantity: '1', modifiers: [], description: '', included: false },\n ],\n })\n }\n >\n {'Add product'}\n </Button>\n <Button\n size=\"small\"\n disabled={readOnly || paid}\n onClick={() =>\n update({\n lines: [\n ...form.lines,\n { key: nextLineKey(), kind: 'custom', name: '', description: '', sku: '', price: '', quantity: '1', ships: true, included: false },\n ],\n })\n }\n >\n {'Add custom item'}\n </Button>\n </Stack>\n </Stack>\n\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <TextField\n label=\"Discount\"\n select\n size=\"small\"\n value={form.discountKind}\n disabled={readOnly || paid}\n onChange={(event) => update({ discountKind: event.target.value as QuoteForm['discountKind'] })}\n sx={mediumField}\n >\n <MenuItem value=\"none\">{'None'}</MenuItem>\n <MenuItem value=\"amount\">{'Amount off'}</MenuItem>\n <MenuItem value=\"percent\">{'Percent off'}</MenuItem>\n </TextField>\n {form.discountKind !== 'none' ? (\n <TextField\n label={form.discountKind === 'amount' ? 'Amount ($)' : 'Percent (%)'}\n size=\"small\"\n value={form.discountValue}\n disabled={readOnly || paid}\n onChange={(event) => update({ discountValue: event.target.value })}\n slotProps={{ htmlInput: { inputMode: 'decimal' } }}\n error={form.discountKind === 'amount' ? centsOf(form.discountValue) === null : !(Number(form.discountValue) >= 0 && Number(form.discountValue) <= 100)}\n />\n ) : null}\n <TextField\n label=\"Shipping ($)\"\n size=\"small\"\n value={form.shipping}\n disabled={readOnly || paid}\n onChange={(event) => update({ shipping: event.target.value })}\n slotProps={{ htmlInput: { inputMode: 'decimal' } }}\n error={centsOf(form.shipping) === null}\n helperText=\"Leave empty when nothing ships.\"\n />\n </Stack>\n\n <QuoteAddressFields\n label=\"Ship to\"\n value={form.shipTo}\n disabled={readOnly || paid}\n helperText=\"Where the order goes. Store tax rates use its state and country.\"\n onChange={(shipTo) => update({ shipTo })}\n />\n <QuoteAddressFields\n label=\"Bill to\"\n value={form.billTo}\n disabled={readOnly || paid}\n onChange={(billTo) => update({ billTo })}\n />\n\n <Stack spacing={2}>\n <TextField\n label=\"Notes for the customer\"\n multiline\n minRows={2}\n value={form.notes}\n disabled={readOnly || paid}\n onChange={(event) => update({ notes: event.target.value })}\n />\n <TextField\n label=\"Terms\"\n multiline\n minRows={2}\n value={form.terms}\n disabled={readOnly || paid}\n onChange={(event) => update({ terms: event.target.value })}\n />\n <FormControlLabel\n control={\n <Switch\n checked={requireProofApproval}\n disabled={readOnly || paid}\n onChange={(event) => update({ requireProofApproval: event.target.checked })}\n />\n }\n label=\"Customers approve the proof before they can pay\"\n />\n </Stack>\n\n <Divider />\n <QuoteTotalsSummary\n totals={totals}\n tax={taxBasis}\n savedService={edited ? null : savedService}\n savedTotals={edited ? null : (quote?.totals ?? null)}\n />\n </Stack>\n </DialogContent>\n <DialogActions sx={{ flexWrap: 'wrap', rowGap: 1 }}>\n {deletable ? (\n <BlockedControl blocked={!canEdit} reason={REFUSAL}>\n <Button color=\"error\" disabled={busy} onClick={() => setConfirmingDelete(true)} sx={{ mr: 'auto' }}>\n {'Delete'}\n </Button>\n </BlockedControl>\n ) : null}\n {quote ? (\n <BlockedControl\n blocked={!canEdit || edited}\n reason={edited ? 'Save your changes first: the PDF shows the quote as it was last saved.' : REFUSAL}\n >\n <Button disabled={busy || downloading} onClick={() => void downloadPdf()}>\n {downloading ? 'Making PDF…' : 'Download PDF'}\n </Button>\n </BlockedControl>\n ) : null}\n <Button onClick={onClose} disabled={busy}>\n {paid || !canEdit ? 'Close' : 'Cancel'}\n </Button>\n {paid ? null : (\n <BlockedControl blocked={!canEdit} reason={REFUSAL}>\n <Button\n variant=\"contained\"\n disabled={busy || form.lines.length === 0 || problems}\n onClick={() => void save()}\n >\n {quote ? 'Save' : 'Create quote'}\n </Button>\n </BlockedControl>\n )}\n </DialogActions>\n <Dialog open={confirmingDelete} onClose={() => setConfirmingDelete(false)} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{`Delete ${title}?`}</DialogTitle>\n <DialogContent>\n <DialogContentText>{'The quote and everything on it is removed. This can’t be undone.'}</DialogContentText>\n </DialogContent>\n <DialogActions>\n <Button onClick={() => setConfirmingDelete(false)} disabled={busy}>\n {'Cancel'}\n </Button>\n <Button color=\"error\" variant=\"contained\" disabled={busy} onClick={() => void remove()}>\n {'Delete'}\n </Button>\n </DialogActions>\n </Dialog>\n </Dialog>\n )\n}\nQuoteEditorDialog.displayName = 'QuoteEditorDialog'\n\n/** A new quote's request (AGL-4098): which form sent it and when, its files by name, and its conversation. */\nfunction QuoteStartedFromRequest(props: {\n formName: string\n receivedAtMs: number | null\n files: ReadonlyArray<{ id: string; name: string; size: number }>\n threaded: boolean\n}) {\n const { formName, receivedAtMs, files, threaded } = props\n const when = receivedAtMs\n ? ` on ${new Date(receivedAtMs).toLocaleString(undefined, { dateStyle: 'medium', timeStyle: 'short' })}`\n : ''\n return (\n <Alert severity=\"info\">\n <Stack spacing={1}>\n <Typography variant=\"body2\">{`From a request sent through “${formName}”${when}.`}</Typography>\n {files.length ? (\n <Stack spacing={0.5}>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Their files, kept on the quote as the customer’s:'}\n </Typography>\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{ flexWrap: 'wrap' }}>\n {files.map((file) => (\n <Chip key={file.id} size=\"small\" variant=\"outlined\" label={file.name} />\n ))}\n </Stack>\n </Stack>\n ) : null}\n <Typography variant=\"caption\" color=\"text.secondary\">\n {threaded\n ? 'When you email the quote, it replies to the confirmation they were sent, in the same conversation.'\n : 'They weren’t sent a confirmation, so the quote’s email starts the conversation.'}\n </Typography>\n </Stack>\n </Alert>\n )\n}\n\n/** Who the quote is for: a person the workspace keeps, or details typed here. */\nfunction QuoteCustomerSection(props: {\n hostId: string\n form: QuoteForm\n disabled: boolean\n onChange: (customer: QuoteForm['customer']) => void\n}) {\n const { hostId, form, disabled, onChange } = props\n const { data: user } = useUser()\n const [text, setText] = useState('')\n const [found, setFound] = useState<FoundCustomer[]>([])\n const [available, setAvailable] = useState(true)\n const ticket = useRef(0)\n const customer = form.customer\n\n useEffect(() => {\n const typed = text.trim()\n if (typed.length < 2 || !user) {\n // Only when something is listed, so an effect that re-runs settles.\n setFound((prev) => (prev.length ? [] : prev))\n return\n }\n const mine = ++ticket.current\n const timer = window.setTimeout(() => {\n void authorizedFetch(user, '/api/commerce/quote', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ action: 'search-customers', hostId, text: typed }),\n })\n .then((response) => response.json().catch(() => ({})))\n .then((payload) => {\n if (mine !== ticket.current) return\n setAvailable(payload?.available !== false)\n setFound(Array.isArray(payload?.customers) ? payload.customers : [])\n })\n .catch(() => undefined)\n }, SEARCH_DEBOUNCE_MS)\n return () => window.clearTimeout(timer)\n }, [text, user, hostId])\n\n const pick = (person: FoundCustomer) => {\n onChange({\n record: person.record,\n name: person.name,\n company: person.company,\n email: person.email ?? '',\n phone: person.phone ?? '',\n })\n setText('')\n setFound([])\n }\n\n return (\n <Stack spacing={1.5}>\n <Typography variant=\"subtitle2\">{'Customer'}</Typography>\n {customer.record ? (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Chip\n color=\"primary\"\n variant=\"outlined\"\n label={customer.name || customer.email || 'Contact'}\n onDelete={disabled ? undefined : () => onChange({ ...customer, record: null })}\n />\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'From your contacts'}\n </Typography>\n </Stack>\n ) : available ? (\n <Box>\n <TextField\n size=\"small\"\n fullWidth\n label=\"Find a contact\"\n placeholder=\"Name, email or phone\"\n value={text}\n disabled={disabled}\n onChange={(event) => setText(event.target.value)}\n />\n {found.length ? (\n <Paper variant=\"outlined\" sx={{ mt: 0.5 }}>\n <List dense disablePadding>\n {found.map((person) => (\n <ListItemButton key={`${person.record.kind}:${person.record.id}`} onClick={() => pick(person)}>\n <ListItemText\n primary={person.name || person.email || 'Contact'}\n secondary={[person.company, person.email, person.phone].filter(Boolean).join(' · ')}\n />\n </ListItemButton>\n ))}\n </List>\n </Paper>\n ) : null}\n </Box>\n ) : null}\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <TextField size=\"small\" fullWidth label=\"Name\" value={customer.name} disabled={disabled} onChange={(event) => onChange({ ...customer, name: event.target.value })} />\n <TextField size=\"small\" fullWidth label=\"Company\" value={customer.company} disabled={disabled} onChange={(event) => onChange({ ...customer, company: event.target.value })} />\n </Stack>\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <TextField size=\"small\" fullWidth label=\"Email\" type=\"email\" value={customer.email} disabled={disabled} onChange={(event) => onChange({ ...customer, email: event.target.value })} />\n <TextField size=\"small\" fullWidth label=\"Phone\" value={customer.phone} disabled={disabled} onChange={(event) => onChange({ ...customer, phone: event.target.value })} />\n </Stack>\n </Stack>\n )\n}\n\n/** One address on the quote. */\nfunction QuoteAddressFields(props: {\n label: string\n value: AddressForm\n disabled: boolean\n helperText?: string\n onChange: (value: AddressForm) => void\n}) {\n const { label, value, disabled, helperText, onChange } = props\n const field = (key: keyof AddressForm, fieldLabel: string, extra: Record<string, unknown> = {}) => (\n <TextField\n size=\"small\"\n fullWidth\n label={fieldLabel}\n value={value[key]}\n disabled={disabled}\n onChange={(event) => onChange({ ...value, [key]: event.target.value })}\n {...extra}\n />\n )\n return (\n <Stack spacing={1.5}>\n <Typography variant=\"subtitle2\">{label}</Typography>\n {helperText ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {helperText}\n </Typography>\n ) : null}\n {field('name', 'Name')}\n {field('line1', 'Address')}\n {field('line2', 'Apartment, suite, unit')}\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n {field('city', 'City')}\n {field('state', 'State or region')}\n {field('postalCode', 'Postal code')}\n {field('country', 'Country code', { placeholder: 'US', slotProps: { htmlInput: { maxLength: 2 } } })}\n </Stack>\n </Stack>\n )\n}\n\n/** One line of the quote: a product with its options and add-ons, or a typed item. */\nfunction QuoteLineEditor(props: {\n line: LineForm\n priced: { line?: CommerceModel.PricedQuoteLine; error?: string } | undefined\n products: readonly Record<string, any>[]\n disabled: boolean\n onChange: (patch: Partial<LineForm>) => void\n onRemove: () => void\n}) {\n const { line, priced, products, disabled, onChange, onRemove } = props\n const product = line.kind === 'catalog' ? products.find((entry) => String(entry.$id) === line.productId) : undefined\n const lifted = product ? CommerceModel.liftLegacyProduct(product) : null\n const groups = lifted ? CommerceModel.productModifierGroups(lifted) : []\n const lineCents = priced?.line ? CommerceModel.quoteLineCents(priced.line) : 0\n\n return (\n <Paper variant=\"outlined\" sx={{ p: 2 }}>\n <Stack spacing={1.5}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'flex-start' }}>\n <Stack spacing={1.5} sx={{ flex: 1, minWidth: 0 }}>\n {line.kind === 'catalog' ? (\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <TextField\n label=\"Product\"\n select\n size=\"small\"\n fullWidth\n value={line.productId}\n disabled={disabled}\n onChange={(event) => onChange({ productId: event.target.value, variantId: '', modifiers: [] })}\n >\n {products.map((entry) => (\n <MenuItem key={String(entry.$id)} value={String(entry.$id)}>\n {String(entry.name ?? entry.$id)}\n </MenuItem>\n ))}\n </TextField>\n {lifted && lifted.variants.length > 1 ? (\n <TextField\n label=\"Option\"\n select\n size=\"small\"\n fullWidth\n value={line.variantId || lifted.variants[0]?.id || ''}\n disabled={disabled}\n onChange={(event) => onChange({ variantId: event.target.value })}\n >\n {lifted.variants.map((variant) => (\n <MenuItem key={variant.id} value={variant.id}>\n {Object.values(variant.options ?? {}).join(' / ') || 'Default'}\n </MenuItem>\n ))}\n </TextField>\n ) : null}\n </Stack>\n ) : (\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>\n <TextField\n label=\"Item\"\n size=\"small\"\n fullWidth\n value={line.name}\n disabled={disabled}\n onChange={(event) => onChange({ name: event.target.value })}\n />\n <TextField\n label=\"SKU (optional)\"\n size=\"small\"\n value={line.sku}\n disabled={disabled}\n onChange={(event) => onChange({ sku: event.target.value })}\n />\n </Stack>\n )}\n {groups.map((group) => {\n const chosen = line.kind === 'catalog' ? line.modifiers.filter((pick) => pick.groupId === group.id).map((pick) => pick.optionId) : []\n return (\n <TextField\n key={group.id}\n label={CommerceModel.modifierGroupRequired(group) ? group.name : `${group.name} (optional)`}\n select\n size=\"small\"\n fullWidth\n value={group.max > 1 ? chosen : (chosen[0] ?? '')}\n disabled={disabled}\n slotProps={{ select: { multiple: group.max > 1 } }}\n onChange={(event) => {\n const raw = event.target.value as unknown\n const picked = (Array.isArray(raw) ? raw : raw ? [raw] : []).map(String)\n if (line.kind !== 'catalog') return\n onChange({\n modifiers: [\n ...line.modifiers.filter((pick) => pick.groupId !== group.id),\n ...picked.map((optionId) => ({ groupId: group.id, optionId })),\n ],\n })\n }}\n >\n {group.max > 1 ? null : <MenuItem value=\"\">{'None'}</MenuItem>}\n {group.options.map((option) => (\n <MenuItem key={option.id} value={option.id}>\n {option.priceCents ? `${option.name} (+${money(option.priceCents)})` : option.name}\n </MenuItem>\n ))}\n </TextField>\n )\n })}\n <TextField\n label=\"Description (optional)\"\n size=\"small\"\n fullWidth\n multiline\n value={line.description}\n disabled={disabled}\n onChange={(event) => onChange({ description: event.target.value })}\n />\n <Stack direction={{ xs: 'column', sm: 'row' }} spacing={2} sx={{ alignItems: { sm: 'center' } }}>\n <TextField\n label=\"Quantity\"\n size=\"small\"\n value={line.quantity}\n disabled={disabled}\n onChange={(event) => onChange({ quantity: event.target.value.replace(/[^0-9]/g, '') })}\n slotProps={{ htmlInput: { inputMode: 'numeric' } }}\n sx={narrowField}\n />\n {line.kind === 'custom' ? (\n <TextField\n label=\"Unit price ($)\"\n size=\"small\"\n value={line.included ? '' : line.price}\n disabled={disabled || line.included}\n onChange={(event) => onChange({ price: event.target.value })}\n slotProps={{ htmlInput: { inputMode: 'decimal' } }}\n error={!line.included && centsOf(line.price) === null}\n sx={mediumField}\n />\n ) : null}\n {line.kind === 'custom' ? (\n <FormControlLabel\n control={<Switch checked={line.ships} disabled={disabled} onChange={(event) => onChange({ ships: event.target.checked })} />}\n label=\"Ships\"\n />\n ) : null}\n <FormControlLabel\n control={\n <Switch checked={line.included} disabled={disabled} onChange={(event) => onChange({ included: event.target.checked })} />\n }\n label=\"Included at no charge\"\n />\n </Stack>\n </Stack>\n <Stack sx={{ alignItems: 'flex-end', flexShrink: 0 }}>\n <Button size=\"small\" color=\"inherit\" disabled={disabled} onClick={onRemove}>\n {'Remove'}\n </Button>\n <Typography variant=\"body2\" sx={{ fontWeight: 'fontWeightMedium' }}>\n {line.included ? 'Included' : money(lineCents)}\n </Typography>\n {priced?.line && !line.included && priced.line.quantity > 1 ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {`${money(priced.line.unitAmountCents)} each`}\n </Typography>\n ) : null}\n </Stack>\n </Stack>\n {priced?.error ? (\n <Typography variant=\"caption\" color=\"error\">\n {priced.error}\n </Typography>\n ) : null}\n </Stack>\n </Paper>\n )\n}\n\n/** The quote's totals, as the customer will read them. */\nfunction QuoteTotalsSummary(props: {\n totals: CommerceModel.QuoteTotals\n tax: CommerceModel.QuoteTaxBasis\n /** A saved quote's tax service answer, shown until the quote is edited. */\n savedService: CommerceModel.QuoteTaxBasis | null\n savedTotals: CommerceModel.OrderTotals | null\n}) {\n const { totals, tax, savedService, savedTotals } = props\n const shown = savedService && savedTotals ? { ...totals, ...savedTotals } : totals\n const taxLabel = CommerceModel.describeQuoteTax(savedService ?? tax)\n const row = (label: string, value: string, strong = false) => (\n <Stack direction=\"row\" sx={{ justifyContent: 'space-between' }}>\n <Typography variant={strong ? 'subtitle1' : 'body2'} color={strong ? 'text.primary' : 'text.secondary'}>\n {label}\n </Typography>\n <Typography variant={strong ? 'subtitle1' : 'body2'}>{value}</Typography>\n </Stack>\n )\n return (\n <Stack spacing={0.5} sx={(theme) => ({ alignSelf: { sm: 'flex-end' }, minWidth: { sm: theme.spacing(40) } })}>\n {row('Items', money(shown.itemsCents))}\n {shown.discountCents ? row('Discount', `−${money(shown.discountCents)}`) : null}\n {shown.shippingCents ? row('Shipping', money(shown.shippingCents)) : null}\n {tax.kind === 'at-payment' && !savedService ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {taxLabel}\n </Typography>\n ) : (\n row(taxLabel, money(shown.taxCents))\n )}\n {row(totals.taxAtPayment && !savedService ? 'Total before tax' : 'Total', money(shown.totalCents), true)}\n </Stack>\n )\n}\n\nexport default QuoteEditorDialog\n"],"names":["CommerceModel","posMoney","commerceSitePermissionRefusal","BlockedControl","PrerequisiteNotice","useSnackbar","authorizedFetch","useFirestore","useFirestoreDoc","useStoreSettingsHref","useUser","Alert","Box","Button","Chip","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","Divider","FormControlLabel","List","ListItemButton","ListItemText","MenuItem","Paper","Stack","Switch","TextField","Typography","doc","useCallback","useEffect","useMemo","useRef","useState","downloadCommercePdf","QuotePayLinkSection","QuoteProofsSection","QuoteRequestFilesSection","QuoteSendSection","REFUSAL","SEARCH_DEBOUNCE_MS","money","cents","narrowField","theme","maxWidth","sm","spacing","mediumField","minWidth","centsOf","text","trimmed","trim","test","Math","round","Number","dollarsOf","toFixed","replace","addressForm","address","name","line1","line2","city","state","postalCode","country","lineSequence","nextLineKey","formFromQuote","quote","requireProofApproval","section","discount","lines","lineItems","map","line","request","quoteLineRequestFromLine","kind","key","description","sku","price","unitAmountCents","quantity","String","ships","included","productId","variantId","modifiers","customer","record","company","email","phone","shipTo","billTo","discountKind","discountValue","amountCents","pct","shipping","notes","terms","formFromStart","start","blank","prefill","lineRequest","length","NaN","addressBody","entries","Object","filter","value","fromEntries","quoteBody","form","discountCents","QuoteEditorDialog","props","hostId","products","canEdit","canSend","onClose","firestore","data","user","enqueueSnackbar","taxesHref","store","storeDefault","quoteRequiresProofApprovalByDefault","quotes","setForm","baseUpdatedAtMs","setBaseUpdatedAtMs","updatedAtMs","busy","setBusy","confirmingDelete","setConfirmingDelete","edited","setEdited","approvalSet","setApprovalSet","update","patch","prev","updateLine","attemptKey","current","productsById","Map","product","$id","priced","error","isInteger","priceQuoteCustomLine","answer","priceQuoteCatalogLine","get","min","shippingCents","taxBasis","quoteTaxBasisFromSettings","tax","toUpperCase","pricedLines","flatMap","entry","totals","computeQuoteTotals","problems","some","savedService","save","payload","globalThis","crypto","randomUUID","Date","now","random","toString","slice","response","method","headers","body","JSON","stringify","action","quoteId","from","json","catch","ok","variant","allowDuplicate","formatQuoteNumber","number","undefined","persist","remove","downloading","setDownloading","downloadPdf","refused","readOnly","paid","isUnpaidQuote","title","status","quoteDisplayStatus","deletable","Boolean","stage","open","fullWidth","scroll","aria-labelledby","id","direction","sx","alignItems","span","size","label","color","QUOTE_STATUS_COLOR","dividers","severity","paidAtMs","toLocaleDateString","onEdited","QuoteStartedFromRequest","formName","receivedAtMs","files","threaded","reason","href","actionLabel","QuoteCustomerSection","disabled","onChange","index","QuoteLineEditor","onRemove","useFlexGap","flexWrap","onClick","xs","select","event","target","slotProps","htmlInput","inputMode","helperText","QuoteAddressFields","multiline","minRows","control","checked","QuoteTotalsSummary","savedTotals","rowGap","blocked","mr","displayName","when","toLocaleString","dateStyle","timeStyle","file","setText","found","setFound","available","setAvailable","ticket","typed","mine","timer","window","setTimeout","then","Array","isArray","customers","clearTimeout","pick","person","onDelete","placeholder","mt","dense","disablePadding","primary","secondary","join","type","field","fieldLabel","extra","maxLength","lifted","find","liftLegacyProduct","groups","productModifierGroups","lineCents","quoteLineCents","p","flex","variants","values","options","group","chosen","groupId","optionId","modifierGroupRequired","max","multiple","raw","picked","option","priceCents","flexShrink","fontWeight","shown","taxLabel","describeQuoteTax","row","strong","justifyContent","alignSelf","itemsCents","taxCents","taxAtPayment","totalCents"],"mappings":"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"}
@@ -18,7 +18,7 @@ import * as CommerceModel from '../../model';
18
18
  export interface QuotePayLinkSectionProps {
19
19
  hostId: string;
20
20
  quoteId: string;
21
- quote: Pick<CommerceModel.HostOrder, 'status' | 'channel' | 'number'>;
21
+ quote: Pick<CommerceModel.HostOrder, 'status' | 'channel' | 'number' | 'quote'>;
22
22
  /** Holds "Send quotes and invoices to customers" (`commerce.quotes.send`). */
23
23
  canSend: boolean;
24
24
  /** The editor holds changes not saved yet, which the link does not show. */
@@ -30,6 +30,13 @@ export interface QuotePayLinkSectionProps {
30
30
  * button. "Copy pay link" asks the server for it (it is signed there) and puts
31
31
  * it on the clipboard and on screen; "Replace link" makes a new one and the
32
32
  * one sent before stops opening the quote.
33
+ *
34
+ * The link shown is kept with the version it was made at, and drops as soon
35
+ * as the quote's stored version (`quote.linkVersion`) moves past it: a
36
+ * revision's first email and Replace link (here or anywhere else) both move
37
+ * it, and the link from before then opens only "This quote was updated". A
38
+ * link already on screen is fetched again at the new version; Copy pay link
39
+ * never copies one older than the quote's.
33
40
  */
34
41
  export declare function QuotePayLinkSection(props: QuotePayLinkSectionProps): import("react").JSX.Element;
35
42
  export declare namespace QuotePayLinkSection {