@zorgo/next 1.1.7 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/cli.js +344 -1
  2. package/dist/cli.js.map +1 -0
  3. package/dist/cli.mjs +344 -1
  4. package/dist/cli.mjs.map +1 -0
  5. package/dist/components.d.mts +315 -87
  6. package/dist/components.d.ts +315 -87
  7. package/dist/components.js +1216 -820
  8. package/dist/components.js.map +1 -1
  9. package/dist/components.mjs +1195 -832
  10. package/dist/components.mjs.map +1 -1
  11. package/dist/images.d.mts +36 -0
  12. package/dist/images.d.ts +36 -0
  13. package/dist/images.js +62 -0
  14. package/dist/images.js.map +1 -0
  15. package/dist/images.mjs +32 -0
  16. package/dist/images.mjs.map +1 -0
  17. package/dist/index.d.mts +175 -6
  18. package/dist/index.d.ts +175 -6
  19. package/dist/index.js +162 -1
  20. package/dist/index.js.map +1 -0
  21. package/dist/index.mjs +162 -1
  22. package/dist/index.mjs.map +1 -0
  23. package/dist/item-page.d.mts +151 -0
  24. package/dist/item-page.d.ts +151 -0
  25. package/dist/item-page.js +166 -0
  26. package/dist/item-page.js.map +1 -0
  27. package/dist/item-page.mjs +129 -0
  28. package/dist/item-page.mjs.map +1 -0
  29. package/dist/seo.d.mts +31 -1
  30. package/dist/seo.d.ts +31 -1
  31. package/dist/server.js +541 -1
  32. package/dist/server.js.map +1 -0
  33. package/dist/server.mjs +504 -1
  34. package/dist/server.mjs.map +1 -0
  35. package/dist/slugs.js.map +1 -1
  36. package/dist/slugs.mjs.map +1 -1
  37. package/dist/tree/app/components/ClientItemForm.tsx +7 -0
  38. package/dist/tree/app/components/Header.tsx +3 -0
  39. package/dist/tree/app/components/ModalRegistry.tsx +3 -2
  40. package/dist/tree/app/components/index.ts +2 -1
  41. package/dist/tree/app/globals.css.gen.ts +1 -0
  42. package/dist/tree/app/menu/[slug]/page.tsx +16 -48
  43. package/dist/tree/gitignore +1 -0
  44. package/dist/tree/image-loader.ts +4 -0
  45. package/dist/tree/next.config.ts +12 -0
  46. package/package.json +11 -1
  47. package/dist/cli.d.mts +0 -9
  48. package/dist/cli.d.ts +0 -9
  49. package/dist/tree/app/menu/[slug]/ItemCustomizationClient.tsx +0 -18
@@ -28,32 +28,59 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  ));
29
29
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
30
 
31
- // src/components/index.ts
32
- var components_exports = {};
33
- __export(components_exports, {
31
+ // src/components/client/index.ts
32
+ var client_exports = {};
33
+ __export(client_exports, {
34
34
  ACCORDION_MENU_DEFAULT_ITEM_CLASSES: () => ACCORDION_MENU_DEFAULT_ITEM_CLASSES,
35
35
  AccordionMenu: () => AccordionMenu,
36
36
  BREADCRUMBS_DEFAULT_ITEM_CLASSES: () => BREADCRUMBS_DEFAULT_ITEM_CLASSES,
37
37
  Breadcrumbs: () => Breadcrumbs,
38
38
  CHECKOUT_FORM_DEFAULT_ITEM_CLASSES: () => CHECKOUT_FORM_DEFAULT_ITEM_CLASSES,
39
+ CHECKOUT_FORM_SLOTS: () => CHECKOUT_FORM_SLOTS,
40
+ CLIENT_ITEM_FORM_DEFAULT_ITEM_CLASSES: () => CLIENT_ITEM_FORM_DEFAULT_ITEM_CLASSES,
41
+ CLIENT_ITEM_FORM_SLOTS: () => CLIENT_ITEM_FORM_SLOTS,
39
42
  CheckoutForm: () => CheckoutForm,
43
+ CheckoutShell: () => CheckoutShell,
44
+ CheckoutSteps: () => CheckoutSteps,
45
+ ClientItemForm: () => ClientItemForm,
46
+ CommentsSection: () => CommentsSection,
47
+ ComponentsSection: () => ComponentsSection,
48
+ ConsentFields: () => ConsentFields,
49
+ ContactFields: () => ContactFields,
40
50
  CookieConsent: () => CookieConsent,
51
+ DetailsStep: () => DetailsStep,
41
52
  FIND_LOCATION_DEFAULT_ITEM_CLASSES: () => FIND_LOCATION_DEFAULT_ITEM_CLASSES,
42
53
  FindLocation: () => FindLocation,
43
54
  GRID_MENU_DEFAULT_ITEM_CLASSES: () => GRID_MENU_DEFAULT_ITEM_CLASSES,
44
55
  GridMenu: () => GridMenu,
45
- ITEM_CUSTOMIZATION_FORM_DEFAULT_ITEM_CLASSES: () => ITEM_CUSTOMIZATION_FORM_DEFAULT_ITEM_CLASSES,
46
- ItemCustomizationForm: () => ItemCustomizationForm,
56
+ ITEM_CUSTOMIZATION_FORM_DEFAULT_ITEM_CLASSES: () => CLIENT_ITEM_FORM_DEFAULT_ITEM_CLASSES,
57
+ ItemCustomizationClient: () => ClientItemForm,
58
+ ItemCustomizationForm: () => ClientItemForm,
59
+ OptionButton: () => OptionButton,
60
+ OrderLine: () => OrderLine,
61
+ OrderLines: () => OrderLines,
62
+ OrderTotals: () => OrderTotals,
63
+ PaymentStep: () => PaymentStep,
64
+ PortionPicker: () => PortionPicker,
65
+ PortionSection: () => PortionSection,
66
+ PromoCode: () => PromoCode,
67
+ QuantitySection: () => QuantitySection,
68
+ RuleSection: () => RuleSection,
69
+ StatusPanel: () => StatusPanel,
70
+ SubmitButton: () => SubmitButton,
71
+ VariantSection: () => VariantSection,
47
72
  mergeAccordionMenuItemClasses: () => mergeAccordionMenuItemClasses,
48
73
  mergeBreadcrumbsItemClasses: () => mergeBreadcrumbsItemClasses,
49
74
  mergeCheckoutFormItemClasses: () => mergeCheckoutFormItemClasses,
75
+ mergeClientItemFormItemClasses: () => mergeClientItemFormItemClasses,
50
76
  mergeFindLocationItemClasses: () => mergeFindLocationItemClasses,
51
77
  mergeGridMenuItemClasses: () => mergeGridMenuItemClasses,
52
- mergeItemCustomizationFormItemClasses: () => mergeItemCustomizationFormItemClasses
78
+ mergeItemCustomizationFormItemClasses: () => mergeClientItemFormItemClasses,
79
+ money: () => money3
53
80
  });
54
- module.exports = __toCommonJS(components_exports);
81
+ module.exports = __toCommonJS(client_exports);
55
82
 
56
- // src/components/CookieConsent.tsx
83
+ // src/components/client/CookieConsent.tsx
57
84
  var import_react12 = require("react");
58
85
 
59
86
  // ../../node_modules/@headlessui/react/dist/utils/env.js
@@ -548,7 +575,7 @@ var me = Y(Fe);
548
575
  var Oe = Y(Le);
549
576
  var Ke = Object.assign(X, { Child: Oe, Root: X });
550
577
 
551
- // src/components/CookieConsent.tsx
578
+ // src/components/client/CookieConsent.tsx
552
579
  var import_hooks = require("@zorgo/next");
553
580
  var import_jsx_runtime = require("react/jsx-runtime");
554
581
  function CookieConsent() {
@@ -603,47 +630,21 @@ function CookieConsent() {
603
630
  );
604
631
  }
605
632
 
606
- // src/components/Breadcrumbs.tsx
633
+ // src/components/client/GridMenu.tsx
634
+ var import_image = __toESM(require("next/image"));
607
635
  var import_link = __toESM(require("next/link"));
608
- var import_lucide_react = require("lucide-react");
636
+ var import_menuSlugs = require("@zorgo/next/slugs");
637
+ var import_menuUtils2 = require("@zorgo/next/images");
638
+
639
+ // src/images.ts
640
+ var import_menuUtils = require("@zorgo/next/images");
641
+ var ITEM_IMAGE_PREFIX = "/images/items/";
642
+
643
+ // src/components/client/GridMenu.tsx
609
644
  var import_jsx_runtime2 = require("react/jsx-runtime");
610
645
  function cn(...parts) {
611
646
  return parts.filter(Boolean).join(" ");
612
647
  }
613
- var BREADCRUMBS_DEFAULT_ITEM_CLASSES = {
614
- baseContainer: "flex flex-row items-center gap-2 text-sm opacity-75",
615
- crumbLink: "hover:opacity-75 transition-all duration-300 underline-offset-2 hover:underline",
616
- crumbText: "font-semibold",
617
- separator: "h-4 w-4 opacity-50"
618
- };
619
- function mergeBreadcrumbsItemClasses(overrides) {
620
- const d3 = BREADCRUMBS_DEFAULT_ITEM_CLASSES;
621
- return {
622
- baseContainer: cn(d3.baseContainer, overrides?.baseContainer),
623
- crumbLink: cn(d3.crumbLink, overrides?.crumbLink),
624
- crumbText: cn(d3.crumbText, overrides?.crumbText),
625
- separator: cn(d3.separator, overrides?.separator)
626
- };
627
- }
628
- function Breadcrumbs({
629
- items,
630
- itemClasses
631
- }) {
632
- const slots = mergeBreadcrumbsItemClasses(itemClasses);
633
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("nav", { "aria-label": "Breadcrumb", className: slots.baseContainer, children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "flex flex-row items-center gap-2", children: [
634
- index > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.ChevronRight, { className: slots.separator }),
635
- item.href ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_link.default, { href: item.href, className: slots.crumbLink, children: item.label }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: slots.crumbText, children: item.label })
636
- ] }, `${item.label}-${index}`)) });
637
- }
638
-
639
- // src/components/GridMenu.tsx
640
- var import_link2 = __toESM(require("next/link"));
641
- var import_hooks2 = require("@zorgo/next");
642
- var import_menuSlugs = require("@zorgo/next/slugs");
643
- var import_jsx_runtime3 = require("react/jsx-runtime");
644
- function cn2(...parts) {
645
- return parts.filter(Boolean).join(" ");
646
- }
647
648
  function money(cents) {
648
649
  return `$${(cents / 100).toFixed(2)}`;
649
650
  }
@@ -662,25 +663,25 @@ var GRID_MENU_DEFAULT_ITEM_CLASSES = {
662
663
  function mergeGridMenuItemClasses(overrides) {
663
664
  const d3 = GRID_MENU_DEFAULT_ITEM_CLASSES;
664
665
  return {
665
- baseContainer: cn2(d3.baseContainer, overrides?.baseContainer),
666
- categoryContainer: cn2(
666
+ baseContainer: cn(d3.baseContainer, overrides?.baseContainer),
667
+ categoryContainer: cn(
667
668
  d3.categoryContainer,
668
669
  overrides?.categoryContainer
669
670
  ),
670
- categoryTitle: cn2(d3.categoryTitle, overrides?.categoryTitle),
671
- itemCardContainer: cn2(
671
+ categoryTitle: cn(d3.categoryTitle, overrides?.categoryTitle),
672
+ itemCardContainer: cn(
672
673
  d3.itemCardContainer,
673
674
  overrides?.itemCardContainer
674
675
  ),
675
- itemCard: cn2(d3.itemCard, overrides?.itemCard),
676
- itemCardImage: cn2(d3.itemCardImage, overrides?.itemCardImage),
677
- itemCardTextContainer: cn2(
676
+ itemCard: cn(d3.itemCard, overrides?.itemCard),
677
+ itemCardImage: cn(d3.itemCardImage, overrides?.itemCardImage),
678
+ itemCardTextContainer: cn(
678
679
  d3.itemCardTextContainer,
679
680
  overrides?.itemCardTextContainer
680
681
  ),
681
- itemCardName: cn2(d3.itemCardName, overrides?.itemCardName),
682
- itemCardPrice: cn2(d3.itemCardPrice, overrides?.itemCardPrice),
683
- itemCardOldPrice: cn2(d3.itemCardOldPrice, overrides?.itemCardOldPrice)
682
+ itemCardName: cn(d3.itemCardName, overrides?.itemCardName),
683
+ itemCardPrice: cn(d3.itemCardPrice, overrides?.itemCardPrice),
684
+ itemCardOldPrice: cn(d3.itemCardOldPrice, overrides?.itemCardOldPrice)
684
685
  };
685
686
  }
686
687
  function GridMenu({
@@ -688,26 +689,25 @@ function GridMenu({
688
689
  categories,
689
690
  itemClasses
690
691
  }) {
691
- const { getItemImageUrl } = (0, import_hooks2.useMenu)();
692
692
  const slots = mergeGridMenuItemClasses(itemClasses);
693
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: slots.baseContainer, children: categories.map((category) => {
693
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: slots.baseContainer, children: categories.map((category) => {
694
694
  const itemsInCategory = items.filter(
695
695
  (item) => item.category_id === category.category_id
696
696
  );
697
697
  if (itemsInCategory.length === 0) {
698
698
  return null;
699
699
  }
700
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
700
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
701
701
  "div",
702
702
  {
703
703
  className: slots.categoryContainer,
704
704
  children: [
705
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h1", { className: slots.categoryTitle, children: category.name }),
706
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: slots.itemCardContainer, children: itemsInCategory.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
705
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { className: slots.categoryTitle, children: category.name }),
706
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: slots.itemCardContainer, children: itemsInCategory.map((item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
707
707
  ItemCard,
708
708
  {
709
709
  item,
710
- imageUrl: getItemImageUrl(item.image_path),
710
+ imageUrl: (0, import_menuUtils2.menuImageUrl)(item.images?.[0]),
711
711
  slots
712
712
  },
713
713
  item.base_item_id
@@ -725,40 +725,43 @@ function ItemCard({
725
725
  }) {
726
726
  const variant = item.variants[0];
727
727
  const onSale = variant?.display_price != null && variant.display_price < variant.price;
728
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
729
- import_link2.default,
728
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
729
+ import_link.default,
730
730
  {
731
731
  href: `/menu/${(0, import_menuSlugs.menuItemSlug)(item.name, item.base_item_id)}`,
732
732
  className: slots.itemCard,
733
733
  children: [
734
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: slots.itemCardImage, children: imageUrl && // eslint-disable-next-line @next/next/no-img-element
735
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
736
- "img",
734
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: slots.itemCardImage, children: imageUrl && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
735
+ import_image.default,
737
736
  {
738
737
  src: imageUrl,
739
738
  alt: item.name,
739
+ width: 640,
740
+ height: 640,
741
+ unoptimized: !imageUrl.startsWith(ITEM_IMAGE_PREFIX),
742
+ sizes: "(min-width: 1024px) 320px, (min-width: 640px) 50vw, 100vw",
740
743
  className: "w-full h-full object-cover"
741
744
  }
742
745
  ) }),
743
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: slots.itemCardTextContainer, children: [
744
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: slots.itemCardName, children: item.name }),
745
- variant && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: onSale ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
746
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: slots.itemCardPrice, children: money(variant.display_price) }),
747
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: slots.itemCardOldPrice, children: money(variant.price) })
748
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: slots.itemCardPrice, children: money(variant.price) }) })
746
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: slots.itemCardTextContainer, children: [
747
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: slots.itemCardName, children: item.name }),
748
+ variant && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: onSale ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
749
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: slots.itemCardPrice, children: money(variant.display_price) }),
750
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: slots.itemCardOldPrice, children: money(variant.price) })
751
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: slots.itemCardPrice, children: money(variant.price) }) })
749
752
  ] })
