@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.
- package/README.md +4 -2
- package/package.json +13 -13
- package/src/lib/components/cart-fulfillment.d.ts +3 -0
- package/src/lib/components/cart-fulfillment.js.map +1 -1
- package/src/lib/components/cart.js +14 -4
- package/src/lib/components/cart.js.map +1 -1
- package/src/lib/components/commerce-console-page.js +2 -1
- package/src/lib/components/commerce-console-page.js.map +1 -1
- package/src/lib/components/console/host-orders-card.component.d.ts +6 -0
- package/src/lib/components/console/host-orders-card.component.js +3 -2
- package/src/lib/components/console/host-orders-card.component.js.map +1 -1
- package/src/lib/components/console/invoice-send.component.d.ts +44 -0
- package/src/lib/components/console/invoice-send.component.js +237 -0
- package/src/lib/components/console/invoice-send.component.js.map +1 -0
- package/src/lib/components/console/order-detail-dialog.component.d.ts +5 -0
- package/src/lib/components/console/order-detail-dialog.component.js +9 -2
- package/src/lib/components/console/order-detail-dialog.component.js.map +1 -1
- package/src/lib/components/console/order-invoice.component.d.ts +9 -0
- package/src/lib/components/console/order-invoice.component.js +27 -2
- package/src/lib/components/console/order-invoice.component.js.map +1 -1
- package/src/lib/components/console/pos/pos-item-dialog.component.js +3 -2
- package/src/lib/components/console/pos/pos-item-dialog.component.js.map +1 -1
- package/src/lib/components/console/pos-kiosk-page.component.js +2 -1
- package/src/lib/components/console/pos-kiosk-page.component.js.map +1 -1
- package/src/lib/components/console/pos-page.component.js +1 -1
- package/src/lib/components/console/pos-page.component.js.map +1 -1
- package/src/lib/components/console/product-add-ons-fields.component.d.ts +41 -0
- package/src/lib/components/console/product-add-ons-fields.component.js +356 -0
- package/src/lib/components/console/product-add-ons-fields.component.js.map +1 -0
- package/src/lib/components/console/product-editor-dialog.component.js +31 -5
- package/src/lib/components/console/product-editor-dialog.component.js.map +1 -1
- package/src/lib/components/console/product-register-fields.component.d.ts +4 -5
- package/src/lib/components/console/product-register-fields.component.js +8 -197
- package/src/lib/components/console/product-register-fields.component.js.map +1 -1
- package/src/lib/components/console/products-hub-zone.component.js +6 -0
- package/src/lib/components/console/products-hub-zone.component.js.map +1 -1
- package/src/lib/components/console/quote-editor-dialog.component.d.ts +29 -0
- package/src/lib/components/console/quote-editor-dialog.component.js +102 -4
- package/src/lib/components/console/quote-editor-dialog.component.js.map +1 -1
- package/src/lib/components/console/quote-pay-link.component.d.ts +8 -1
- package/src/lib/components/console/quote-pay-link.component.js +29 -3
- package/src/lib/components/console/quote-pay-link.component.js.map +1 -1
- package/src/lib/components/console/quote-proofs.component.d.ts +11 -0
- package/src/lib/components/console/quote-proofs.component.js +68 -0
- package/src/lib/components/console/quote-proofs.component.js.map +1 -1
- package/src/lib/components/console/quote-send.component.d.ts +42 -0
- package/src/lib/components/console/quote-send.component.js +304 -0
- package/src/lib/components/console/quote-send.component.js.map +1 -0
- package/src/lib/components/console/quote-start.component.d.ts +45 -0
- package/src/lib/components/console/quote-start.component.js +182 -0
- package/src/lib/components/console/quote-start.component.js.map +1 -0
- package/src/lib/components/product-add-ons.d.ts +28 -0
- package/src/lib/components/product-add-ons.js +136 -0
- package/src/lib/components/product-add-ons.js.map +1 -0
- package/src/lib/components/product-detail.d.ts +16 -0
- package/src/lib/components/product-detail.js +112 -19
- package/src/lib/components/product-detail.js.map +1 -1
- package/src/lib/components/product-grid.d.ts +8 -2
- package/src/lib/components/product-grid.js +6 -1
- package/src/lib/components/product-grid.js.map +1 -1
- package/src/lib/components/product-options-field-body.d.ts +44 -0
- package/src/lib/components/product-options-field-body.js +260 -0
- package/src/lib/components/product-options-field-body.js.map +1 -0
- package/src/lib/components/product-options-field.d.ts +32 -0
- package/src/lib/components/product-options-field.js +128 -0
- package/src/lib/components/product-options-field.js.map +1 -0
- package/src/lib/components/quote-page-body.js +39 -20
- package/src/lib/components/quote-page-body.js.map +1 -1
- package/src/lib/model/commerce-cart.d.ts +15 -3
- package/src/lib/model/commerce-cart.js +10 -3
- package/src/lib/model/commerce-cart.js.map +1 -1
- package/src/lib/model/commerce-invoices.d.ts +139 -0
- package/src/lib/model/commerce-invoices.js +343 -0
- package/src/lib/model/commerce-invoices.js.map +1 -0
- package/src/lib/model/commerce-orders.d.ts +35 -5
- package/src/lib/model/commerce-orders.js +3 -0
- package/src/lib/model/commerce-orders.js.map +1 -1
- package/src/lib/model/commerce-pos-kiosk.d.ts +1 -1
- package/src/lib/model/commerce-pos-kiosk.js +3 -2
- package/src/lib/model/commerce-pos-kiosk.js.map +1 -1
- package/src/lib/model/commerce-product-field.d.ts +23 -0
- package/src/lib/model/commerce-product-field.js +26 -0
- package/src/lib/model/commerce-product-field.js.map +1 -0
- package/src/lib/model/commerce-quote-email.d.ts +81 -0
- package/src/lib/model/commerce-quote-email.js +170 -0
- package/src/lib/model/commerce-quote-email.js.map +1 -0
- package/src/lib/model/commerce-quote-pay.d.ts +49 -6
- package/src/lib/model/commerce-quote-pay.js +69 -36
- package/src/lib/model/commerce-quote-pay.js.map +1 -1
- package/src/lib/model/commerce-quote-request.d.ts +93 -0
- package/src/lib/model/commerce-quote-request.js +207 -0
- package/src/lib/model/commerce-quote-request.js.map +1 -0
- package/src/lib/model/commerce-quotes.d.ts +81 -0
- package/src/lib/model/commerce-quotes.js +1 -1
- package/src/lib/model/commerce-quotes.js.map +1 -1
- package/src/lib/model/commerce.d.ts +18 -0
- package/src/lib/model/commerce.js +26 -0
- package/src/lib/model/commerce.js.map +1 -1
- package/src/lib/model/index.d.ts +3 -0
- package/src/lib/model/index.js +3 -0
- package/src/lib/model/index.js.map +1 -1
- package/src/lib/model/product-modifiers.d.ts +74 -4
- package/src/lib/model/product-modifiers.js +131 -10
- package/src/lib/model/product-modifiers.js.map +1 -1
- package/src/lib/plugin.js +19 -0
- package/src/lib/plugin.js.map +1 -1
- package/src/lib/server/billing-webhook.js +164 -98
- package/src/lib/server/billing-webhook.js.map +1 -1
- package/src/lib/server/cart-checkout.js +14 -2
- package/src/lib/server/cart-checkout.js.map +1 -1
- package/src/lib/server/cart.d.ts +5 -0
- package/src/lib/server/cart.js +41 -4
- package/src/lib/server/cart.js.map +1 -1
- package/src/lib/server/catalog.d.ts +6 -0
- package/src/lib/server/catalog.js +2 -0
- package/src/lib/server/catalog.js.map +1 -1
- package/src/lib/server/checkout-extras.js +3 -1
- package/src/lib/server/checkout-extras.js.map +1 -1
- package/src/lib/server/checkout.js +28 -3
- package/src/lib/server/checkout.js.map +1 -1
- package/src/lib/server/commerce-pdf.d.ts +5 -1
- package/src/lib/server/commerce-pdf.js +37 -10
- package/src/lib/server/commerce-pdf.js.map +1 -1
- package/src/lib/server/draft-order.js +23 -3
- package/src/lib/server/draft-order.js.map +1 -1
- package/src/lib/server/invoice-email.d.ts +76 -0
- package/src/lib/server/invoice-email.js +183 -0
- package/src/lib/server/invoice-email.js.map +1 -0
- package/src/lib/server/local-fulfillment.js +5 -1
- package/src/lib/server/local-fulfillment.js.map +1 -1
- package/src/lib/server/order-invoice-send.d.ts +43 -0
- package/src/lib/server/order-invoice-send.js +218 -0
- package/src/lib/server/order-invoice-send.js.map +1 -0
- package/src/lib/server/order-status.d.ts +11 -0
- package/src/lib/server/order-status.js +44 -8
- package/src/lib/server/order-status.js.map +1 -1
- package/src/lib/server/person-eraser.d.ts +3 -2
- package/src/lib/server/person-eraser.js +25 -6
- package/src/lib/server/person-eraser.js.map +1 -1
- package/src/lib/server/pos-offline-sync.js +1 -1
- package/src/lib/server/pos-offline-sync.js.map +1 -1
- package/src/lib/server/pos-order.js +1 -1
- package/src/lib/server/pos-order.js.map +1 -1
- package/src/lib/server/product.d.ts +26 -0
- package/src/lib/server/product.js +18 -0
- package/src/lib/server/product.js.map +1 -1
- package/src/lib/server/products-write.js +5 -2
- package/src/lib/server/products-write.js.map +1 -1
- package/src/lib/server/quote-email.d.ts +85 -0
- package/src/lib/server/quote-email.js +211 -0
- package/src/lib/server/quote-email.js.map +1 -0
- package/src/lib/server/quote-link-token.d.ts +11 -0
- package/src/lib/server/quote-link-token.js +21 -0
- package/src/lib/server/quote-link-token.js.map +1 -1
- package/src/lib/server/quote-pay.d.ts +8 -3
- package/src/lib/server/quote-pay.js +105 -43
- package/src/lib/server/quote-pay.js.map +1 -1
- package/src/lib/server/quote.d.ts +11 -0
- package/src/lib/server/quote.js +309 -12
- package/src/lib/server/quote.js.map +1 -1
- package/src/lib/server/site-page-resolver.js +2 -1
- package/src/lib/server/site-page-resolver.js.map +1 -1
- package/src/lib/server.js +5 -0
- package/src/lib/server.js.map +1 -1
- package/src/lib/site.js +8 -0
- package/src/lib/site.js.map +1 -1
- package/src/lib/tenant-emails.js +243 -0
- package/src/lib/tenant-emails.js.map +1 -1
- package/src/lib/utils/add-to-cart.d.ts +8 -0
- package/src/lib/utils/add-to-cart.js +10 -2
- package/src/lib/utils/add-to-cart.js.map +1 -1
- package/src/lib/utils/commerce-document-pdf.d.ts +5 -0
- package/src/lib/utils/commerce-document-pdf.js +6 -1
- package/src/lib/utils/commerce-document-pdf.js.map +1 -1
- package/src/lib/utils/invoice-email-content.d.ts +45 -0
- package/src/lib/utils/invoice-email-content.js +126 -0
- package/src/lib/utils/invoice-email-content.js.map +1 -0
- package/src/lib/utils/order-invoice.d.ts +1 -1
- package/src/lib/utils/order-invoice.js +14 -6
- package/src/lib/utils/order-invoice.js.map +1 -1
- package/src/lib/utils/quote-email-content.d.ts +63 -0
- package/src/lib/utils/quote-email-content.js +157 -0
- package/src/lib/utils/quote-email-content.js.map +1 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ 'use client';
|
|
17
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
18
|
+
import Checkbox from "@mui/material/Checkbox";
|
|
19
|
+
import FormControl from "@mui/material/FormControl";
|
|
20
|
+
import FormControlLabel from "@mui/material/FormControlLabel";
|
|
21
|
+
import FormGroup from "@mui/material/FormGroup";
|
|
22
|
+
import FormHelperText from "@mui/material/FormHelperText";
|
|
23
|
+
import FormLabel from "@mui/material/FormLabel";
|
|
24
|
+
import MenuItem from "@mui/material/MenuItem";
|
|
25
|
+
import Stack from "@mui/material/Stack";
|
|
26
|
+
import TextField from "@mui/material/TextField";
|
|
27
|
+
import { modifierGroupRequired, modifierOptionPriceCents } from "../model/product-modifiers.js";
|
|
28
|
+
/** The picks with one group's answer replaced, in the groups' own order. */ export function withGroupAnswer(groups, value, groupId, optionIds) {
|
|
29
|
+
const others = value.filter((pick)=>pick.groupId !== groupId);
|
|
30
|
+
const answer = optionIds.map((optionId)=>({
|
|
31
|
+
groupId,
|
|
32
|
+
optionId
|
|
33
|
+
}));
|
|
34
|
+
const order = new Map(groups.map((group, index)=>[
|
|
35
|
+
group.id,
|
|
36
|
+
index
|
|
37
|
+
]));
|
|
38
|
+
return [
|
|
39
|
+
...others,
|
|
40
|
+
...answer
|
|
41
|
+
].sort((a, b)=>{
|
|
42
|
+
var _order_get, _order_get1;
|
|
43
|
+
return ((_order_get = order.get(a.groupId)) != null ? _order_get : 0) - ((_order_get1 = order.get(b.groupId)) != null ? _order_get1 : 0);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/** What a group asks for, said under it. */ export function addOnGroupHint(group) {
|
|
47
|
+
if (group.max === 1) return group.min > 0 ? 'Choose one' : 'Optional';
|
|
48
|
+
if (group.min > 0 && group.min === group.max) return `Choose ${group.min}`;
|
|
49
|
+
if (group.min > 0) return `Choose ${group.min} to ${group.max}`;
|
|
50
|
+
return `Choose up to ${group.max}`;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The add-ons a product's page offers (AGL-4100): a group that takes one
|
|
54
|
+
* choice is a select, one that takes several is a set of checkboxes, each
|
|
55
|
+
* choice with what it adds on the picked variant. A required group is marked
|
|
56
|
+
* as the form builder marks a required field. Its own chunk, loaded only by a
|
|
57
|
+
* product that has add-ons on the website.
|
|
58
|
+
*/ export function ProductAddOns(props) {
|
|
59
|
+
const { groups, variantId, value, onChange, formatCents, disabled } = props;
|
|
60
|
+
const priceLabel = (option)=>{
|
|
61
|
+
const cents = modifierOptionPriceCents(option, variantId);
|
|
62
|
+
return cents > 0 ? `${option.name} (+${formatCents(cents)})` : option.name;
|
|
63
|
+
};
|
|
64
|
+
return /*#__PURE__*/ _jsx(Stack, {
|
|
65
|
+
spacing: 1.5,
|
|
66
|
+
sx: {
|
|
67
|
+
mb: 1.5
|
|
68
|
+
},
|
|
69
|
+
children: groups.map((group)=>{
|
|
70
|
+
const chosen = value.filter((pick)=>pick.groupId === group.id).map((pick)=>pick.optionId);
|
|
71
|
+
const required = modifierGroupRequired(group);
|
|
72
|
+
if (group.max === 1) {
|
|
73
|
+
var _chosen_;
|
|
74
|
+
return /*#__PURE__*/ _jsxs(TextField, {
|
|
75
|
+
select: true,
|
|
76
|
+
size: "small",
|
|
77
|
+
fullWidth: true,
|
|
78
|
+
required: required,
|
|
79
|
+
disabled: disabled,
|
|
80
|
+
label: group.name,
|
|
81
|
+
value: (_chosen_ = chosen[0]) != null ? _chosen_ : '',
|
|
82
|
+
onChange: (event)=>onChange(withGroupAnswer(groups, value, group.id, event.target.value ? [
|
|
83
|
+
String(event.target.value)
|
|
84
|
+
] : [])),
|
|
85
|
+
helperText: addOnGroupHint(group),
|
|
86
|
+
children: [
|
|
87
|
+
required ? null : /*#__PURE__*/ _jsx(MenuItem, {
|
|
88
|
+
value: "",
|
|
89
|
+
children: /*#__PURE__*/ _jsx("em", {
|
|
90
|
+
children: 'None'
|
|
91
|
+
})
|
|
92
|
+
}),
|
|
93
|
+
group.options.map((option)=>/*#__PURE__*/ _jsx(MenuItem, {
|
|
94
|
+
value: option.id,
|
|
95
|
+
children: priceLabel(option)
|
|
96
|
+
}, option.id))
|
|
97
|
+
]
|
|
98
|
+
}, group.id);
|
|
99
|
+
}
|
|
100
|
+
const full = chosen.length >= group.max;
|
|
101
|
+
return /*#__PURE__*/ _jsxs(FormControl, {
|
|
102
|
+
component: "fieldset",
|
|
103
|
+
required: required,
|
|
104
|
+
disabled: disabled,
|
|
105
|
+
variant: "standard",
|
|
106
|
+
children: [
|
|
107
|
+
/*#__PURE__*/ _jsx(FormLabel, {
|
|
108
|
+
component: "legend",
|
|
109
|
+
children: group.name
|
|
110
|
+
}),
|
|
111
|
+
/*#__PURE__*/ _jsx(FormGroup, {
|
|
112
|
+
children: group.options.map((option)=>{
|
|
113
|
+
const checked = chosen.includes(option.id);
|
|
114
|
+
return /*#__PURE__*/ _jsx(FormControlLabel, {
|
|
115
|
+
control: /*#__PURE__*/ _jsx(Checkbox, {
|
|
116
|
+
size: "small",
|
|
117
|
+
checked: checked,
|
|
118
|
+
disabled: disabled || !checked && full,
|
|
119
|
+
onChange: (event)=>onChange(withGroupAnswer(groups, value, group.id, event.target.checked ? group.options.map((entry)=>entry.id).filter((id)=>id === option.id || chosen.includes(id)) : chosen.filter((id)=>id !== option.id)))
|
|
120
|
+
}),
|
|
121
|
+
label: priceLabel(option)
|
|
122
|
+
}, option.id);
|
|
123
|
+
})
|
|
124
|
+
}),
|
|
125
|
+
/*#__PURE__*/ _jsx(FormHelperText, {
|
|
126
|
+
children: addOnGroupHint(group)
|
|
127
|
+
})
|
|
128
|
+
]
|
|
129
|
+
}, group.id);
|
|
130
|
+
})
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
ProductAddOns.displayName = 'ProductAddOns';
|
|
134
|
+
export default ProductAddOns;
|
|
135
|
+
|
|
136
|
+
//# sourceMappingURL=product-add-ons.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/commerce/src/lib/components/product-add-ons.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport Checkbox from '@mui/material/Checkbox'\nimport FormControl from '@mui/material/FormControl'\nimport FormControlLabel from '@mui/material/FormControlLabel'\nimport FormGroup from '@mui/material/FormGroup'\nimport FormHelperText from '@mui/material/FormHelperText'\nimport FormLabel from '@mui/material/FormLabel'\nimport MenuItem from '@mui/material/MenuItem'\nimport Stack from '@mui/material/Stack'\nimport TextField from '@mui/material/TextField'\nimport {\n modifierGroupRequired,\n modifierOptionPriceCents,\n type ModifierSelection,\n type ProductModifierGroup,\n type ProductModifierOption,\n} from '../model/product-modifiers'\n\nexport interface ProductAddOnsProps {\n /** The groups the website shows, as the product's page received them. */\n groups: readonly ProductModifierGroup[]\n /** The variant picked: a choice priced by variant shows its price on it. */\n variantId?: string\n value: readonly ModifierSelection[]\n onChange: (next: ModifierSelection[]) => void\n /** The store's money, e.g. `$1,250.00`. */\n formatCents: (cents: number) => string\n disabled?: boolean\n}\n\n/** The picks with one group's answer replaced, in the groups' own order. */\nexport function withGroupAnswer(\n groups: readonly ProductModifierGroup[],\n value: readonly ModifierSelection[],\n groupId: string,\n optionIds: readonly string[],\n): ModifierSelection[] {\n const others = value.filter((pick) => pick.groupId !== groupId)\n const answer = optionIds.map((optionId) => ({ groupId, optionId }))\n const order = new Map(groups.map((group, index) => [group.id, index]))\n return [...others, ...answer].sort(\n (a, b) => (order.get(a.groupId) ?? 0) - (order.get(b.groupId) ?? 0),\n )\n}\n\n/** What a group asks for, said under it. */\nexport function addOnGroupHint(group: Pick<ProductModifierGroup, 'min' | 'max'>): string {\n if (group.max === 1) return group.min > 0 ? 'Choose one' : 'Optional'\n if (group.min > 0 && group.min === group.max) return `Choose ${group.min}`\n if (group.min > 0) return `Choose ${group.min} to ${group.max}`\n return `Choose up to ${group.max}`\n}\n\n/**\n * The add-ons a product's page offers (AGL-4100): a group that takes one\n * choice is a select, one that takes several is a set of checkboxes, each\n * choice with what it adds on the picked variant. A required group is marked\n * as the form builder marks a required field. Its own chunk, loaded only by a\n * product that has add-ons on the website.\n */\nexport function ProductAddOns(props: ProductAddOnsProps) {\n const { groups, variantId, value, onChange, formatCents, disabled } = props\n const priceLabel = (option: ProductModifierOption) => {\n const cents = modifierOptionPriceCents(option, variantId)\n return cents > 0 ? `${option.name} (+${formatCents(cents)})` : option.name\n }\n return (\n <Stack spacing={1.5} sx={{ mb: 1.5 }}>\n {groups.map((group) => {\n const chosen = value\n .filter((pick) => pick.groupId === group.id)\n .map((pick) => pick.optionId)\n const required = modifierGroupRequired(group)\n if (group.max === 1) {\n return (\n <TextField\n key={group.id}\n select\n size=\"small\"\n fullWidth\n required={required}\n disabled={disabled}\n label={group.name}\n value={chosen[0] ?? ''}\n onChange={(event) =>\n onChange(\n withGroupAnswer(\n groups,\n value,\n group.id,\n event.target.value ? [String(event.target.value)] : [],\n ),\n )\n }\n helperText={addOnGroupHint(group)}\n >\n {required ? null : (\n <MenuItem value=\"\">\n <em>{'None'}</em>\n </MenuItem>\n )}\n {group.options.map((option) => (\n <MenuItem key={option.id} value={option.id}>\n {priceLabel(option)}\n </MenuItem>\n ))}\n </TextField>\n )\n }\n const full = chosen.length >= group.max\n return (\n <FormControl\n key={group.id}\n component=\"fieldset\"\n required={required}\n disabled={disabled}\n variant=\"standard\"\n >\n <FormLabel component=\"legend\">{group.name}</FormLabel>\n <FormGroup>\n {group.options.map((option) => {\n const checked = chosen.includes(option.id)\n return (\n <FormControlLabel\n key={option.id}\n control={\n <Checkbox\n size=\"small\"\n checked={checked}\n disabled={disabled || (!checked && full)}\n onChange={(event) =>\n onChange(\n withGroupAnswer(\n groups,\n value,\n group.id,\n event.target.checked\n ? group.options\n .map((entry) => entry.id)\n .filter((id) => id === option.id || chosen.includes(id))\n : chosen.filter((id) => id !== option.id),\n ),\n )\n }\n />\n }\n label={priceLabel(option)}\n />\n )\n })}\n </FormGroup>\n <FormHelperText>{addOnGroupHint(group)}</FormHelperText>\n </FormControl>\n )\n })}\n </Stack>\n )\n}\n\nProductAddOns.displayName = 'ProductAddOns'\n\nexport default ProductAddOns\n"],"names":["Checkbox","FormControl","FormControlLabel","FormGroup","FormHelperText","FormLabel","MenuItem","Stack","TextField","modifierGroupRequired","modifierOptionPriceCents","withGroupAnswer","groups","value","groupId","optionIds","others","filter","pick","answer","map","optionId","order","Map","group","index","id","sort","a","b","get","addOnGroupHint","max","min","ProductAddOns","props","variantId","onChange","formatCents","disabled","priceLabel","option","cents","name","spacing","sx","mb","chosen","required","select","size","fullWidth","label","event","target","String","helperText","em","options","full","length","component","variant","checked","includes","control","entry","displayName"],"mappings":"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"}
|
|
@@ -70,7 +70,23 @@ interface Detail {
|
|
|
70
70
|
subscriptionOptional?: boolean;
|
|
71
71
|
/** The store's time zone, when a variant asks for a use day (AGL-4043). */
|
|
72
72
|
useDayTimeZone?: string;
|
|
73
|
+
/**
|
|
74
|
+
* The add-ons the page offers (AGL-4100): only groups shown on the
|
|
75
|
+
* website ever arrive here.
|
|
76
|
+
*/
|
|
77
|
+
modifierGroups?: CommerceModel.ProductModifierGroup[];
|
|
73
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* The page's add-ons for the variant picked (AGL-4100): whether every
|
|
81
|
+
* required group is answered — the server's own check, run on the groups the
|
|
82
|
+
* page was sent — and what the picks so far add to one unit, for the live
|
|
83
|
+
* price. Display only; every sale door prices them again from the product.
|
|
84
|
+
*/
|
|
85
|
+
export declare function productPageAddOns(product: Pick<Detail, 'name' | 'modifierGroups'>, picks: readonly CommerceModel.ModifierSelection[], variantId: string | undefined): {
|
|
86
|
+
ready: boolean;
|
|
87
|
+
extraCents: number;
|
|
88
|
+
error?: string;
|
|
89
|
+
};
|
|
74
90
|
/** How one option is offered on the page. */
|
|
75
91
|
export interface OptionPresentation {
|
|
76
92
|
name: string;
|
|
@@ -65,6 +65,12 @@ export const ID = 'product-detail';
|
|
|
65
65
|
* The use-day picker (AGL-4043), in its own chunk: only a product whose
|
|
66
66
|
* variant asks for a day downloads the date picker.
|
|
67
67
|
*/ const UseDayPicker = /*#__PURE__*/ lazy(()=>import("./use-day-picker.js"));
|
|
68
|
+
/**
|
|
69
|
+
* The add-on pickers (AGL-4100), in their own chunk: only a product with
|
|
70
|
+
* add-ons on the website downloads them.
|
|
71
|
+
*/ const ProductAddOns = /*#__PURE__*/ lazy(()=>import("./product-add-ons.js"));
|
|
72
|
+
/** Money on the product page, in the store's currency: `$1,250.00`, never `$1250`. */ const money = (cents)=>CommerceModel.formatOrderMoney(cents);
|
|
73
|
+
/** A price in dollars as the page prints it. */ const moneyFromUsd = (priceUsd)=>money(Math.round(priceUsd * 100));
|
|
68
74
|
const SAMPLE = {
|
|
69
75
|
id: 'sample',
|
|
70
76
|
name: 'Sample product',
|
|
@@ -119,15 +125,43 @@ const SAMPLE = {
|
|
|
119
125
|
* `price` is the resolved variant's, which arrived from the server's product
|
|
120
126
|
* payload — the same figure `checkout` prices the charge from, so the reported
|
|
121
127
|
* value and the amount Stripe collects come from one source.
|
|
122
|
-
*/ function buyItem(product, variant, quantity) {
|
|
128
|
+
*/ function buyItem(product, variant, quantity, /** What one unit costs with its add-ons (AGL-4100), when the page has some. */ unitCents) {
|
|
123
129
|
var _ref;
|
|
124
130
|
return {
|
|
125
131
|
item_id: product.id,
|
|
126
132
|
item_name: product.name,
|
|
127
|
-
price: (_ref = variant == null ? void 0 : variant.priceUsd) != null ? _ref : undefined,
|
|
133
|
+
price: unitCents !== undefined && typeof (variant == null ? void 0 : variant.priceUsd) === 'number' ? unitCents / 100 : (_ref = variant == null ? void 0 : variant.priceUsd) != null ? _ref : undefined,
|
|
128
134
|
quantity
|
|
129
135
|
};
|
|
130
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* The page's add-ons for the variant picked (AGL-4100): whether every
|
|
139
|
+
* required group is answered — the server's own check, run on the groups the
|
|
140
|
+
* page was sent — and what the picks so far add to one unit, for the live
|
|
141
|
+
* price. Display only; every sale door prices them again from the product.
|
|
142
|
+
*/ export function productPageAddOns(product, picks, variantId) {
|
|
143
|
+
var _product_modifierGroups;
|
|
144
|
+
const groups = (_product_modifierGroups = product.modifierGroups) != null ? _product_modifierGroups : [];
|
|
145
|
+
if (!groups.length) return {
|
|
146
|
+
ready: true,
|
|
147
|
+
extraCents: 0
|
|
148
|
+
};
|
|
149
|
+
const source = {
|
|
150
|
+
name: product.name,
|
|
151
|
+
modifierGroups: groups
|
|
152
|
+
};
|
|
153
|
+
const checked = CommerceModel.resolveLineModifiers(source, picks, variantId);
|
|
154
|
+
const extraCents = CommerceModel.soldLineModifiers(source, picks, variantId).reduce((sum, modifier)=>sum + modifier.priceCents, 0);
|
|
155
|
+
return checked.ok ? {
|
|
156
|
+
ready: true,
|
|
157
|
+
extraCents
|
|
158
|
+
} : _extends({
|
|
159
|
+
ready: false,
|
|
160
|
+
extraCents
|
|
161
|
+
}, checked.error ? {
|
|
162
|
+
error: checked.error
|
|
163
|
+
} : {});
|
|
164
|
+
}
|
|
131
165
|
/**
|
|
132
166
|
* Which options are a CHOICE (AGL-3676 follow-up). A select with one entry —
|
|
133
167
|
* or with entries no variant carries — is not a choice, and on a live store
|
|
@@ -218,7 +252,7 @@ function slugFromLocation() {
|
|
|
218
252
|
* variant. Resolves its product from the /products/{slug} URL unless a
|
|
219
253
|
* slug prop pins it; sample data on the inert canvas.
|
|
220
254
|
*/ const ProductDetail = /*#__PURE__*/ forwardRef((props, ref)=>{
|
|
221
|
-
var _ref, _ref1, _ref2;
|
|
255
|
+
var _ref, _ref1, _ref2, _ref3;
|
|
222
256
|
var _site_pageData;
|
|
223
257
|
const { slug: slugProp, buyLabel, hideDescription, showCoupon, showDetails, showShipping } = props, rest = _object_without_properties_loose(props, [
|
|
224
258
|
"slug",
|
|
@@ -255,6 +289,8 @@ function slugFromLocation() {
|
|
|
255
289
|
// used to set this, so it opened with nothing selected — an empty select.
|
|
256
290
|
const [selections, setSelections] = useState(()=>initialSelections(seededProduct));
|
|
257
291
|
const [quantity, setQuantity] = useState(1);
|
|
292
|
+
/** The add-ons picked (AGL-4100), ids only. */ const [addOns, setAddOns] = useState([]);
|
|
293
|
+
/** Why the cart refused the line, when it did. */ const [addRefusal, setAddRefusal] = useState('');
|
|
258
294
|
/**
|
|
259
295
|
* The day the buyer chose to use a pass (AGL-4043), `YYYY-MM-DD` on the
|
|
260
296
|
* store's calendar; '' is the day they buy, which is also the default.
|
|
@@ -326,6 +362,7 @@ function slugFromLocation() {
|
|
|
326
362
|
]
|
|
327
363
|
});
|
|
328
364
|
setSelections(initialSelections(product));
|
|
365
|
+
setAddOns([]);
|
|
329
366
|
}
|
|
330
367
|
}).catch(()=>{
|
|
331
368
|
if (active) setDetail('missing');
|
|
@@ -349,6 +386,14 @@ function slugFromLocation() {
|
|
|
349
386
|
resolved,
|
|
350
387
|
selections
|
|
351
388
|
]);
|
|
389
|
+
// The add-ons picked, checked and priced on this variant (AGL-4100).
|
|
390
|
+
const addOnGroups = (_ref = resolved == null ? void 0 : resolved.modifierGroups) != null ? _ref : [];
|
|
391
|
+
const pageAddOns = resolved ? productPageAddOns(resolved, addOns, variant == null ? void 0 : variant.id) : {
|
|
392
|
+
ready: true,
|
|
393
|
+
extraCents: 0
|
|
394
|
+
};
|
|
395
|
+
const unitCents = typeof (variant == null ? void 0 : variant.priceUsd) === 'number' ? Math.round(variant.priceUsd * 100) + pageAddOns.extraCents : 0;
|
|
396
|
+
const addOnsKey = CommerceModel.modifierSelectionKey(addOns);
|
|
352
397
|
// The day to send with this variant: only when it asks for one and the
|
|
353
398
|
// buyer chose a day (AGL-4043).
|
|
354
399
|
const chosenUseDay = (variant == null ? void 0 : variant.asksUseDate) && useDay ? useDay : '';
|
|
@@ -356,8 +401,11 @@ function slugFromLocation() {
|
|
|
356
401
|
const storeTodayKey = (resolved == null ? void 0 : resolved.useDayTimeZone) ? zonedDayKey(Date.now(), resolved.useDayTimeZone) : '';
|
|
357
402
|
// Add to cart (AGL-293) beside instant buy; badge refresh via event.
|
|
358
403
|
const handleAddToCart = async ()=>{
|
|
359
|
-
|
|
404
|
+
// A required add-on unanswered is refused here, before any request
|
|
405
|
+
// (AGL-4100); the button says so too.
|
|
406
|
+
if (!hostId || !resolved || !variant || !pageAddOns.ready) return;
|
|
360
407
|
setAdded(false);
|
|
408
|
+
setAddRefusal('');
|
|
361
409
|
// Priced (AGL-1591's shape, completed): the resolved variant's price
|
|
362
410
|
// and the chosen quantity both come from the server's product payload,
|
|
363
411
|
// so GA4's "value added to cart" is a real number. The funnel step
|
|
@@ -371,8 +419,11 @@ function slugFromLocation() {
|
|
|
371
419
|
quantity
|
|
372
420
|
}, chosenUseDay ? {
|
|
373
421
|
useDayKey: chosenUseDay
|
|
422
|
+
} : {}, addOns.length ? {
|
|
423
|
+
modifiers: addOns
|
|
374
424
|
} : {}, {
|
|
375
|
-
item: buyItem(resolved, variant, quantity)
|
|
425
|
+
item: buyItem(resolved, variant, quantity, addOnGroups.length ? unitCents : undefined),
|
|
426
|
+
onRefused: setAddRefusal
|
|
376
427
|
}));
|
|
377
428
|
if (ok) setAdded(true);
|
|
378
429
|
};
|
|
@@ -387,11 +438,13 @@ function slugFromLocation() {
|
|
|
387
438
|
* subscription).
|
|
388
439
|
*/ // Pickup or the store's own delivery (AGL-3624), for a one-time sale; the
|
|
389
440
|
// server offers nothing for a product with nothing physical to collect.
|
|
390
|
-
const fulfillment = useCartFulfillment(hostId, (
|
|
441
|
+
const fulfillment = useCartFulfillment(hostId, (_ref1 = resolved == null ? void 0 : resolved.id) != null ? _ref1 : '[]', resolved && variant && !(resolved.subscription && (!resolved.subscriptionOptional || billing === 'subscribe')) ? _extends({
|
|
391
442
|
productId: resolved.id,
|
|
392
443
|
variantId: variant.id,
|
|
393
444
|
quantity
|
|
394
|
-
}
|
|
445
|
+
}, addOns.length ? {
|
|
446
|
+
modifiers: addOns
|
|
447
|
+
} : {}) : null);
|
|
395
448
|
const attemptKey = useRef('');
|
|
396
449
|
useEffect(()=>{
|
|
397
450
|
attemptKey.current = '';
|
|
@@ -400,6 +453,7 @@ function slugFromLocation() {
|
|
|
400
453
|
// key, and the server replays the original full-price session — a quoted
|
|
401
454
|
// number that is not the number charged, which is the whole defect class
|
|
402
455
|
// this path has been cleared of.
|
|
456
|
+
// `addOnsKey` too: different add-ons are a different price (AGL-4100).
|
|
403
457
|
}, [
|
|
404
458
|
resolved == null ? void 0 : resolved.id,
|
|
405
459
|
variant == null ? void 0 : variant.id,
|
|
@@ -409,10 +463,11 @@ function slugFromLocation() {
|
|
|
409
463
|
shipPostal,
|
|
410
464
|
coupon,
|
|
411
465
|
fulfillment.signature,
|
|
412
|
-
chosenUseDay
|
|
466
|
+
chosenUseDay,
|
|
467
|
+
addOnsKey
|
|
413
468
|
]);
|
|
414
469
|
const handleBuy = async ()=>{
|
|
415
|
-
if (!hostId || !resolved || !variant || status === 'sending') return;
|
|
470
|
+
if (!hostId || !resolved || !variant || status === 'sending' || !pageAddOns.ready) return;
|
|
416
471
|
setStatus('sending');
|
|
417
472
|
setMessage('');
|
|
418
473
|
if (!attemptKey.current) {
|
|
@@ -435,6 +490,8 @@ function slugFromLocation() {
|
|
|
435
490
|
quantity
|
|
436
491
|
}, chosenUseDay ? {
|
|
437
492
|
useDayKey: chosenUseDay
|
|
493
|
+
} : {}, addOns.length ? {
|
|
494
|
+
modifiers: addOns
|
|
438
495
|
} : {}, resolved.subscriptionOptional ? {
|
|
439
496
|
billing
|
|
440
497
|
} : {}, shipTo && !fulfillment.request ? {
|
|
@@ -466,7 +523,7 @@ function slugFromLocation() {
|
|
|
466
523
|
// flag flipped would look like a conversion collapse.
|
|
467
524
|
trackEvent('begin_checkout', buildBeginCheckoutParams({
|
|
468
525
|
items: [
|
|
469
|
-
buyItem(resolved, variant, quantity)
|
|
526
|
+
buyItem(resolved, variant, quantity, addOnGroups.length ? unitCents : undefined)
|
|
470
527
|
]
|
|
471
528
|
}));
|
|
472
529
|
setNativeCheckout({
|
|
@@ -484,7 +541,7 @@ function slugFromLocation() {
|
|
|
484
541
|
// property that makes a bare call safe is invisible from this file.
|
|
485
542
|
await trackEventBeforeNavigation('begin_checkout', buildBeginCheckoutParams({
|
|
486
543
|
items: [
|
|
487
|
-
buyItem(resolved, variant, quantity)
|
|
544
|
+
buyItem(resolved, variant, quantity, addOnGroups.length ? unitCents : undefined)
|
|
488
545
|
]
|
|
489
546
|
}));
|
|
490
547
|
window.location.assign(payload.url);
|
|
@@ -593,7 +650,7 @@ function slugFromLocation() {
|
|
|
593
650
|
// schema.org `image` array below is read out of band by a crawler, where
|
|
594
651
|
// an absolute URL is the point. That one wants `absoluteMediaSrc` with
|
|
595
652
|
// the site's own origin, which is the tenant page's job (AGL-1725).
|
|
596
|
-
const galleryImage = Aglyn.siteRelativeMediaSrc((
|
|
653
|
+
const galleryImage = Aglyn.siteRelativeMediaSrc((_ref2 = (_ref3 = activeImage !== null ? resolved.mediaUrls[activeImage] : undefined) != null ? _ref3 : variant == null ? void 0 : variant.imageUrl) != null ? _ref2 : resolved.mediaUrls[0], {
|
|
597
654
|
hostId
|
|
598
655
|
});
|
|
599
656
|
const presentedOptions = optionPresentation(resolved.options, resolved.variants);
|
|
@@ -743,7 +800,7 @@ function slugFromLocation() {
|
|
|
743
800
|
children: [
|
|
744
801
|
/*#__PURE__*/ _jsx(Typography, {
|
|
745
802
|
variant: "h6",
|
|
746
|
-
children: priced ?
|
|
803
|
+
children: priced ? `${money(unitCents)}${subscribing ? intervalSuffix : ''}` : PRICE_COMING_SOON_LABEL
|
|
747
804
|
}),
|
|
748
805
|
subscribing && (subscription == null ? void 0 : subscription.trialDays) ? /*#__PURE__*/ _jsx(Typography, {
|
|
749
806
|
variant: "caption",
|
|
@@ -758,7 +815,7 @@ function slugFromLocation() {
|
|
|
758
815
|
sx: {
|
|
759
816
|
textDecoration: 'line-through'
|
|
760
817
|
},
|
|
761
|
-
children:
|
|
818
|
+
children: moneyFromUsd(variant.compareAtPriceUsd)
|
|
762
819
|
}),
|
|
763
820
|
/*#__PURE__*/ _jsx(Chip, {
|
|
764
821
|
label: "Sale",
|
|
@@ -798,11 +855,11 @@ function slugFromLocation() {
|
|
|
798
855
|
children: [
|
|
799
856
|
/*#__PURE__*/ _jsx(ToggleButton, {
|
|
800
857
|
value: "once",
|
|
801
|
-
children: priced ? `One-time
|
|
858
|
+
children: priced ? `One-time ${money(unitCents)}` : 'One-time'
|
|
802
859
|
}),
|
|
803
860
|
/*#__PURE__*/ _jsx(ToggleButton, {
|
|
804
861
|
value: "subscribe",
|
|
805
|
-
children: priced ? `Subscribe
|
|
862
|
+
children: priced ? `Subscribe ${money(unitCents)}${intervalSuffix}` : 'Subscribe'
|
|
806
863
|
})
|
|
807
864
|
]
|
|
808
865
|
}) : null,
|
|
@@ -837,6 +894,17 @@ function slugFromLocation() {
|
|
|
837
894
|
}, value))
|
|
838
895
|
}, option.name);
|
|
839
896
|
}),
|
|
897
|
+
addOnGroups.length && priced ? /*#__PURE__*/ _jsx(Suspense, {
|
|
898
|
+
fallback: null,
|
|
899
|
+
children: /*#__PURE__*/ _jsx(ProductAddOns, {
|
|
900
|
+
groups: addOnGroups,
|
|
901
|
+
variantId: variant == null ? void 0 : variant.id,
|
|
902
|
+
value: addOns,
|
|
903
|
+
onChange: setAddOns,
|
|
904
|
+
formatCents: money,
|
|
905
|
+
disabled: Boolean(variant == null ? void 0 : variant.soldOut)
|
|
906
|
+
})
|
|
907
|
+
}) : null,
|
|
840
908
|
showCoupon ? /*#__PURE__*/ _jsx(TextField, {
|
|
841
909
|
label: "Discount code",
|
|
842
910
|
value: coupon,
|
|
@@ -896,7 +964,7 @@ function slugFromLocation() {
|
|
|
896
964
|
variant: "outlined",
|
|
897
965
|
color: "primary",
|
|
898
966
|
size: "large",
|
|
899
|
-
disabled: !hostId || !priced || (variant == null ? void 0 : variant.soldOut),
|
|
967
|
+
disabled: !hostId || !priced || (variant == null ? void 0 : variant.soldOut) || !pageAddOns.ready,
|
|
900
968
|
onClick: handleAddToCart,
|
|
901
969
|
children: added ? 'Added ✓' : 'Add to cart'
|
|
902
970
|
}),
|
|
@@ -904,7 +972,8 @@ function slugFromLocation() {
|
|
|
904
972
|
variant: "contained",
|
|
905
973
|
color: "primary",
|
|
906
974
|
size: "large",
|
|
907
|
-
disabled: !hostId || !priced || status === 'sending' || (variant == null ? void 0 : variant.soldOut) || //
|
|
975
|
+
disabled: !hostId || !priced || status === 'sending' || (variant == null ? void 0 : variant.soldOut) || // A required add-on unanswered (AGL-4100).
|
|
976
|
+
!pageAddOns.ready || // No payments on this deployment: the same 501 every time, so
|
|
908
977
|
// the control latches off rather than inviting a retry that
|
|
909
978
|
// cannot succeed (AGL-2019).
|
|
910
979
|
status === 'unconfigured' || // Asked but unanswered: the server would only refuse again.
|
|
@@ -919,6 +988,30 @@ function slugFromLocation() {
|
|
|
919
988
|
})
|
|
920
989
|
]
|
|
921
990
|
}),
|
|
991
|
+
addOnGroups.length && priced ? /*#__PURE__*/ _jsxs(Box, {
|
|
992
|
+
sx: {
|
|
993
|
+
mb: 2
|
|
994
|
+
},
|
|
995
|
+
children: [
|
|
996
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
997
|
+
variant: "subtitle1",
|
|
998
|
+
component: "p",
|
|
999
|
+
children: quantity > 1 ? `Total for ${quantity}: ${money(unitCents * quantity)}` : `Total: ${money(unitCents)}`
|
|
1000
|
+
}),
|
|
1001
|
+
!pageAddOns.ready && pageAddOns.error && !(variant == null ? void 0 : variant.soldOut) ? /*#__PURE__*/ _jsx(Typography, {
|
|
1002
|
+
variant: "body2",
|
|
1003
|
+
color: "text.secondary",
|
|
1004
|
+
children: pageAddOns.error
|
|
1005
|
+
}) : null
|
|
1006
|
+
]
|
|
1007
|
+
}) : null,
|
|
1008
|
+
addRefusal ? /*#__PURE__*/ _jsx(Alert, {
|
|
1009
|
+
severity: "warning",
|
|
1010
|
+
sx: {
|
|
1011
|
+
mb: 2
|
|
1012
|
+
},
|
|
1013
|
+
children: addRefusal
|
|
1014
|
+
}) : null,
|
|
922
1015
|
nativeCheckout ? /*#__PURE__*/ _jsx(Suspense, {
|
|
923
1016
|
fallback: /*#__PURE__*/ _jsx(StorefrontPaymentElementFallback, {}),
|
|
924
1017
|
children: /*#__PURE__*/ _jsx(StorefrontPaymentElement, {
|
|
@@ -947,7 +1040,7 @@ function slugFromLocation() {
|
|
|
947
1040
|
},
|
|
948
1041
|
children: /*#__PURE__*/ _jsx(CartFulfillmentChoice, {
|
|
949
1042
|
state: fulfillment,
|
|
950
|
-
formatCents:
|
|
1043
|
+
formatCents: money
|
|
951
1044
|
})
|
|
952
1045
|
}) : null,
|
|
953
1046
|
shipCountries && fulfillment.method === 'shipping' && priced ? /*#__PURE__*/ _jsx(TextField, {
|