@aglyn/plugins-commerce 1.0.0-beta.288 → 1.0.0-beta.289
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +13 -13
- package/src/lib/components/commerce-console-page.js +29 -2
- package/src/lib/components/commerce-console-page.js.map +1 -1
- package/src/lib/components/console/commerce-analytics-card.component.js +4 -2
- package/src/lib/components/console/commerce-analytics-card.component.js.map +1 -1
- package/src/lib/components/console/host-orders-card.component.js +5 -1
- package/src/lib/components/console/host-orders-card.component.js.map +1 -1
- package/src/lib/components/console/host-quotes-card.component.d.ts +34 -0
- package/src/lib/components/console/host-quotes-card.component.js +247 -0
- package/src/lib/components/console/host-quotes-card.component.js.map +1 -0
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js +33 -28
- package/src/lib/components/console/pos-ops/pos-check-ins-card.component.js.map +1 -1
- package/src/lib/components/console/quote-editor-dialog.component.d.ts +45 -0
- package/src/lib/components/console/quote-editor-dialog.component.js +1266 -0
- package/src/lib/components/console/quote-editor-dialog.component.js.map +1 -0
- package/src/lib/components/console/quote-pay-link.component.d.ts +38 -0
- package/src/lib/components/console/quote-pay-link.component.js +213 -0
- package/src/lib/components/console/quote-pay-link.component.js.map +1 -0
- package/src/lib/components/console/quote-settings-card.component.d.ts +29 -0
- package/src/lib/components/console/quote-settings-card.component.js +121 -0
- package/src/lib/components/console/quote-settings-card.component.js.map +1 -0
- package/src/lib/components/console/tax-settings-card.component.js +4 -1
- package/src/lib/components/console/tax-settings-card.component.js.map +1 -1
- package/src/lib/components/quote-page-body.d.ts +33 -0
- package/src/lib/components/quote-page-body.js +696 -0
- package/src/lib/components/quote-page-body.js.map +1 -0
- package/src/lib/components/quote-page.d.ts +29 -0
- package/src/lib/components/quote-page.js +96 -0
- package/src/lib/components/quote-page.js.map +1 -0
- package/src/lib/components/storefront-payment-element.d.ts +7 -1
- package/src/lib/components/storefront-payment-element.js +8 -3
- package/src/lib/components/storefront-payment-element.js.map +1 -1
- package/src/lib/constants/orders-list-query.js +6 -1
- package/src/lib/constants/orders-list-query.js.map +1 -1
- package/src/lib/constants/quote-page.d.ts +30 -0
- package/src/lib/constants/quote-page.js +35 -0
- package/src/lib/constants/quote-page.js.map +1 -0
- package/src/lib/model/commerce-orders.d.ts +25 -2
- package/src/lib/model/commerce-orders.js +10 -1
- package/src/lib/model/commerce-orders.js.map +1 -1
- package/src/lib/model/commerce-quote-pay.d.ts +229 -0
- package/src/lib/model/commerce-quote-pay.js +393 -0
- package/src/lib/model/commerce-quote-pay.js.map +1 -0
- package/src/lib/model/commerce-quotes.d.ts +279 -0
- package/src/lib/model/commerce-quotes.js +522 -0
- package/src/lib/model/commerce-quotes.js.map +1 -0
- package/src/lib/model/index.d.ts +2 -0
- package/src/lib/model/index.js +2 -0
- package/src/lib/model/index.js.map +1 -1
- package/src/lib/model/plugin-permissions.d.ts +1 -1
- package/src/lib/model/plugin-permissions.js +20 -0
- package/src/lib/model/plugin-permissions.js.map +1 -1
- package/src/lib/server/api-v1/orders-and-products.js +6 -2
- package/src/lib/server/api-v1/orders-and-products.js.map +1 -1
- package/src/lib/server/billing-webhook.js +127 -52
- package/src/lib/server/billing-webhook.js.map +1 -1
- package/src/lib/server/checkout-session-expiry.d.ts +36 -0
- package/src/lib/server/checkout-session-expiry.js +63 -0
- package/src/lib/server/checkout-session-expiry.js.map +1 -0
- package/src/lib/server/draft-order.js +16 -8
- package/src/lib/server/draft-order.js.map +1 -1
- package/src/lib/server/person-eraser.d.ts +7 -0
- package/src/lib/server/person-eraser.js +24 -2
- package/src/lib/server/person-eraser.js.map +1 -1
- package/src/lib/server/pos-return.js +3 -1
- package/src/lib/server/pos-return.js.map +1 -1
- package/src/lib/server/quote-link-token.d.ts +39 -0
- package/src/lib/server/quote-link-token.js +97 -0
- package/src/lib/server/quote-link-token.js.map +1 -0
- package/src/lib/server/quote-pay.d.ts +83 -0
- package/src/lib/server/quote-pay.js +606 -0
- package/src/lib/server/quote-pay.js.map +1 -0
- package/src/lib/server/quote.d.ts +49 -0
- package/src/lib/server/quote.js +513 -0
- package/src/lib/server/quote.js.map +1 -0
- package/src/lib/server/related.js +2 -0
- package/src/lib/server/related.js.map +1 -1
- package/src/lib/server/site-page-resolver.d.ts +2 -0
- package/src/lib/server/site-page-resolver.js +75 -0
- package/src/lib/server/site-page-resolver.js.map +1 -1
- package/src/lib/server.js +14 -0
- package/src/lib/server.js.map +1 -1
- package/src/lib/site.js +6 -0
- package/src/lib/site.js.map +1 -1
- package/src/lib/transfer/tracking.server.js +6 -0
- package/src/lib/transfer/tracking.server.js.map +1 -1
|
@@ -0,0 +1,696 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
4
|
+
/**
|
|
5
|
+
* @license
|
|
6
|
+
* Copyright 2026 Aglyn LLC
|
|
7
|
+
*
|
|
8
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
* you may not use this file except in compliance with the License.
|
|
10
|
+
* You may obtain a copy of the License at
|
|
11
|
+
*
|
|
12
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
*
|
|
14
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
* See the License for the specific language governing permissions and
|
|
18
|
+
* limitations under the License.
|
|
19
|
+
*/ import * as Aglyn from "@aglyn/aglyn";
|
|
20
|
+
import Alert from "@mui/material/Alert";
|
|
21
|
+
import Box from "@mui/material/Box";
|
|
22
|
+
import Button from "@mui/material/Button";
|
|
23
|
+
import Chip from "@mui/material/Chip";
|
|
24
|
+
import CircularProgress from "@mui/material/CircularProgress";
|
|
25
|
+
import Divider from "@mui/material/Divider";
|
|
26
|
+
import Paper from "@mui/material/Paper";
|
|
27
|
+
import Stack from "@mui/material/Stack";
|
|
28
|
+
import Typography from "@mui/material/Typography";
|
|
29
|
+
import { forwardRef, lazy, Suspense, useCallback, useEffect, useRef, useState } from "react";
|
|
30
|
+
import { formatOrderMoney, readStorefrontCheckoutWallets } from "../model/index.js";
|
|
31
|
+
import { StorefrontPaymentElementFallback } from "./storefront-payment-element-fallback.js";
|
|
32
|
+
/** The Payment Element, lazily: Stripe.js loads only when a customer presses Pay. */ const StorefrontPaymentElement = /*#__PURE__*/ lazy(()=>import("./storefront-payment-element.js").then((module)=>({
|
|
33
|
+
default: module.StorefrontPaymentElement
|
|
34
|
+
})));
|
|
35
|
+
/** After a payment returns here, how often and how long the page asks whether it landed. */ const CONFIRM_POLL_MS = 2000;
|
|
36
|
+
const CONFIRM_POLLS = 15;
|
|
37
|
+
function dateLabel(atMs) {
|
|
38
|
+
if (!atMs) return '';
|
|
39
|
+
return new Date(atMs).toLocaleDateString(undefined, {
|
|
40
|
+
month: 'short',
|
|
41
|
+
day: 'numeric',
|
|
42
|
+
year: 'numeric'
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function addressLines(address) {
|
|
46
|
+
const cityLine = [
|
|
47
|
+
address.city,
|
|
48
|
+
[
|
|
49
|
+
address.state,
|
|
50
|
+
address.postalCode
|
|
51
|
+
].filter(Boolean).join(' ')
|
|
52
|
+
].filter(Boolean).join(', ');
|
|
53
|
+
return [
|
|
54
|
+
address.name,
|
|
55
|
+
address.line1,
|
|
56
|
+
address.line2,
|
|
57
|
+
cityLine,
|
|
58
|
+
address.country
|
|
59
|
+
].filter((line)=>Boolean(line));
|
|
60
|
+
}
|
|
61
|
+
function stripeContact(address) {
|
|
62
|
+
if (!(address == null ? void 0 : address.country)) return undefined;
|
|
63
|
+
return {
|
|
64
|
+
name: address.name,
|
|
65
|
+
address: {
|
|
66
|
+
country: address.country,
|
|
67
|
+
line1: address.line1,
|
|
68
|
+
line2: address.line2,
|
|
69
|
+
city: address.city,
|
|
70
|
+
state: address.state,
|
|
71
|
+
postal_code: address.postalCode
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function AddressBlock({ label, lines }) {
|
|
76
|
+
return /*#__PURE__*/ _jsxs(Stack, {
|
|
77
|
+
spacing: 0.25,
|
|
78
|
+
sx: {
|
|
79
|
+
minWidth: 0,
|
|
80
|
+
flex: 1
|
|
81
|
+
},
|
|
82
|
+
children: [
|
|
83
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
84
|
+
variant: "overline",
|
|
85
|
+
color: "text.secondary",
|
|
86
|
+
children: label
|
|
87
|
+
}),
|
|
88
|
+
lines.map((line, index)=>/*#__PURE__*/ _jsx(Typography, {
|
|
89
|
+
variant: "body2",
|
|
90
|
+
children: line
|
|
91
|
+
}, index))
|
|
92
|
+
]
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function TotalRow({ label, value, strong }) {
|
|
96
|
+
return /*#__PURE__*/ _jsxs(Stack, {
|
|
97
|
+
direction: "row",
|
|
98
|
+
spacing: 2,
|
|
99
|
+
sx: {
|
|
100
|
+
justifyContent: 'space-between'
|
|
101
|
+
},
|
|
102
|
+
children: [
|
|
103
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
104
|
+
variant: strong ? 'subtitle1' : 'body2',
|
|
105
|
+
color: strong ? 'text.primary' : 'text.secondary',
|
|
106
|
+
children: label
|
|
107
|
+
}),
|
|
108
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
109
|
+
variant: strong ? 'subtitle1' : 'body2',
|
|
110
|
+
color: strong ? 'text.primary' : 'text.secondary',
|
|
111
|
+
children: value
|
|
112
|
+
})
|
|
113
|
+
]
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* The customer's quote page (AGL-4094), loaded when the page draws it (see
|
|
118
|
+
* `quote-page.tsx`): what a customer sees when they open
|
|
119
|
+
* the pay link a business sent them. The commerce page resolver serves it at
|
|
120
|
+
* `/pay-quote` inside the site's own header and footer; a business can also
|
|
121
|
+
* place it on a page of their own design at that address.
|
|
122
|
+
*
|
|
123
|
+
* The quote is read AFTER hydration from `?q=&t=`, so the page itself is the
|
|
124
|
+
* same for every customer and may be cached, and the quote never is. Pay asks
|
|
125
|
+
* the server for a fresh payment for the quote as the page shows it: Stripe's
|
|
126
|
+
* own page, or the payment form here when in-page payments are on. Nothing
|
|
127
|
+
* here decides a quote is paid; after paying, the page reads that from the
|
|
128
|
+
* server like any other visit.
|
|
129
|
+
*/ const QuotePageBody = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
130
|
+
const { heading } = props, rest = _object_without_properties_loose(props, [
|
|
131
|
+
"heading"
|
|
132
|
+
]);
|
|
133
|
+
const nodeSx = Array.isArray(props['sx']) ? props['sx'] : [
|
|
134
|
+
props['sx']
|
|
135
|
+
];
|
|
136
|
+
const { hostId } = Aglyn.useSite();
|
|
137
|
+
const siteFetch = Aglyn.useSiteFetch();
|
|
138
|
+
const [state, setState] = useState({
|
|
139
|
+
kind: 'loading'
|
|
140
|
+
});
|
|
141
|
+
const [paying, setPaying] = useState(false);
|
|
142
|
+
const [payError, setPayError] = useState('');
|
|
143
|
+
const [nativeCheckout, setNativeCheckout] = useState(null);
|
|
144
|
+
/** What a return from paying turned out to be: still being confirmed, or not paid. */ const [returned, setReturned] = useState(null);
|
|
145
|
+
const link = useRef({
|
|
146
|
+
quoteId: '',
|
|
147
|
+
token: '',
|
|
148
|
+
sessionId: ''
|
|
149
|
+
});
|
|
150
|
+
const load = useCallback(async ()=>{
|
|
151
|
+
const { quoteId, token } = link.current;
|
|
152
|
+
try {
|
|
153
|
+
var _payload_storeName;
|
|
154
|
+
const response = await siteFetch(`/api/commerce/quote-view?hostId=${encodeURIComponent(hostId != null ? hostId : '')}` + `&q=${encodeURIComponent(quoteId)}&t=${encodeURIComponent(token)}`);
|
|
155
|
+
const payload = await response.json().catch(()=>({}));
|
|
156
|
+
if (!response.ok) {
|
|
157
|
+
var _ref;
|
|
158
|
+
return {
|
|
159
|
+
kind: 'missing',
|
|
160
|
+
message: String((_ref = payload == null ? void 0 : payload.error) != null ? _ref : 'We could not find that quote.')
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
if ((payload == null ? void 0 : payload.state) === 'replaced') return {
|
|
164
|
+
kind: 'replaced',
|
|
165
|
+
storeName: String((_payload_storeName = payload.storeName) != null ? _payload_storeName : '')
|
|
166
|
+
};
|
|
167
|
+
return {
|
|
168
|
+
kind: 'ready',
|
|
169
|
+
view: payload
|
|
170
|
+
};
|
|
171
|
+
} catch (unused) {
|
|
172
|
+
return {
|
|
173
|
+
kind: 'missing',
|
|
174
|
+
message: 'This quote could not be loaded. Check your connection and try again.'
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}, [
|
|
178
|
+
hostId,
|
|
179
|
+
siteFetch
|
|
180
|
+
]);
|
|
181
|
+
useEffect(()=>{
|
|
182
|
+
var _params_get, _params_get1, _params_get2;
|
|
183
|
+
if (!hostId) return;
|
|
184
|
+
const params = new URLSearchParams(window.location.search);
|
|
185
|
+
link.current = {
|
|
186
|
+
quoteId: (_params_get = params.get('q')) != null ? _params_get : '',
|
|
187
|
+
token: (_params_get1 = params.get('t')) != null ? _params_get1 : '',
|
|
188
|
+
sessionId: (_params_get2 = params.get('session_id')) != null ? _params_get2 : ''
|
|
189
|
+
};
|
|
190
|
+
if (!link.current.quoteId || !link.current.token) {
|
|
191
|
+
setState({
|
|
192
|
+
kind: 'missing',
|
|
193
|
+
message: 'Open this page from the link you were sent with your quote.'
|
|
194
|
+
});
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
let live = true;
|
|
198
|
+
void (async ()=>{
|
|
199
|
+
const first = await load();
|
|
200
|
+
if (!live) return;
|
|
201
|
+
setState(first);
|
|
202
|
+
const sessionId = link.current.sessionId;
|
|
203
|
+
if (first.kind !== 'ready' || first.view.status !== 'unpaid' || !sessionId) return;
|
|
204
|
+
// Back from paying: the payment may have landed before the record of it.
|
|
205
|
+
const status = await siteFetch(`/api/commerce/checkout-status?hostId=${encodeURIComponent(hostId)}` + `&sessionId=${encodeURIComponent(sessionId)}`).then((response)=>response.ok ? response.json() : null).catch(()=>null);
|
|
206
|
+
if (!live) return;
|
|
207
|
+
if ((status == null ? void 0 : status.status) === 'open') {
|
|
208
|
+
setReturned('failed');
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
if ((status == null ? void 0 : status.status) !== 'complete') return;
|
|
212
|
+
setReturned('confirming');
|
|
213
|
+
for(let poll = 0; poll < CONFIRM_POLLS && live; poll++){
|
|
214
|
+
await new Promise((resolve)=>setTimeout(resolve, CONFIRM_POLL_MS));
|
|
215
|
+
if (!live) return;
|
|
216
|
+
const next = await load();
|
|
217
|
+
if (!live) return;
|
|
218
|
+
if (next.kind === 'ready' && next.view.status !== 'unpaid') {
|
|
219
|
+
setState(next);
|
|
220
|
+
setReturned(null);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (live) setReturned('unconfirmed');
|
|
225
|
+
})();
|
|
226
|
+
return ()=>{
|
|
227
|
+
live = false;
|
|
228
|
+
};
|
|
229
|
+
}, [
|
|
230
|
+
hostId,
|
|
231
|
+
load,
|
|
232
|
+
siteFetch
|
|
233
|
+
]);
|
|
234
|
+
const view = state.kind === 'ready' ? state.view : null;
|
|
235
|
+
const pay = useCallback(async ()=>{
|
|
236
|
+
var _ref;
|
|
237
|
+
var _globalThis_crypto_randomUUID, _globalThis_crypto;
|
|
238
|
+
if (!view || paying) return;
|
|
239
|
+
setPaying(true);
|
|
240
|
+
setPayError('');
|
|
241
|
+
setReturned(null);
|
|
242
|
+
// One key per press: a press is one attempt, and a retry after a failure is a new one.
|
|
243
|
+
const attemptKey = (_ref = (_globalThis_crypto = globalThis.crypto) == null ? void 0 : (_globalThis_crypto_randomUUID = _globalThis_crypto.randomUUID) == null ? void 0 : _globalThis_crypto_randomUUID.call(_globalThis_crypto)) != null ? _ref : `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
244
|
+
try {
|
|
245
|
+
var _ref1;
|
|
246
|
+
const response = await siteFetch('/api/commerce/quote-pay', {
|
|
247
|
+
method: 'POST',
|
|
248
|
+
headers: {
|
|
249
|
+
'Content-Type': 'application/json',
|
|
250
|
+
'Idempotency-Key': attemptKey
|
|
251
|
+
},
|
|
252
|
+
body: JSON.stringify({
|
|
253
|
+
hostId,
|
|
254
|
+
q: link.current.quoteId,
|
|
255
|
+
t: link.current.token,
|
|
256
|
+
v: view.version
|
|
257
|
+
})
|
|
258
|
+
});
|
|
259
|
+
const payload = await response.json().catch(()=>({}));
|
|
260
|
+
// A session with a client secret is the in-page form; checked before the
|
|
261
|
+
// redirect, so a form is never navigated away from.
|
|
262
|
+
if (response.ok && (payload == null ? void 0 : payload.clientSecret) && (payload == null ? void 0 : payload.publishableKey)) {
|
|
263
|
+
setNativeCheckout({
|
|
264
|
+
clientSecret: String(payload.clientSecret),
|
|
265
|
+
publishableKey: String(payload.publishableKey),
|
|
266
|
+
wallets: readStorefrontCheckoutWallets(payload.wallets)
|
|
267
|
+
});
|
|
268
|
+
setPaying(false);
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
if (response.ok && (payload == null ? void 0 : payload.url)) {
|
|
272
|
+
window.location.assign(String(payload.url));
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (payload == null ? void 0 : payload.replaced) {
|
|
276
|
+
setState({
|
|
277
|
+
kind: 'replaced',
|
|
278
|
+
storeName: view.storeName
|
|
279
|
+
});
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
if ((payload == null ? void 0 : payload.reason) === 'paid' || (payload == null ? void 0 : payload.reason) === 'updated') {
|
|
283
|
+
const next = await load();
|
|
284
|
+
setState(next);
|
|
285
|
+
}
|
|
286
|
+
setPayError(String((_ref1 = payload == null ? void 0 : payload.error) != null ? _ref1 : 'Your payment could not be set up. Try again.'));
|
|
287
|
+
setPaying(false);
|
|
288
|
+
} catch (unused) {
|
|
289
|
+
setPayError('Your payment could not be set up. Check your connection and try again.');
|
|
290
|
+
setPaying(false);
|
|
291
|
+
}
|
|
292
|
+
}, [
|
|
293
|
+
view,
|
|
294
|
+
paying,
|
|
295
|
+
siteFetch,
|
|
296
|
+
hostId,
|
|
297
|
+
load
|
|
298
|
+
]);
|
|
299
|
+
if (!hostId) {
|
|
300
|
+
return /*#__PURE__*/ _jsx(Box, _extends({
|
|
301
|
+
ref: ref
|
|
302
|
+
}, rest, {
|
|
303
|
+
sx: [
|
|
304
|
+
{
|
|
305
|
+
p: 3,
|
|
306
|
+
border: '1px dashed',
|
|
307
|
+
borderColor: 'divider',
|
|
308
|
+
borderRadius: 1
|
|
309
|
+
},
|
|
310
|
+
...nodeSx
|
|
311
|
+
],
|
|
312
|
+
children: /*#__PURE__*/ _jsx(Typography, {
|
|
313
|
+
variant: "body2",
|
|
314
|
+
color: "text.secondary",
|
|
315
|
+
children: 'Quote — a customer’s quote and its Pay button render here'
|
|
316
|
+
})
|
|
317
|
+
}));
|
|
318
|
+
}
|
|
319
|
+
if (state.kind === 'loading') {
|
|
320
|
+
return /*#__PURE__*/ _jsx(Box, _extends({
|
|
321
|
+
ref: ref
|
|
322
|
+
}, rest, {
|
|
323
|
+
sx: [
|
|
324
|
+
{
|
|
325
|
+
py: 6,
|
|
326
|
+
textAlign: 'center'
|
|
327
|
+
},
|
|
328
|
+
...nodeSx
|
|
329
|
+
],
|
|
330
|
+
children: /*#__PURE__*/ _jsx(CircularProgress, {
|
|
331
|
+
size: 28,
|
|
332
|
+
"aria-label": "Loading your quote"
|
|
333
|
+
})
|
|
334
|
+
}));
|
|
335
|
+
}
|
|
336
|
+
if (state.kind === 'missing') {
|
|
337
|
+
return /*#__PURE__*/ _jsx(Box, _extends({
|
|
338
|
+
ref: ref
|
|
339
|
+
}, rest, {
|
|
340
|
+
sx: nodeSx,
|
|
341
|
+
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
342
|
+
spacing: 2,
|
|
343
|
+
children: [
|
|
344
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
345
|
+
variant: "h4",
|
|
346
|
+
component: "h1",
|
|
347
|
+
children: heading || 'Your quote'
|
|
348
|
+
}),
|
|
349
|
+
/*#__PURE__*/ _jsx(Alert, {
|
|
350
|
+
severity: "info",
|
|
351
|
+
children: state.message
|
|
352
|
+
})
|
|
353
|
+
]
|
|
354
|
+
})
|
|
355
|
+
}));
|
|
356
|
+
}
|
|
357
|
+
if (state.kind === 'replaced') {
|
|
358
|
+
const business = state.storeName || 'The business';
|
|
359
|
+
return /*#__PURE__*/ _jsx(Box, _extends({
|
|
360
|
+
ref: ref
|
|
361
|
+
}, rest, {
|
|
362
|
+
sx: nodeSx,
|
|
363
|
+
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
364
|
+
spacing: 2,
|
|
365
|
+
children: [
|
|
366
|
+
state.storeName ? /*#__PURE__*/ _jsx(Typography, {
|
|
367
|
+
variant: "overline",
|
|
368
|
+
color: "text.secondary",
|
|
369
|
+
children: state.storeName
|
|
370
|
+
}) : null,
|
|
371
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
372
|
+
variant: "h4",
|
|
373
|
+
component: "h1",
|
|
374
|
+
children: 'This quote was updated'
|
|
375
|
+
}),
|
|
376
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
377
|
+
variant: "body1",
|
|
378
|
+
color: "text.secondary",
|
|
379
|
+
children: `${business} updated this quote and sent you a newer link. Open their most recent message to see it.`
|
|
380
|
+
})
|
|
381
|
+
]
|
|
382
|
+
})
|
|
383
|
+
}));
|
|
384
|
+
}
|
|
385
|
+
const quote = state.view;
|
|
386
|
+
const money = (cents)=>formatOrderMoney(cents, quote.currency);
|
|
387
|
+
const unpaid = quote.status === 'unpaid';
|
|
388
|
+
const addresses = [
|
|
389
|
+
quote.customerName || quote.company ? {
|
|
390
|
+
label: 'Prepared for',
|
|
391
|
+
lines: [
|
|
392
|
+
quote.customerName,
|
|
393
|
+
quote.company
|
|
394
|
+
].filter((line)=>Boolean(line))
|
|
395
|
+
} : null,
|
|
396
|
+
quote.billTo ? {
|
|
397
|
+
label: 'Bill to',
|
|
398
|
+
lines: addressLines(quote.billTo)
|
|
399
|
+
} : null,
|
|
400
|
+
quote.shipTo ? {
|
|
401
|
+
label: 'Ship to',
|
|
402
|
+
lines: addressLines(quote.shipTo)
|
|
403
|
+
} : null
|
|
404
|
+
].filter((block)=>Boolean(block && block.lines.length));
|
|
405
|
+
const totalRows = [
|
|
406
|
+
[
|
|
407
|
+
'Subtotal',
|
|
408
|
+
money(quote.totals.itemsCents),
|
|
409
|
+
true
|
|
410
|
+
],
|
|
411
|
+
[
|
|
412
|
+
quote.discountLabel ? `Discount (${quote.discountLabel})` : 'Discount',
|
|
413
|
+
`−${money(quote.totals.discountCents)}`,
|
|
414
|
+
quote.totals.discountCents > 0
|
|
415
|
+
],
|
|
416
|
+
[
|
|
417
|
+
'Shipping',
|
|
418
|
+
money(quote.totals.shippingCents),
|
|
419
|
+
quote.totals.shippingCents > 0
|
|
420
|
+
],
|
|
421
|
+
[
|
|
422
|
+
quote.taxLabel,
|
|
423
|
+
money(quote.totals.taxCents),
|
|
424
|
+
quote.totals.taxCents > 0
|
|
425
|
+
],
|
|
426
|
+
// `Tax is added at payment`, with no figure: Stripe works it out from the address.
|
|
427
|
+
[
|
|
428
|
+
quote.taxLabel,
|
|
429
|
+
'',
|
|
430
|
+
quote.taxAtPayment
|
|
431
|
+
]
|
|
432
|
+
].filter(([, , shown])=>shown);
|
|
433
|
+
return /*#__PURE__*/ _jsx(Box, _extends({
|
|
434
|
+
ref: ref
|
|
435
|
+
}, rest, {
|
|
436
|
+
sx: nodeSx,
|
|
437
|
+
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
438
|
+
spacing: 3,
|
|
439
|
+
children: [
|
|
440
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
441
|
+
spacing: 1,
|
|
442
|
+
children: [
|
|
443
|
+
quote.storeName ? /*#__PURE__*/ _jsx(Typography, {
|
|
444
|
+
variant: "overline",
|
|
445
|
+
color: "text.secondary",
|
|
446
|
+
children: quote.storeName
|
|
447
|
+
}) : null,
|
|
448
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
449
|
+
direction: "row",
|
|
450
|
+
spacing: 1.5,
|
|
451
|
+
sx: {
|
|
452
|
+
alignItems: 'center',
|
|
453
|
+
flexWrap: 'wrap',
|
|
454
|
+
rowGap: 1
|
|
455
|
+
},
|
|
456
|
+
children: [
|
|
457
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
458
|
+
variant: "h4",
|
|
459
|
+
component: "h1",
|
|
460
|
+
children: heading || quote.number
|
|
461
|
+
}),
|
|
462
|
+
/*#__PURE__*/ _jsx(Chip, {
|
|
463
|
+
label: quote.statusLabel,
|
|
464
|
+
color: quote.status === 'paid' ? 'success' : unpaid ? 'primary' : 'default',
|
|
465
|
+
size: "small"
|
|
466
|
+
})
|
|
467
|
+
]
|
|
468
|
+
}),
|
|
469
|
+
quote.dateMs ? /*#__PURE__*/ _jsx(Typography, {
|
|
470
|
+
variant: "body2",
|
|
471
|
+
color: "text.secondary",
|
|
472
|
+
children: `Dated ${dateLabel(quote.dateMs)}`
|
|
473
|
+
}) : null
|
|
474
|
+
]
|
|
475
|
+
}),
|
|
476
|
+
addresses.length ? /*#__PURE__*/ _jsx(Stack, {
|
|
477
|
+
direction: {
|
|
478
|
+
xs: 'column',
|
|
479
|
+
sm: 'row'
|
|
480
|
+
},
|
|
481
|
+
spacing: {
|
|
482
|
+
xs: 2,
|
|
483
|
+
sm: 3
|
|
484
|
+
},
|
|
485
|
+
children: addresses.map((block)=>/*#__PURE__*/ _jsx(AddressBlock, {
|
|
486
|
+
label: block.label,
|
|
487
|
+
lines: block.lines
|
|
488
|
+
}, block.label))
|
|
489
|
+
}) : null,
|
|
490
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
491
|
+
spacing: 1.5,
|
|
492
|
+
children: [
|
|
493
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
494
|
+
variant: "h6",
|
|
495
|
+
component: "h2",
|
|
496
|
+
children: 'Items'
|
|
497
|
+
}),
|
|
498
|
+
quote.lines.map((line, index)=>/*#__PURE__*/ _jsxs(Stack, {
|
|
499
|
+
direction: "row",
|
|
500
|
+
spacing: 2,
|
|
501
|
+
sx: {
|
|
502
|
+
justifyContent: 'space-between'
|
|
503
|
+
},
|
|
504
|
+
children: [
|
|
505
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
506
|
+
spacing: 0.25,
|
|
507
|
+
sx: {
|
|
508
|
+
minWidth: 0
|
|
509
|
+
},
|
|
510
|
+
children: [
|
|
511
|
+
/*#__PURE__*/ _jsxs(Typography, {
|
|
512
|
+
variant: "body2",
|
|
513
|
+
children: [
|
|
514
|
+
line.name,
|
|
515
|
+
line.variantLabel ? ` (${line.variantLabel})` : ''
|
|
516
|
+
]
|
|
517
|
+
}),
|
|
518
|
+
line.description ? /*#__PURE__*/ _jsx(Typography, {
|
|
519
|
+
variant: "body2",
|
|
520
|
+
color: "text.secondary",
|
|
521
|
+
sx: {
|
|
522
|
+
whiteSpace: 'pre-line'
|
|
523
|
+
},
|
|
524
|
+
children: line.description
|
|
525
|
+
}) : null,
|
|
526
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
527
|
+
variant: "caption",
|
|
528
|
+
color: "text.secondary",
|
|
529
|
+
children: [
|
|
530
|
+
line.included ? `${line.quantity} included` : `${line.quantity} × ${money(line.unitAmountCents)}`,
|
|
531
|
+
line.sku ? `SKU ${line.sku}` : ''
|
|
532
|
+
].filter(Boolean).join(' · ')
|
|
533
|
+
})
|
|
534
|
+
]
|
|
535
|
+
}),
|
|
536
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
537
|
+
variant: "body2",
|
|
538
|
+
sx: {
|
|
539
|
+
flexShrink: 0
|
|
540
|
+
},
|
|
541
|
+
children: line.included ? 'Included' : money(line.amountCents)
|
|
542
|
+
})
|
|
543
|
+
]
|
|
544
|
+
}, index)),
|
|
545
|
+
/*#__PURE__*/ _jsx(Divider, {}),
|
|
546
|
+
totalRows.map(([label, value])=>/*#__PURE__*/ _jsx(TotalRow, {
|
|
547
|
+
label: label,
|
|
548
|
+
value: value
|
|
549
|
+
}, `${label}-${value}`)),
|
|
550
|
+
/*#__PURE__*/ _jsx(TotalRow, {
|
|
551
|
+
label: "Total",
|
|
552
|
+
value: money(quote.totals.totalCents),
|
|
553
|
+
strong: true
|
|
554
|
+
})
|
|
555
|
+
]
|
|
556
|
+
}),
|
|
557
|
+
quote.notes ? /*#__PURE__*/ _jsxs(Stack, {
|
|
558
|
+
spacing: 0.5,
|
|
559
|
+
children: [
|
|
560
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
561
|
+
variant: "h6",
|
|
562
|
+
component: "h2",
|
|
563
|
+
children: 'Notes'
|
|
564
|
+
}),
|
|
565
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
566
|
+
variant: "body2",
|
|
567
|
+
sx: {
|
|
568
|
+
whiteSpace: 'pre-line'
|
|
569
|
+
},
|
|
570
|
+
children: quote.notes
|
|
571
|
+
})
|
|
572
|
+
]
|
|
573
|
+
}) : null,
|
|
574
|
+
quote.terms ? /*#__PURE__*/ _jsxs(Stack, {
|
|
575
|
+
spacing: 0.5,
|
|
576
|
+
children: [
|
|
577
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
578
|
+
variant: "h6",
|
|
579
|
+
component: "h2",
|
|
580
|
+
children: 'Terms'
|
|
581
|
+
}),
|
|
582
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
583
|
+
variant: "body2",
|
|
584
|
+
color: "text.secondary",
|
|
585
|
+
sx: {
|
|
586
|
+
whiteSpace: 'pre-line'
|
|
587
|
+
},
|
|
588
|
+
children: quote.terms
|
|
589
|
+
})
|
|
590
|
+
]
|
|
591
|
+
}) : null,
|
|
592
|
+
unpaid ? /*#__PURE__*/ _jsx(Paper, {
|
|
593
|
+
variant: "outlined",
|
|
594
|
+
sx: {
|
|
595
|
+
p: {
|
|
596
|
+
xs: 2,
|
|
597
|
+
sm: 3
|
|
598
|
+
}
|
|
599
|
+
},
|
|
600
|
+
children: /*#__PURE__*/ _jsx(Stack, {
|
|
601
|
+
spacing: 2,
|
|
602
|
+
children: returned === 'confirming' ? /*#__PURE__*/ _jsx(Alert, {
|
|
603
|
+
severity: "info",
|
|
604
|
+
icon: /*#__PURE__*/ _jsx(CircularProgress, {
|
|
605
|
+
size: 20
|
|
606
|
+
}),
|
|
607
|
+
children: 'Thank you. We’re confirming your payment.'
|
|
608
|
+
}) : returned === 'unconfirmed' ? /*#__PURE__*/ _jsx(Alert, {
|
|
609
|
+
severity: "info",
|
|
610
|
+
children: 'Your payment is still being confirmed. Your receipt will arrive by email.'
|
|
611
|
+
}) : quote.approvalRequired ? /*#__PURE__*/ _jsx(Alert, {
|
|
612
|
+
severity: "info",
|
|
613
|
+
children: `${quote.storeName || 'The business'} asks you to approve the proof before you pay.`
|
|
614
|
+
}) : quote.payable ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
615
|
+
children: [
|
|
616
|
+
returned === 'failed' ? /*#__PURE__*/ _jsx(Alert, {
|
|
617
|
+
severity: "warning",
|
|
618
|
+
children: 'Your payment did not go through. Nothing was charged.'
|
|
619
|
+
}) : null,
|
|
620
|
+
nativeCheckout ? /*#__PURE__*/ _jsx(Suspense, {
|
|
621
|
+
fallback: /*#__PURE__*/ _jsx(StorefrontPaymentElementFallback, {}),
|
|
622
|
+
children: /*#__PURE__*/ _jsx(StorefrontPaymentElement, {
|
|
623
|
+
clientSecret: nativeCheckout.clientSecret,
|
|
624
|
+
publishableKey: nativeCheckout.publishableKey,
|
|
625
|
+
wallets: nativeCheckout.wallets,
|
|
626
|
+
payLabel: quote.taxAtPayment ? 'Pay now' : `Pay ${money(quote.totals.totalCents)}`,
|
|
627
|
+
defaultShippingAddress: stripeContact(quote.shipTo),
|
|
628
|
+
// An expired or unloadable session is replaced by a new press.
|
|
629
|
+
onRestart: ()=>{
|
|
630
|
+
setNativeCheckout(null);
|
|
631
|
+
void pay();
|
|
632
|
+
},
|
|
633
|
+
onCancel: ()=>setNativeCheckout(null)
|
|
634
|
+
})
|
|
635
|
+
}) : /*#__PURE__*/ _jsx(Button, {
|
|
636
|
+
variant: "contained",
|
|
637
|
+
size: "large",
|
|
638
|
+
onClick: ()=>void pay(),
|
|
639
|
+
disabled: paying,
|
|
640
|
+
sx: {
|
|
641
|
+
alignSelf: {
|
|
642
|
+
xs: 'stretch',
|
|
643
|
+
sm: 'flex-start'
|
|
644
|
+
}
|
|
645
|
+
},
|
|
646
|
+
children: paying ? 'Opening…' : quote.taxAtPayment ? `Pay ${money(quote.totals.totalCents)} plus tax` : `Pay ${money(quote.totals.totalCents)}`
|
|
647
|
+
}),
|
|
648
|
+
payError ? /*#__PURE__*/ _jsx(Alert, {
|
|
649
|
+
severity: "error",
|
|
650
|
+
children: payError
|
|
651
|
+
}) : null
|
|
652
|
+
]
|
|
653
|
+
}) : /*#__PURE__*/ _jsx(Alert, {
|
|
654
|
+
severity: "info",
|
|
655
|
+
children: `Contact ${quote.storeName || 'the business'} to pay this quote.`
|
|
656
|
+
})
|
|
657
|
+
})
|
|
658
|
+
}) : /*#__PURE__*/ _jsx(Paper, {
|
|
659
|
+
variant: "outlined",
|
|
660
|
+
sx: {
|
|
661
|
+
p: {
|
|
662
|
+
xs: 2,
|
|
663
|
+
sm: 3
|
|
664
|
+
}
|
|
665
|
+
},
|
|
666
|
+
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
667
|
+
spacing: 1.5,
|
|
668
|
+
sx: {
|
|
669
|
+
alignItems: 'flex-start'
|
|
670
|
+
},
|
|
671
|
+
children: [
|
|
672
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
673
|
+
variant: "body1",
|
|
674
|
+
children: quote.status === 'paid' ? quote.paidAtMs ? `Paid ${dateLabel(quote.paidAtMs)}. Thank you.` : 'Paid. Thank you.' : `This quote is ${quote.statusLabel.toLowerCase()}.`
|
|
675
|
+
}),
|
|
676
|
+
quote.receiptUrl ? /*#__PURE__*/ _jsx(Button, {
|
|
677
|
+
variant: "outlined",
|
|
678
|
+
href: quote.receiptUrl,
|
|
679
|
+
children: 'View your order'
|
|
680
|
+
}) : null
|
|
681
|
+
]
|
|
682
|
+
})
|
|
683
|
+
}),
|
|
684
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
685
|
+
variant: "body2",
|
|
686
|
+
color: "text.secondary",
|
|
687
|
+
children: `Questions about this quote? Contact ${quote.storeName || 'the business'}.`
|
|
688
|
+
})
|
|
689
|
+
]
|
|
690
|
+
})
|
|
691
|
+
}));
|
|
692
|
+
});
|
|
693
|
+
QuotePageBody.displayName = 'QuotePageBody';
|
|
694
|
+
export default QuotePageBody;
|
|
695
|
+
|
|
696
|
+
//# sourceMappingURL=quote-page-body.js.map
|