750
753
  ]
751
754
  }
752
755
  );
753
756
  }
754
757
 
755
- // src/components/AccordionMenu.tsx
756
- var import_link3 = __toESM(require("next/link"));
758
+ // src/components/client/AccordionMenu.tsx
759
+ var import_link2 = __toESM(require("next/link"));
757
760
  var import_react14 = require("react");
758
- var import_lucide_react2 = require("lucide-react");
761
+ var import_lucide_react = require("lucide-react");
759
762
  var import_menuSlugs2 = require("@zorgo/next/slugs");
760
- var import_jsx_runtime4 = require("react/jsx-runtime");
761
- function cn3(...parts) {
763
+ var import_jsx_runtime3 = require("react/jsx-runtime");
764
+ function cn2(...parts) {
762
765
  return parts.filter(Boolean).join(" ");
763
766
  }
764
767
  function money2(cents) {
@@ -782,34 +785,34 @@ var ACCORDION_MENU_DEFAULT_ITEM_CLASSES = {
782
785
  function mergeAccordionMenuItemClasses(overrides) {
783
786
  const d3 = ACCORDION_MENU_DEFAULT_ITEM_CLASSES;
784
787
  return {
785
- baseContainer: cn3(d3.baseContainer, overrides?.baseContainer),
786
- categoryContainer: cn3(
788
+ baseContainer: cn2(d3.baseContainer, overrides?.baseContainer),
789
+ categoryContainer: cn2(
787
790
  d3.categoryContainer,
788
791
  overrides?.categoryContainer
789
792
  ),
790
- categoryTrigger: cn3(d3.categoryTrigger, overrides?.categoryTrigger),
791
- categoryTitle: cn3(d3.categoryTitle, overrides?.categoryTitle),
792
- categoryIndicator: cn3(
793
+ categoryTrigger: cn2(d3.categoryTrigger, overrides?.categoryTrigger),
794
+ categoryTitle: cn2(d3.categoryTitle, overrides?.categoryTitle),
795
+ categoryIndicator: cn2(
793
796
  d3.categoryIndicator,
794
797
  overrides?.categoryIndicator
795
798
  ),
796
- itemsContainer: cn3(d3.itemsContainer, overrides?.itemsContainer),
797
- itemCard: cn3(d3.itemCard, overrides?.itemCard),
798
- itemCardTextContainer: cn3(
799
+ itemsContainer: cn2(d3.itemsContainer, overrides?.itemsContainer),
800
+ itemCard: cn2(d3.itemCard, overrides?.itemCard),
801
+ itemCardTextContainer: cn2(
799
802
  d3.itemCardTextContainer,
800
803
  overrides?.itemCardTextContainer
801
804
  ),
802
- itemCardName: cn3(d3.itemCardName, overrides?.itemCardName),
803
- itemCardDescription: cn3(
805
+ itemCardName: cn2(d3.itemCardName, overrides?.itemCardName),
806
+ itemCardDescription: cn2(
804
807
  d3.itemCardDescription,
805
808
  overrides?.itemCardDescription
806
809
  ),
807
- itemCardPriceContainer: cn3(
810
+ itemCardPriceContainer: cn2(
808
811
  d3.itemCardPriceContainer,
809
812
  overrides?.itemCardPriceContainer
810
813
  ),
811
- itemCardPrice: cn3(d3.itemCardPrice, overrides?.itemCardPrice),
812
- itemCardOldPrice: cn3(d3.itemCardOldPrice, overrides?.itemCardOldPrice)
814
+ itemCardPrice: cn2(d3.itemCardPrice, overrides?.itemCardPrice),
815
+ itemCardOldPrice: cn2(d3.itemCardOldPrice, overrides?.itemCardOldPrice)
813
816
  };
814
817
  }
815
818
  function AccordionMenu({
@@ -818,14 +821,14 @@ function AccordionMenu({
818
821
  itemClasses
819
822
  }) {
820
823
  const slots = mergeAccordionMenuItemClasses(itemClasses);
821
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: slots.baseContainer, children: categories.map((category) => {
824
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: slots.baseContainer, children: categories.map((category) => {
822
825
  const itemsInCategory = items.filter(
823
826
  (item) => item.category_id === category.category_id
824
827
  );
825
828
  if (itemsInCategory.length === 0) {
826
829
  return null;
827
830
  }
828
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
831
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
829
832
  MenuCategory,
830
833
  {
831
834
  category,
@@ -842,27 +845,27 @@ function MenuCategory({
842
845
  slots
843
846
  }) {
844
847
  const [isExpanded, setIsExpanded] = (0, import_react14.useState)(false);
845
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: slots.categoryContainer, children: [
846
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
848
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: slots.categoryContainer, children: [
849
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
847
850
  "button",
848
851
  {
849
852
  type: "button",
850
853
  onClick: () => setIsExpanded(!isExpanded),
851
854
  className: slots.categoryTrigger,
852
855
  children: [
853
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: slots.categoryTitle, children: category.name }),
854
- isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.ChevronUp, { className: slots.categoryIndicator }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.ChevronDown, { className: slots.categoryIndicator })
856
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { className: slots.categoryTitle, children: category.name }),
857
+ isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.ChevronUp, { className: slots.categoryIndicator }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.ChevronDown, { className: slots.categoryIndicator })
855
858
  ]
856
859
  }
857
860
  ),
858
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
861
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
859
862
  "div",
860
863
  {
861
- className: cn3(
864
+ className: cn2(
862
865
  isExpanded ? "flex" : "hidden",
863
866
  slots.itemsContainer
864
867
  ),
865
- children: itemsInCategory.map((item) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
868
+ children: itemsInCategory.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
866
869
  ItemCard2,
867
870
  {
868
871
  item,
@@ -880,36 +883,33 @@ function ItemCard2({
880
883
  }) {
881
884
  const variant = item.variants[0];
882
885
  const onSale = variant?.display_price != null && variant.display_price < variant.price;
883
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
884
- import_link3.default,
886
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
887
+ import_link2.default,
885
888
  {
886
889
  href: `/menu/${(0, import_menuSlugs2.menuItemSlug)(item.name, item.base_item_id)}`,
887
890
  className: slots.itemCard,
888
891
  children: [
889
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: slots.itemCardTextContainer, children: [
890
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: slots.itemCardName, children: item.name }),
891
- item.description && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: slots.itemCardDescription, children: item.description })
892
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: slots.itemCardTextContainer, children: [
893
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: slots.itemCardName, children: item.name }),
894
+ item.description && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: slots.itemCardDescription, children: item.description })
892
895
  ] }),
893
- variant && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: slots.itemCardPriceContainer, children: onSale ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
894
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: slots.itemCardPrice, children: money2(variant.display_price) }),
895
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: slots.itemCardOldPrice, children: money2(variant.price) })
896
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: slots.itemCardPrice, children: money2(variant.price) }) })
896
+ variant && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: slots.itemCardPriceContainer, children: onSale ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
897
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: slots.itemCardPrice, children: money2(variant.display_price) }),
898
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: slots.itemCardOldPrice, children: money2(variant.price) })
899
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: slots.itemCardPrice, children: money2(variant.price) }) })
897
900
  ]
898
901
  }
899
902
  );
900
903
  }
901
904
 
