@zappie/theme-base 0.1.0 → 0.1.2
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/CHANGELOG.md +39 -0
- package/README.md +26 -53
- package/dist/address.js +99 -2
- package/dist/address.js.map +7 -1
- package/dist/cart/address-sheet.js +143 -0
- package/dist/cart/address-sheet.js.map +7 -0
- package/dist/cart/cart-issues.js +72 -0
- package/dist/cart/cart-issues.js.map +7 -0
- package/dist/cart/cart-line-groups.js +34 -0
- package/dist/cart/cart-line-groups.js.map +7 -0
- package/dist/{chunk-FB5DRCU7.js → cart/cart-line.js} +9 -70
- package/dist/cart/cart-line.js.map +7 -0
- package/dist/cart/cart-lines.js +27 -0
- package/dist/cart/cart-lines.js.map +7 -0
- package/dist/cart/cart-schedule.js +24 -0
- package/dist/cart/cart-schedule.js.map +7 -0
- package/dist/cart/cart-sheet.js +35 -0
- package/dist/cart/cart-sheet.js.map +7 -0
- package/dist/cart/checkout-cta.js +81 -0
- package/dist/cart/checkout-cta.js.map +7 -0
- package/dist/cart/checkout-state.js +74 -0
- package/dist/cart/checkout-state.js.map +7 -0
- package/dist/cart/clear-cart.js +44 -0
- package/dist/cart/clear-cart.js.map +7 -0
- package/dist/cart/customer-details.js +70 -0
- package/dist/cart/customer-details.js.map +7 -0
- package/dist/cart/delivery-distance.js +22 -0
- package/dist/cart/delivery-distance.js.map +7 -0
- package/dist/cart/empty-cart.js +14 -0
- package/dist/cart/empty-cart.js.map +7 -0
- package/dist/cart/fulfilment-panel.js +83 -0
- package/dist/cart/fulfilment-panel.js.map +7 -0
- package/dist/cart/line-editor.js +35 -0
- package/dist/cart/line-editor.js.map +7 -0
- package/dist/cart/line-options.js +96 -0
- package/dist/cart/line-options.js.map +7 -0
- package/dist/cart/loading.js +17 -0
- package/dist/cart/loading.js.map +7 -0
- package/dist/cart/promo-sheet.js +103 -0
- package/dist/cart/promo-sheet.js.map +7 -0
- package/dist/cart/region-picker.js +40 -0
- package/dist/cart/region-picker.js.map +7 -0
- package/dist/cart/rewards-sheet.js +86 -0
- package/dist/cart/rewards-sheet.js.map +7 -0
- package/dist/cart/schedule-sheet.js +87 -0
- package/dist/cart/schedule-sheet.js.map +7 -0
- package/dist/{chunk-JFEI2OUZ.js → cart/theme-class.js} +7 -5
- package/dist/cart/theme-class.js.map +7 -0
- package/dist/cart/totals.js +81 -0
- package/dist/cart/totals.js.map +7 -0
- package/dist/cart/use-address-selection.js +130 -0
- package/dist/cart/use-address-selection.js.map +7 -0
- package/dist/cart.js +21 -1069
- package/dist/cart.js.map +7 -1
- package/dist/catalogue/catalogue-cart.js +25 -0
- package/dist/catalogue/catalogue-cart.js.map +7 -0
- package/dist/catalogue/catalogue-header.js +88 -0
- package/dist/catalogue/catalogue-header.js.map +7 -0
- package/dist/catalogue/catalogue-pages.js +68 -0
- package/dist/catalogue/catalogue-pages.js.map +7 -0
- package/dist/catalogue/catalogue-search.js +89 -0
- package/dist/catalogue/catalogue-search.js.map +7 -0
- package/dist/catalogue/category-navigation.js +98 -0
- package/dist/catalogue/category-navigation.js.map +7 -0
- package/dist/catalogue/category-section.js +113 -0
- package/dist/catalogue/category-section.js.map +7 -0
- package/dist/catalogue/info-banners.js +148 -0
- package/dist/catalogue/info-banners.js.map +7 -0
- package/dist/catalogue/item-tile.js +55 -0
- package/dist/catalogue/item-tile.js.map +7 -0
- package/dist/catalogue/loader.js +136 -0
- package/dist/catalogue/loader.js.map +7 -0
- package/dist/{chunk-USSLDBDY.js → catalogue/presentation.js} +12 -9
- package/dist/catalogue/presentation.js.map +7 -0
- package/dist/catalogue/saved-catalogue-sync.js +115 -0
- package/dist/catalogue/saved-catalogue-sync.js.map +7 -0
- package/dist/catalogue/types.js +1 -0
- package/dist/catalogue/types.js.map +7 -0
- package/dist/catalogue/use-catalogue-data.js +88 -0
- package/dist/catalogue/use-catalogue-data.js.map +7 -0
- package/dist/catalogue/use-category-scroll.js +115 -0
- package/dist/catalogue/use-category-scroll.js.map +7 -0
- package/dist/catalogue/use-item-opener.js +46 -0
- package/dist/catalogue/use-item-opener.js.map +7 -0
- package/dist/catalogue/use-search-source.js +132 -0
- package/dist/catalogue/use-search-source.js.map +7 -0
- package/dist/catalogue.js +26 -1216
- package/dist/catalogue.js.map +7 -1
- package/dist/checkout.js +149 -2
- package/dist/checkout.js.map +7 -1
- package/dist/host-bridge.js +22 -2
- package/dist/host-bridge.js.map +7 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +7 -1
- package/dist/item/configurator-commit.js +15 -0
- package/dist/item/configurator-commit.js.map +7 -0
- package/dist/item/configurator-draft.js +63 -0
- package/dist/item/configurator-draft.js.map +7 -0
- package/dist/item/configurator.js +135 -0
- package/dist/item/configurator.js.map +7 -0
- package/dist/item/note.js +65 -0
- package/dist/item/note.js.map +7 -0
- package/dist/item/variant-status.js +23 -0
- package/dist/item/variant-status.js.map +7 -0
- package/dist/item-frame.js +60 -3
- package/dist/item-frame.js.map +7 -1
- package/dist/item.js +11 -11
- package/dist/item.js.map +7 -1
- package/dist/navigation.js +39 -2
- package/dist/navigation.js.map +7 -1
- package/dist/url-navigation-state.js +61 -0
- package/dist/url-navigation-state.js.map +7 -0
- package/dist/{chunk-ILOCSCZL.js → url-navigation.js} +12 -89
- package/dist/url-navigation.js.map +7 -0
- package/package.json +8 -7
- package/dist/chunk-2MV6KU3R.js +0 -352
- package/dist/chunk-2MV6KU3R.js.map +0 -1
- package/dist/chunk-FB5DRCU7.js.map +0 -1
- package/dist/chunk-IG63ONID.js +0 -139
- package/dist/chunk-IG63ONID.js.map +0 -1
- package/dist/chunk-ILOCSCZL.js.map +0 -1
- package/dist/chunk-JFEI2OUZ.js.map +0 -1
- package/dist/chunk-NTJONY3N.js +0 -95
- package/dist/chunk-NTJONY3N.js.map +0 -1
- package/dist/chunk-QWST2TA2.js +0 -22
- package/dist/chunk-QWST2TA2.js.map +0 -1
- package/dist/chunk-USSLDBDY.js.map +0 -1
- package/dist/chunk-VIAJ27YC.js +0 -59
- package/dist/chunk-VIAJ27YC.js.map +0 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/cart/cart-line.tsx"],
|
|
4
|
+
"sourcesContent": ["import { Cart, Money, Overlay, Quantity } from \"@zappie/foundations\";\nimport type { CartLine as Line } from \"@zappie/sdk\";\nimport { useCart } from \"@zappie/sdk/react\";\nimport { LineEditor } from \"./line-editor\";\nexport function CartLine({ line }: { line: Line }) {\n const cart = useCart();\n const invalid = cart.issues.some(\n (issue) => issue.lineId === line.id && issue.severity === \"blocking\",\n );\n return (\n <Cart.Line line={line} className=\"z-base-line\">\n {({ item }) => (\n <>\n <div className=\"z-base-line-heading\">\n <h3>{line.name}</h3>\n {item && !invalid ? (\n <Money value={line.lineSubtotal} />\n ) : (\n <span>Price unavailable</span>\n )}\n </div>\n <ul className=\"z-base-line-options\">\n {line.choices.map((selection) => {\n const group = item?.optionGroups.find(\n (group) => group.id === selection.groupId,\n );\n const choice = group?.choices.find(\n (choice) => choice.id === selection.choiceId,\n );\n return (\n <li key={`${selection.groupId}:${selection.choiceId}`}>\n {choice?.name ?? \"Unavailable option\"}\n {selection.quantity > 1 ? ` \u00D7 ${selection.quantity}` : \"\"}\n </li>\n );\n })}\n {Object.entries(line.inputs).map(([id, value]) => (\n <li key={id}>\n {item?.optionGroups.find((group) => group.id === id)?.name ??\n \"Details\"}\n : {value}\n </li>\n ))}\n </ul>\n {line.note && <p className=\"z-base-muted\">{line.note}</p>}\n <div className=\"z-base-line-actions\">\n <Cart.Quantity\n lineId={line.id}\n disabled={invalid}\n className=\"z-base-quantity\"\n >\n <Quantity.Decrement aria-label={`Decrease ${line.name} quantity`}>\n \u2212\n </Quantity.Decrement>\n <Quantity.Value aria-label={`${line.name} quantity`} />\n <Quantity.Increment aria-label={`Increase ${line.name} quantity`}>\n +\n </Quantity.Increment>\n </Cart.Quantity>\n <Overlay.Root\n param=\"cart_edit\"\n id={line.id}\n presentation={{ base: \"sheet\", lg: \"dialog\" }}\n >\n <Overlay.Trigger\n className=\"z-base-button-secondary\"\n disabled={!item}\n aria-label={`Edit ${line.name}`}\n >\n Edit\n </Overlay.Trigger>\n {item && <LineEditor line={line} item={item} />}\n </Overlay.Root>\n <Cart.Remove\n lineId={line.id}\n className=\"z-base-button-secondary\"\n aria-label={`Remove ${line.name}`}\n >\n Remove\n </Cart.Remove>\n </div>\n </>\n )}\n </Cart.Line>\n );\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,MAAM,OAAO,SAAS,gBAAgB;AAE/C,SAAS,eAAe;AACxB,SAAS,kBAAkB;AASnB,mBAEI,KADF,YADF;AARD,SAAS,SAAS,EAAE,KAAK,GAAmB;AACjD,QAAM,OAAO,QAAQ;AACrB,QAAM,UAAU,KAAK,OAAO;AAAA,IAC1B,CAAC,UAAU,MAAM,WAAW,KAAK,MAAM,MAAM,aAAa;AAAA,EAC5D;AACA,SACE,oBAAC,KAAK,MAAL,EAAU,MAAY,WAAU,eAC9B,WAAC,EAAE,KAAK,MACP,iCACE;AAAA,yBAAC,SAAI,WAAU,uBACb;AAAA,0BAAC,QAAI,eAAK,MAAK;AAAA,MACd,QAAQ,CAAC,UACR,oBAAC,SAAM,OAAO,KAAK,cAAc,IAEjC,oBAAC,UAAK,+BAAiB;AAAA,OAE3B;AAAA,IACA,qBAAC,QAAG,WAAU,uBACX;AAAA,WAAK,QAAQ,IAAI,CAAC,cAAc;AAC/B,cAAM,QAAQ,MAAM,aAAa;AAAA,UAC/B,CAACA,WAAUA,OAAM,OAAO,UAAU;AAAA,QACpC;AACA,cAAM,SAAS,OAAO,QAAQ;AAAA,UAC5B,CAACC,YAAWA,QAAO,OAAO,UAAU;AAAA,QACtC;AACA,eACE,qBAAC,QACE;AAAA,kBAAQ,QAAQ;AAAA,UAChB,UAAU,WAAW,IAAI,SAAM,UAAU,QAAQ,KAAK;AAAA,aAFhD,GAAG,UAAU,OAAO,IAAI,UAAU,QAAQ,EAGnD;AAAA,MAEJ,CAAC;AAAA,MACA,OAAO,QAAQ,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,IAAI,KAAK,MAC1C,qBAAC,QACE;AAAA,cAAM,aAAa,KAAK,CAAC,UAAU,MAAM,OAAO,EAAE,GAAG,QACpD;AAAA,QAAU;AAAA,QACT;AAAA,WAHI,EAIT,CACD;AAAA,OACH;AAAA,IACC,KAAK,QAAQ,oBAAC,OAAE,WAAU,gBAAgB,eAAK,MAAK;AAAA,IACrD,qBAAC,SAAI,WAAU,uBACb;AAAA;AAAA,QAAC,KAAK;AAAA,QAAL;AAAA,UACC,QAAQ,KAAK;AAAA,UACb,UAAU;AAAA,UACV,WAAU;AAAA,UAEV;AAAA,gCAAC,SAAS,WAAT,EAAmB,cAAY,YAAY,KAAK,IAAI,aAAa,oBAElE;AAAA,YACA,oBAAC,SAAS,OAAT,EAAe,cAAY,GAAG,KAAK,IAAI,aAAa;AAAA,YACrD,oBAAC,SAAS,WAAT,EAAmB,cAAY,YAAY,KAAK,IAAI,aAAa,eAElE;AAAA;AAAA;AAAA,MACF;AAAA,MACA;AAAA,QAAC,QAAQ;AAAA,QAAR;AAAA,UACC,OAAM;AAAA,UACN,IAAI,KAAK;AAAA,UACT,cAAc,EAAE,MAAM,SAAS,IAAI,SAAS;AAAA,UAE5C;AAAA;AAAA,cAAC,QAAQ;AAAA,cAAR;AAAA,gBACC,WAAU;AAAA,gBACV,UAAU,CAAC;AAAA,gBACX,cAAY,QAAQ,KAAK,IAAI;AAAA,gBAC9B;AAAA;AAAA,YAED;AAAA,YACC,QAAQ,oBAAC,cAAW,MAAY,MAAY;AAAA;AAAA;AAAA,MAC/C;AAAA,MACA;AAAA,QAAC,KAAK;AAAA,QAAL;AAAA,UACC,QAAQ,KAAK;AAAA,UACb,WAAU;AAAA,UACV,cAAY,UAAU,KAAK,IAAI;AAAA,UAChC;AAAA;AAAA,MAED;AAAA,OACF;AAAA,KACF,GAEJ;AAEJ;",
|
|
6
|
+
"names": ["group", "choice"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// src/cart/cart-lines.tsx
|
|
2
|
+
import { useCart, useCartCatalogue } from "@zappie/sdk/react";
|
|
3
|
+
import { CartLine } from "./cart-line.js";
|
|
4
|
+
import { groupCartLinesByMenu } from "./cart-line-groups.js";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
function CartLines() {
|
|
7
|
+
const { lines } = useCart();
|
|
8
|
+
const catalogue = useCartCatalogue();
|
|
9
|
+
const groups = groupCartLinesByMenu(lines, catalogue);
|
|
10
|
+
const grouped = (catalogue?.menus?.length ?? 0) > 1;
|
|
11
|
+
return /* @__PURE__ */ jsx("section", { "aria-label": "Cart items", className: "z-base-lines", children: groups.map((group) => /* @__PURE__ */ jsxs(
|
|
12
|
+
"section",
|
|
13
|
+
{
|
|
14
|
+
"aria-label": group.menuName ?? "Other items",
|
|
15
|
+
className: "z-base-line-group",
|
|
16
|
+
children: [
|
|
17
|
+
grouped && /* @__PURE__ */ jsx("h2", { children: group.menuName ?? "Other items" }),
|
|
18
|
+
group.lines.map((line) => /* @__PURE__ */ jsx(CartLine, { line }, line.id))
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
group.menuId
|
|
22
|
+
)) });
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
CartLines
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=cart-lines.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/cart/cart-lines.tsx"],
|
|
4
|
+
"sourcesContent": ["import { useCart, useCartCatalogue } from \"@zappie/sdk/react\";\nimport { CartLine } from \"./cart-line\";\nimport { groupCartLinesByMenu } from \"./cart-line-groups\";\nexport function CartLines() {\n const { lines } = useCart();\n const catalogue = useCartCatalogue();\n const groups = groupCartLinesByMenu(lines, catalogue);\n const grouped = (catalogue?.menus?.length ?? 0) > 1;\n return (\n <section aria-label=\"Cart items\" className=\"z-base-lines\">\n {groups.map((group) => (\n <section\n key={group.menuId}\n aria-label={group.menuName ?? \"Other items\"}\n className=\"z-base-line-group\"\n >\n {grouped && <h2>{group.menuName ?? \"Other items\"}</h2>}\n {group.lines.map((line) => (\n <CartLine key={line.id} line={line} />\n ))}\n </section>\n ))}\n </section>\n );\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,SAAS,wBAAwB;AAC1C,SAAS,gBAAgB;AACzB,SAAS,4BAA4B;AAS7B,SAKc,KALd;AARD,SAAS,YAAY;AAC1B,QAAM,EAAE,MAAM,IAAI,QAAQ;AAC1B,QAAM,YAAY,iBAAiB;AACnC,QAAM,SAAS,qBAAqB,OAAO,SAAS;AACpD,QAAM,WAAW,WAAW,OAAO,UAAU,KAAK;AAClD,SACE,oBAAC,aAAQ,cAAW,cAAa,WAAU,gBACxC,iBAAO,IAAI,CAAC,UACX;AAAA,IAAC;AAAA;AAAA,MAEC,cAAY,MAAM,YAAY;AAAA,MAC9B,WAAU;AAAA,MAET;AAAA,mBAAW,oBAAC,QAAI,gBAAM,YAAY,eAAc;AAAA,QAChD,MAAM,MAAM,IAAI,CAAC,SAChB,oBAAC,YAAuB,QAAT,KAAK,EAAgB,CACrC;AAAA;AAAA;AAAA,IAPI,MAAM;AAAA,EAQb,CACD,GACH;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// src/cart/cart-schedule.ts
|
|
2
|
+
function cartScheduleLimits(menu, lines, maxDays) {
|
|
3
|
+
const sections = (menu?.menus ?? []).filter(
|
|
4
|
+
(section) => section.schedule?.preorder && lines.some(
|
|
5
|
+
(line) => line.menuId ? line.menuId === section.id : section.categoryIds.some(
|
|
6
|
+
(id) => menu?.categories.find((category) => category.id === id)?.itemIds.includes(line.itemId)
|
|
7
|
+
)
|
|
8
|
+
)
|
|
9
|
+
);
|
|
10
|
+
const notice = Math.max(
|
|
11
|
+
0,
|
|
12
|
+
...sections.map((section) => section.schedule?.preorderNoticeHours ?? 0)
|
|
13
|
+
);
|
|
14
|
+
const horizons = sections.map((section) => section.schedule?.preorderMaxDays).filter((days) => typeof days === "number" && days > 0);
|
|
15
|
+
const limit = horizons.length > 0 ? Math.min(maxDays ?? Number.POSITIVE_INFINITY, ...horizons) : maxDays;
|
|
16
|
+
return {
|
|
17
|
+
noticeMinutes: notice * 60,
|
|
18
|
+
maxDays: limit === void 0 ? void 0 : Math.max(1, Math.min(90, limit))
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
cartScheduleLimits
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=cart-schedule.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/cart/cart-schedule.ts"],
|
|
4
|
+
"sourcesContent": ["import type { CartLine, Menu } from \"@zappie/sdk\";\n/**\n * Pre-order limits for the menus the cart's lines come from. Schedule reads a\n * menu's notice only from a single-menu catalogue; with several menus the\n * tightest notice and horizon among the cart's pre-order menus apply.\n */\nexport function cartScheduleLimits(\n menu: Menu | undefined,\n lines: readonly CartLine[],\n maxDays: number | undefined,\n): { noticeMinutes: number; maxDays: number | undefined } {\n const sections = (menu?.menus ?? []).filter(\n (section) =>\n section.schedule?.preorder &&\n lines.some((line) =>\n line.menuId\n ? line.menuId === section.id\n : section.categoryIds.some((id) =>\n menu?.categories\n .find((category) => category.id === id)\n ?.itemIds.includes(line.itemId),\n ),\n ),\n );\n const notice = Math.max(\n 0,\n ...sections.map((section) => section.schedule?.preorderNoticeHours ?? 0),\n );\n const horizons = sections\n .map((section) => section.schedule?.preorderMaxDays)\n .filter((days): days is number => typeof days === \"number\" && days > 0);\n const limit =\n horizons.length > 0\n ? Math.min(maxDays ?? Number.POSITIVE_INFINITY, ...horizons)\n : maxDays;\n return {\n noticeMinutes: notice * 60,\n maxDays: limit === undefined ? undefined : Math.max(1, Math.min(90, limit)),\n };\n}\n"],
|
|
5
|
+
"mappings": ";AAMO,SAAS,mBACd,MACA,OACA,SACwD;AACxD,QAAM,YAAY,MAAM,SAAS,CAAC,GAAG;AAAA,IACnC,CAAC,YACC,QAAQ,UAAU,YAClB,MAAM;AAAA,MAAK,CAAC,SACV,KAAK,SACD,KAAK,WAAW,QAAQ,KACxB,QAAQ,YAAY;AAAA,QAAK,CAAC,OACxB,MAAM,WACH,KAAK,CAAC,aAAa,SAAS,OAAO,EAAE,GACpC,QAAQ,SAAS,KAAK,MAAM;AAAA,MAClC;AAAA,IACN;AAAA,EACJ;AACA,QAAM,SAAS,KAAK;AAAA,IAClB;AAAA,IACA,GAAG,SAAS,IAAI,CAAC,YAAY,QAAQ,UAAU,uBAAuB,CAAC;AAAA,EACzE;AACA,QAAM,WAAW,SACd,IAAI,CAAC,YAAY,QAAQ,UAAU,eAAe,EAClD,OAAO,CAAC,SAAyB,OAAO,SAAS,YAAY,OAAO,CAAC;AACxE,QAAM,QACJ,SAAS,SAAS,IACd,KAAK,IAAI,WAAW,OAAO,mBAAmB,GAAG,QAAQ,IACzD;AACN,SAAO;AAAA,IACL,eAAe,SAAS;AAAA,IACxB,SAAS,UAAU,SAAY,SAAY,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,CAAC;AAAA,EAC5E;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// src/cart/cart-sheet.tsx
|
|
2
|
+
import { Overlay, useOverlay } from "@zappie/foundations";
|
|
3
|
+
import { useThemeClass } from "./theme-class.js";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
function CartSheet({
|
|
6
|
+
id,
|
|
7
|
+
title,
|
|
8
|
+
trigger,
|
|
9
|
+
children
|
|
10
|
+
}) {
|
|
11
|
+
const rootClass = useThemeClass("z-base-cart z-base-editor");
|
|
12
|
+
const overlay = useOverlay("cart_sheet", id);
|
|
13
|
+
return /* @__PURE__ */ jsxs(
|
|
14
|
+
Overlay.Root,
|
|
15
|
+
{
|
|
16
|
+
param: "cart_sheet",
|
|
17
|
+
id,
|
|
18
|
+
presentation: { base: "sheet", lg: "dialog" },
|
|
19
|
+
children: [
|
|
20
|
+
/* @__PURE__ */ jsx(Overlay.Trigger, { className: "z-base-button-secondary", children: trigger }),
|
|
21
|
+
/* @__PURE__ */ jsxs(Overlay.Content, { "data-zappie-theme": "base", className: rootClass, children: [
|
|
22
|
+
/* @__PURE__ */ jsxs("header", { className: "z-base-cart-header", children: [
|
|
23
|
+
/* @__PURE__ */ jsx(Overlay.Title, { children: title }),
|
|
24
|
+
/* @__PURE__ */ jsx(Overlay.Close, { className: "z-base-button-secondary", children: "Cancel" })
|
|
25
|
+
] }),
|
|
26
|
+
overlay.isOpen && /* @__PURE__ */ jsx("div", { className: "z-base-cart-body", children })
|
|
27
|
+
] })
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
export {
|
|
33
|
+
CartSheet
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=cart-sheet.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/cart/cart-sheet.tsx"],
|
|
4
|
+
"sourcesContent": ["import { Overlay, useOverlay } from \"@zappie/foundations\";\nimport type { ReactNode } from \"react\";\nimport { useThemeClass } from \"./theme-class\";\nexport function CartSheet({\n id,\n title,\n trigger,\n children,\n}: {\n id: string;\n title: string;\n trigger: string;\n children: ReactNode;\n}) {\n const rootClass = useThemeClass(\"z-base-cart z-base-editor\");\n const overlay = useOverlay(\"cart_sheet\", id);\n return (\n <Overlay.Root\n param=\"cart_sheet\"\n id={id}\n presentation={{ base: \"sheet\", lg: \"dialog\" }}\n >\n <Overlay.Trigger className=\"z-base-button-secondary\">\n {trigger}\n </Overlay.Trigger>\n <Overlay.Content data-zappie-theme=\"base\" className={rootClass}>\n <header className=\"z-base-cart-header\">\n <Overlay.Title>{title}</Overlay.Title>\n <Overlay.Close className=\"z-base-button-secondary\">\n Cancel\n </Overlay.Close>\n </header>\n {overlay.isOpen && <div className=\"z-base-cart-body\">{children}</div>}\n </Overlay.Content>\n </Overlay.Root>\n );\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,SAAS,kBAAkB;AAEpC,SAAS,qBAAqB;AAoBxB,cAIE,YAJF;AAnBC,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,YAAY,cAAc,2BAA2B;AAC3D,QAAM,UAAU,WAAW,cAAc,EAAE;AAC3C,SACE;AAAA,IAAC,QAAQ;AAAA,IAAR;AAAA,MACC,OAAM;AAAA,MACN;AAAA,MACA,cAAc,EAAE,MAAM,SAAS,IAAI,SAAS;AAAA,MAE5C;AAAA,4BAAC,QAAQ,SAAR,EAAgB,WAAU,2BACxB,mBACH;AAAA,QACA,qBAAC,QAAQ,SAAR,EAAgB,qBAAkB,QAAO,WAAW,WACnD;AAAA,+BAAC,YAAO,WAAU,sBAChB;AAAA,gCAAC,QAAQ,OAAR,EAAe,iBAAM;AAAA,YACtB,oBAAC,QAAQ,OAAR,EAAc,WAAU,2BAA0B,oBAEnD;AAAA,aACF;AAAA,UACC,QAAQ,UAAU,oBAAC,SAAI,WAAU,oBAAoB,UAAS;AAAA,WACjE;AAAA;AAAA;AAAA,EACF;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// src/cart/checkout-cta.tsx
|
|
2
|
+
import { isContactPhoneValid } from "@zappie/sdk/checkout";
|
|
3
|
+
import { useCart } from "@zappie/sdk/react";
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
import { useCheckoutHandoff } from "../checkout.js";
|
|
6
|
+
import { useBaseHostBridge } from "../host-bridge.js";
|
|
7
|
+
import { checkoutButtonState } from "./checkout-state.js";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
function CheckoutCta({
|
|
10
|
+
totalsStatus,
|
|
11
|
+
contactPhone
|
|
12
|
+
}) {
|
|
13
|
+
const cart = useCart();
|
|
14
|
+
const bridge = useBaseHostBridge();
|
|
15
|
+
const handoff = useCheckoutHandoff();
|
|
16
|
+
const [busy, setBusy] = useState(false);
|
|
17
|
+
const [error, setError] = useState(null);
|
|
18
|
+
const showContactPhone = Boolean(
|
|
19
|
+
contactPhone && handoff.contactPhone && handoff.customer
|
|
20
|
+
);
|
|
21
|
+
const buttonInput = {
|
|
22
|
+
busy,
|
|
23
|
+
cartState: cart.state,
|
|
24
|
+
totalsStatus,
|
|
25
|
+
fulfilment: cart.fulfilment,
|
|
26
|
+
customer: handoff.customer,
|
|
27
|
+
contactPhoneValid: !showContactPhone || isContactPhoneValid(contactPhone?.value ?? "")
|
|
28
|
+
};
|
|
29
|
+
if (bridge.deliveryDistance) {
|
|
30
|
+
buttonInput.deliveryDistance = bridge.deliveryDistance;
|
|
31
|
+
}
|
|
32
|
+
const button = checkoutButtonState(buttonInput);
|
|
33
|
+
const checkout = async () => {
|
|
34
|
+
if (!button.enabled) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (button.status === "phone") {
|
|
38
|
+
contactPhone?.touch();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
setBusy(true);
|
|
42
|
+
setError(null);
|
|
43
|
+
try {
|
|
44
|
+
if (!handoff.customer) {
|
|
45
|
+
await handoff.signIn();
|
|
46
|
+
} else {
|
|
47
|
+
const payload = cart.actions.toCheckoutPayload();
|
|
48
|
+
if (showContactPhone && contactPhone) {
|
|
49
|
+
await handoff.pay(payload, { contactPhone: contactPhone.value });
|
|
50
|
+
} else {
|
|
51
|
+
await handoff.pay(payload);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} catch (error2) {
|
|
55
|
+
setError(
|
|
56
|
+
error2 instanceof Error ? error2.message : "Unable to continue to checkout"
|
|
57
|
+
);
|
|
58
|
+
} finally {
|
|
59
|
+
setBusy(false);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
return /* @__PURE__ */ jsxs("div", { className: "z-base-checkout", children: [
|
|
63
|
+
error && /* @__PURE__ */ jsx("p", { role: "alert", children: error }),
|
|
64
|
+
/* @__PURE__ */ jsx(
|
|
65
|
+
"button",
|
|
66
|
+
{
|
|
67
|
+
type: "button",
|
|
68
|
+
className: "z-base-button",
|
|
69
|
+
disabled: !button.enabled,
|
|
70
|
+
onClick: () => {
|
|
71
|
+
void checkout();
|
|
72
|
+
},
|
|
73
|
+
children: button.label
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
] });
|
|
77
|
+
}
|
|
78
|
+
export {
|
|
79
|
+
CheckoutCta
|
|
80
|
+
};
|
|
81
|
+
//# sourceMappingURL=checkout-cta.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/cart/checkout-cta.tsx"],
|
|
4
|
+
"sourcesContent": ["import type { TotalsState } from \"@zappie/foundations\";\nimport { isContactPhoneValid } from \"@zappie/sdk/checkout\";\nimport { useCart } from \"@zappie/sdk/react\";\nimport { useState } from \"react\";\nimport { useCheckoutHandoff } from \"../checkout\";\nimport { useBaseHostBridge } from \"../host-bridge\";\nimport { checkoutButtonState } from \"./checkout-state\";\nimport type { ContactPhoneState } from \"./customer-details\";\nexport function CheckoutCta({\n totalsStatus,\n contactPhone,\n}: {\n totalsStatus: TotalsState[\"status\"];\n contactPhone?: ContactPhoneState;\n}) {\n const cart = useCart();\n const bridge = useBaseHostBridge();\n const handoff = useCheckoutHandoff();\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const showContactPhone = Boolean(\n contactPhone && handoff.contactPhone && handoff.customer,\n );\n const buttonInput: Parameters<typeof checkoutButtonState>[0] = {\n busy,\n cartState: cart.state,\n totalsStatus,\n fulfilment: cart.fulfilment,\n customer: handoff.customer,\n contactPhoneValid:\n !showContactPhone || isContactPhoneValid(contactPhone?.value ?? \"\"),\n };\n if (bridge.deliveryDistance) {\n buttonInput.deliveryDistance = bridge.deliveryDistance;\n }\n const button = checkoutButtonState(buttonInput);\n const checkout = async () => {\n if (!button.enabled) {\n return;\n }\n if (button.status === \"phone\") {\n contactPhone?.touch();\n return;\n }\n setBusy(true);\n setError(null);\n try {\n if (!handoff.customer) {\n await handoff.signIn();\n } else {\n const payload = cart.actions.toCheckoutPayload();\n if (showContactPhone && contactPhone) {\n await handoff.pay(payload, { contactPhone: contactPhone.value });\n } else {\n await handoff.pay(payload);\n }\n }\n } catch (error) {\n setError(\n error instanceof Error\n ? error.message\n : \"Unable to continue to checkout\",\n );\n } finally {\n setBusy(false);\n }\n };\n return (\n <div className=\"z-base-checkout\">\n {error && <p role=\"alert\">{error}</p>}\n <button\n type=\"button\"\n className=\"z-base-button\"\n disabled={!button.enabled}\n onClick={() => {\n void checkout();\n }}\n >\n {button.label}\n </button>\n </div>\n );\n}\n"],
|
|
5
|
+
"mappings": ";AACA,SAAS,2BAA2B;AACpC,SAAS,eAAe;AACxB,SAAS,gBAAgB;AACzB,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AA8DhC,SACY,KADZ;AA5DG,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AACF,GAGG;AACD,QAAM,OAAO,QAAQ;AACrB,QAAM,SAAS,kBAAkB;AACjC,QAAM,UAAU,mBAAmB;AACnC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AACtD,QAAM,mBAAmB;AAAA,IACvB,gBAAgB,QAAQ,gBAAgB,QAAQ;AAAA,EAClD;AACA,QAAM,cAAyD;AAAA,IAC7D;AAAA,IACA,WAAW,KAAK;AAAA,IAChB;AAAA,IACA,YAAY,KAAK;AAAA,IACjB,UAAU,QAAQ;AAAA,IAClB,mBACE,CAAC,oBAAoB,oBAAoB,cAAc,SAAS,EAAE;AAAA,EACtE;AACA,MAAI,OAAO,kBAAkB;AAC3B,gBAAY,mBAAmB,OAAO;AAAA,EACxC;AACA,QAAM,SAAS,oBAAoB,WAAW;AAC9C,QAAM,WAAW,YAAY;AAC3B,QAAI,CAAC,OAAO,SAAS;AACnB;AAAA,IACF;AACA,QAAI,OAAO,WAAW,SAAS;AAC7B,oBAAc,MAAM;AACpB;AAAA,IACF;AACA,YAAQ,IAAI;AACZ,aAAS,IAAI;AACb,QAAI;AACF,UAAI,CAAC,QAAQ,UAAU;AACrB,cAAM,QAAQ,OAAO;AAAA,MACvB,OAAO;AACL,cAAM,UAAU,KAAK,QAAQ,kBAAkB;AAC/C,YAAI,oBAAoB,cAAc;AACpC,gBAAM,QAAQ,IAAI,SAAS,EAAE,cAAc,aAAa,MAAM,CAAC;AAAA,QACjE,OAAO;AACL,gBAAM,QAAQ,IAAI,OAAO;AAAA,QAC3B;AAAA,MACF;AAAA,IACF,SAASA,QAAO;AACd;AAAA,QACEA,kBAAiB,QACbA,OAAM,UACN;AAAA,MACN;AAAA,IACF,UAAE;AACA,cAAQ,KAAK;AAAA,IACf;AAAA,EACF;AACA,SACE,qBAAC,SAAI,WAAU,mBACZ;AAAA,aAAS,oBAAC,OAAE,MAAK,SAAS,iBAAM;AAAA,IACjC;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,WAAU;AAAA,QACV,UAAU,CAAC,OAAO;AAAA,QAClB,SAAS,MAAM;AACb,eAAK,SAAS;AAAA,QAChB;AAAA,QAEC,iBAAO;AAAA;AAAA,IACV;AAAA,KACF;AAEJ;",
|
|
6
|
+
"names": ["error"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// src/cart/checkout-state.ts
|
|
2
|
+
import {
|
|
3
|
+
payReadiness
|
|
4
|
+
} from "@zappie/sdk/checkout";
|
|
5
|
+
var labels = {
|
|
6
|
+
pay: "Continue to payment",
|
|
7
|
+
sign_in: "Sign in to continue",
|
|
8
|
+
busy: "Please wait\u2026",
|
|
9
|
+
quoting: "Updating total\u2026",
|
|
10
|
+
retry: "Update totals to continue",
|
|
11
|
+
address: "Add a delivery address",
|
|
12
|
+
choose_area: "Choose a delivery area",
|
|
13
|
+
fix_issues: "Review your cart",
|
|
14
|
+
too_far: "Too far for delivery",
|
|
15
|
+
phone: "Check your phone number"
|
|
16
|
+
};
|
|
17
|
+
function toPayReadinessQuoteState(cartState, totalsStatus) {
|
|
18
|
+
if (cartState.status === "quoting") {
|
|
19
|
+
return { status: "loading" };
|
|
20
|
+
}
|
|
21
|
+
if (totalsStatus === "stale" || totalsStatus === "offline") {
|
|
22
|
+
return { status: "error" };
|
|
23
|
+
}
|
|
24
|
+
if (cartState.status === "quoted") {
|
|
25
|
+
return { status: "ready", quote: cartState.quote };
|
|
26
|
+
}
|
|
27
|
+
if (cartState.status === "needs_attention") {
|
|
28
|
+
if (cartState.quote) {
|
|
29
|
+
return { status: "ready", quote: cartState.quote };
|
|
30
|
+
}
|
|
31
|
+
return { status: "error" };
|
|
32
|
+
}
|
|
33
|
+
return { status: "idle" };
|
|
34
|
+
}
|
|
35
|
+
function checkoutButtonState({
|
|
36
|
+
busy,
|
|
37
|
+
cartState,
|
|
38
|
+
totalsStatus,
|
|
39
|
+
fulfilment,
|
|
40
|
+
customer,
|
|
41
|
+
contactPhoneValid = true,
|
|
42
|
+
deliveryDistance
|
|
43
|
+
}) {
|
|
44
|
+
let status;
|
|
45
|
+
if (busy) {
|
|
46
|
+
status = "busy";
|
|
47
|
+
} else if (!customer) {
|
|
48
|
+
status = "sign_in";
|
|
49
|
+
} else if (deliveryDistance?.status === "too_far") {
|
|
50
|
+
status = "too_far";
|
|
51
|
+
} else {
|
|
52
|
+
const addressValid = fulfilment?.type !== "delivery" || Boolean(
|
|
53
|
+
fulfilment.address.line1 || fulfilment.address.placeId || fulfilment.address.coordinates
|
|
54
|
+
);
|
|
55
|
+
status = payReadiness(
|
|
56
|
+
toPayReadinessQuoteState(cartState, totalsStatus),
|
|
57
|
+
contactPhoneValid,
|
|
58
|
+
addressValid
|
|
59
|
+
);
|
|
60
|
+
if (status === "pay" && cartState.status === "needs_attention") {
|
|
61
|
+
status = "fix_issues";
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
status,
|
|
66
|
+
label: labels[status],
|
|
67
|
+
enabled: status === "pay" || status === "sign_in" || status === "phone"
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export {
|
|
71
|
+
checkoutButtonState,
|
|
72
|
+
toPayReadinessQuoteState
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=checkout-state.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/cart/checkout-state.ts"],
|
|
4
|
+
"sourcesContent": ["import type { TotalsState } from \"@zappie/foundations\";\nimport type { CartFulfilment, CartState } from \"@zappie/sdk\";\nimport {\n payReadiness,\n type PayReadiness,\n type PayReadinessQuoteState,\n} from \"@zappie/sdk/checkout\";\n\nexport type CheckoutButtonStatus = PayReadiness | \"busy\" | \"too_far\";\n\nexport type CheckoutButtonState = {\n status: CheckoutButtonStatus;\n label: string;\n enabled: boolean;\n};\n\nconst labels: Record<CheckoutButtonStatus, string> = {\n pay: \"Continue to payment\",\n sign_in: \"Sign in to continue\",\n busy: \"Please wait\u2026\",\n quoting: \"Updating total\u2026\",\n retry: \"Update totals to continue\",\n address: \"Add a delivery address\",\n choose_area: \"Choose a delivery area\",\n fix_issues: \"Review your cart\",\n too_far: \"Too far for delivery\",\n phone: \"Check your phone number\",\n};\n\nexport function toPayReadinessQuoteState(\n cartState: CartState,\n totalsStatus: TotalsState[\"status\"],\n): PayReadinessQuoteState {\n if (cartState.status === \"quoting\") {\n return { status: \"loading\" };\n }\n if (totalsStatus === \"stale\" || totalsStatus === \"offline\") {\n return { status: \"error\" };\n }\n if (cartState.status === \"quoted\") {\n return { status: \"ready\", quote: cartState.quote };\n }\n if (cartState.status === \"needs_attention\") {\n if (cartState.quote) {\n return { status: \"ready\", quote: cartState.quote };\n }\n return { status: \"error\" };\n }\n return { status: \"idle\" };\n}\n\nexport function checkoutButtonState({\n busy,\n cartState,\n totalsStatus,\n fulfilment,\n customer,\n contactPhoneValid = true,\n deliveryDistance,\n}: {\n busy: boolean;\n cartState: CartState;\n totalsStatus: TotalsState[\"status\"];\n fulfilment: CartFulfilment | null;\n customer: { name?: string } | null;\n contactPhoneValid?: boolean;\n deliveryDistance?: { status: \"unknown\" | \"far\" | \"too_far\" };\n}): CheckoutButtonState {\n let status: CheckoutButtonStatus;\n if (busy) {\n status = \"busy\";\n } else if (!customer) {\n status = \"sign_in\";\n } else if (deliveryDistance?.status === \"too_far\") {\n status = \"too_far\";\n } else {\n const addressValid =\n fulfilment?.type !== \"delivery\" ||\n Boolean(\n fulfilment.address.line1 ||\n fulfilment.address.placeId ||\n fulfilment.address.coordinates,\n );\n status = payReadiness(\n toPayReadinessQuoteState(cartState, totalsStatus),\n contactPhoneValid,\n addressValid,\n );\n // Unresolved warnings (a changed price, a refused promo) still hold payment\n // until the shopper deals with them, although the API would accept the order.\n if (status === \"pay\" && cartState.status === \"needs_attention\") {\n status = \"fix_issues\";\n }\n }\n return {\n status,\n label: labels[status],\n enabled: status === \"pay\" || status === \"sign_in\" || status === \"phone\",\n };\n}\n"],
|
|
5
|
+
"mappings": ";AAEA;AAAA,EACE;AAAA,OAGK;AAUP,IAAM,SAA+C;AAAA,EACnD,KAAK;AAAA,EACL,SAAS;AAAA,EACT,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,OAAO;AACT;AAEO,SAAS,yBACd,WACA,cACwB;AACxB,MAAI,UAAU,WAAW,WAAW;AAClC,WAAO,EAAE,QAAQ,UAAU;AAAA,EAC7B;AACA,MAAI,iBAAiB,WAAW,iBAAiB,WAAW;AAC1D,WAAO,EAAE,QAAQ,QAAQ;AAAA,EAC3B;AACA,MAAI,UAAU,WAAW,UAAU;AACjC,WAAO,EAAE,QAAQ,SAAS,OAAO,UAAU,MAAM;AAAA,EACnD;AACA,MAAI,UAAU,WAAW,mBAAmB;AAC1C,QAAI,UAAU,OAAO;AACnB,aAAO,EAAE,QAAQ,SAAS,OAAO,UAAU,MAAM;AAAA,IACnD;AACA,WAAO,EAAE,QAAQ,QAAQ;AAAA,EAC3B;AACA,SAAO,EAAE,QAAQ,OAAO;AAC1B;AAEO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,oBAAoB;AAAA,EACpB;AACF,GAQwB;AACtB,MAAI;AACJ,MAAI,MAAM;AACR,aAAS;AAAA,EACX,WAAW,CAAC,UAAU;AACpB,aAAS;AAAA,EACX,WAAW,kBAAkB,WAAW,WAAW;AACjD,aAAS;AAAA,EACX,OAAO;AACL,UAAM,eACJ,YAAY,SAAS,cACrB;AAAA,MACE,WAAW,QAAQ,SACnB,WAAW,QAAQ,WACnB,WAAW,QAAQ;AAAA,IACrB;AACF,aAAS;AAAA,MACP,yBAAyB,WAAW,YAAY;AAAA,MAChD;AAAA,MACA;AAAA,IACF;AAGA,QAAI,WAAW,SAAS,UAAU,WAAW,mBAAmB;AAC9D,eAAS;AAAA,IACX;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA,OAAO,OAAO,MAAM;AAAA,IACpB,SAAS,WAAW,SAAS,WAAW,aAAa,WAAW;AAAA,EAClE;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// src/cart/clear-cart.tsx
|
|
2
|
+
import { Overlay, useOverlay } from "@zappie/foundations";
|
|
3
|
+
import { useCart } from "@zappie/sdk/react";
|
|
4
|
+
import { useThemeClass } from "./theme-class.js";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
function ClearCart() {
|
|
7
|
+
const rootClass = useThemeClass("z-base-cart z-base-confirm");
|
|
8
|
+
const cart = useCart();
|
|
9
|
+
const confirm = useOverlay("cart_clear", "confirm");
|
|
10
|
+
return /* @__PURE__ */ jsxs(Overlay.Root, { param: "cart_clear", id: "confirm", presentation: "dialog", children: [
|
|
11
|
+
/* @__PURE__ */ jsx(Overlay.Trigger, { className: "z-base-button-secondary", children: "Clear cart" }),
|
|
12
|
+
/* @__PURE__ */ jsxs(
|
|
13
|
+
Overlay.Content,
|
|
14
|
+
{
|
|
15
|
+
"data-zappie-theme": "base",
|
|
16
|
+
role: "alertdialog",
|
|
17
|
+
className: rootClass,
|
|
18
|
+
children: [
|
|
19
|
+
/* @__PURE__ */ jsx(Overlay.Title, { children: "Clear your cart?" }),
|
|
20
|
+
/* @__PURE__ */ jsx("p", { children: "This removes every item in your cart." }),
|
|
21
|
+
/* @__PURE__ */ jsxs("div", { className: "z-base-confirm-actions", children: [
|
|
22
|
+
/* @__PURE__ */ jsx(Overlay.Close, { className: "z-base-button-secondary", children: "Keep items" }),
|
|
23
|
+
/* @__PURE__ */ jsx(
|
|
24
|
+
"button",
|
|
25
|
+
{
|
|
26
|
+
type: "button",
|
|
27
|
+
className: "z-base-button",
|
|
28
|
+
onClick: () => {
|
|
29
|
+
cart.actions.clear();
|
|
30
|
+
confirm.close();
|
|
31
|
+
},
|
|
32
|
+
children: "Clear cart"
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
] })
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
] });
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
ClearCart
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=clear-cart.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/cart/clear-cart.tsx"],
|
|
4
|
+
"sourcesContent": ["import { Overlay, useOverlay } from \"@zappie/foundations\";\nimport { useCart } from \"@zappie/sdk/react\";\nimport { useThemeClass } from \"./theme-class\";\n/** Clearing removes every line, so it asks first, as the legacy cart does. */\nexport function ClearCart() {\n const rootClass = useThemeClass(\"z-base-cart z-base-confirm\");\n const cart = useCart();\n const confirm = useOverlay(\"cart_clear\", \"confirm\");\n return (\n <Overlay.Root param=\"cart_clear\" id=\"confirm\" presentation=\"dialog\">\n <Overlay.Trigger className=\"z-base-button-secondary\">\n Clear cart\n </Overlay.Trigger>\n <Overlay.Content\n data-zappie-theme=\"base\"\n role=\"alertdialog\"\n className={rootClass}\n >\n <Overlay.Title>Clear your cart?</Overlay.Title>\n <p>This removes every item in your cart.</p>\n <div className=\"z-base-confirm-actions\">\n <Overlay.Close className=\"z-base-button-secondary\">\n Keep items\n </Overlay.Close>\n <button\n type=\"button\"\n className=\"z-base-button\"\n onClick={() => {\n cart.actions.clear();\n confirm.close();\n }}\n >\n Clear cart\n </button>\n </div>\n </Overlay.Content>\n </Overlay.Root>\n );\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,SAAS,kBAAkB;AACpC,SAAS,eAAe;AACxB,SAAS,qBAAqB;AAQxB,cAUE,YAVF;AANC,SAAS,YAAY;AAC1B,QAAM,YAAY,cAAc,4BAA4B;AAC5D,QAAM,OAAO,QAAQ;AACrB,QAAM,UAAU,WAAW,cAAc,SAAS;AAClD,SACE,qBAAC,QAAQ,MAAR,EAAa,OAAM,cAAa,IAAG,WAAU,cAAa,UACzD;AAAA,wBAAC,QAAQ,SAAR,EAAgB,WAAU,2BAA0B,wBAErD;AAAA,IACA;AAAA,MAAC,QAAQ;AAAA,MAAR;AAAA,QACC,qBAAkB;AAAA,QAClB,MAAK;AAAA,QACL,WAAW;AAAA,QAEX;AAAA,8BAAC,QAAQ,OAAR,EAAc,8BAAgB;AAAA,UAC/B,oBAAC,OAAE,mDAAqC;AAAA,UACxC,qBAAC,SAAI,WAAU,0BACb;AAAA,gCAAC,QAAQ,OAAR,EAAc,WAAU,2BAA0B,wBAEnD;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,SAAS,MAAM;AACb,uBAAK,QAAQ,MAAM;AACnB,0BAAQ,MAAM;AAAA,gBAChB;AAAA,gBACD;AAAA;AAAA,YAED;AAAA,aACF;AAAA;AAAA;AAAA,IACF;AAAA,KACF;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// src/cart/customer-details.tsx
|
|
2
|
+
import { isContactPhoneValid } from "@zappie/sdk/checkout";
|
|
3
|
+
import { useId } from "react";
|
|
4
|
+
import { useCheckoutHandoff } from "../checkout.js";
|
|
5
|
+
import { useBaseHostBridge } from "../host-bridge.js";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
var FIELDS = [
|
|
8
|
+
{ field: "firstName", label: "First name", autoComplete: "given-name" },
|
|
9
|
+
{ field: "lastName", label: "Last name", autoComplete: "family-name" },
|
|
10
|
+
{ field: "email", label: "Email", autoComplete: "email" }
|
|
11
|
+
];
|
|
12
|
+
function CustomerDetails({
|
|
13
|
+
contactPhone
|
|
14
|
+
} = {}) {
|
|
15
|
+
const { customerDetails } = useBaseHostBridge();
|
|
16
|
+
const handoff = useCheckoutHandoff();
|
|
17
|
+
const showPhone = Boolean(
|
|
18
|
+
contactPhone && handoff.contactPhone && handoff.customer
|
|
19
|
+
);
|
|
20
|
+
const inputId = useId();
|
|
21
|
+
const hintId = useId();
|
|
22
|
+
const errorId = useId();
|
|
23
|
+
const invalid = Boolean(
|
|
24
|
+
contactPhone?.touched && !isContactPhoneValid(contactPhone.value)
|
|
25
|
+
);
|
|
26
|
+
if (!customerDetails && !showPhone) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return /* @__PURE__ */ jsxs("section", { className: "z-base-fulfilment-panel", "aria-label": "Your details", children: [
|
|
30
|
+
/* @__PURE__ */ jsx("h2", { children: "Your details" }),
|
|
31
|
+
customerDetails && FIELDS.filter(
|
|
32
|
+
({ field }) => field !== "email" || customerDetails.requiresEmail
|
|
33
|
+
).map(({ field, label, autoComplete }) => /* @__PURE__ */ jsxs("label", { className: "z-base-field", children: [
|
|
34
|
+
label,
|
|
35
|
+
/* @__PURE__ */ jsx(
|
|
36
|
+
"input",
|
|
37
|
+
{
|
|
38
|
+
type: field === "email" ? "email" : "text",
|
|
39
|
+
autoComplete,
|
|
40
|
+
required: field !== "lastName",
|
|
41
|
+
value: customerDetails.values[field],
|
|
42
|
+
onChange: (event) => customerDetails.update(field, event.target.value)
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
] }, field)),
|
|
46
|
+
showPhone && contactPhone && /* @__PURE__ */ jsxs("div", { className: "z-base-field", children: [
|
|
47
|
+
/* @__PURE__ */ jsx("label", { htmlFor: inputId, children: "Contact phone (optional)" }),
|
|
48
|
+
/* @__PURE__ */ jsx(
|
|
49
|
+
"input",
|
|
50
|
+
{
|
|
51
|
+
id: inputId,
|
|
52
|
+
type: "tel",
|
|
53
|
+
inputMode: "tel",
|
|
54
|
+
autoComplete: "tel",
|
|
55
|
+
value: contactPhone.value,
|
|
56
|
+
"aria-describedby": invalid ? `${hintId} ${errorId}` : hintId,
|
|
57
|
+
"aria-invalid": invalid,
|
|
58
|
+
onBlur: contactPhone.touch,
|
|
59
|
+
onChange: (event) => contactPhone.update(event.target.value)
|
|
60
|
+
}
|
|
61
|
+
),
|
|
62
|
+
/* @__PURE__ */ jsx("span", { id: hintId, children: handoff.customer?.phoneLast4 ? `Leave blank to use your Zappie number ending ${handoff.customer.phoneLast4}` : "Leave blank to use your Zappie number" }),
|
|
63
|
+
invalid && /* @__PURE__ */ jsx("span", { id: errorId, role: "alert", children: "Enter a phone number with 7 to 15 digits" })
|
|
64
|
+
] })
|
|
65
|
+
] });
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
CustomerDetails
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=customer-details.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/cart/customer-details.tsx"],
|
|
4
|
+
"sourcesContent": ["import { isContactPhoneValid } from \"@zappie/sdk/checkout\";\nimport { useId } from \"react\";\nimport { useCheckoutHandoff } from \"../checkout\";\nimport { useBaseHostBridge } from \"../host-bridge\";\nconst FIELDS = [\n { field: \"firstName\", label: \"First name\", autoComplete: \"given-name\" },\n { field: \"lastName\", label: \"Last name\", autoComplete: \"family-name\" },\n { field: \"email\", label: \"Email\", autoComplete: \"email\" },\n] as const;\n\nexport type ContactPhoneState = {\n value: string;\n touched: boolean;\n update(value: string): void;\n touch(): void;\n};\n\n/** The details a business requires before payment, such as a name for the order. */\nexport function CustomerDetails({\n contactPhone,\n}: {\n contactPhone?: ContactPhoneState;\n} = {}) {\n const { customerDetails } = useBaseHostBridge();\n const handoff = useCheckoutHandoff();\n const showPhone = Boolean(\n contactPhone && handoff.contactPhone && handoff.customer,\n );\n const inputId = useId();\n const hintId = useId();\n const errorId = useId();\n const invalid = Boolean(\n contactPhone?.touched && !isContactPhoneValid(contactPhone.value),\n );\n if (!customerDetails && !showPhone) {\n return null;\n }\n return (\n <section className=\"z-base-fulfilment-panel\" aria-label=\"Your details\">\n <h2>Your details</h2>\n {customerDetails &&\n FIELDS.filter(\n ({ field }) => field !== \"email\" || customerDetails.requiresEmail,\n ).map(({ field, label, autoComplete }) => (\n <label key={field} className=\"z-base-field\">\n {label}\n <input\n type={field === \"email\" ? \"email\" : \"text\"}\n autoComplete={autoComplete}\n required={field !== \"lastName\"}\n value={customerDetails.values[field]}\n onChange={(event) =>\n customerDetails.update(field, event.target.value)\n }\n />\n </label>\n ))}\n {showPhone && contactPhone && (\n <div className=\"z-base-field\">\n <label htmlFor={inputId}>Contact phone (optional)</label>\n <input\n id={inputId}\n type=\"tel\"\n inputMode=\"tel\"\n autoComplete=\"tel\"\n value={contactPhone.value}\n aria-describedby={invalid ? `${hintId} ${errorId}` : hintId}\n aria-invalid={invalid}\n onBlur={contactPhone.touch}\n onChange={(event) => contactPhone.update(event.target.value)}\n />\n <span id={hintId}>\n {handoff.customer?.phoneLast4\n ? `Leave blank to use your Zappie number ending ${handoff.customer.phoneLast4}`\n : \"Leave blank to use your Zappie number\"}\n </span>\n {invalid && (\n <span id={errorId} role=\"alert\">\n Enter a phone number with 7 to 15 digits\n </span>\n )}\n </div>\n )}\n </section>\n );\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,2BAA2B;AACpC,SAAS,aAAa;AACtB,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAoC5B,cAKI,YALJ;AAnCN,IAAM,SAAS;AAAA,EACb,EAAE,OAAO,aAAa,OAAO,cAAc,cAAc,aAAa;AAAA,EACtE,EAAE,OAAO,YAAY,OAAO,aAAa,cAAc,cAAc;AAAA,EACrE,EAAE,OAAO,SAAS,OAAO,SAAS,cAAc,QAAQ;AAC1D;AAUO,SAAS,gBAAgB;AAAA,EAC9B;AACF,IAEI,CAAC,GAAG;AACN,QAAM,EAAE,gBAAgB,IAAI,kBAAkB;AAC9C,QAAM,UAAU,mBAAmB;AACnC,QAAM,YAAY;AAAA,IAChB,gBAAgB,QAAQ,gBAAgB,QAAQ;AAAA,EAClD;AACA,QAAM,UAAU,MAAM;AACtB,QAAM,SAAS,MAAM;AACrB,QAAM,UAAU,MAAM;AACtB,QAAM,UAAU;AAAA,IACd,cAAc,WAAW,CAAC,oBAAoB,aAAa,KAAK;AAAA,EAClE;AACA,MAAI,CAAC,mBAAmB,CAAC,WAAW;AAClC,WAAO;AAAA,EACT;AACA,SACE,qBAAC,aAAQ,WAAU,2BAA0B,cAAW,gBACtD;AAAA,wBAAC,QAAG,0BAAY;AAAA,IACf,mBACC,OAAO;AAAA,MACL,CAAC,EAAE,MAAM,MAAM,UAAU,WAAW,gBAAgB;AAAA,IACtD,EAAE,IAAI,CAAC,EAAE,OAAO,OAAO,aAAa,MAClC,qBAAC,WAAkB,WAAU,gBAC1B;AAAA;AAAA,MACD;AAAA,QAAC;AAAA;AAAA,UACC,MAAM,UAAU,UAAU,UAAU;AAAA,UACpC;AAAA,UACA,UAAU,UAAU;AAAA,UACpB,OAAO,gBAAgB,OAAO,KAAK;AAAA,UACnC,UAAU,CAAC,UACT,gBAAgB,OAAO,OAAO,MAAM,OAAO,KAAK;AAAA;AAAA,MAEpD;AAAA,SAVU,KAWZ,CACD;AAAA,IACF,aAAa,gBACZ,qBAAC,SAAI,WAAU,gBACb;AAAA,0BAAC,WAAM,SAAS,SAAS,sCAAwB;AAAA,MACjD;AAAA,QAAC;AAAA;AAAA,UACC,IAAI;AAAA,UACJ,MAAK;AAAA,UACL,WAAU;AAAA,UACV,cAAa;AAAA,UACb,OAAO,aAAa;AAAA,UACpB,oBAAkB,UAAU,GAAG,MAAM,IAAI,OAAO,KAAK;AAAA,UACrD,gBAAc;AAAA,UACd,QAAQ,aAAa;AAAA,UACrB,UAAU,CAAC,UAAU,aAAa,OAAO,MAAM,OAAO,KAAK;AAAA;AAAA,MAC7D;AAAA,MACA,oBAAC,UAAK,IAAI,QACP,kBAAQ,UAAU,aACf,gDAAgD,QAAQ,SAAS,UAAU,KAC3E,yCACN;AAAA,MACC,WACC,oBAAC,UAAK,IAAI,SAAS,MAAK,SAAQ,sDAEhC;AAAA,OAEJ;AAAA,KAEJ;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// src/cart/delivery-distance.tsx
|
|
2
|
+
import { useBaseHostBridge } from "../host-bridge.js";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
function DeliveryDistance() {
|
|
5
|
+
const distance = useBaseHostBridge().deliveryDistance;
|
|
6
|
+
if (!distance?.message) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
return /* @__PURE__ */ jsx(
|
|
10
|
+
"p",
|
|
11
|
+
{
|
|
12
|
+
role: distance.status === "too_far" ? "alert" : "status",
|
|
13
|
+
className: "z-base-notice",
|
|
14
|
+
"data-severity": distance.status === "too_far" ? "error" : "warning",
|
|
15
|
+
children: distance.message
|
|
16
|
+
}
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
DeliveryDistance
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=delivery-distance.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/cart/delivery-distance.tsx"],
|
|
4
|
+
"sourcesContent": ["import { useBaseHostBridge } from \"../host-bridge\";\n\nexport function DeliveryDistance() {\n const distance = useBaseHostBridge().deliveryDistance;\n if (!distance?.message) {\n return null;\n }\n return (\n <p\n role={distance.status === \"too_far\" ? \"alert\" : \"status\"}\n className=\"z-base-notice\"\n data-severity={distance.status === \"too_far\" ? \"error\" : \"warning\"}\n >\n {distance.message}\n </p>\n );\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,yBAAyB;AAQ9B;AANG,SAAS,mBAAmB;AACjC,QAAM,WAAW,kBAAkB,EAAE;AACrC,MAAI,CAAC,UAAU,SAAS;AACtB,WAAO;AAAA,EACT;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAM,SAAS,WAAW,YAAY,UAAU;AAAA,MAChD,WAAU;AAAA,MACV,iBAAe,SAAS,WAAW,YAAY,UAAU;AAAA,MAExD,mBAAS;AAAA;AAAA,EACZ;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// src/cart/empty-cart.tsx
|
|
2
|
+
import { Cart, Overlay } from "@zappie/foundations";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
function EmptyCart() {
|
|
5
|
+
return /* @__PURE__ */ jsxs(Cart.Empty, { className: "z-base-cart-empty", children: [
|
|
6
|
+
/* @__PURE__ */ jsx("h2", { children: "Your cart is empty" }),
|
|
7
|
+
/* @__PURE__ */ jsx("p", { children: "Add something from the menu to get started." }),
|
|
8
|
+
/* @__PURE__ */ jsx(Overlay.Close, { className: "z-base-button", children: "Browse menu" })
|
|
9
|
+
] });
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
EmptyCart
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=empty-cart.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/cart/empty-cart.tsx"],
|
|
4
|
+
"sourcesContent": ["import { Cart, Overlay } from \"@zappie/foundations\";\nexport function EmptyCart() {\n return (\n <Cart.Empty className=\"z-base-cart-empty\">\n <h2>Your cart is empty</h2>\n <p>Add something from the menu to get started.</p>\n <Overlay.Close className=\"z-base-button\">Browse menu</Overlay.Close>\n </Cart.Empty>\n );\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,MAAM,eAAe;AAG1B,SACE,KADF;AAFG,SAAS,YAAY;AAC1B,SACE,qBAAC,KAAK,OAAL,EAAW,WAAU,qBACpB;AAAA,wBAAC,QAAG,gCAAkB;AAAA,IACtB,oBAAC,OAAE,yDAA2C;AAAA,IAC9C,oBAAC,QAAQ,OAAR,EAAc,WAAU,iBAAgB,yBAAW;AAAA,KACtD;AAEJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// src/cart/fulfilment-panel.tsx
|
|
2
|
+
import { Branch, Fulfilment } from "@zappie/foundations";
|
|
3
|
+
import { useCart, useStore } from "@zappie/sdk/react";
|
|
4
|
+
import { Fragment, useState } from "react";
|
|
5
|
+
import { useAddressLookup } from "../address.js";
|
|
6
|
+
import { useBaseHostBridge } from "../host-bridge.js";
|
|
7
|
+
import { AddressSheet } from "./address-sheet.js";
|
|
8
|
+
import { RegionPicker } from "./region-picker.js";
|
|
9
|
+
import { ScheduleSheet } from "./schedule-sheet.js";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
function FulfilmentPanel() {
|
|
12
|
+
const cart = useCart();
|
|
13
|
+
const store = useStore();
|
|
14
|
+
const bridge = useBaseHostBridge();
|
|
15
|
+
const lookup = useAddressLookup();
|
|
16
|
+
const [error, setError] = useState(null);
|
|
17
|
+
const branch = store.data?.branches.find(
|
|
18
|
+
(branch2) => branch2.id === cart.branchId
|
|
19
|
+
);
|
|
20
|
+
const mode = bridge.fulfilmentMode ?? cart.fulfilment?.type ?? "delivery";
|
|
21
|
+
if (!branch) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const scheduledFor = cart.fulfilment && "scheduledFor" in cart.fulfilment ? cart.fulfilment.scheduledFor : void 0;
|
|
25
|
+
return /* @__PURE__ */ jsxs("section", { className: "z-base-fulfilment-panel", "aria-label": "Fulfilment", children: [
|
|
26
|
+
/* @__PURE__ */ jsx("h2", { children: "Fulfilment" }),
|
|
27
|
+
/* @__PURE__ */ jsx(Fulfilment.Switch, { "aria-label": "Order fulfilment", children: ({ options }) => /* @__PURE__ */ jsx("div", { className: "z-base-line-actions", children: options.filter((option) => option !== "dine_in").map((option) => /* @__PURE__ */ jsx(
|
|
28
|
+
"button",
|
|
29
|
+
{
|
|
30
|
+
type: "button",
|
|
31
|
+
"aria-pressed": mode === option,
|
|
32
|
+
className: "z-base-button-secondary",
|
|
33
|
+
onClick: () => {
|
|
34
|
+
setError(null);
|
|
35
|
+
try {
|
|
36
|
+
if (!bridge.setFulfilmentMode(
|
|
37
|
+
option
|
|
38
|
+
)) {
|
|
39
|
+
setError(
|
|
40
|
+
"This menu does not allow that fulfilment option."
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
} catch (failure) {
|
|
44
|
+
setError(
|
|
45
|
+
failure instanceof Error ? failure.message : "Unable to change fulfilment"
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
children: option === "pickup" ? "Pickup" : "Delivery"
|
|
50
|
+
},
|
|
51
|
+
option
|
|
52
|
+
)) }) }),
|
|
53
|
+
/* @__PURE__ */ jsx(Branch.Picker, { branches: [branch], children: ({ selected }) => /* @__PURE__ */ jsxs("p", { children: [
|
|
54
|
+
mode === "pickup" ? "Collect from" : "Ordering from",
|
|
55
|
+
" ",
|
|
56
|
+
selected?.name,
|
|
57
|
+
selected?.address ? ` \u2014 ${selected.address}` : ""
|
|
58
|
+
] }) }),
|
|
59
|
+
error && /* @__PURE__ */ jsx("p", { role: "alert", children: error }),
|
|
60
|
+
mode === "delivery" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
61
|
+
cart.fulfilment?.type === "delivery" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
62
|
+
/* @__PURE__ */ jsx("p", { children: cart.fulfilment.address.line1 }),
|
|
63
|
+
lookup.Map && /* @__PURE__ */ jsx(lookup.Map, { address: cart.fulfilment.address })
|
|
64
|
+
] }),
|
|
65
|
+
/* @__PURE__ */ jsx(AddressSheet, {}),
|
|
66
|
+
/* @__PURE__ */ jsx(RegionPicker, {})
|
|
67
|
+
] }),
|
|
68
|
+
scheduledFor && /* @__PURE__ */ jsxs("p", { children: [
|
|
69
|
+
"Scheduled for",
|
|
70
|
+
" ",
|
|
71
|
+
new Intl.DateTimeFormat("en", {
|
|
72
|
+
dateStyle: "medium",
|
|
73
|
+
timeStyle: "short",
|
|
74
|
+
timeZone: branch.timezone ?? store.data?.timezone
|
|
75
|
+
}).format(new Date(scheduledFor))
|
|
76
|
+
] }),
|
|
77
|
+
branch.fulfilment.scheduling && /* @__PURE__ */ jsx(ScheduleSheet, { branch })
|
|
78
|
+
] });
|
|
79
|
+
}
|
|
80
|
+
export {
|
|
81
|
+
FulfilmentPanel
|
|
82
|
+
};
|
|
83
|
+
//# sourceMappingURL=fulfilment-panel.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/cart/fulfilment-panel.tsx"],
|
|
4
|
+
"sourcesContent": ["import { Branch, Fulfilment } from \"@zappie/foundations\";\nimport { useCart, useStore } from \"@zappie/sdk/react\";\nimport { Fragment, useState } from \"react\";\nimport { useAddressLookup } from \"../address\";\nimport { useBaseHostBridge } from \"../host-bridge\";\nimport { AddressSheet } from \"./address-sheet\";\nimport { RegionPicker } from \"./region-picker\";\nimport { ScheduleSheet } from \"./schedule-sheet\";\nexport function FulfilmentPanel() {\n const cart = useCart();\n const store = useStore();\n const bridge = useBaseHostBridge();\n const lookup = useAddressLookup();\n const [error, setError] = useState<string | null>(null);\n const branch = store.data?.branches.find(\n (branch) => branch.id === cart.branchId,\n );\n const mode = bridge.fulfilmentMode ?? cart.fulfilment?.type ?? \"delivery\";\n if (!branch) {\n return null;\n }\n const scheduledFor =\n cart.fulfilment && \"scheduledFor\" in cart.fulfilment\n ? cart.fulfilment.scheduledFor\n : undefined;\n return (\n <section className=\"z-base-fulfilment-panel\" aria-label=\"Fulfilment\">\n <h2>Fulfilment</h2>\n <Fulfilment.Switch aria-label=\"Order fulfilment\">\n {({ options }) => (\n <div className=\"z-base-line-actions\">\n {options\n .filter((option) => option !== \"dine_in\")\n .map((option) => (\n <button\n type=\"button\"\n key={option}\n aria-pressed={mode === option}\n className=\"z-base-button-secondary\"\n onClick={() => {\n setError(null);\n try {\n if (\n !bridge.setFulfilmentMode(\n option as \"delivery\" | \"pickup\",\n )\n ) {\n setError(\n \"This menu does not allow that fulfilment option.\",\n );\n }\n } catch (failure) {\n setError(\n failure instanceof Error\n ? failure.message\n : \"Unable to change fulfilment\",\n );\n }\n }}\n >\n {option === \"pickup\" ? \"Pickup\" : \"Delivery\"}\n </button>\n ))}\n </div>\n )}\n </Fulfilment.Switch>\n <Branch.Picker branches={[branch]}>\n {({ selected }) => (\n <p>\n {mode === \"pickup\" ? \"Collect from\" : \"Ordering from\"}{\" \"}\n {selected?.name}\n {selected?.address ? ` \u2014 ${selected.address}` : \"\"}\n </p>\n )}\n </Branch.Picker>\n {error && <p role=\"alert\">{error}</p>}\n {mode === \"delivery\" && (\n <Fragment>\n {cart.fulfilment?.type === \"delivery\" && (\n <Fragment>\n <p>{cart.fulfilment.address.line1}</p>\n {lookup.Map && <lookup.Map address={cart.fulfilment.address} />}\n </Fragment>\n )}\n <AddressSheet />\n <RegionPicker />\n </Fragment>\n )}\n {scheduledFor && (\n <p>\n Scheduled for{\" \"}\n {new Intl.DateTimeFormat(\"en\", {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n timeZone: branch.timezone ?? store.data?.timezone,\n }).format(new Date(scheduledFor))}\n </p>\n )}\n {branch.fulfilment.scheduling && <ScheduleSheet branch={branch} />}\n </section>\n );\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,QAAQ,kBAAkB;AACnC,SAAS,SAAS,gBAAgB;AAClC,SAAS,UAAU,gBAAgB;AACnC,SAAS,wBAAwB;AACjC,SAAS,yBAAyB;AAClC,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAoBxB,cAyCI,YAzCJ;AAnBC,SAAS,kBAAkB;AAChC,QAAM,OAAO,QAAQ;AACrB,QAAM,QAAQ,SAAS;AACvB,QAAM,SAAS,kBAAkB;AACjC,QAAM,SAAS,iBAAiB;AAChC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AACtD,QAAM,SAAS,MAAM,MAAM,SAAS;AAAA,IAClC,CAACA,YAAWA,QAAO,OAAO,KAAK;AAAA,EACjC;AACA,QAAM,OAAO,OAAO,kBAAkB,KAAK,YAAY,QAAQ;AAC/D,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,QAAM,eACJ,KAAK,cAAc,kBAAkB,KAAK,aACtC,KAAK,WAAW,eAChB;AACN,SACE,qBAAC,aAAQ,WAAU,2BAA0B,cAAW,cACtD;AAAA,wBAAC,QAAG,wBAAU;AAAA,IACd,oBAAC,WAAW,QAAX,EAAkB,cAAW,oBAC3B,WAAC,EAAE,QAAQ,MACV,oBAAC,SAAI,WAAU,uBACZ,kBACE,OAAO,CAAC,WAAW,WAAW,SAAS,EACvC,IAAI,CAAC,WACJ;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QAEL,gBAAc,SAAS;AAAA,QACvB,WAAU;AAAA,QACV,SAAS,MAAM;AACb,mBAAS,IAAI;AACb,cAAI;AACF,gBACE,CAAC,OAAO;AAAA,cACN;AAAA,YACF,GACA;AACA;AAAA,gBACE;AAAA,cACF;AAAA,YACF;AAAA,UACF,SAAS,SAAS;AAChB;AAAA,cACE,mBAAmB,QACf,QAAQ,UACR;AAAA,YACN;AAAA,UACF;AAAA,QACF;AAAA,QAEC,qBAAW,WAAW,WAAW;AAAA;AAAA,MAxB7B;AAAA,IAyBP,CACD,GACL,GAEJ;AAAA,IACA,oBAAC,OAAO,QAAP,EAAc,UAAU,CAAC,MAAM,GAC7B,WAAC,EAAE,SAAS,MACX,qBAAC,OACE;AAAA,eAAS,WAAW,iBAAiB;AAAA,MAAiB;AAAA,MACtD,UAAU;AAAA,MACV,UAAU,UAAU,WAAM,SAAS,OAAO,KAAK;AAAA,OAClD,GAEJ;AAAA,IACC,SAAS,oBAAC,OAAE,MAAK,SAAS,iBAAM;AAAA,IAChC,SAAS,cACR,qBAAC,YACE;AAAA,WAAK,YAAY,SAAS,cACzB,qBAAC,YACC;AAAA,4BAAC,OAAG,eAAK,WAAW,QAAQ,OAAM;AAAA,QACjC,OAAO,OAAO,oBAAC,OAAO,KAAP,EAAW,SAAS,KAAK,WAAW,SAAS;AAAA,SAC/D;AAAA,MAEF,oBAAC,gBAAa;AAAA,MACd,oBAAC,gBAAa;AAAA,OAChB;AAAA,IAED,gBACC,qBAAC,OAAE;AAAA;AAAA,MACa;AAAA,MACb,IAAI,KAAK,eAAe,MAAM;AAAA,QAC7B,WAAW;AAAA,QACX,WAAW;AAAA,QACX,UAAU,OAAO,YAAY,MAAM,MAAM;AAAA,MAC3C,CAAC,EAAE,OAAO,IAAI,KAAK,YAAY,CAAC;AAAA,OAClC;AAAA,IAED,OAAO,WAAW,cAAc,oBAAC,iBAAc,QAAgB;AAAA,KAClE;AAEJ;",
|
|
6
|
+
"names": ["branch"]
|
|
7
|
+
}
|