902
- // src/components/ItemCustomizationForm.tsx
903
- var import_lucide_react3 = require("lucide-react");
904
- var import_hooks3 = require("@zorgo/next");
905
- var import_jsx_runtime5 = require("react/jsx-runtime");
906
- function cn4(...parts) {
905
+ // src/components/client/ItemForm/classes.ts
906
+ function cn3(...parts) {
907
907
  return parts.filter(Boolean).join(" ");
908
908
  }
909
909
  function money3(cents) {
910
910
  return `$${(cents / 100).toFixed(2)}`;
911
911
  }
912
- var ITEM_CUSTOMIZATION_FORM_DEFAULT_ITEM_CLASSES = {
912
+ var CLIENT_ITEM_FORM_DEFAULT_ITEM_CLASSES = {
913
913
  baseContainer: "flex flex-col gap-8",
914
914
  title: "text-4xl font-extrabold text-primary",
915
915
  description: "opacity-70 text-xl",
@@ -927,57 +927,492 @@ var ITEM_CUSTOMIZATION_FORM_DEFAULT_ITEM_CLASSES = {
927
927
  incrementButton: "bg-background text-foreground w-10 h-10 rounded-xl flex items-center justify-center hover:bg-foreground hover:text-background transition-all duration-300",
928
928
  servingsValue: "w-8 md:w-12 font-semibold opacity-75 text-center",
929
929
  ruleError: "text-sm text-red-500",
930
+ portionHint: "text-base font-normal opacity-60",
930
931
  commentsTextarea: "p-4 rounded-xl border-3 border-foreground/[15%] outline-none resize-none",
931
932
  quantityRow: "flex flex-row items-center gap-4 text-xl",
932
933
  submitButton: "bg-primary text-primary-foreground p-4 rounded-xl text-lg font-semibold hover:bg-primary/80 disabled:opacity-50 disabled:cursor-not-allowed transition-all duration-300",
933
934
  notFound: ""
934
935
  };
935
- function mergeItemCustomizationFormItemClasses(overrides) {
936
- const d3 = ITEM_CUSTOMIZATION_FORM_DEFAULT_ITEM_CLASSES;
936
+ function mergeClientItemFormItemClasses(overrides) {
937
+ const d3 = CLIENT_ITEM_FORM_DEFAULT_ITEM_CLASSES;
937
938
  return {
938
- baseContainer: cn4(d3.baseContainer, overrides?.baseContainer),
939
- title: cn4(d3.title, overrides?.title),
940
- description: cn4(d3.description, overrides?.description),
941
- section: cn4(d3.section, overrides?.section),
942
- sectionTitle: cn4(d3.sectionTitle, overrides?.sectionTitle),
943
- optionsRow: cn4(d3.optionsRow, overrides?.optionsRow),
944
- optionButton: cn4(d3.optionButton, overrides?.optionButton),
945
- optionButtonSelected: cn4(
939
+ baseContainer: cn3(d3.baseContainer, overrides?.baseContainer),
940
+ title: cn3(d3.title, overrides?.title),
941
+ description: cn3(d3.description, overrides?.description),
942
+ section: cn3(d3.section, overrides?.section),
943
+ sectionTitle: cn3(d3.sectionTitle, overrides?.sectionTitle),
944
+ optionsRow: cn3(d3.optionsRow, overrides?.optionsRow),
945
+ optionButton: cn3(d3.optionButton, overrides?.optionButton),
946
+ optionButtonSelected: cn3(
946
947
  d3.optionButtonSelected,
947
948
  overrides?.optionButtonSelected
948
949
  ),
949
- optionButtonUnselected: cn4(
950
+ optionButtonUnselected: cn3(
950
951
  d3.optionButtonUnselected,
951
952
  overrides?.optionButtonUnselected
952
953
  ),
953
- optionButtonLabel: cn4(
954
+ optionButtonLabel: cn3(
954
955
  d3.optionButtonLabel,
955
956
  overrides?.optionButtonLabel
956
957
  ),
957
- optionButtonUpcharge: cn4(
958
+ optionButtonUpcharge: cn3(
958
959
  d3.optionButtonUpcharge,
959
960
  overrides?.optionButtonUpcharge
960
961
  ),
961
- servingsRow: cn4(d3.servingsRow, overrides?.servingsRow),
962
- servingsLabel: cn4(d3.servingsLabel, overrides?.servingsLabel),
963
- servingsControls: cn4(d3.servingsControls, overrides?.servingsControls),
964
- incrementButton: cn4(d3.incrementButton, overrides?.incrementButton),
965
- servingsValue: cn4(d3.servingsValue, overrides?.servingsValue),
966
- ruleError: cn4(d3.ruleError, overrides?.ruleError),
967
- commentsTextarea: cn4(d3.commentsTextarea, overrides?.commentsTextarea),
968
- quantityRow: cn4(d3.quantityRow, overrides?.quantityRow),
969
- submitButton: cn4(d3.submitButton, overrides?.submitButton),
970
- notFound: cn4(d3.notFound, overrides?.notFound)
962
+ servingsRow: cn3(d3.servingsRow, overrides?.servingsRow),
963
+ servingsLabel: cn3(d3.servingsLabel, overrides?.servingsLabel),
964
+ servingsControls: cn3(d3.servingsControls, overrides?.servingsControls),
965
+ incrementButton: cn3(d3.incrementButton, overrides?.incrementButton),
966
+ servingsValue: cn3(d3.servingsValue, overrides?.servingsValue),
967
+ ruleError: cn3(d3.ruleError, overrides?.ruleError),
968
+ portionHint: cn3(d3.portionHint, overrides?.portionHint),
969
+ commentsTextarea: cn3(d3.commentsTextarea, overrides?.commentsTextarea),
970
+ quantityRow: cn3(d3.quantityRow, overrides?.quantityRow),
971
+ submitButton: cn3(d3.submitButton, overrides?.submitButton),
972
+ notFound: cn3(d3.notFound, overrides?.notFound)
973
+ };
974
+ }
975
+ var CLIENT_ITEM_FORM_SLOTS = mergeClientItemFormItemClasses();
976
+
977
+ // src/components/client/ItemForm/ClientItemForm.tsx
978
+ var import_react15 = require("react");
979
+ var import_navigation = require("next/navigation");
980
+ var import_hooks2 = require("@zorgo/next");
981
+
982
+ // src/components/client/ItemForm/Breadcrumbs.tsx
983
+ var import_link3 = __toESM(require("next/link"));
984
+ var import_lucide_react2 = require("lucide-react");
985
+ var import_jsx_runtime4 = require("react/jsx-runtime");
986
+ function cn4(...parts) {
987
+ return parts.filter(Boolean).join(" ");
988
+ }
989
+ var BREADCRUMBS_DEFAULT_ITEM_CLASSES = {
990
+ baseContainer: "flex flex-row items-center gap-2 text-sm opacity-75",
991
+ crumbLink: "hover:opacity-75 transition-all duration-300 underline-offset-2 hover:underline",
992
+ crumbText: "font-semibold",
993
+ separator: "h-4 w-4 opacity-50"
994
+ };
995
+ function mergeBreadcrumbsItemClasses(overrides) {
996
+ const d3 = BREADCRUMBS_DEFAULT_ITEM_CLASSES;
997
+ return {
998
+ baseContainer: cn4(d3.baseContainer, overrides?.baseContainer),
999
+ crumbLink: cn4(d3.crumbLink, overrides?.crumbLink),
1000
+ crumbText: cn4(d3.crumbText, overrides?.crumbText),
1001
+ separator: cn4(d3.separator, overrides?.separator)
971
1002
  };
972
1003
  }
973
- function ItemCustomizationForm({
1004
+ function Breadcrumbs({
1005
+ items,
1006
+ itemClasses
1007
+ }) {
1008
+ const slots = mergeBreadcrumbsItemClasses(itemClasses);
1009
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("nav", { "aria-label": "Breadcrumb", className: slots.baseContainer, children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "flex flex-row items-center gap-2", children: [
1010
+ index > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.ChevronRight, { className: slots.separator }),
1011
+ item.href ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_link3.default, { href: item.href, className: slots.crumbLink, children: item.label }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: slots.crumbText, children: item.label })
1012
+ ] }, `${item.label}-${index}`)) });
1013
+ }
1014
+
1015
+ // src/components/client/ItemForm/CommentsSection.tsx
1016
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1017
+ function CommentsSection({
1018
+ comments,
1019
+ setComments,
1020
+ title = "Comments",
1021
+ placeholder = "Special instructions...",
1022
+ rows = 2,
1023
+ slots = CLIENT_ITEM_FORM_SLOTS
1024
+ }) {
1025
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: slots.section, children: [
1026
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: slots.sectionTitle, children: title }),
1027
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1028
+ "textarea",
1029
+ {
1030
+ value: comments,
1031
+ onChange: (e) => setComments(e.target.value),
1032
+ placeholder,
1033
+ className: slots.commentsTextarea,
1034
+ rows
1035
+ }
1036
+ )
1037
+ ] });
1038
+ }
1039
+
1040
+ // src/components/client/ItemForm/ComponentsSection.tsx
1041
+ var import_portionUtils = require("@zorgo/next");
1042
+
1043
+ // src/components/client/ItemForm/OptionButton.tsx
1044
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1045
+ function OptionButton({
1046
+ label,
1047
+ subtext,
1048
+ selected,
1049
+ onClick,
1050
+ slots = CLIENT_ITEM_FORM_SLOTS
1051
+ }) {
1052
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1053
+ "button",
1054
+ {
1055
+ type: "button",
1056
+ onClick,
1057
+ className: cn3(
1058
+ slots.optionButton,
1059
+ selected ? slots.optionButtonSelected : slots.optionButtonUnselected
1060
+ ),
1061
+ children: [
1062
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: slots.optionButtonLabel, children: label }),
1063
+ subtext && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: slots.optionButtonUpcharge, children: subtext })
1064
+ ]
1065
+ }
1066
+ );
1067
+ }
1068
+
1069
+ // src/components/client/ItemForm/ComponentsSection.tsx
1070
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1071
+ function ComponentsSection({
1072
+ variant,
1073
+ draft,
1074
+ setComponentServings,
1075
+ activeSection = null,
1076
+ divisions = 1,
1077
+ scheme,
1078
+ title = "Includes",
1079
+ slots = CLIENT_ITEM_FORM_SLOTS
1080
+ }) {
1081
+ const components = variant.components ?? [];
1082
+ if (components.length === 0) return null;
1083
+ const portion = activeSection != null ? `${activeSection}/${divisions}` : null;
1084
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.section, children: [
1085
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h2", { className: slots.sectionTitle, children: title }),
1086
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: slots.optionsRow, children: components.map((component) => {
1087
+ const defaultServings = component.servings_per_item ?? 1;
1088
+ const rows = (draft?.components ?? []).filter(
1089
+ (c6) => c6.id === component.id
1090
+ );
1091
+ const row = rows.find((c6) => c6.portion === portion) ?? rows.find((c6) => !c6.portion);
1092
+ const servings = row?.quantity_servings ?? defaultServings;
1093
+ const selected = servings > 0;
1094
+ const removedElsewhere = !portion && rows.some((c6) => c6.quantity_servings === 0);
1095
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1096
+ OptionButton,
1097
+ {
1098
+ label: component.name,
1099
+ subtext: removedElsewhere && scheme ? `No ${component.name.toLowerCase()} on ${rows.filter((c6) => c6.quantity_servings === 0).map(
1100
+ (c6) => (0, import_portionUtils.portionLabel)(c6.portion, scheme).toLowerCase()
1101
+ ).join(", ")}` : void 0,
1102
+ selected,
1103
+ onClick: () => setComponentServings(
1104
+ component.id,
1105
+ selected ? 0 : defaultServings,
1106
+ portion
1107
+ ),
1108
+ slots
1109
+ },
1110
+ component.id
1111
+ );
1112
+ }) })
1113
+ ] });
1114
+ }
1115
+
1116
+ // src/components/client/ItemForm/PortionPicker.tsx
1117
+ var import_portionUtils2 = require("@zorgo/next");
1118
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1119
+ function cn5(...parts) {
1120
+ return parts.filter(Boolean).join(" ");
1121
+ }
1122
+ var SECTION_FILL = "var(--color-background-elevated, #fff)";
1123
+ function sectionClass(isActive, isCovered) {
1124
+ return cn5(
1125
+ "transition-all duration-200 cursor-pointer",
1126
+ isActive ? "fill-primary stroke-primary" : isCovered ? "fill-primary/30 stroke-foreground/20" : "stroke-foreground/20 hover:fill-primary/10"
1127
+ );
1128
+ }
1129
+ function RadialPicker({ divisions, active, covered = [], onSelect }) {
1130
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("svg", { viewBox: "0 0 100 100", className: "w-32 h-32", role: "group", children: Array.from({ length: divisions }, (_, i4) => {
1131
+ const index = i4 + 1;
1132
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1133
+ "path",
1134
+ {
1135
+ d: (0, import_portionUtils2.radialSectionPath)(index, divisions),
1136
+ strokeWidth: 2,
1137
+ style: { fill: SECTION_FILL },
1138
+ className: sectionClass(active === index, covered.includes(index)),
1139
+ onClick: () => onSelect(active === index ? null : index)
1140
+ },
1141
+ index
1142
+ );
1143
+ }) });
1144
+ }
1145
+ function GridPicker({ divisions, active, covered = [], onSelect }) {
1146
+ const cols = Math.ceil(Math.sqrt(divisions));
1147
+ const rows = Math.ceil(divisions / cols);
1148
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1149
+ "div",
1150
+ {
1151
+ className: "grid gap-1 w-32 h-32",
1152
+ style: {
1153
+ gridTemplateColumns: `repeat(${cols}, 1fr)`,
1154
+ gridTemplateRows: `repeat(${rows}, 1fr)`,
1155
+ gridAutoFlow: "column"
1156
+ },
1157
+ children: Array.from({ length: divisions }, (_, i4) => {
1158
+ const index = i4 + 1;
1159
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1160
+ "button",
1161
+ {
1162
+ type: "button",
1163
+ "aria-pressed": active === index,
1164
+ onClick: () => onSelect(active === index ? null : index),
1165
+ className: cn5(
1166
+ "rounded-lg border-3 transition-all duration-200",
1167
+ active === index ? "bg-primary border-primary" : covered.includes(index) ? "bg-primary/30 border-foreground/15" : "bg-background-elevated border-foreground/15 hover:bg-primary/10"
1168
+ )
1169
+ },
1170
+ index
1171
+ );
1172
+ })
1173
+ }
1174
+ );
1175
+ }
1176
+ function LinearPicker({ divisions, active, covered = [], onSelect }) {
1177
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex flex-row w-full max-w-xs h-12 gap-1", children: Array.from({ length: divisions }, (_, i4) => {
1178
+ const index = i4 + 1;
1179
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1180
+ "button",
1181
+ {
1182
+ type: "button",
1183
+ "aria-pressed": active === index,
1184
+ onClick: () => onSelect(active === index ? null : index),
1185
+ className: cn5(
1186
+ "flex-1 rounded-lg border-3 transition-all duration-200",
1187
+ active === index ? "bg-primary border-primary" : covered.includes(index) ? "bg-primary/30 border-foreground/15" : "bg-background-elevated border-foreground/15 hover:bg-primary/10"
1188
+ )
1189
+ },
1190
+ index
1191
+ );
1192
+ }) });
1193
+ }
1194
+ function CountPicker({
1195
+ divisions,
1196
+ active,
1197
+ covered = [],
1198
+ onSelect,
1199
+ scheme
1200
+ }) {
1201
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex flex-row flex-wrap gap-2", children: Array.from({ length: divisions }, (_, i4) => {
1202
+ const index = i4 + 1;
1203
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1204
+ "button",
1205
+ {
1206
+ type: "button",
1207
+ "aria-pressed": active === index,
1208
+ onClick: () => onSelect(active === index ? null : index),
1209
+ className: cn5(
1210
+ "px-4 py-2 rounded-xl border-3 font-semibold transition-all duration-200",
1211
+ active === index ? "bg-primary text-primary-foreground border-primary" : covered.includes(index) ? "bg-primary/30 border-foreground/15" : "bg-background-elevated border-foreground/15 hover:bg-primary/10"
1212
+ ),
1213
+ children: (0, import_portionUtils2.portionLabel)(`${index}/${divisions}`, scheme)
1214
+ },
1215
+ index
1216
+ );
1217
+ }) });
1218
+ }
1219
+ function PortionPicker({
1220
+ scheme,
1221
+ divisions,
1222
+ active,
1223
+ covered,
1224
+ onSelect,
1225
+ onDivisionsChange,
1226
+ className
1227
+ }) {
1228
+ const cuts = (0, import_portionUtils2.divisionsFor)(scheme);
1229
+ const shapeProps = { divisions, active, covered, onSelect };
1230
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: cn5("flex flex-col gap-4 items-center", className), children: [
1231
+ cuts.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex flex-row gap-2", children: cuts.map((count) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1232
+ "button",
1233
+ {
1234
+ type: "button",
1235
+ "aria-pressed": divisions === count,
1236
+ onClick: () => onDivisionsChange(count),
1237
+ className: cn5(
1238
+ "px-4 py-2 rounded-xl border-3 font-semibold transition-all duration-200",
1239
+ divisions === count ? "bg-primary text-primary-foreground border-primary" : "bg-background-elevated border-foreground/15 hover:bg-primary/10"
1240
+ ),
1241
+ children: count === 1 ? "Whole" : `${count} parts`
1242
+ },
1243
+ count
1244
+ )) }),
1245
+ divisions > 1 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
1246
+ scheme.geometry === "radial" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(RadialPicker, { ...shapeProps }),
1247
+ scheme.geometry === "grid" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(GridPicker, { ...shapeProps }),
1248
+ scheme.geometry === "linear" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(LinearPicker, { ...shapeProps }),
1249
+ scheme.geometry === "count" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CountPicker, { ...shapeProps, scheme })
1250
+ ] }),
1251
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "opacity-70", children: active == null ? divisions > 1 ? "Editing the whole item \u2014 tap a section to edit just that part" : "Editing the whole item" : `Editing ${(0, import_portionUtils2.portionLabel)(`${active}/${divisions}`, scheme).toLowerCase()}` })
1252
+ ] });
1253
+ }
1254
+
1255
+ // src/components/client/ItemForm/PortionSection.tsx
1256
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1257
+ function PortionSection({
1258
+ scheme,
1259
+ divisions,
1260
+ activeSection,
1261
+ setActiveSection,
1262
+ setDivisions,
1263
+ slots = CLIENT_ITEM_FORM_SLOTS
1264
+ }) {
1265
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: slots.section, children: [
1266
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("h2", { className: slots.sectionTitle, children: scheme.name }),
1267
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1268
+ PortionPicker,
1269
+ {
1270
+ scheme,
1271
+ divisions,
1272
+ active: activeSection,
1273
+ onSelect: setActiveSection,
1274
+ onDivisionsChange: setDivisions
1275
+ }
1276
+ )
1277
+ ] });
1278
+ }
1279
+
1280
+ // src/components/client/ItemForm/QuantitySection.tsx
1281
+ var import_lucide_react3 = require("lucide-react");
1282
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1283
+ function QuantitySection({
1284
+ quantity,
1285
+ setQuantity,
1286
+ title = "How many?",
1287
+ slots = CLIENT_ITEM_FORM_SLOTS
1288
+ }) {
1289
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: slots.section, children: [
1290
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { className: slots.sectionTitle, children: title }),
1291
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: slots.quantityRow, children: [
1292
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1293
+ "button",
1294
+ {
1295
+ type: "button",
1296
+ className: slots.incrementButton,
1297
+ onClick: () => setQuantity((q2) => q2 - 1),
1298
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.Minus, { className: "h-4 w-4" })
1299
+ }
1300
+ ),
1301
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: slots.servingsValue, children: quantity }),
1302
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1303
+ "button",
1304
+ {
1305
+ type: "button",
1306
+ className: slots.incrementButton,
1307
+ onClick: () => setQuantity((q2) => q2 + 1),
1308
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react3.Plus, { className: "h-4 w-4" })
1309
+ }
1310
+ )
1311
+ ] })
1312
+ ] });
1313
+ }
1314
+
1315
+ // src/components/client/ItemForm/RuleSection.tsx
1316
+ var import_portionUtils3 = require("@zorgo/next");
1317
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1318
+ function RuleSection({
1319
+ rule,
1320
+ activeSection = null,
1321
+ divisions = 1,
1322
+ scheme,
1323
+ placeOption,
1324
+ slots = CLIENT_ITEM_FORM_SLOTS
1325
+ }) {
1326
+ const portion = rule.portionable && activeSection != null ? `${activeSection}/${divisions}` : null;
1327
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: slots.section, children: [
1328
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("h2", { className: slots.sectionTitle, children: [
1329
+ rule.group_name,
1330
+ activeSection != null && !rule.portionable && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: slots.portionHint, children: " \u2014 whole item only" })
1331
+ ] }),
1332
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: slots.optionsRow, children: rule.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1333
+ OptionButton,
1334
+ {
1335
+ label: option.name,
1336
+ subtext: (
1337
+ // where it sits beats what it costs — the price is
1338
+ // already in the running total
1339
+ option.portion && scheme ? (0, import_portionUtils3.portionLabel)(option.portion, scheme) : option.upcharge > 0 ? `+${money3(option.upcharge)}` : void 0
1340
+ ),
1341
+ selected: option.selected,
1342
+ onClick: () => placeOption ? placeOption(
1343
+ rule.rule_id,
1344
+ (0, import_portionUtils3.parsePortionKey)(option.key).baseKey,
1345
+ portion,
1346
+ rule.max
1347
+ ) : option.toggle(),
1348
+ slots
1349
+ },
1350
+ (0, import_portionUtils3.parsePortionKey)(option.key).baseKey
1351
+ )) }),
1352
+ rule.message() && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: slots.ruleError, children: rule.message() })
1353
+ ] });
1354
+ }
1355
+
1356
+ // src/components/client/ItemForm/SubmitButton.tsx
1357
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1358
+ function SubmitButton({
1359
+ canSubmit,
1360
+ unmetRule,
1361
+ price,
1362
+ salePrice,
1363
+ isEditMode,
1364
+ onSubmit,
1365
+ slots = CLIENT_ITEM_FORM_SLOTS
1366
+ }) {
1367
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1368
+ "button",
1369
+ {
1370
+ type: "button",
1371
+ disabled: !canSubmit,
1372
+ onClick: onSubmit,
1373
+ className: slots.submitButton,
1374
+ children: unmetRule ? `Choose ${unmetRule.group_name}` : `${isEditMode ? "Save changes" : "Add to cart"} \u2014 ${money3(salePrice ?? price)}`
1375
+ }
1376
+ );
1377
+ }
1378
+
1379
+ // src/components/client/ItemForm/VariantSection.tsx
1380
+ var import_jsx_runtime13 = require("react/jsx-runtime");
1381
+ function VariantSection({
1382
+ variants,
1383
+ variant,
1384
+ setVariant,
1385
+ title = "Variants",
1386
+ slots = CLIENT_ITEM_FORM_SLOTS
1387
+ }) {
1388
+ if (variants.length <= 1) return null;
1389
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: slots.section, children: [
1390
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h2", { className: slots.sectionTitle, children: title }),
1391
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: slots.optionsRow, children: variants.map((v2) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1392
+ OptionButton,
1393
+ {
1394
+ label: v2.name,
1395
+ subtext: money3(v2.price),
1396
+ selected: v2.item_id === variant.item_id,
1397
+ onClick: () => setVariant(v2),
1398
+ slots
1399
+ },
1400
+ v2.item_id
1401
+ )) })
1402
+ ] });
1403
+ }
1404
+
1405
+ // src/components/client/ItemForm/ClientItemForm.tsx
1406
+ var import_jsx_runtime14 = require("react/jsx-runtime");
1407
+ function ClientItemForm({
974
1408
  baseItemId,
975
1409
  seed,
976
1410
  editIndex,
977
1411
  itemClasses,
978
1412
  onSubmitSuccess
979
1413
  }) {
980
- const slots = mergeItemCustomizationFormItemClasses(itemClasses);
1414
+ const router = (0, import_navigation.useRouter)();
1415
+ const slots = mergeClientItemFormItemClasses(itemClasses);
981
1416
  const {
982
1417
  item,
983
1418
  variant,
@@ -995,17 +1430,21 @@ function ItemCustomizationForm({
995
1430
  price,
996
1431
  salePrice,
997
1432
  isEditMode,
998
- draft
999
- } = (0, import_hooks3.useItemCustomization)(baseItemId, seed, editIndex);
1000
- const { categories } = (0, import_hooks3.useMenu)();
1433
+ draft,
1434
+ portionScheme,
1435
+ placeOption,
1436
+ recutSelections
1437
+ } = (0, import_hooks2.useItemCustomization)(baseItemId, seed, editIndex);
1438
+ const { categories } = (0, import_hooks2.useMenu)();
1439
+ const [cut, setCut] = (0, import_react15.useState)(1);
1440
+ const [activeSection, setActiveSection] = (0, import_react15.useState)(null);
1441
+ const divisions = portionScheme ? Math.min(Math.max(cut, portionScheme.min_divisions), portionScheme.max_divisions) : 1;
1001
1442
  if (!item) {
1002
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: slots.notFound, children: "Item not found." });
1443
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: slots.notFound, children: "Item not found." });
1003
1444
  }
1004
- const category = categories.find(
1005
- (c6) => c6.category_id === item.category_id
1006
- );
1007
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: slots.baseContainer, children: [
1008
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1445
+ const category = categories.find((c6) => c6.category_id === item.category_id);
1446
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: slots.baseContainer, children: [
1447
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1009
1448
  Breadcrumbs,
1010
1449
  {
1011
1450
  items: [
@@ -1015,141 +1454,98 @@ function ItemCustomizationForm({
1015
1454
  ]
1016
1455
  }
1017
1456
  ),
1018
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h1", { className: slots.title, children: item.name }),
1019
- item.description && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: slots.description, children: item.description }),
1020
- variants.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: slots.section, children: [
1021
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: slots.sectionTitle, children: "Variants" }),
1022
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: slots.optionsRow, children: variants.map((v2) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1023
- OptionButton,
1024
- {
1025
- label: v2.name,
1026
- subtext: money3(v2.price),
1027
- selected: v2.item_id === variant.item_id,
1028
- onClick: () => setVariant(v2),
1029
- slots
1030
- },
1031
- v2.item_id
1032
- )) })
1033
- ] }),
1034
- (variant.components?.length ?? 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: slots.section, children: [
1035
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: slots.sectionTitle, children: "Includes" }),
1036
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: slots.optionsRow, children: variant.components.map((component) => {
1037
- const defaultServings = component.servings_per_item ?? 1;
1038
- const servings = draft?.components?.find(
1039
- (c6) => c6.id === component.id
1040
- )?.quantity_servings ?? defaultServings;
1041
- const selected = servings > 0;
1042
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1043
- OptionButton,
1044
- {
1045
- label: component.name,
1046
- selected,
1047
- onClick: () => setComponentServings(
1048
- component.id,
1049
- selected ? 0 : defaultServings
1050
- ),
1051
- slots
1052
- },
1053
- component.id
1054
- );
1055
- }) })
1056
- ] }),
1057
- ruleGroups.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: slots.section, children: [
1058
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: slots.sectionTitle, children: rule.group_name }),
1059
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: slots.optionsRow, children: rule.options.map((option) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1060
- OptionButton,
1061
- {
1062
- label: option.name,
1063
- subtext: option.upcharge > 0 ? `+${money3(option.upcharge)}` : void 0,
1064
- selected: option.selected,
1065
- onClick: option.toggle,
1066
- slots
1457
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h1", { className: slots.title, children: item.name }),
1458
+ item.description && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: slots.description, children: item.description }),
1459
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1460
+ VariantSection,
1461
+ {
1462
+ variants,
1463
+ variant,
1464
+ setVariant,
1465
+ slots
1466
+ }
1467
+ ),
1468
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1469
+ ComponentsSection,
1470
+ {
1471
+ variant,
1472
+ draft,
1473
+ setComponentServings,
1474
+ activeSection,
1475
+ divisions,
1476
+ scheme: portionScheme,
1477
+ slots
1478
+ }
1479
+ ),
1480
+ portionScheme && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1481
+ PortionSection,
1482
+ {
1483
+ scheme: portionScheme,
1484
+ divisions,
1485
+ activeSection,
1486
+ setActiveSection,
1487
+ setDivisions: (next) => {
1488
+ recutSelections(next);
1489
+ setCut(next);
1490
+ setActiveSection(
1491
+ (s5) => s5 != null && (next === 1 || s5 > next) ? null : s5
1492
+ );
1067
1493
  },
1068
- option.key
1069
- )) }),
1070
- rule.message() && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: slots.ruleError, children: rule.message() })
1071
- ] }, rule.rule_id)),
1072
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: slots.section, children: [
1073
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: slots.sectionTitle, children: "Comments" }),
1074
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1075
- "textarea",
1076
- {
1077
- value: comments,
1078
- onChange: (e) => setComments(e.target.value),
1079
- placeholder: "Special instructions...",
1080
- className: slots.commentsTextarea,
1081
- rows: 2
1082
- }
1083
- )
1084
- ] }),
1085
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: slots.section, children: [
1086
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: slots.sectionTitle, children: "How many?" }),
1087
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: slots.quantityRow, children: [
1088
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1089
- "button",
1090
- {
1091
- type: "button",
1092
- className: slots.incrementButton,
1093
- onClick: () => setQuantity((q2) => Math.max(1, q2 - 1)),
1094
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react3.Minus, { className: "h-4 w-4" })
1095
- }
1096
- ),
1097
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: slots.servingsValue, children: quantity }),
1098
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1099
- "button",
1100
- {
1101
- type: "button",
1102
- className: slots.incrementButton,
1103
- onClick: () => setQuantity((q2) => q2 + 1),
1104
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react3.Plus, { className: "h-4 w-4" })
1105
- }
1106
- )
1107
- ] })
1108
- ] }),
1109
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1110
- "button",
1494
+ slots
1495
+ }
1496
+ ),
1497
+ ruleGroups.map((rule) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1498
+ RuleSection,
1111
1499
  {
1112
- type: "button",
1113
- disabled: !canSubmit,
1114
- onClick: () => {
1500
+ rule,
1501
+ activeSection,
1502
+ divisions,
1503
+ scheme: portionScheme,
1504
+ placeOption,
1505
+ slots
1506
+ },
1507
+ rule.rule_id
1508
+ )),
1509
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1510
+ CommentsSection,
1511
+ {
1512
+ comments,
1513
+ setComments,
1514
+ slots
1515
+ }
1516
+ ),
1517
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1518
+ QuantitySection,
1519
+ {
1520
+ quantity,
1521
+ setQuantity,
1522
+ slots
1523
+ }
1524
+ ),
1525
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
1526
+ SubmitButton,
1527
+ {
1528
+ canSubmit,
1529
+ unmetRule,
1530
+ price,
1531
+ salePrice,
1532
+ isEditMode,
1533
+ onSubmit: () => {
1115
1534
  submit();
1116
- onSubmitSuccess?.();
1535
+ if (onSubmitSuccess) onSubmitSuccess();
1536
+ else router.push("/menu");
1117
1537
  },
1118
- className: slots.submitButton,
1119
- children: unmetRule ? `Choose ${unmetRule.group_name}` : `${isEditMode ? "Save changes" : "Add to cart"} \u2014 ${money3(salePrice ?? price)}`
1538
+ slots
1120
1539
  }
1121
1540
  )
1122
1541
  ] });
1123
1542
  }
1124
- function OptionButton({
1125
- label,
1126
- subtext,
1127
- selected,
1128
- onClick,
1129
- slots
1130
- }) {
1131
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1132
- "button",
1133
- {
1134
- type: "button",
1135
- onClick,
1136
- className: cn4(
1137
- slots.optionButton,
1138
- selected ? slots.optionButtonSelected : slots.optionButtonUnselected
1139
- ),
1140
- children: [
1141
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: slots.optionButtonLabel, children: label }),
1142
- subtext && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: slots.optionButtonUpcharge, children: subtext })
1143
- ]
1144
- }
1145
- );
1146
- }
1147
1543
 
1148
- // src/components/FindLocation.tsx
1149
- var import_react15 = require("react");
1544
+ // src/components/client/FindLocation.tsx
1545
+ var import_react16 = require("react");
1150
1546
  var import_lucide_react4 = require("lucide-react");
1151
- var import_jsx_runtime6 = require("react/jsx-runtime");
1152
- function cn5(...parts) {
1547
+ var import_jsx_runtime15 = require("react/jsx-runtime");
1548
+ function cn6(...parts) {
1153
1549
  return parts.filter(Boolean).join(" ");
1154
1550
  }
1155
1551
  function searchableText(location) {
@@ -1200,26 +1596,26 @@ var FIND_LOCATION_DEFAULT_ITEM_CLASSES = {
1200
1596
  function mergeFindLocationItemClasses(overrides) {
1201
1597
  const d3 = FIND_LOCATION_DEFAULT_ITEM_CLASSES;
1202
1598
  return {
1203
- baseContainer: cn5(d3.baseContainer, overrides?.baseContainer),
1204
- searchContainer: cn5(d3.searchContainer, overrides?.searchContainer),
1205
- searchIcon: cn5(d3.searchIcon, overrides?.searchIcon),
1206
- searchInput: cn5(d3.searchInput, overrides?.searchInput),
1207
- noMatchesMessage: cn5(d3.noMatchesMessage, overrides?.noMatchesMessage),
1208
- emptyMessage: cn5(d3.emptyMessage, overrides?.emptyMessage),
1209
- list: cn5(d3.list, overrides?.list),
1210
- locationRow: cn5(d3.locationRow, overrides?.locationRow),
1211
- locationRowSelected: cn5(
1599
+ baseContainer: cn6(d3.baseContainer, overrides?.baseContainer),
1600
+ searchContainer: cn6(d3.searchContainer, overrides?.searchContainer),
1601
+ searchIcon: cn6(d3.searchIcon, overrides?.searchIcon),
1602
+ searchInput: cn6(d3.searchInput, overrides?.searchInput),
1603
+ noMatchesMessage: cn6(d3.noMatchesMessage, overrides?.noMatchesMessage),
1604
+ emptyMessage: cn6(d3.emptyMessage, overrides?.emptyMessage),
1605
+ list: cn6(d3.list, overrides?.list),
1606
+ locationRow: cn6(d3.locationRow, overrides?.locationRow),
1607
+ locationRowSelected: cn6(
1212
1608
  d3.locationRowSelected,
1213
1609
  overrides?.locationRowSelected
1214
1610
  ),
1215
- locationRowUnselected: cn5(
1611
+ locationRowUnselected: cn6(
1216
1612
  d3.locationRowUnselected,
1217
1613
  overrides?.locationRowUnselected
1218
1614
  ),
1219
- locationButton: cn5(d3.locationButton, overrides?.locationButton),
1220
- locationName: cn5(d3.locationName, overrides?.locationName),
1221
- locationAddress: cn5(d3.locationAddress, overrides?.locationAddress),
1222
- selectButton: cn5(d3.selectButton, overrides?.selectButton)
1615
+ locationButton: cn6(d3.locationButton, overrides?.locationButton),
1616
+ locationName: cn6(d3.locationName, overrides?.locationName),
1617
+ locationAddress: cn6(d3.locationAddress, overrides?.locationAddress),
1618
+ selectButton: cn6(d3.selectButton, overrides?.selectButton)
1223
1619
  };
1224
1620
  }
1225
1621
  function FindLocation({
@@ -1228,22 +1624,22 @@ function FindLocation({
1228
1624
  onSelect,
1229
1625
  itemClasses
1230
1626
  }) {
1231
- const [query, setQuery] = (0, import_react15.useState)("");
1232
- const [selected, setSelected] = (0, import_react15.useState)(
1627
+ const [query, setQuery] = (0, import_react16.useState)("");
1628
+ const [selected, setSelected] = (0, import_react16.useState)(
1233
1629
  () => initialSelected ?? null
1234
1630
  );
1235
1631
  const slots = mergeFindLocationItemClasses(itemClasses);
1236
1632
  const pinnedLocationId = initialSelected?.location_id;
1237
- const ranked = (0, import_react15.useMemo)(
1633
+ const ranked = (0, import_react16.useMemo)(
1238
1634
  () => rankLocations(locations, query, pinnedLocationId),
1239
1635
  [locations, query, pinnedLocationId]
1240
1636
  );
1241
1637
  const trimmedQuery = query.trim();
1242
1638
  const noMatches = trimmedQuery.length > 0 && locations.every((location) => matchRank(location, trimmedQuery) === 2);
1243
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: slots.baseContainer, children: [
1244
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: slots.searchContainer, children: [
1245
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Search, { className: slots.searchIcon, strokeWidth: 2 }),
1246
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1639
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: slots.baseContainer, children: [
1640
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: slots.searchContainer, children: [
1641
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react4.Search, { className: slots.searchIcon, strokeWidth: 2 }),
1642
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1247
1643
  "input",
1248
1644
  {
1249
1645
  type: "search",
@@ -1255,22 +1651,22 @@ function FindLocation({
1255
1651
  }
1256
1652
  )
1257
1653
  ] }),
1258
- noMatches && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: slots.noMatchesMessage, children: [
1654
+ noMatches && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("p", { className: slots.noMatchesMessage, children: [
1259
1655
  "No locations match \u201C",
1260
1656
  trimmedQuery,
1261
1657
  "\u201D. Showing all locations anyway."
1262
1658
  ] }),
1263
- ranked.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: slots.emptyMessage, children: "No locations available." }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { className: slots.list, children: ranked.map((location) => {
1659
+ ranked.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: slots.emptyMessage, children: "No locations available." }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("ul", { className: slots.list, children: ranked.map((location) => {
1264
1660
  const isSelected = selected?.location_id === location.location_id;
1265
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1661
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1266
1662
  "li",
1267
1663
  {
1268
- className: cn5(
1664
+ className: cn6(
1269
1665
  slots.locationRow,
1270
1666
  isSelected ? slots.locationRowSelected : slots.locationRowUnselected
1271
1667
  ),
1272
1668
  children: [
1273
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1669
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
1274
1670
  "button",
1275
1671
  {
1276
1672
  type: "button",
@@ -1278,12 +1674,12 @@ function FindLocation({
1278
1674
  "aria-pressed": isSelected,
1279
1675
  className: slots.locationButton,
1280
1676
  children: [
1281
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: slots.locationName, children: location.name }),
1282
- location.address && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: slots.locationAddress, children: location.address })
1677
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: slots.locationName, children: location.name }),
1678
+ location.address && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: slots.locationAddress, children: location.address })
1283
1679
  ]
1284
1680
  }
1285
1681
  ),
1286
- isSelected && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1682
+ isSelected && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
1287
1683
  "button",
1288
1684
  {
1289
1685
  type: "button",
@@ -1300,20 +1696,7 @@ function FindLocation({
1300
1696
  ] });
1301
1697
  }
1302
1698
 
1303
- // src/components/CheckoutForm.tsx
1304
- var import_react16 = require("react");
1305
- var import_link4 = __toESM(require("next/link"));
1306
- var import_react_stripe_js = require("@stripe/react-stripe-js");
1307
- var import_lucide_react5 = require("lucide-react");
1308
- var import_hooks4 = require("@zorgo/next");
1309
- var import_Form = require("@zorgo/next");
1310
- var import_jsx_runtime7 = require("react/jsx-runtime");
1311
- function money4(cents) {
1312
- return `$${(cents / 100).toFixed(2)}`;
1313
- }
1314
- function cn6(...parts) {
1315
- return parts.filter(Boolean).join(" ");
1316
- }
1699
+ // src/components/client/CheckoutForm/classes.ts
1317
1700
  var CHECKOUT_FORM_DEFAULT_ITEM_CLASSES = {
1318
1701
  shell: "",
1319
1702
  shellInner: "max-w-2xl mx-auto w-full flex flex-col gap-6",
@@ -1366,522 +1749,198 @@ var CHECKOUT_FORM_DEFAULT_ITEM_CLASSES = {
1366
1749
  };
1367
1750
  function mergeCheckoutFormItemClasses(overrides) {
1368
1751
  const d3 = CHECKOUT_FORM_DEFAULT_ITEM_CLASSES;
1369
- return {
1370
- shell: cn6(d3.shell, overrides?.shell),
1371
- shellInner: cn6(d3.shellInner, overrides?.shellInner),
1372
- pageTitle: cn6(d3.pageTitle, overrides?.pageTitle),
1373
- primaryButton: cn6(d3.primaryButton, overrides?.primaryButton),
1374
- secondaryButton: cn6(d3.secondaryButton, overrides?.secondaryButton),
1375
- incrementButton: cn6(d3.incrementButton, overrides?.incrementButton),
1376
- surface: cn6(d3.surface, overrides?.surface),
1377
- fieldInput: cn6(d3.fieldInput, overrides?.fieldInput),
1378
- fieldContainer: cn6(d3.fieldContainer, overrides?.fieldContainer),
1379
- fieldLabel: cn6(d3.fieldLabel, overrides?.fieldLabel),
1380
- fieldError: cn6(d3.fieldError, overrides?.fieldError),
1381
- statusPanel: cn6(d3.statusPanel, overrides?.statusPanel),
1382
- statusTitle: cn6(d3.statusTitle, overrides?.statusTitle),
1383
- statusMessage: cn6(d3.statusMessage, overrides?.statusMessage),
1384
- statusMessageError: cn6(
1385
- d3.statusMessageError,
1386
- overrides?.statusMessageError
1387
- ),
1388
- statusActions: cn6(d3.statusActions, overrides?.statusActions),
1389
- stepSection: cn6(d3.stepSection, overrides?.stepSection),
1390
- sectionTitle: cn6(d3.sectionTitle, overrides?.sectionTitle),
1391
- cartList: cn6(d3.cartList, overrides?.cartList),
1392
- totals: cn6(d3.totals, overrides?.totals),
1393
- totalsRow: cn6(d3.totalsRow, overrides?.totalsRow),
1394
- totalsDivider: cn6(d3.totalsDivider, overrides?.totalsDivider),
1395
- totalsTotalRow: cn6(d3.totalsTotalRow, overrides?.totalsTotalRow),
1396
- form: cn6(d3.form, overrides?.form),
1397
- formActions: cn6(d3.formActions, overrides?.formActions),
1398
- submitError: cn6(d3.submitError, overrides?.submitError),
1399
- paymentSurface: cn6(d3.paymentSurface, overrides?.paymentSurface),
1400
- steps: cn6(d3.steps, overrides?.steps),
1401
- stepBadge: cn6(d3.stepBadge, overrides?.stepBadge),
1402
- stepBadgeActive: cn6(d3.stepBadgeActive, overrides?.stepBadgeActive),
1403
- stepBadgeInactive: cn6(
1404
- d3.stepBadgeInactive,
1405
- overrides?.stepBadgeInactive
1406
- ),
1407
- stepLabel: cn6(d3.stepLabel, overrides?.stepLabel),
1408
- stepLabelActive: cn6(d3.stepLabelActive, overrides?.stepLabelActive),
1409
- stepLabelInactive: cn6(
1410
- d3.stepLabelInactive,
1411
- overrides?.stepLabelInactive
1412
- ),
1413
- stepDivider: cn6(d3.stepDivider, overrides?.stepDivider),
1414
- stepDividerActive: cn6(
1415
- d3.stepDividerActive,
1416
- overrides?.stepDividerActive
1417
- ),
1418
- stepDividerInactive: cn6(
1419
- d3.stepDividerInactive,
1420
- overrides?.stepDividerInactive
1421
- ),
1422
- cartLine: cn6(d3.cartLine, overrides?.cartLine),
1423
- cartLineName: cn6(d3.cartLineName, overrides?.cartLineName),
1424
- cartLineSelection: cn6(
1425
- d3.cartLineSelection,
1426
- overrides?.cartLineSelection
1427
- ),
1428
- cartLinePrice: cn6(d3.cartLinePrice, overrides?.cartLinePrice),
1429
- cartLineControls: cn6(d3.cartLineControls, overrides?.cartLineControls),
1430
- cartLineQuantity: cn6(d3.cartLineQuantity, overrides?.cartLineQuantity),
1431
- promoApplied: cn6(d3.promoApplied, overrides?.promoApplied),
1432
- promoAppliedLabel: cn6(
1433
- d3.promoAppliedLabel,
1434
- overrides?.promoAppliedLabel
1435
- ),
1436
- promoRow: cn6(d3.promoRow, overrides?.promoRow),
1437
- promoInput: cn6(d3.promoInput, overrides?.promoInput),
1438
- promoError: cn6(d3.promoError, overrides?.promoError)
1439
- };
1752
+ return Object.fromEntries(
1753
+ Object.keys(d3).map((key) => [
1754
+ key,
1755
+ cn3(d3[key], overrides?.[key])
1756
+ ])
1757
+ );
1440
1758
  }
1441
- function CheckoutForm({
1442
- itemClasses,
1443
- homeHref = "/",
1444
- menuHref = "/menu",
1445
- checkoutHref = "/checkout"
1759
+ var CHECKOUT_FORM_SLOTS = mergeCheckoutFormItemClasses();
1760
+
1761
+ // src/components/client/CheckoutForm/CheckoutForm.tsx
1762
+ var import_react20 = require("react");
1763
+ var import_link4 = __toESM(require("next/link"));
1764
+ var import_react_stripe_js2 = require("@stripe/react-stripe-js");
1765
+ var import_hooks9 = require("@zorgo/next");
1766
+
1767
+ // src/components/client/CheckoutForm/CheckoutShell.tsx
1768
+ var import_jsx_runtime16 = require("react/jsx-runtime");
1769
+ function CheckoutShell({
1770
+ children,
1771
+ title = "Checkout",
1772
+ slots = CHECKOUT_FORM_SLOTS
1446
1773
  }) {
1447
- const slots = mergeCheckoutFormItemClasses(itemClasses);
1448
- const {
1449
- clientSecret,
1450
- stripe,
1451
- elementOptions,
1452
- isReady,
1453
- isLoading,
1454
- error,
1455
- getReturnStatus
1456
- } = (0, import_hooks4.usePayment)();
1457
- const { isEmpty, resetCart } = (0, import_hooks4.useCart)();
1458
- const { currentLocation, needsLocationSelection } = (0, import_hooks4.useLocation)({
1459
- promptLocationSelection: true
1460
- });
1461
- const { open } = (0, import_hooks4.useModal)();
1462
- const [returnStatus, setReturnStatus] = (0, import_react16.useState)(null);
1463
- (0, import_react16.useEffect)(() => {
1464
- if (window.location.search.includes("redirect_status")) {
1465
- const status = getReturnStatus(window.location.href);
1466
- setReturnStatus(status);
1467
- if (status.succeeded) resetCart();
1468
- }
1469
- }, []);
1470
- if (returnStatus) {
1471
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shell, { slots, children: returnStatus.succeeded ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1472
- StatusPanel,
1473
- {
1474
- slots,
1475
- title: "You're all set",
1476
- message: "Payment successful. Thank you!",
1477
- action: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1478
- import_link4.default,
1479
- {
1480
- href: homeHref,
1481
- className: cn6(
1482
- slots.primaryButton,
1483
- "block w-full text-center"
1484
- ),
1485
- children: "Back home"
1486
- }
1487
- )
1488
- }
1489
- ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1490
- StatusPanel,
1491
- {
1492
- slots,
1493
- title: "Payment didn't go through",
1494
- message: returnStatus.error,
1495
- tone: "error",
1496
- action: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1497
- import_link4.default,
1498
- {
1499
- href: checkoutHref,
1500
- className: cn6(
1501
- slots.primaryButton,
1502
- "block w-full text-center"
1503
- ),
1504
- children: "Try again"
1505
- }
1506
- )
1507
- }
1508
- ) });
1509
- }
1510
- if (isEmpty && !isLoading && !clientSecret) {
1511
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shell, { slots, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1512
- StatusPanel,
1513
- {
1514
- slots,
1515
- title: "Your cart is empty",
1516
- message: "Add something from the menu to get started.",
1517
- action: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1518
- import_link4.default,
1774
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: slots.shell, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: slots.shellInner, children: [
1775
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h1", { className: slots.pageTitle, children: title }),
1776
+ children
1777
+ ] }) });
1778
+ }
1779
+
1780
+ // src/components/client/CheckoutForm/DetailsStep.tsx
1781
+ var import_react18 = require("react");
1782
+ var import_Form3 = require("@zorgo/next");
1783
+ var import_hooks7 = require("@zorgo/next");
1784
+
1785
+ // src/components/client/CheckoutForm/CheckoutSteps.tsx
1786
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1787
+ function CheckoutSteps({
1788
+ current,
1789
+ labels = ["Your details", "Payment"],
1790
+ slots = CHECKOUT_FORM_SLOTS
1791
+ }) {
1792
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: slots.steps, children: labels.map((label, i4) => {
1793
+ const n3 = i4 + 1;
1794
+ const active = n3 <= current;
1795
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "contents", children: [
1796
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-2", children: [
1797
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1798
+ "div",
1519
1799
  {
1520
- href: menuHref,
1521
- className: cn6(
1522
- slots.primaryButton,
1523
- "block w-full text-center"
1800
+ className: cn3(
1801
+ slots.stepBadge,
1802
+ active ? slots.stepBadgeActive : slots.stepBadgeInactive
1524
1803
  ),
1525
- children: "Browse the menu"
1804
+ children: n3
1526
1805
  }
1527
- )
1528
- }
1529
- ) });
1530
- }
1531
- if (error) {
1532
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shell, { slots, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1533
- StatusPanel,
1534
- {
1535
- slots,
1536
- title: "Something went wrong",
1537
- message: error,
1538
- tone: "error",
1539
- action: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1540
- import_link4.default,
1806
+ ),
1807
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1808
+ "p",
1541
1809
  {
1542
- href: menuHref,
1543
- className: cn6(
1544
- slots.primaryButton,
1545
- "block w-full text-center"
1810
+ className: cn3(
1811
+ slots.stepLabel,
1812
+ active ? slots.stepLabelActive : slots.stepLabelInactive
1546
1813
  ),
1547
- children: "Back to menu"
1548
- }
1549
- )
1550
- }
1551
- ) });
1552
- }
1553
- if (needsLocationSelection) {
1554
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shell, { slots, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1555
- StatusPanel,
1556
- {
1557
- slots,
1558
- title: "Choose a location",
1559
- message: "Please choose a location to continue checkout.",
1560
- action: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1561
- "button",
1562
- {
1563
- type: "button",
1564
- onClick: () => open("FIND_LOCATION_MODAL"),
1565
- className: cn6(slots.primaryButton, "w-full"),
1566
- children: "Select a location"
1814
+ children: label
1567
1815
  }
1568
1816
  )
1569
- }
1570
- ) });
1571
- }
1572
- if (isReady && elementOptions) {
1573
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shell, { slots, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1574
- import_react_stripe_js.Elements,
1575
- {
1576
- stripe,
1577
- options: elementOptions,
1578
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PaymentStep, { slots, checkoutHref })
1579
- },
1580
- currentLocation?.stripe_account_id
1581
- ) });
1582
- }
1583
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Shell, { slots, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(DetailsStep, { slots }) });
1817
+ ] }),
1818
+ i4 < labels.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1819
+ "div",
1820
+ {
1821
+ className: cn3(
1822
+ slots.stepDivider,
1823
+ current > n3 ? slots.stepDividerActive : slots.stepDividerInactive
1824
+ )
1825
+ }
1826
+ )
1827
+ ] }, label);
1828
+ }) });
1584
1829
  }
1585
- function StatusPanel({
1586
- title,
1587
- message,
1588
- action,
1589
- tone = "default",
1590
- slots
1830
+
1831
+ // src/components/client/CheckoutForm/ConsentFields.tsx
1832
+ var import_Form = require("@zorgo/next");
1833
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1834
+ function ConsentFields({
1835
+ termsLabel = "I have read and agree to the terms of service.",
1836
+ marketingLabel = "I consent to receive promotions via text and email.",
1837
+ slots = CHECKOUT_FORM_SLOTS
1591
1838
  }) {
1592
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn6(slots.statusPanel, slots.surface), children: [
1593
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h2", { className: slots.statusTitle, children: title }),
1594
- message && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1595
- "p",
1839
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
1840
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1841
+ import_Form.CheckboxField,
1596
1842
  {
1597
- className: tone === "error" ? slots.statusMessageError : slots.statusMessage,
1598
- children: message
1843
+ fieldId: "termsAccepted",
1844
+ required: true,
1845
+ requiredText: "You must agree to the terms of service to continue.",
1846
+ fieldErrorClassName: slots.fieldError,
1847
+ children: termsLabel
1599
1848
  }
1600
1849
  ),
1601
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: slots.statusActions, children: action })
1850
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_Form.CheckboxField, { fieldId: "marketingConsent", required: false, children: marketingLabel })
1602
1851
  ] });
1603
1852
  }
1604
- function DetailsStep({ slots }) {
1605
- const {
1606
- items,
1607
- subtotal,
1608
- discount,
1609
- tax,
1610
- serviceFee,
1611
- total,
1612
- removeItem,
1613
- resetCart
1614
- } = (0, import_hooks4.useCart)();
1615
- const { customer, setCustomer } = (0, import_hooks4.useCustomer)();
1616
- const { startCheckout } = (0, import_hooks4.usePayment)();
1617
- const [submitError, setSubmitError] = (0, import_react16.useState)();
1618
- const fieldContainerClass = slots.fieldContainer;
1853
+
1854
+ // src/components/client/CheckoutForm/ContactFields.tsx
1855
+ var import_Form2 = require("@zorgo/next");
1856
+ var import_hooks3 = require("@zorgo/next");
1857
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1858
+ function ContactFields({
1859
+ slots = CHECKOUT_FORM_SLOTS
1860
+ }) {
1861
+ const { customer } = (0, import_hooks3.useCustomer)();
1619
1862
  const fieldStyleProps = {
1620
1863
  fieldClassName: slots.fieldInput,
1621
- containerClassName: fieldContainerClass,
1864
+ containerClassName: slots.fieldContainer,
1622
1865
  fieldLabelClassName: slots.fieldLabel,
1623
1866
  fieldErrorClassName: slots.fieldError
1624
1867
  };
1625
- const handleSubmit = async (values) => {
1626
- const filledCustomer = {
1627
- first_name: values.firstName,
1628
- last_name: values.lastName,
1629
- phone: values.phone,
1630
- email: values.email,
1631
- allow_marketing: values.marketingConsent
1632
- };
1633
- setCustomer(filledCustomer);
1634
- try {
1635
- await startCheckout();
1636
- } catch (err) {
1637
- setSubmitError(
1638
- err instanceof Error ? err.message : "Could not start payment."
1639
- );
1640
- }
1641
- };
1642
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.stepSection, children: [
1643
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Steps, { current: 1, slots }),
1644
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h2", { className: slots.sectionTitle, children: "Your order" }),
1645
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: slots.cartList, children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1646
- CartLine,
1868
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
1869
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1870
+ import_Form2.NameFields,
1647
1871
  {
1648
- item,
1649
- index,
1650
- onRemove: () => removeItem(index),
1651
- slots
1652
- },
1653
- `${item.item_id}-${index}`
1654
- )) }),
1655
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn6(slots.totals, slots.surface), children: [
1656
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.totalsRow, children: [
1657
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Subtotal" }),
1658
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: money4(subtotal) })
1659
- ] }),
1660
- discount > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.totalsRow, children: [
1661
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Discount" }),
1662
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: money4(-discount) })
1663
- ] }),
1664
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.totalsRow, children: [
1665
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Tax" }),
1666
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: money4(tax) })
1667
- ] }),
1668
- serviceFee > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.totalsRow, children: [
1669
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Service fee" }),
1670
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: serviceFee })
1671
- ] }),
1672
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: slots.totalsDivider }),
1673
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.totalsTotalRow, children: [
1674
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "Total" }),
1675
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: money4(total) })
1676
- ] })
1677
- ] }),
1678
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PromoCode, { slots }),
1679
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h2", { className: slots.sectionTitle, children: "Contact information" }),
1680
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_Form.DynamicFormShell, { onSubmit: handleSubmit, className: slots.form, children: [
1681
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1682
- import_Form.NameFields,
1872
+ firstNameInitialValue: customer.first_name ?? "",
1873
+ lastNameInitialValue: customer.last_name ?? "",
1874
+ fieldClassName: slots.fieldInput,
1875
+ fieldLabelClassName: slots.fieldLabel,
1876
+ fieldErrorClassName: slots.fieldError,
1877
+ childClassName: cn3(
1878
+ slots.fieldContainer,
1879
+ "md:flex-1 md:min-w-0"
1880
+ )
1881
+ }
1882
+ ),
1883
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col w-full gap-1", children: [
1884
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1885
+ import_Form2.PhoneField,
1683
1886
  {
1684
- firstNameInitialValue: customer.first_name ?? "",
1685
- lastNameInitialValue: customer.last_name ?? "",
1686
- fieldClassName: slots.fieldInput,
1687
- fieldLabelClassName: slots.fieldLabel,
1688
- fieldErrorClassName: slots.fieldError,
1689
- childClassName: cn6(
1690
- fieldContainerClass,
1691
- "md:flex-1 md:min-w-0"
1692
- )
1887
+ initialValue: customer.phone ?? "",
1888
+ showError: false,
1889
+ ...fieldStyleProps
1693
1890
  }
1694
1891
  ),
1695
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col w-full gap-1", children: [
1696
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1697
- import_Form.PhoneField,
1698
- {
1699
- initialValue: customer.phone ?? "",
1700
- showError: false,
1701
- ...fieldStyleProps
1702
- }
1703
- ),
1704
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_Form.FieldError, { name: "phone", className: slots.fieldError })
1705
- ] }),
1706
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col w-full gap-1", children: [
1707
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1708
- import_Form.EmailField,
1709
- {
1710
- initialValue: customer.email ?? "",
1711
- showError: false,
1712
- ...fieldStyleProps
1713
- }
1714
- ),
1715
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_Form.FieldError, { name: "email", className: slots.fieldError })
1716
- ] }),
1717
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1718
- import_Form.CheckboxField,
1892
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_Form2.FieldError, { name: "phone", className: slots.fieldError })
1893
+ ] }),
1894
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col w-full gap-1", children: [
1895
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1896
+ import_Form2.EmailField,
1719
1897
  {
1720
- fieldId: "termsAccepted",
1721
- required: true,
1722
- requiredText: "You must agree to the terms of service to continue.",
1723
- fieldErrorClassName: slots.fieldError,
1724
- children: "I have read and agree to the terms of service."
1898
+ initialValue: customer.email ?? "",
1899
+ showError: false,
1900
+ ...fieldStyleProps
1725
1901
  }
1726
1902
  ),
1727
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_Form.CheckboxField, { fieldId: "marketingConsent", required: false, children: "I consent to receive promotions via text and email." }),
1728
- submitError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: slots.submitError, children: submitError }),
1729
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.formActions, children: [
1730
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1731
- "button",
1732
- {
1733
- type: "button",
1734
- onClick: resetCart,
1735
- className: slots.secondaryButton,
1736
- children: "Clear cart"
1737
- }
1738
- ),
1739
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1740
- import_Form.SubmitButton,
1741
- {
1742
- label: "Continue to payment",
1743
- loadingLabel: "Setting up...",
1744
- className: cn6("flex-1", slots.primaryButton)
1745
- }
1746
- )
1747
- ] })
1903
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_Form2.FieldError, { name: "email", className: slots.fieldError })
1748
1904
  ] })
1749
1905
  ] });
1750
1906
  }
1751
- function PaymentStep({
1752
- slots,
1753
- checkoutHref
1754
- }) {
1755
- const stripe = (0, import_react_stripe_js.useStripe)();
1756
- const elements = (0, import_react_stripe_js.useElements)();
1757
- const {
1758
- total,
1759
- clientSecret,
1760
- submitPayment,
1761
- paymentElementOptions,
1762
- getReturnUrl,
1763
- resetCheckout
1764
- } = (0, import_hooks4.usePayment)();
1765
- const { customer } = (0, import_hooks4.useCustomer)();
1766
- const [submitError, setSubmitError] = (0, import_react16.useState)();
1767
- const handleSubmit = async () => {
1768
- if (!stripe || !elements || !clientSecret) return;
1769
- const { error } = await elements.submit();
1770
- if (error) {
1771
- setSubmitError(error.message ?? "Please check your card details.");
1772
- throw error;
1773
- }
1774
- const returnUrl = `${getReturnUrl()}${checkoutHref.startsWith("/") ? checkoutHref : `/${checkoutHref}`}`;
1775
- const result = await submitPayment(
1776
- stripe,
1777
- elements,
1778
- clientSecret,
1779
- returnUrl,
1780
- customer
1781
- );
1782
- if (!result.success) setSubmitError(result.error);
1783
- };
1784
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.stepSection, children: [
1785
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Steps, { current: 2, slots }),
1786
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_Form.DynamicFormShell, { onSubmit: handleSubmit, className: slots.form, children: [
1787
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: cn6(slots.paymentSurface, slots.surface), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_react_stripe_js.PaymentElement, { options: paymentElementOptions }) }),
1788
- submitError && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: slots.submitError, children: submitError }),
1789
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.formActions, children: [
1790
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1791
- "button",
1792
- {
1793
- type: "button",
1794
- onClick: resetCheckout,
1795
- className: slots.secondaryButton,
1796
- children: "Back to order"
1797
- }
1798
- ),
1799
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1800
- import_Form.SubmitButton,
1801
- {
1802
- label: `Pay ${money4(total ?? 0)}`,
1803
- loadingLabel: "Processing...",
1804
- className: cn6("flex-1", slots.primaryButton)
1805
- }
1806
- )
1807
- ] })
1808
- ] })
1809
- ] });
1810
- }
1811
- function Steps({ current, slots }) {
1812
- const labels = ["Your details", "Payment"];
1813
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: slots.steps, children: labels.map((label, i4) => {
1814
- const n3 = i4 + 1;
1815
- const active = n3 <= current;
1816
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "contents", children: [
1817
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
1818
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1819
- "div",
1820
- {
1821
- className: cn6(
1822
- slots.stepBadge,
1823
- active ? slots.stepBadgeActive : slots.stepBadgeInactive
1824
- ),
1825
- children: n3
1826
- }
1827
- ),
1828
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1829
- "p",
1830
- {
1831
- className: cn6(
1832
- slots.stepLabel,
1833
- active ? slots.stepLabelActive : slots.stepLabelInactive
1834
- ),
1835
- children: label
1836
- }
1837
- )
1838
- ] }),
1839
- i4 < labels.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1840
- "div",
1841
- {
1842
- className: cn6(
1843
- slots.stepDivider,
1844
- current > n3 ? slots.stepDividerActive : slots.stepDividerInactive
1845
- )
1846
- }
1847
- )
1848
- ] }, label);
1849
- }) });
1850
- }
1851
- function CartLine({
1907
+
1908
+ // src/components/client/CheckoutForm/OrderLine.tsx
1909
+ var import_lucide_react5 = require("lucide-react");
1910
+ var import_hooks4 = require("@zorgo/next");
1911
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1912
+ function OrderLine({
1852
1913
  item,
1853
1914
  index,
1854
1915
  onRemove,
1855
- slots
1916
+ slots = CHECKOUT_FORM_SLOTS
1856
1917
  }) {
1857
1918
  const { open } = (0, import_hooks4.useModal)();
1858
1919
  const { updateItem, getItemTotal } = (0, import_hooks4.useCart)();
1859
1920
  const setQuantity = (next) => next < 1 ? onRemove() : updateItem({ ...item, quantity: next }, index);
1860
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn6(slots.cartLine, slots.surface), children: [
1861
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-1 flex-1 min-w-0", children: [
1862
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: slots.cartLineName, children: item.name }),
1863
- (() => {
1864
- const added = (item.selections ?? []).flatMap((rs) => rs.selections.map((s5) => s5.name));
1865
- const removed = (item.components ?? []).filter((c6) => c6.quantity_servings === 0).map((c6) => c6.name);
1866
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
1867
- added.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: slots.cartLineSelection, children: [
1868
- "Add ",
1869
- added.join(", ")
1870
- ] }),
1871
- removed.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: slots.cartLineSelection, children: [
1872
- "Remove ",
1873
- removed.join(", ")
1874
- ] }),
1875
- item.comments && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: slots.cartLineSelection, children: [
1876
- "Comments: ",
1877
- item.comments
1878
- ] })
1879
- ] });
1880
- })(),
1881
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: slots.cartLinePrice, children: money4(getItemTotal(item)) })
1921
+ const added = (item.selections ?? []).flatMap(
1922
+ (rs) => rs.selections.map((s5) => s5.name)
1923
+ );
1924
+ const removed = (item.components ?? []).filter((c6) => c6.quantity_servings === 0).map((c6) => c6.name);
1925
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: cn3(slots.cartLine, slots.surface), children: [
1926
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-col gap-1 flex-1 min-w-0", children: [
1927
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: slots.cartLineName, children: item.name }),
1928
+ added.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("p", { className: slots.cartLineSelection, children: [
1929
+ "Add ",
1930
+ added.join(", ")
1931
+ ] }),
1932
+ removed.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("p", { className: slots.cartLineSelection, children: [
1933
+ "Remove ",
1934
+ removed.join(", ")
1935
+ ] }),
1936
+ item.comments && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("p", { className: slots.cartLineSelection, children: [
1937
+ "Comments: ",
1938
+ item.comments
1939
+ ] }),
1940
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: slots.cartLinePrice, children: money3(getItemTotal(item)) })
1882
1941
  ] }),
1883
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.cartLineControls, children: [
1884
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1942
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: slots.cartLineControls, children: [
1943
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1885
1944
  "button",
1886
1945
  {
1887
1946
  type: "button",
@@ -1892,41 +1951,96 @@ function CartLine({
1892
1951
  seed: item,
1893
1952
  editIndex: index
1894
1953
  }),
1895
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react5.Pencil, { className: "w-5 h-5" })
1954
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react5.Pencil, { className: "w-5 h-5" })
1896
1955
  }
1897
1956
  ),
1898
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1957
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1899
1958
  "button",
1900
1959
  {
1901
1960
  type: "button",
1902
1961
  className: slots.incrementButton,
1903
1962
  onClick: () => setQuantity(item.quantity - 1),
1904
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react5.Minus, { className: "w-5 h-5" })
1963
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react5.Minus, { className: "w-5 h-5" })
1905
1964
  }
1906
1965
  ),
1907
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: slots.cartLineQuantity, children: item.quantity }),
1908
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1966
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: slots.cartLineQuantity, children: item.quantity }),
1967
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1909
1968
  "button",
1910
1969
  {
1911
1970
  type: "button",
1912
1971
  className: slots.incrementButton,
1913
1972
  onClick: () => setQuantity(item.quantity + 1),
1914
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react5.Plus, { className: "w-5 h-5" })
1973
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react5.Plus, { className: "w-5 h-5" })
1915
1974
  }
1916
1975
  )
1917
1976
  ] })
1918
1977
  ] });
1919
1978
  }
1920
- function PromoCode({ slots }) {
1921
- const { promoCode, appliedPromo, applyPromo, removePromo, error, loading } = (0, import_hooks4.usePromotions)();
1922
- const [draft, setDraft] = (0, import_react16.useState)("");
1979
+ function OrderLines({
1980
+ slots = CHECKOUT_FORM_SLOTS
1981
+ }) {
1982
+ const { items, removeItem } = (0, import_hooks4.useCart)();
1983
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: slots.cartList, children: items.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
1984
+ OrderLine,
1985
+ {
1986
+ item,
1987
+ index,
1988
+ onRemove: () => removeItem(index),
1989
+ slots
1990
+ },
1991
+ `${item.item_id}-${index}`
1992
+ )) });
1993
+ }
1994
+
1995
+ // src/components/client/CheckoutForm/OrderTotals.tsx
1996
+ var import_hooks5 = require("@zorgo/next");
1997
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1998
+ function OrderTotals({
1999
+ slots = CHECKOUT_FORM_SLOTS
2000
+ }) {
2001
+ const { subtotal, discount, tax, serviceFee, total } = (0, import_hooks5.useCart)();
2002
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: cn3(slots.totals, slots.surface), children: [
2003
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: slots.totalsRow, children: [
2004
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "Subtotal" }),
2005
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: money3(subtotal) })
2006
+ ] }),
2007
+ discount > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: slots.totalsRow, children: [
2008
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "Discount" }),
2009
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: money3(-discount) })
2010
+ ] }),
2011
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: slots.totalsRow, children: [
2012
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "Tax" }),
2013
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: money3(tax) })
2014
+ ] }),
2015
+ serviceFee > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: slots.totalsRow, children: [
2016
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "Service fee" }),
2017
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: money3(serviceFee) })
2018
+ ] }),
2019
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: slots.totalsDivider }),
2020
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: slots.totalsTotalRow, children: [
2021
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: "Total" }),
2022
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { children: money3(total) })
2023
+ ] })
2024
+ ] });
2025
+ }
2026
+
2027
+ // src/components/client/CheckoutForm/PromoCode.tsx
2028
+ var import_react17 = require("react");
2029
+ var import_hooks6 = require("@zorgo/next");
2030
+ var import_jsx_runtime22 = require("react/jsx-runtime");
2031
+ function PromoCode({
2032
+ placeholder = "Promo code",
2033
+ slots = CHECKOUT_FORM_SLOTS
2034
+ }) {
2035
+ const { promoCode, appliedPromo, applyPromo, removePromo, error, loading } = (0, import_hooks6.usePromotions)();
2036
+ const [draft, setDraft] = (0, import_react17.useState)("");
1923
2037
  if (appliedPromo) {
1924
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn6(slots.promoApplied, slots.surface), children: [
1925
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: slots.promoAppliedLabel, children: [
2038
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: cn3(slots.promoApplied, slots.surface), children: [
2039
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("span", { className: slots.promoAppliedLabel, children: [
1926
2040
  appliedPromo.name,
1927
2041
  " applied"
1928
2042
  ] }),
1929
- promoCode && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2043
+ promoCode && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1930
2044
  "button",
1931
2045
  {
1932
2046
  type: "button",
@@ -1937,39 +2051,294 @@ function PromoCode({ slots }) {
1937
2051
  )
1938
2052
  ] });
1939
2053
  }
1940
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-2 w-full", children: [
1941
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.promoRow, children: [
1942
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2054
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-col gap-2 w-full", children: [
2055
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: slots.promoRow, children: [
2056
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1943
2057
  "input",
1944
2058
  {
1945
2059
  value: draft,
1946
2060
  onChange: (e) => setDraft(e.target.value),
1947
- placeholder: "Promo code",
2061
+ placeholder,
1948
2062
  className: slots.promoInput
1949
2063
  }
1950
2064
  ),
1951
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2065
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1952
2066
  "button",
1953
2067
  {
1954
2068
  type: "button",
1955
2069
  disabled: loading || !draft.trim(),
1956
2070
  onClick: () => applyPromo(draft),
1957
- className: cn6(slots.primaryButton, "shrink-0"),
2071
+ className: cn3(slots.primaryButton, "shrink-0"),
1958
2072
  children: loading ? "Applying\u2026" : "Apply"
1959
2073
  }
1960
2074
  )
1961
2075
  ] }),
1962
- error && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: slots.promoError, children: error })
2076
+ error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: slots.promoError, children: error })
1963
2077
  ] });
1964
2078
  }
1965
- function Shell({
1966
- children,
1967
- slots
2079
+
2080
+ // src/components/client/CheckoutForm/DetailsStep.tsx
2081
+ var import_jsx_runtime23 = require("react/jsx-runtime");
2082
+ function DetailsStep({
2083
+ slots = CHECKOUT_FORM_SLOTS
1968
2084
  }) {
1969
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: slots.shell, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: slots.shellInner, children: [
1970
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h1", { className: slots.pageTitle, children: "Checkout" }),
1971
- children
1972
- ] }) });
2085
+ const { resetCart } = (0, import_hooks7.useCart)();
2086
+ const { setCustomer } = (0, import_hooks7.useCustomer)();
2087
+ const { startCheckout } = (0, import_hooks7.usePayment)();
2088
+ const [submitError, setSubmitError] = (0, import_react18.useState)();
2089
+ const handleSubmit = async (values) => {
2090
+ const filledCustomer = {
2091
+ first_name: values.firstName,
2092
+ last_name: values.lastName,
2093
+ phone: values.phone,
2094
+ email: values.email,
2095
+ allow_marketing: values.marketingConsent
2096
+ };
2097
+ setCustomer(filledCustomer);
2098
+ try {
2099
+ await startCheckout();
2100
+ } catch (err) {
2101
+ setSubmitError(
2102
+ err instanceof Error ? err.message : "Could not start payment."
2103
+ );
2104
+ }
2105
+ };
2106
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: slots.stepSection, children: [
2107
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CheckoutSteps, { current: 1, slots }),
2108
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: slots.sectionTitle, children: "Your order" }),
2109
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(OrderLines, { slots }),
2110
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(OrderTotals, { slots }),
2111
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PromoCode, { slots }),
2112
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("h2", { className: slots.sectionTitle, children: "Contact information" }),
2113
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_Form3.DynamicFormShell, { onSubmit: handleSubmit, className: slots.form, children: [
2114
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ContactFields, { slots }),
2115
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ConsentFields, { slots }),
2116
+ submitError && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: slots.submitError, children: submitError }),
2117
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: slots.formActions, children: [
2118
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2119
+ "button",
2120
+ {
2121
+ type: "button",
2122
+ onClick: resetCart,
2123
+ className: slots.secondaryButton,
2124
+ children: "Clear cart"
2125
+ }
2126
+ ),
2127
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
2128
+ import_Form3.SubmitButton,
2129
+ {
2130
+ label: "Continue to payment",
2131
+ loadingLabel: "Setting up...",
2132
+ className: cn3("flex-1", slots.primaryButton)
2133
+ }
2134
+ )
2135
+ ] })
2136
+ ] })
2137
+ ] });
2138
+ }
2139
+
2140
+ // src/components/client/CheckoutForm/PaymentStep.tsx
2141
+ var import_react19 = require("react");
2142
+ var import_react_stripe_js = require("@stripe/react-stripe-js");
2143
+ var import_Form4 = require("@zorgo/next");
2144
+ var import_hooks8 = require("@zorgo/next");
2145
+ var import_jsx_runtime24 = require("react/jsx-runtime");
2146
+ function PaymentStep({
2147
+ slots = CHECKOUT_FORM_SLOTS,
2148
+ checkoutHref = "/checkout"
2149
+ }) {
2150
+ const stripe = (0, import_react_stripe_js.useStripe)();
2151
+ const elements = (0, import_react_stripe_js.useElements)();
2152
+ const {
2153
+ total,
2154
+ clientSecret,
2155
+ submitPayment,
2156
+ paymentElementOptions,
2157
+ getReturnUrl,
2158
+ resetCheckout
2159
+ } = (0, import_hooks8.usePayment)();
2160
+ const { customer } = (0, import_hooks8.useCustomer)();
2161
+ const [submitError, setSubmitError] = (0, import_react19.useState)();
2162
+ const handleSubmit = async () => {
2163
+ if (!stripe || !elements || !clientSecret) return;
2164
+ const { error } = await elements.submit();
2165
+ if (error) {
2166
+ setSubmitError(error.message ?? "Please check your card details.");
2167
+ throw error;
2168
+ }
2169
+ const returnUrl = `${getReturnUrl()}${checkoutHref.startsWith("/") ? checkoutHref : `/${checkoutHref}`}`;
2170
+ const result = await submitPayment(
2171
+ stripe,
2172
+ elements,
2173
+ clientSecret,
2174
+ returnUrl,
2175
+ customer
2176
+ );
2177
+ if (!result.success) setSubmitError(result.error);
2178
+ };
2179
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: slots.stepSection, children: [
2180
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CheckoutSteps, { current: 2, slots }),
2181
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_Form4.DynamicFormShell, { onSubmit: handleSubmit, className: slots.form, children: [
2182
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: cn3(slots.paymentSurface, slots.surface), children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_react_stripe_js.PaymentElement, { options: paymentElementOptions }) }),
2183
+ submitError && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: slots.submitError, children: submitError }),
2184
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: slots.formActions, children: [
2185
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2186
+ "button",
2187
+ {
2188
+ type: "button",
2189
+ onClick: resetCheckout,
2190
+ className: slots.secondaryButton,
2191
+ children: "Back to order"
2192
+ }
2193
+ ),
2194
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
2195
+ import_Form4.SubmitButton,
2196
+ {
2197
+ label: `Pay ${money3(total ?? 0)}`,
2198
+ loadingLabel: "Processing...",
2199
+ className: cn3("flex-1", slots.primaryButton)
2200
+ }
2201
+ )
2202
+ ] })
2203
+ ] })
2204
+ ] });
2205
+ }
2206
+
2207
+ // src/components/client/CheckoutForm/StatusPanel.tsx
2208
+ var import_jsx_runtime25 = require("react/jsx-runtime");
2209
+ function StatusPanel({
2210
+ title,
2211
+ message,
2212
+ action,
2213
+ tone = "default",
2214
+ slots = CHECKOUT_FORM_SLOTS
2215
+ }) {
2216
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: cn3(slots.statusPanel, slots.surface), children: [
2217
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h2", { className: slots.statusTitle, children: title }),
2218
+ message && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
2219
+ "p",
2220
+ {
2221
+ className: tone === "error" ? slots.statusMessageError : slots.statusMessage,
2222
+ children: message
2223
+ }
2224
+ ),
2225
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: slots.statusActions, children: action })
2226
+ ] });
2227
+ }
2228
+
2229
+ // src/components/client/CheckoutForm/CheckoutForm.tsx
2230
+ var import_jsx_runtime26 = require("react/jsx-runtime");
2231
+ function CheckoutForm({
2232
+ itemClasses,
2233
+ homeHref = "/",
2234
+ menuHref = "/menu",
2235
+ checkoutHref = "/checkout"
2236
+ }) {
2237
+ const slots = mergeCheckoutFormItemClasses(itemClasses);
2238
+ const {
2239
+ clientSecret,
2240
+ stripe,
2241
+ elementOptions,
2242
+ isReady,
2243
+ isLoading,
2244
+ error,
2245
+ getReturnStatus
2246
+ } = (0, import_hooks9.usePayment)();
2247
+ const { isEmpty, resetCart } = (0, import_hooks9.useCart)();
2248
+ const { currentLocation, needsLocationSelection } = (0, import_hooks9.useLocation)({
2249
+ promptLocationSelection: true
2250
+ });
2251
+ const { open } = (0, import_hooks9.useModal)();
2252
+ const [returnStatus, setReturnStatus] = (0, import_react20.useState)(null);
2253
+ (0, import_react20.useEffect)(() => {
2254
+ if (window.location.search.includes("redirect_status")) {
2255
+ const status = getReturnStatus(window.location.href);
2256
+ setReturnStatus(status);
2257
+ if (status.succeeded) resetCart();
2258
+ }
2259
+ }, []);
2260
+ const linkAction = (href, label) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2261
+ import_link4.default,
2262
+ {
2263
+ href,
2264
+ className: cn3(slots.primaryButton, "block w-full text-center"),
2265
+ children: label
2266
+ }
2267
+ );
2268
+ if (returnStatus) {
2269
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CheckoutShell, { slots, children: returnStatus.succeeded ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2270
+ StatusPanel,
2271
+ {
2272
+ slots,
2273
+ title: "You're all set",
2274
+ message: "Payment successful. Thank you!",
2275
+ action: linkAction(homeHref, "Back home")
2276
+ }
2277
+ ) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2278
+ StatusPanel,
2279
+ {
2280
+ slots,
2281
+ title: "Payment didn't go through",
2282
+ message: returnStatus.error,
2283
+ tone: "error",
2284
+ action: linkAction(checkoutHref, "Try again")
2285
+ }
2286
+ ) });
2287
+ }
2288
+ if (isEmpty && !isLoading && !clientSecret) {
2289
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CheckoutShell, { slots, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2290
+ StatusPanel,
2291
+ {
2292
+ slots,
2293
+ title: "Your cart is empty",
2294
+ message: "Add something from the menu to get started.",
2295
+ action: linkAction(menuHref, "Browse the menu")
2296
+ }
2297
+ ) });
2298
+ }
2299
+ if (error) {
2300
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CheckoutShell, { slots, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2301
+ StatusPanel,
2302
+ {
2303
+ slots,
2304
+ title: "Something went wrong",
2305
+ message: error,
2306
+ tone: "error",
2307
+ action: linkAction(menuHref, "Back to menu")
2308
+ }
2309
+ ) });
2310
+ }
2311
+ if (needsLocationSelection) {
2312
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CheckoutShell, { slots, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2313
+ StatusPanel,
2314
+ {
2315
+ slots,
2316
+ title: "Choose a location",
2317
+ message: "Please choose a location to continue checkout.",
2318
+ action: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2319
+ "button",
2320
+ {
2321
+ type: "button",
2322
+ onClick: () => open("FIND_LOCATION_MODAL"),
2323
+ className: cn3(slots.primaryButton, "w-full"),
2324
+ children: "Select a location"
2325
+ }
2326
+ )
2327
+ }
2328
+ ) });
2329
+ }
2330
+ if (isReady && elementOptions) {
2331
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CheckoutShell, { slots, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2332
+ import_react_stripe_js2.Elements,
2333
+ {
2334
+ stripe,
2335
+ options: elementOptions,
2336
+ children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(PaymentStep, { slots, checkoutHref })
2337
+ },
2338
+ currentLocation?.stripe_account_id
2339
+ ) });
2340
+ }
2341
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(CheckoutShell, { slots, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(DetailsStep, { slots }) });
1973
2342
  }
1974
2343
  // Annotate the CommonJS export names for ESM import in node:
1975
2344
  0 && (module.exports = {
@@ -1978,19 +2347,46 @@ function Shell({
1978
2347
  BREADCRUMBS_DEFAULT_ITEM_CLASSES,
1979
2348
  Breadcrumbs,
1980
2349
  CHECKOUT_FORM_DEFAULT_ITEM_CLASSES,
2350
+ CHECKOUT_FORM_SLOTS,
2351
+ CLIENT_ITEM_FORM_DEFAULT_ITEM_CLASSES,
2352
+ CLIENT_ITEM_FORM_SLOTS,
1981
2353
  CheckoutForm,
2354
+ CheckoutShell,
2355
+ CheckoutSteps,
2356
+ ClientItemForm,
2357
+ CommentsSection,
2358
+ ComponentsSection,
2359
+ ConsentFields,
2360
+ ContactFields,
1982
2361
  CookieConsent,
2362
+ DetailsStep,
1983
2363
  FIND_LOCATION_DEFAULT_ITEM_CLASSES,
1984
2364
  FindLocation,
1985
2365
  GRID_MENU_DEFAULT_ITEM_CLASSES,
1986
2366
  GridMenu,
1987
2367
  ITEM_CUSTOMIZATION_FORM_DEFAULT_ITEM_CLASSES,
2368
+ ItemCustomizationClient,
1988
2369
  ItemCustomizationForm,
2370
+ OptionButton,
2371
+ OrderLine,
2372
+ OrderLines,
2373
+ OrderTotals,
2374
+ PaymentStep,
2375
+ PortionPicker,
2376
+ PortionSection,
2377
+ PromoCode,
2378
+ QuantitySection,
2379
+ RuleSection,
2380
+ StatusPanel,
2381
+ SubmitButton,
2382
+ VariantSection,
1989
2383
  mergeAccordionMenuItemClasses,
1990
2384
  mergeBreadcrumbsItemClasses,
1991
2385
  mergeCheckoutFormItemClasses,
2386
+ mergeClientItemFormItemClasses,
1992
2387
  mergeFindLocationItemClasses,
1993
2388
  mergeGridMenuItemClasses,
1994
- mergeItemCustomizationFormItemClasses
2389
+ mergeItemCustomizationFormItemClasses,
2390
+ money
1995
2391
  });
1996
2392
  //# sourceMappingURL=components.js.map