@swift-food-services/catering-widget 0.2.0-beta.10 → 0.2.0-beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -3615,6 +3615,9 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
3615
3615
  .swift-catering-widget .bottom-1\\.5 {
3616
3616
  bottom: calc(var(--spacing) * 1.5);
3617
3617
  }
3618
+ .swift-catering-widget .bottom-2 {
3619
+ bottom: calc(var(--spacing) * 2);
3620
+ }
3618
3621
  .swift-catering-widget .bottom-3 {
3619
3622
  bottom: calc(var(--spacing) * 3);
3620
3623
  }
@@ -4582,6 +4585,10 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
4582
4585
  border-top-left-radius: var(--radius-2xl);
4583
4586
  border-top-right-radius: var(--radius-2xl);
4584
4587
  }
4588
+ .swift-catering-widget .rounded-t-xl {
4589
+ border-top-left-radius: var(--radius-xl);
4590
+ border-top-right-radius: var(--radius-xl);
4591
+ }
4585
4592
  .swift-catering-widget .rounded-l-full {
4586
4593
  border-top-left-radius: 3.40282e38px;
4587
4594
  border-bottom-left-radius: 3.40282e38px;
@@ -5340,6 +5347,9 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
5340
5347
  .swift-catering-widget .pb-4 {
5341
5348
  padding-bottom: calc(var(--spacing) * 4);
5342
5349
  }
5350
+ .swift-catering-widget .pb-5 {
5351
+ padding-bottom: calc(var(--spacing) * 5);
5352
+ }
5343
5353
  .swift-catering-widget .pb-6 {
5344
5354
  padding-bottom: calc(var(--spacing) * 6);
5345
5355
  }
@@ -6342,6 +6352,9 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
6342
6352
  .swift-catering-widget .hover\\:text-gray-700:hover {
6343
6353
  color: var(--color-gray-700);
6344
6354
  }
6355
+ .swift-catering-widget .hover\\:text-gray-800:hover {
6356
+ color: var(--color-gray-800);
6357
+ }
6345
6358
  .swift-catering-widget .hover\\:text-green-600:hover {
6346
6359
  color: var(--color-green-600);
6347
6360
  }
@@ -6375,6 +6388,9 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
6375
6388
  .swift-catering-widget .hover\\:opacity-90:hover {
6376
6389
  opacity: .9;
6377
6390
  }
6391
+ .swift-catering-widget .hover\\:opacity-100:hover {
6392
+ opacity: 1;
6393
+ }
6378
6394
  .swift-catering-widget .hover\\:shadow-md:hover {
6379
6395
  --tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);
6380
6396
  box-shadow:
@@ -6474,6 +6490,18 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
6474
6490
  .swift-catering-widget .disabled\\:opacity-50:disabled {
6475
6491
  opacity: .5;
6476
6492
  }
6493
+ .swift-catering-widget .disabled\\:opacity-60:disabled {
6494
+ opacity: .6;
6495
+ }
6496
+ .swift-catering-widget .disabled\\:shadow-none:disabled {
6497
+ --tw-shadow:0 0 #0000;
6498
+ box-shadow:
6499
+ var(--tw-inset-shadow),
6500
+ var(--tw-inset-ring-shadow),
6501
+ var(--tw-ring-offset-shadow),
6502
+ var(--tw-ring-shadow),
6503
+ var(--tw-shadow);
6504
+ }
6477
6505
  @media (hover: hover) {
6478
6506
  .swift-catering-widget .disabled\\:hover\\:bg-base-100:disabled:hover {
6479
6507
  background-color: var(--color-base-100);
@@ -7451,6 +7479,19 @@ function createCateringApi(client) {
7451
7479
  };
7452
7480
  }
7453
7481
 
7482
+ // src/api/endpoints/shared-cart.ts
7483
+ function createSharedCartApi(client) {
7484
+ return {
7485
+ create: (payload) => client.requestJson("/shared-carts", {
7486
+ method: "POST",
7487
+ body: JSON.stringify(payload)
7488
+ }),
7489
+ get: (id) => client.requestJson(
7490
+ `/shared-carts/${id}`
7491
+ )
7492
+ };
7493
+ }
7494
+
7454
7495
  // src/api/endpoints/me.ts
7455
7496
  async function safeJson(res) {
7456
7497
  try {
@@ -7601,6 +7642,7 @@ function createApiEndpoints(client) {
7601
7642
  bundles: createBundlesApi(client),
7602
7643
  pricing: createPricingApi(client),
7603
7644
  catering: createCateringApi(client),
7645
+ sharedCart: createSharedCartApi(client),
7604
7646
  me: createMeApi(client),
7605
7647
  chat: createChatEndpoints(client)
7606
7648
  };
@@ -7928,6 +7970,12 @@ function CateringStateProvider({ children }) {
7928
7970
  return updated;
7929
7971
  });
7930
7972
  };
7973
+ const loadMealSessions = (sessions) => {
7974
+ const next = sessions.length > 0 ? sessions : [createDefaultSession()];
7975
+ setMealSessionsState(next);
7976
+ saveMealSessions(next);
7977
+ setActiveSessionIndex(0);
7978
+ };
7931
7979
  const updateMealSession = (index, updates) => {
7932
7980
  setMealSessionsState((prev) => {
7933
7981
  if (index < 0 || index >= prev.length) return prev;
@@ -8119,6 +8167,7 @@ function CateringStateProvider({ children }) {
8119
8167
  updateMealSession,
8120
8168
  removeMealSession,
8121
8169
  setActiveSessionIndex,
8170
+ loadMealSessions,
8122
8171
  addMenuItem,
8123
8172
  removeMenuItem,
8124
8173
  removeMenuItemByIndex,
@@ -8149,54 +8198,6 @@ function useCateringState() {
8149
8198
  }
8150
8199
  return context;
8151
8200
  }
8152
- var FilterContext = react.createContext(void 0);
8153
- var STORAGE_KEY = "catering_filters";
8154
- var defaultFilters = {
8155
- dietaryRestrictions: [],
8156
- allergens: [],
8157
- pricePerPersonRange: null,
8158
- restaurantPriceRange: null
8159
- };
8160
- function CateringFilterProvider({ children }) {
8161
- const storage = useStorage();
8162
- const [filters, setFiltersState] = react.useState(defaultFilters);
8163
- const [isInitialized, setIsInitialized] = react.useState(false);
8164
- react.useEffect(() => {
8165
- try {
8166
- const stored = storage.getItem(STORAGE_KEY);
8167
- if (stored) {
8168
- setFiltersState(JSON.parse(stored));
8169
- }
8170
- } catch (error) {
8171
- console.error("Failed to load filters from storage:", error);
8172
- }
8173
- setIsInitialized(true);
8174
- }, [storage]);
8175
- react.useEffect(() => {
8176
- if (isInitialized) {
8177
- try {
8178
- storage.setItem(STORAGE_KEY, JSON.stringify(filters));
8179
- } catch (error) {
8180
- console.error("Failed to save filters to storage:", error);
8181
- }
8182
- }
8183
- }, [filters, isInitialized, storage]);
8184
- const setFilters = (newFilters) => setFiltersState(newFilters);
8185
- const clearFilters = () => setFiltersState(defaultFilters);
8186
- return /* @__PURE__ */ jsxRuntime.jsx(FilterContext.Provider, { value: { filters, setFilters, clearFilters }, children });
8187
- }
8188
- function useCateringFilters() {
8189
- const context = react.useContext(FilterContext);
8190
- if (context === void 0) {
8191
- throw new Error(
8192
- "useCateringFilters must be used within a CateringFilterProvider"
8193
- );
8194
- }
8195
- return context;
8196
- }
8197
- function useSearchParams() {
8198
- return new URLSearchParams();
8199
- }
8200
8201
 
8201
8202
  // src/shims/cateringService.ts
8202
8203
  var endpoints = null;
@@ -8215,6 +8216,8 @@ var cateringService = {
8215
8216
  searchMenuItems: (query, filters) => ep().menu.searchMenuItems(query, filters),
8216
8217
  getMenuItems: () => ep().menu.getMenuItems(),
8217
8218
  getMenuItemsByRestaurant: (restaurantId) => ep().menu.getMenuItemsByRestaurant(restaurantId),
8219
+ createSharedCart: (snapshot) => ep().sharedCart.create(snapshot),
8220
+ getSharedCart: (id) => ep().sharedCart.get(id),
8218
8221
  getBundleById: (bundleId) => ep().bundles.getBundleById(bundleId),
8219
8222
  getCateringBundles: () => ep().bundles.getCateringBundles(),
8220
8223
  getBundlesByRestaurant: (restaurantId) => ep().bundles.getBundlesByRestaurant(restaurantId),
@@ -8323,6 +8326,199 @@ var cateringService = {
8323
8326
  }
8324
8327
  };
8325
8328
 
8329
+ // src/utils/cart-hydration.ts
8330
+ async function hydrateCartFromSnapshot(snapshot, fetchMenuByRestaurant) {
8331
+ const restaurantIds = Array.from(
8332
+ new Set(
8333
+ snapshot.mealSessions.flatMap((s) => s.items.map((i) => i.restaurantId))
8334
+ )
8335
+ ).filter(Boolean);
8336
+ const menus = await Promise.all(
8337
+ restaurantIds.map(
8338
+ (rid) => fetchMenuByRestaurant(rid).catch(() => [])
8339
+ )
8340
+ );
8341
+ const lookup = /* @__PURE__ */ new Map();
8342
+ for (const menu of menus) {
8343
+ for (const item of menu) {
8344
+ if (item?.id) lookup.set(item.id, item);
8345
+ }
8346
+ }
8347
+ const missing = [];
8348
+ const mealSessions = snapshot.mealSessions.map(
8349
+ (session) => {
8350
+ const orderItems = [];
8351
+ for (const snapItem of session.items) {
8352
+ const live = lookup.get(snapItem.menuItemId);
8353
+ if (!live) {
8354
+ missing.push({ menuItemId: snapItem.menuItemId });
8355
+ continue;
8356
+ }
8357
+ const built = applySelectedAddons(live, snapItem.selectedAddons);
8358
+ const liveRestaurant = built.restaurant;
8359
+ const restaurantName = built.restaurantName || liveRestaurant?.name || liveRestaurant?.restaurant_name;
8360
+ orderItems.push({
8361
+ item: restaurantName && !built.restaurantName ? { ...built, restaurantName } : built,
8362
+ quantity: snapItem.quantity,
8363
+ bundleId: snapItem.bundleId,
8364
+ bundleName: snapItem.bundleName
8365
+ });
8366
+ }
8367
+ return {
8368
+ sessionName: session.sessionName ?? "Main Event",
8369
+ sessionDate: session.sessionDate ?? "",
8370
+ eventTime: session.eventTime ?? "",
8371
+ guestCount: session.guestCount,
8372
+ orderItems
8373
+ };
8374
+ }
8375
+ );
8376
+ return { mealSessions, missing };
8377
+ }
8378
+ function serializeCartToSnapshot(mealSessions, eventDetails) {
8379
+ return {
8380
+ mealSessions: mealSessions.map((session) => ({
8381
+ sessionName: session.sessionName,
8382
+ sessionDate: session.sessionDate,
8383
+ eventTime: session.eventTime,
8384
+ guestCount: session.guestCount,
8385
+ items: session.orderItems.map((oi) => {
8386
+ const item = oi.item;
8387
+ return {
8388
+ menuItemId: item.id,
8389
+ restaurantId: item.restaurant?.restaurantId || item.restaurantId || "",
8390
+ quantity: oi.quantity,
8391
+ bundleId: oi.bundleId,
8392
+ bundleName: oi.bundleName,
8393
+ selectedAddons: (item.selectedAddons || []).map((a) => ({
8394
+ name: a.name,
8395
+ quantity: a.quantity,
8396
+ groupTitle: a.groupTitle
8397
+ }))
8398
+ };
8399
+ })
8400
+ })),
8401
+ eventDetails
8402
+ };
8403
+ }
8404
+ function applySelectedAddons(live, snapshotAddons) {
8405
+ if (!snapshotAddons || snapshotAddons.length === 0) return live;
8406
+ const selectedAddons = snapshotAddons.map((sa) => {
8407
+ const group = (live.addons || []).find(
8408
+ (g) => g.groupTitle === sa.groupTitle
8409
+ );
8410
+ const def = group?.items.find((a) => a.name === sa.name);
8411
+ if (!def) return null;
8412
+ return {
8413
+ name: sa.name,
8414
+ price: parseFloat(def.price) || 0,
8415
+ quantity: sa.quantity,
8416
+ groupTitle: sa.groupTitle ?? group?.groupTitle ?? "",
8417
+ allergens: def.allergens,
8418
+ dietaryRestrictions: def.dietaryRestrictions
8419
+ };
8420
+ }).filter((a) => a !== null);
8421
+ const addonPrice = selectedAddons.reduce(
8422
+ (sum, a) => sum + a.price * a.quantity,
8423
+ 0
8424
+ );
8425
+ return { ...live, selectedAddons, addonPrice };
8426
+ }
8427
+
8428
+ // src/components/SharedCartLoader.tsx
8429
+ function SharedCartLoader() {
8430
+ const { loadMealSessions } = useCateringState();
8431
+ react.useEffect(() => {
8432
+ if (typeof window === "undefined") return;
8433
+ const id = new URLSearchParams(window.location.search).get("sharedCart");
8434
+ if (!id) return;
8435
+ let cancelled = false;
8436
+ void (async () => {
8437
+ try {
8438
+ const { cart } = await cateringService.getSharedCart(id);
8439
+ const { mealSessions, missing } = await hydrateCartFromSnapshot(
8440
+ cart,
8441
+ (rid) => cateringService.getMenuItemsByRestaurant(rid)
8442
+ );
8443
+ if (cancelled) return;
8444
+ if (mealSessions.every((s) => s.orderItems.length === 0)) {
8445
+ window.alert(
8446
+ "The items in this shared cart are no longer available."
8447
+ );
8448
+ } else {
8449
+ loadMealSessions(mealSessions);
8450
+ if (missing.length > 0) {
8451
+ const n = missing.length;
8452
+ window.alert(
8453
+ `${n} item${n === 1 ? "" : "s"} from this shared cart ${n === 1 ? "is" : "are"} no longer available and ${n === 1 ? "was" : "were"} removed.`
8454
+ );
8455
+ }
8456
+ }
8457
+ const url = new URL(window.location.href);
8458
+ url.searchParams.delete("sharedCart");
8459
+ window.history.replaceState({}, "", url.toString());
8460
+ } catch (err) {
8461
+ console.error("[catering] failed to load shared cart", err);
8462
+ window.alert(
8463
+ "We couldn't load this shared cart \u2014 the link may have expired."
8464
+ );
8465
+ }
8466
+ })();
8467
+ return () => {
8468
+ cancelled = true;
8469
+ };
8470
+ }, []);
8471
+ return null;
8472
+ }
8473
+ var FilterContext = react.createContext(void 0);
8474
+ var STORAGE_KEY = "catering_filters";
8475
+ var defaultFilters = {
8476
+ dietaryRestrictions: [],
8477
+ allergens: [],
8478
+ pricePerPersonRange: null,
8479
+ restaurantPriceRange: null
8480
+ };
8481
+ function CateringFilterProvider({ children }) {
8482
+ const storage = useStorage();
8483
+ const [filters, setFiltersState] = react.useState(defaultFilters);
8484
+ const [isInitialized, setIsInitialized] = react.useState(false);
8485
+ react.useEffect(() => {
8486
+ try {
8487
+ const stored = storage.getItem(STORAGE_KEY);
8488
+ if (stored) {
8489
+ setFiltersState(JSON.parse(stored));
8490
+ }
8491
+ } catch (error) {
8492
+ console.error("Failed to load filters from storage:", error);
8493
+ }
8494
+ setIsInitialized(true);
8495
+ }, [storage]);
8496
+ react.useEffect(() => {
8497
+ if (isInitialized) {
8498
+ try {
8499
+ storage.setItem(STORAGE_KEY, JSON.stringify(filters));
8500
+ } catch (error) {
8501
+ console.error("Failed to save filters to storage:", error);
8502
+ }
8503
+ }
8504
+ }, [filters, isInitialized, storage]);
8505
+ const setFilters = (newFilters) => setFiltersState(newFilters);
8506
+ const clearFilters = () => setFiltersState(defaultFilters);
8507
+ return /* @__PURE__ */ jsxRuntime.jsx(FilterContext.Provider, { value: { filters, setFilters, clearFilters }, children });
8508
+ }
8509
+ function useCateringFilters() {
8510
+ const context = react.useContext(FilterContext);
8511
+ if (context === void 0) {
8512
+ throw new Error(
8513
+ "useCateringFilters must be used within a CateringFilterProvider"
8514
+ );
8515
+ }
8516
+ return context;
8517
+ }
8518
+ function useSearchParams() {
8519
+ return new URLSearchParams();
8520
+ }
8521
+
8326
8522
  // src/constants/allergens.ts
8327
8523
  var ALLERGENS = [
8328
8524
  { label: "Celery", value: "celery" },
@@ -8375,10 +8571,10 @@ Array.from({ length: 12 }, (_, i) => ({
8375
8571
  ].sort((a, b) => a.label.localeCompare(b.label));
8376
8572
 
8377
8573
  // src/assets/dietary-icons/vegetarian.png
8378
- var vegetarian_default = "data:image/png;base64,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";
8574
+ var vegetarian_default = "data:image/png;base64,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";
8379
8575
 
8380
8576
  // src/assets/dietary-icons/vegan.png
8381
- var vegan_default = "data:image/png;base64,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";
8577
+ var vegan_default = "data:image/png;base64,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";
8382
8578
 
8383
8579
  // src/assets/dietary-icons/halal.png
8384
8580
  var halal_default = "data:image/png;base64,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";
@@ -8405,6 +8601,21 @@ var formatAllergen = (allergen) => {
8405
8601
  const allergenObj = ALLERGENS.find((a) => a.value === allergen);
8406
8602
  return allergenObj?.label || allergen.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
8407
8603
  };
8604
+ var normalizeAllergens = (allergens) => {
8605
+ if (!allergens) return [];
8606
+ const list = Array.isArray(allergens) ? allergens : allergens.split(",");
8607
+ return list.map((a) => a.trim()).filter(
8608
+ (a) => a.length > 0 && a.toLowerCase() !== "no specific allergens" && a.toLowerCase() !== "no_specific_allergens"
8609
+ );
8610
+ };
8611
+ var AddonAllergens = ({ allergens }) => {
8612
+ const list = normalizeAllergens(allergens);
8613
+ if (list.length === 0) return null;
8614
+ return /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[9px] md:text-[11px] text-base-content/60 leading-snug", children: [
8615
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Allergens: " }),
8616
+ list.map(formatAllergen).join(", ")
8617
+ ] });
8618
+ };
8408
8619
  function MenuItemModal({
8409
8620
  item,
8410
8621
  isOpen,
@@ -8427,15 +8638,20 @@ function MenuItemModal({
8427
8638
  }) {
8428
8639
  const MIN_PORTIONS = item.minOrderQuantity && item.minOrderQuantity > 0 ? item.minOrderQuantity : 1;
8429
8640
  const [itemQuantity, setItemQuantity] = react.useState(MIN_PORTIONS);
8430
- const [itemQuantityInput, setItemQuantityInput] = react.useState(MIN_PORTIONS.toString());
8641
+ const [itemQuantityInput, setItemQuantityInput] = react.useState(
8642
+ MIN_PORTIONS.toString()
8643
+ );
8431
8644
  const [selectedAddons, setSelectedAddons] = react.useState({});
8432
8645
  const [addonQuantities, setAddonQuantities] = react.useState({});
8433
8646
  const [addonQuantityInputs, setAddonQuantityInputs] = react.useState({});
8434
- const [addonGroups, setAddonGroups] = react.useState({});
8647
+ const [addonGroups, setAddonGroups] = react.useState(
8648
+ {}
8649
+ );
8435
8650
  const [totalPrice, setTotalPrice] = react.useState(0);
8436
8651
  const [isAllergenExpanded, setIsAllergenExpanded] = react.useState(false);
8437
8652
  const [hasModifiedQuantity, setHasModifiedQuantity] = react.useState(false);
8438
8653
  const [initialModalQuantity, setInitialModalQuantity] = react.useState(0);
8654
+ const [selectedImageIndex, setSelectedImageIndex] = react.useState(0);
8439
8655
  const price = parseFloat(item.price?.toString() || "0");
8440
8656
  const discountPrice = parseFloat(item.discountPrice?.toString() || "0");
8441
8657
  const displayPrice = item.isDiscount && discountPrice > 0 ? discountPrice : price;
@@ -8507,7 +8723,16 @@ function MenuItemModal({
8507
8723
  setSelectedAddons(selections);
8508
8724
  setAddonQuantities(quantities);
8509
8725
  setAddonQuantityInputs(quantityInputs);
8510
- }, [isOpen, item, quantity, BACKEND_QUANTITY_UNIT, MIN_PORTIONS, isEditMode, aiAddonMode, initialAiAddons]);
8726
+ }, [
8727
+ isOpen,
8728
+ item,
8729
+ quantity,
8730
+ BACKEND_QUANTITY_UNIT,
8731
+ MIN_PORTIONS,
8732
+ isEditMode,
8733
+ aiAddonMode,
8734
+ initialAiAddons
8735
+ ]);
8511
8736
  react.useEffect(() => {
8512
8737
  if (!item) return;
8513
8738
  let basePrice = BACKEND_QUANTITY_UNIT * (item.isDiscount ? parseFloat(item.discountPrice || "0") : parseFloat(item.price || "0"));
@@ -8758,7 +8983,9 @@ function MenuItemModal({
8758
8983
  }
8759
8984
  });
8760
8985
  if (multipleSelectionErrors.length > 0) {
8761
- alert("Please adjust your selections:\n\n" + multipleSelectionErrors.join("\n"));
8986
+ alert(
8987
+ "Please adjust your selections:\n\n" + multipleSelectionErrors.join("\n")
8988
+ );
8762
8989
  return;
8763
8990
  }
8764
8991
  const addonsForCart = [];
@@ -8851,7 +9078,9 @@ function MenuItemModal({
8851
9078
  }
8852
9079
  });
8853
9080
  if (multipleSelectionErrors.length > 0) {
8854
- alert("Please adjust your selections:\n\n" + multipleSelectionErrors.join("\n"));
9081
+ alert(
9082
+ "Please adjust your selections:\n\n" + multipleSelectionErrors.join("\n")
9083
+ );
8855
9084
  return;
8856
9085
  }
8857
9086
  const selections = [];
@@ -8901,7 +9130,9 @@ function MenuItemModal({
8901
9130
  const isMinSelectionsUnmet = Object.entries(addonGroups).some(
8902
9131
  ([groupTitle, group]) => {
8903
9132
  if (group.selectionType === "single") {
8904
- const hasAnySelection = Object.values(selectedAddons[groupTitle] || {}).some(Boolean);
9133
+ const hasAnySelection = Object.values(
9134
+ selectedAddons[groupTitle] || {}
9135
+ ).some(Boolean);
8905
9136
  if (!hasAnySelection) return false;
8906
9137
  return getSingleSelectionTotal(groupTitle) !== itemQuantity;
8907
9138
  }
@@ -8934,31 +9165,47 @@ function MenuItemModal({
8934
9165
  }
8935
9166
  ),
8936
9167
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 md:p-6 overflow-y-auto flex-1", children: [
8937
- item.image && /* @__PURE__ */ jsxRuntime.jsx(
8938
- "div",
8939
- {
8940
- className: "flex-shrink-0 -mx-4 md:-mx-6 -mt-4 md:-mt-6 mb-3 overflow-hidden md:rounded-t-xl",
8941
- style: { maxHeight: "50vh", aspectRatio: "5/4" },
8942
- onClick: (e) => {
8943
- e.stopPropagation();
9168
+ (item.images?.length ?? 0) > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-shrink-0 -mx-4 md:-mx-6 -mt-4 md:-mt-6 mb-3", children: [
9169
+ /* @__PURE__ */ jsxRuntime.jsx(
9170
+ "div",
9171
+ {
9172
+ className: "overflow-hidden md:rounded-t-xl",
9173
+ style: { maxHeight: "50vh", aspectRatio: "5/4" },
9174
+ onClick: (e) => {
9175
+ e.stopPropagation();
9176
+ },
9177
+ children: /* @__PURE__ */ jsxRuntime.jsx(
9178
+ "img",
9179
+ {
9180
+ src: item.images?.[selectedImageIndex] ?? item.images?.[0],
9181
+ alt: item.menuItemName,
9182
+ className: "w-full h-full object-cover"
9183
+ }
9184
+ )
9185
+ }
9186
+ ),
9187
+ (item.images?.length ?? 0) > 1 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-2 px-4 md:px-6 pt-2 overflow-x-auto", children: (item.images ?? []).map((img, idx) => /* @__PURE__ */ jsxRuntime.jsx(
9188
+ "button",
9189
+ {
9190
+ type: "button",
9191
+ onClick: (e) => {
9192
+ e.stopPropagation();
9193
+ setSelectedImageIndex(idx);
9194
+ },
9195
+ className: `flex-shrink-0 w-14 h-14 rounded-lg overflow-hidden border-2 transition-all ${idx === selectedImageIndex ? "border-primary" : "border-transparent opacity-60 hover:opacity-100"}`,
9196
+ "aria-label": `View image ${idx + 1}`,
9197
+ children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: img, alt: "", className: "w-full h-full object-cover" })
8944
9198
  },
8945
- children: /* @__PURE__ */ jsxRuntime.jsx(
8946
- "img",
8947
- {
8948
- src: item.image,
8949
- alt: item.menuItemName,
8950
- className: "w-full h-full object-cover"
8951
- }
8952
- )
8953
- }
8954
- ),
9199
+ idx
9200
+ )) })
9201
+ ] }),
8955
9202
  /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "font-bold text-lg md:text-2xl text-base-content mb-1 pr-8", children: item.menuItemName }),
8956
9203
  item.restaurantName && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs md:text-sm text-primary font-medium mb-3 md:mb-4", children: [
8957
9204
  "From ",
8958
9205
  item.restaurantName
8959
9206
  ] }),
8960
9207
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 md:space-y-4 mt-2", children: [
8961
- item.description && /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base-content/70 text-xs md:text-sm leading-relaxed", children: item.description }) }),
9208
+ item.description && /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-base-content/70 text-xs md:text-sm leading-relaxed whitespace-pre-line", children: item.description }) }),
8962
9209
  item.allergens && item.allergens.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-warning/5 border border-warning/20 rounded-lg p-3 md:p-4", children: [
8963
9210
  /* @__PURE__ */ jsxRuntime.jsx(
8964
9211
  "button",
@@ -9028,7 +9275,9 @@ function MenuItemModal({
9028
9275
  setItemQuantity(newQty);
9029
9276
  setItemQuantityInput(newQty.toString());
9030
9277
  if (quantity > 0 && (!item.addons || item.addons.length === 0)) {
9031
- setHasModifiedQuantity(newQty !== initialModalQuantity);
9278
+ setHasModifiedQuantity(
9279
+ newQty !== initialModalQuantity
9280
+ );
9032
9281
  }
9033
9282
  },
9034
9283
  disabled: itemQuantity <= MIN_PORTIONS,
@@ -9048,7 +9297,10 @@ function MenuItemModal({
9048
9297
  if (val === "" || /^\d+$/.test(val)) {
9049
9298
  setItemQuantityInput(val);
9050
9299
  if (val !== "" && !isNaN(parseInt(val))) {
9051
- const newQty = Math.max(MIN_PORTIONS, parseInt(val));
9300
+ const newQty = Math.max(
9301
+ MIN_PORTIONS,
9302
+ parseInt(val)
9303
+ );
9052
9304
  setItemQuantity(newQty);
9053
9305
  if (quantity > 0 && (!item.addons || item.addons.length === 0)) {
9054
9306
  setHasModifiedQuantity(
@@ -9087,7 +9339,9 @@ function MenuItemModal({
9087
9339
  setItemQuantity(newQty);
9088
9340
  setItemQuantityInput(newQty.toString());
9089
9341
  if (quantity > 0 && (!item.addons || item.addons.length === 0)) {
9090
- setHasModifiedQuantity(newQty !== initialModalQuantity);
9342
+ setHasModifiedQuantity(
9343
+ newQty !== initialModalQuantity
9344
+ );
9091
9345
  }
9092
9346
  },
9093
9347
  className: "group w-8 h-8 md:w-10 md:h-10 bg-base-100 border border-base-300 rounded-lg flex items-center justify-center text-base md:text-lg font-medium flex-shrink-0",
@@ -9147,28 +9401,31 @@ function MenuItemModal({
9147
9401
  {
9148
9402
  className: "w-full flex items-center justify-between p-3 rounded-lg border border-base-300 bg-base-100",
9149
9403
  children: [
9150
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
9151
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-base-content", children: addon.name }),
9152
- addon.dietaryRestrictions && addon.dietaryRestrictions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5", children: addon.dietaryRestrictions.map((restriction) => {
9153
- const iconInfo = DIETARY_ICON_MAP[restriction];
9154
- if (!iconInfo) return null;
9155
- return /* @__PURE__ */ jsxRuntime.jsx(
9156
- "div",
9157
- {
9158
- className: "relative w-4 h-4",
9159
- title: iconInfo.label,
9160
- children: /* @__PURE__ */ jsxRuntime.jsx(
9161
- "img",
9162
- {
9163
- src: iconInfo.src,
9164
- alt: iconInfo.label,
9165
- className: "object-contain"
9166
- }
9167
- )
9168
- },
9169
- restriction
9170
- );
9171
- }) })
9404
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 mr-2", children: [
9405
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-sm text-base-content", children: addon.name }),
9406
+ /* @__PURE__ */ jsxRuntime.jsx(AddonAllergens, { allergens: addon.allergens }),
9407
+ addon.dietaryRestrictions && addon.dietaryRestrictions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5 mt-0.5", children: addon.dietaryRestrictions.map(
9408
+ (restriction) => {
9409
+ const iconInfo = DIETARY_ICON_MAP[restriction];
9410
+ if (!iconInfo) return null;
9411
+ return /* @__PURE__ */ jsxRuntime.jsx(
9412
+ "div",
9413
+ {
9414
+ className: "relative w-4 h-4",
9415
+ title: iconInfo.label,
9416
+ children: /* @__PURE__ */ jsxRuntime.jsx(
9417
+ "img",
9418
+ {
9419
+ src: iconInfo.src,
9420
+ alt: iconInfo.label,
9421
+ className: "object-contain"
9422
+ }
9423
+ )
9424
+ },
9425
+ restriction
9426
+ );
9427
+ }
9428
+ ) })
9172
9429
  ] }),
9173
9430
  parseFloat(addon.price) > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-medium text-primary", children: [
9174
9431
  "+\xA3",
@@ -9189,31 +9446,34 @@ function MenuItemModal({
9189
9446
  children: [
9190
9447
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 mr-2", children: [
9191
9448
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-sm text-base-content", children: addon.name }),
9449
+ /* @__PURE__ */ jsxRuntime.jsx(AddonAllergens, { allergens: addon.allergens }),
9192
9450
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mt-0.5", children: [
9193
9451
  parseFloat(addon.price) > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] font-medium text-primary", children: [
9194
9452
  "+\xA3",
9195
9453
  parseFloat(addon.price).toFixed(2)
9196
9454
  ] }),
9197
- addon.dietaryRestrictions && addon.dietaryRestrictions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5", children: addon.dietaryRestrictions.map((restriction) => {
9198
- const iconInfo = DIETARY_ICON_MAP[restriction];
9199
- if (!iconInfo) return null;
9200
- return /* @__PURE__ */ jsxRuntime.jsx(
9201
- "div",
9202
- {
9203
- className: "relative w-4 h-4",
9204
- title: iconInfo.label,
9205
- children: /* @__PURE__ */ jsxRuntime.jsx(
9206
- "img",
9207
- {
9208
- src: iconInfo.src,
9209
- alt: iconInfo.label,
9210
- className: "object-contain"
9211
- }
9212
- )
9213
- },
9214
- restriction
9215
- );
9216
- }) })
9455
+ addon.dietaryRestrictions && addon.dietaryRestrictions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5", children: addon.dietaryRestrictions.map(
9456
+ (restriction) => {
9457
+ const iconInfo = DIETARY_ICON_MAP[restriction];
9458
+ if (!iconInfo) return null;
9459
+ return /* @__PURE__ */ jsxRuntime.jsx(
9460
+ "div",
9461
+ {
9462
+ className: "relative w-4 h-4",
9463
+ title: iconInfo.label,
9464
+ children: /* @__PURE__ */ jsxRuntime.jsx(
9465
+ "img",
9466
+ {
9467
+ src: iconInfo.src,
9468
+ alt: iconInfo.label,
9469
+ className: "object-contain"
9470
+ }
9471
+ )
9472
+ },
9473
+ restriction
9474
+ );
9475
+ }
9476
+ ) })
9217
9477
  ] })
9218
9478
  ] }),
9219
9479
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -9315,24 +9575,47 @@ function MenuItemModal({
9315
9575
  children: [
9316
9576
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 mr-2", children: [
9317
9577
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-sm text-base-content", children: addon.name }),
9578
+ /* @__PURE__ */ jsxRuntime.jsx(AddonAllergens, { allergens: addon.allergens }),
9318
9579
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mt-0.5", children: [
9319
9580
  parseFloat(addon.price) > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] font-medium text-primary", children: [
9320
9581
  "+\xA3",
9321
9582
  parseFloat(addon.price).toFixed(2),
9322
- " each"
9583
+ " ",
9584
+ "each"
9323
9585
  ] }),
9324
- addon.dietaryRestrictions && addon.dietaryRestrictions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5", children: addon.dietaryRestrictions.map((restriction) => {
9325
- const iconInfo = DIETARY_ICON_MAP[restriction];
9326
- if (!iconInfo) return null;
9327
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-4 h-4", title: iconInfo.label, children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: iconInfo.src, alt: iconInfo.label, className: "object-contain" }) }, restriction);
9328
- }) })
9586
+ addon.dietaryRestrictions && addon.dietaryRestrictions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5", children: addon.dietaryRestrictions.map(
9587
+ (restriction) => {
9588
+ const iconInfo = DIETARY_ICON_MAP[restriction];
9589
+ if (!iconInfo) return null;
9590
+ return /* @__PURE__ */ jsxRuntime.jsx(
9591
+ "div",
9592
+ {
9593
+ className: "relative w-4 h-4",
9594
+ title: iconInfo.label,
9595
+ children: /* @__PURE__ */ jsxRuntime.jsx(
9596
+ "img",
9597
+ {
9598
+ src: iconInfo.src,
9599
+ alt: iconInfo.label,
9600
+ className: "object-contain"
9601
+ }
9602
+ )
9603
+ },
9604
+ restriction
9605
+ );
9606
+ }
9607
+ ) })
9329
9608
  ] })
9330
9609
  ] }),
9331
9610
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
9332
9611
  /* @__PURE__ */ jsxRuntime.jsx(
9333
9612
  "button",
9334
9613
  {
9335
- onClick: () => updateAddonQuantity(groupTitle, addon.name, -1),
9614
+ onClick: () => updateAddonQuantity(
9615
+ groupTitle,
9616
+ addon.name,
9617
+ -1
9618
+ ),
9336
9619
  disabled: addonQtyMR === 0,
9337
9620
  className: "w-7 h-7 bg-base-100 border border-base-300 rounded hover:bg-base-200 flex items-center justify-center text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-base-100",
9338
9621
  children: "\u2212"
@@ -9352,22 +9635,36 @@ function MenuItemModal({
9352
9635
  Object.keys(prev).forEach((key) => {
9353
9636
  newInputs[key] = { ...prev[key] };
9354
9637
  });
9355
- if (!newInputs[groupTitle]) newInputs[groupTitle] = {};
9638
+ if (!newInputs[groupTitle])
9639
+ newInputs[groupTitle] = {};
9356
9640
  newInputs[groupTitle][addon.name] = val;
9357
9641
  return newInputs;
9358
9642
  });
9359
9643
  if (val !== "" && !isNaN(parseInt(val))) {
9360
9644
  const requested = parseInt(val);
9361
- const totalWithoutCurrent = getMultipleSelectionCount(groupTitle) - addonQtyMR;
9645
+ const totalWithoutCurrent = getMultipleSelectionCount(
9646
+ groupTitle
9647
+ ) - addonQtyMR;
9362
9648
  const maxAllowed = group.maxSelections != null ? group.maxSelections * itemQuantity - totalWithoutCurrent : Infinity;
9363
- const finalQty = Math.min(requested, Math.max(0, maxAllowed));
9364
- setAddonQuantityDirect(groupTitle, addon.name, finalQty);
9649
+ const finalQty = Math.min(
9650
+ requested,
9651
+ Math.max(0, maxAllowed)
9652
+ );
9653
+ setAddonQuantityDirect(
9654
+ groupTitle,
9655
+ addon.name,
9656
+ finalQty
9657
+ );
9365
9658
  }
9366
9659
  }
9367
9660
  },
9368
9661
  onBlur: (e) => {
9369
9662
  if (e.target.value === "" || parseInt(e.target.value) < 0) {
9370
- setAddonQuantityDirect(groupTitle, addon.name, 0);
9663
+ setAddonQuantityDirect(
9664
+ groupTitle,
9665
+ addon.name,
9666
+ 0
9667
+ );
9371
9668
  }
9372
9669
  },
9373
9670
  className: "w-12 text-center text-sm font-medium text-base-content bg-base-100 border border-base-300 rounded px-1 py-0.5"
@@ -9376,7 +9673,11 @@ function MenuItemModal({
9376
9673
  /* @__PURE__ */ jsxRuntime.jsx(
9377
9674
  "button",
9378
9675
  {
9379
- onClick: () => updateAddonQuantity(groupTitle, addon.name, 1),
9676
+ onClick: () => updateAddonQuantity(
9677
+ groupTitle,
9678
+ addon.name,
9679
+ 1
9680
+ ),
9380
9681
  disabled: isMaxReached,
9381
9682
  className: "w-7 h-7 bg-base-100 border border-base-300 rounded hover:bg-base-200 flex items-center justify-center text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-base-100",
9382
9683
  children: "+"
@@ -9425,26 +9726,34 @@ function MenuItemModal({
9425
9726
  ),
9426
9727
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 text-left", children: [
9427
9728
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-sm text-base-content", children: addon.name }),
9428
- addon.dietaryRestrictions && addon.dietaryRestrictions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5 mt-1", children: addon.dietaryRestrictions.map((restriction) => {
9429
- const iconInfo = DIETARY_ICON_MAP[restriction];
9430
- if (!iconInfo) return null;
9431
- return /* @__PURE__ */ jsxRuntime.jsx(
9432
- "div",
9433
- {
9434
- className: "relative w-4 h-4",
9435
- title: iconInfo.label,
9436
- children: /* @__PURE__ */ jsxRuntime.jsx(
9437
- "img",
9438
- {
9439
- src: iconInfo.src,
9440
- alt: iconInfo.label,
9441
- className: "object-contain"
9442
- }
9443
- )
9444
- },
9445
- restriction
9446
- );
9447
- }) })
9729
+ /* @__PURE__ */ jsxRuntime.jsx(
9730
+ AddonAllergens,
9731
+ {
9732
+ allergens: addon.allergens
9733
+ }
9734
+ ),
9735
+ addon.dietaryRestrictions && addon.dietaryRestrictions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0.5 mt-1", children: addon.dietaryRestrictions.map(
9736
+ (restriction) => {
9737
+ const iconInfo = DIETARY_ICON_MAP[restriction];
9738
+ if (!iconInfo) return null;
9739
+ return /* @__PURE__ */ jsxRuntime.jsx(
9740
+ "div",
9741
+ {
9742
+ className: "relative w-4 h-4",
9743
+ title: iconInfo.label,
9744
+ children: /* @__PURE__ */ jsxRuntime.jsx(
9745
+ "img",
9746
+ {
9747
+ src: iconInfo.src,
9748
+ alt: iconInfo.label,
9749
+ className: "object-contain"
9750
+ }
9751
+ )
9752
+ },
9753
+ restriction
9754
+ );
9755
+ }
9756
+ ) })
9448
9757
  ] })
9449
9758
  ] }),
9450
9759
  parseFloat(addon.price) > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex-shrink-0 ml-2 text-sm font-medium text-primary", children: [
@@ -10130,19 +10439,19 @@ var styles = renderer.StyleSheet.create({
10130
10439
  // Page Styles
10131
10440
  page: {
10132
10441
  backgroundColor: "#fdfdfd",
10133
- padding: 48,
10134
- paddingBottom: 70,
10442
+ padding: 36,
10443
+ paddingBottom: 55,
10135
10444
  fontFamily: FONT_FAMILY
10136
10445
  },
10137
10446
  menuPage: {
10138
10447
  backgroundColor: "#fdfdfd",
10139
- padding: 48,
10140
- paddingBottom: 70,
10448
+ padding: 36,
10449
+ paddingBottom: 55,
10141
10450
  fontFamily: FONT_FAMILY
10142
10451
  },
10143
10452
  // Day Section
10144
10453
  daySection: {
10145
- marginBottom: 50
10454
+ marginBottom: 24
10146
10455
  },
10147
10456
  dayHeader: {
10148
10457
  flexDirection: "row",
@@ -10150,17 +10459,17 @@ var styles = renderer.StyleSheet.create({
10150
10459
  alignItems: "flex-end",
10151
10460
  borderBottomWidth: 2,
10152
10461
  borderBottomColor: "#000",
10153
- paddingBottom: 4,
10154
- marginBottom: 24
10462
+ paddingBottom: 2,
10463
+ marginBottom: 12
10155
10464
  },
10156
10465
  dayTitle: {
10157
- fontSize: 18,
10466
+ fontSize: 14,
10158
10467
  fontFamily: FONT_FAMILY_BOLD_OBLIQUE,
10159
10468
  textTransform: "uppercase",
10160
10469
  letterSpacing: -0.3
10161
10470
  },
10162
10471
  dayLabel: {
10163
- fontSize: 8,
10472
+ fontSize: 7,
10164
10473
  fontFamily: FONT_FAMILY_BOLD,
10165
10474
  color: "#9ca3af",
10166
10475
  textTransform: "uppercase",
@@ -10170,27 +10479,27 @@ var styles = renderer.StyleSheet.create({
10170
10479
  sessionHeader: {
10171
10480
  flexDirection: "row",
10172
10481
  alignItems: "flex-end",
10173
- marginBottom: 20
10482
+ marginBottom: 10
10174
10483
  },
10175
10484
  sessionTitle: {
10176
- fontSize: 28,
10485
+ fontSize: 20,
10177
10486
  fontFamily: FONT_FAMILY_BOLD,
10178
10487
  textTransform: "uppercase",
10179
10488
  letterSpacing: -0.5
10180
10489
  },
10181
10490
  sessionTime: {
10182
- fontSize: 14,
10491
+ fontSize: 11,
10183
10492
  fontFamily: FONT_FAMILY_OBLIQUE,
10184
10493
  color: "#9ca3af",
10185
- marginLeft: 12,
10494
+ marginLeft: 10,
10186
10495
  marginBottom: 2
10187
10496
  },
10188
10497
  // Category Header
10189
10498
  categoryHeader: {
10190
- fontSize: 10,
10499
+ fontSize: 9,
10191
10500
  fontFamily: FONT_FAMILY_BOLD,
10192
- marginBottom: 16,
10193
- marginTop: 12,
10501
+ marginBottom: 8,
10502
+ marginTop: 6,
10194
10503
  textTransform: "uppercase",
10195
10504
  letterSpacing: 1,
10196
10505
  textDecoration: "underline"
@@ -10198,145 +10507,145 @@ var styles = renderer.StyleSheet.create({
10198
10507
  // Menu Item - Editorial Layout
10199
10508
  menuItem: {
10200
10509
  flexDirection: "row",
10201
- marginBottom: 28,
10202
- paddingBottom: 20
10510
+ marginBottom: 12,
10511
+ paddingBottom: 10
10203
10512
  },
10204
10513
  menuItemContent: {
10205
10514
  flex: 1,
10206
- paddingRight: 16
10515
+ paddingRight: 12
10207
10516
  },
10208
10517
  menuItemName: {
10209
- fontSize: 14,
10518
+ fontSize: 11,
10210
10519
  fontFamily: FONT_FAMILY_BOLD,
10211
10520
  textTransform: "uppercase",
10212
10521
  letterSpacing: -0.3,
10213
- marginBottom: 4
10522
+ marginBottom: 3
10214
10523
  },
10215
10524
  menuItemDescription: {
10216
- fontSize: 10,
10525
+ fontSize: 9,
10217
10526
  fontFamily: FONT_FAMILY_OBLIQUE,
10218
10527
  color: "#4b5563",
10219
- marginBottom: 8,
10528
+ marginBottom: 4,
10220
10529
  lineHeight: 1.4
10221
10530
  },
10222
10531
  // Add-ons Container - Editorial Style
10223
10532
  addonsContainer: {
10224
- marginTop: 8,
10225
- marginBottom: 8,
10226
- paddingLeft: 8,
10227
- paddingVertical: 8,
10533
+ marginTop: 4,
10534
+ marginBottom: 4,
10535
+ paddingLeft: 6,
10536
+ paddingVertical: 4,
10228
10537
  backgroundColor: "#f9fafb",
10229
10538
  borderLeftWidth: 2,
10230
10539
  borderLeftColor: "rgba(0,0,0,0.1)"
10231
10540
  },
10232
10541
  addonsSection: {
10233
- marginBottom: 4
10542
+ marginBottom: 2
10234
10543
  },
10235
10544
  addonsSectionHeader: {
10236
- fontSize: 8,
10545
+ fontSize: 7,
10237
10546
  fontFamily: FONT_FAMILY_BOLD,
10238
10547
  color: "#9ca3af",
10239
10548
  textTransform: "uppercase",
10240
10549
  letterSpacing: 2,
10241
- marginBottom: 4
10550
+ marginBottom: 2
10242
10551
  },
10243
10552
  addonRow: {
10244
10553
  flexDirection: "row",
10245
10554
  alignItems: "center",
10246
10555
  flexWrap: "wrap",
10247
- marginBottom: 2
10556
+ marginBottom: 1
10248
10557
  },
10249
10558
  addonBullet: {
10250
- fontSize: 9,
10559
+ fontSize: 8,
10251
10560
  color: "#4b5563",
10252
- marginRight: 4
10561
+ marginRight: 3
10253
10562
  },
10254
10563
  addonText: {
10255
- fontSize: 9,
10564
+ fontSize: 8,
10256
10565
  color: "#374151"
10257
10566
  },
10258
10567
  addonDietaryBadges: {
10259
10568
  flexDirection: "row",
10260
10569
  alignItems: "center",
10261
- marginLeft: 4
10570
+ marginLeft: 3
10262
10571
  },
10263
10572
  addonDietaryBadge: {
10264
- width: 14,
10265
- height: 14,
10573
+ width: 12,
10574
+ height: 12,
10266
10575
  borderRadius: 2,
10267
10576
  alignItems: "center",
10268
10577
  justifyContent: "center",
10269
10578
  marginRight: 2
10270
10579
  },
10271
10580
  addonDietaryBadgeText: {
10272
- fontSize: 6,
10581
+ fontSize: 5,
10273
10582
  fontFamily: FONT_FAMILY_BOLD,
10274
10583
  color: "#fff"
10275
10584
  },
10276
10585
  addonAllergenText: {
10277
- fontSize: 9,
10586
+ fontSize: 8,
10278
10587
  color: "#6b7280",
10279
- marginLeft: 4
10588
+ marginLeft: 3
10280
10589
  },
10281
10590
  // Main Item Allergen
10282
10591
  mainItemAllergenContainer: {
10283
- marginTop: 8,
10284
- marginBottom: 6
10592
+ marginTop: 4,
10593
+ marginBottom: 3
10285
10594
  },
10286
10595
  mainItemAllergenLabel: {
10287
- fontSize: 9,
10596
+ fontSize: 8,
10288
10597
  fontFamily: FONT_FAMILY_BOLD,
10289
10598
  textTransform: "uppercase",
10290
10599
  letterSpacing: 0.5
10291
10600
  },
10292
10601
  mainItemAllergenText: {
10293
- fontSize: 9,
10602
+ fontSize: 8,
10294
10603
  fontFamily: FONT_FAMILY_BOLD
10295
10604
  },
10296
10605
  // Dietary Badges
10297
10606
  menuItemDietaryFilters: {
10298
10607
  flexDirection: "row",
10299
10608
  flexWrap: "wrap",
10300
- marginBottom: 8,
10301
- marginTop: 4
10609
+ marginBottom: 4,
10610
+ marginTop: 2
10302
10611
  },
10303
10612
  dietaryBadge: {
10304
- width: 18,
10305
- height: 18,
10613
+ width: 14,
10614
+ height: 14,
10306
10615
  borderRadius: 2,
10307
10616
  alignItems: "center",
10308
10617
  justifyContent: "center",
10309
- marginRight: 4
10618
+ marginRight: 3
10310
10619
  },
10311
10620
  dietaryBadgeText: {
10312
- fontSize: 7,
10621
+ fontSize: 6,
10313
10622
  fontFamily: FONT_FAMILY_BOLD,
10314
10623
  color: "#fff"
10315
10624
  },
10316
10625
  // Portions & Price
10317
10626
  menuItemPortions: {
10318
- fontSize: 9,
10627
+ fontSize: 8,
10319
10628
  color: "#9ca3af",
10320
- marginTop: 4
10629
+ marginTop: 2
10321
10630
  },
10322
10631
  menuItemPrice: {
10323
10632
  flexDirection: "row",
10324
- marginTop: 2
10633
+ marginTop: 1
10325
10634
  },
10326
10635
  menuItemPriceLabel: {
10327
- fontSize: 10,
10636
+ fontSize: 9,
10328
10637
  fontFamily: FONT_FAMILY_BOLD_OBLIQUE,
10329
10638
  letterSpacing: -0.3
10330
10639
  },
10331
10640
  menuItemPriceValue: {
10332
- fontSize: 10,
10641
+ fontSize: 9,
10333
10642
  fontFamily: FONT_FAMILY_BOLD_OBLIQUE,
10334
10643
  letterSpacing: -0.3
10335
10644
  },
10336
10645
  // Menu Item Image
10337
10646
  menuItemImage: {
10338
- width: 100,
10339
- height: 65,
10647
+ width: 80,
10648
+ height: 52,
10340
10649
  objectFit: "cover",
10341
10650
  borderWidth: 1,
10342
10651
  borderColor: "#e5e7eb"
@@ -10345,41 +10654,41 @@ var styles = renderer.StyleSheet.create({
10345
10654
  subtotalContainer: {
10346
10655
  flexDirection: "row",
10347
10656
  justifyContent: "flex-end",
10348
- marginTop: 16,
10349
- marginBottom: 32,
10350
- paddingTop: 12,
10657
+ marginTop: 8,
10658
+ marginBottom: 16,
10659
+ paddingTop: 8,
10351
10660
  borderTopWidth: 2,
10352
10661
  borderTopColor: "#000"
10353
10662
  },
10354
10663
  subtotalText: {
10355
- fontSize: 12,
10664
+ fontSize: 10,
10356
10665
  fontFamily: FONT_FAMILY_BOLD
10357
10666
  },
10358
10667
  deliveryFeeText: {
10359
- fontSize: 9,
10668
+ fontSize: 8,
10360
10669
  fontFamily: FONT_FAMILY_OBLIQUE,
10361
10670
  color: "#9ca3af",
10362
- marginTop: 6
10671
+ marginTop: 4
10363
10672
  },
10364
10673
  // Totals Container - Full Width Editorial Style
10365
10674
  totalsContainer: {
10366
- marginTop: 40,
10367
- paddingTop: 20
10675
+ marginTop: 20,
10676
+ paddingTop: 12
10368
10677
  },
10369
10678
  totalsRow: {
10370
10679
  flexDirection: "row",
10371
10680
  justifyContent: "space-between",
10372
10681
  alignItems: "baseline",
10373
- marginBottom: 16
10682
+ marginBottom: 8
10374
10683
  },
10375
10684
  totalsLabel: {
10376
- fontSize: 24,
10685
+ fontSize: 18,
10377
10686
  fontFamily: FONT_FAMILY_BOLD_OBLIQUE,
10378
10687
  textTransform: "uppercase",
10379
10688
  letterSpacing: -0.5
10380
10689
  },
10381
10690
  totalsValue: {
10382
- fontSize: 24,
10691
+ fontSize: 18,
10383
10692
  fontFamily: FONT_FAMILY_BOLD_OBLIQUE,
10384
10693
  letterSpacing: -0.5
10385
10694
  },
@@ -10388,46 +10697,46 @@ var styles = renderer.StyleSheet.create({
10388
10697
  borderTopColor: "#e5e7eb",
10389
10698
  borderBottomWidth: 1,
10390
10699
  borderBottomColor: "#e5e7eb",
10391
- paddingVertical: 16,
10392
- marginBottom: 20
10700
+ paddingVertical: 10,
10701
+ marginBottom: 12
10393
10702
  },
10394
10703
  totalsBreakdownRow: {
10395
10704
  flexDirection: "row",
10396
10705
  justifyContent: "space-between",
10397
10706
  alignItems: "baseline",
10398
- marginBottom: 6
10707
+ marginBottom: 4
10399
10708
  },
10400
10709
  totalsBreakdownLabel: {
10401
- fontSize: 11,
10710
+ fontSize: 9,
10402
10711
  fontFamily: FONT_FAMILY_BOLD,
10403
10712
  color: "#9ca3af",
10404
10713
  textTransform: "uppercase",
10405
10714
  letterSpacing: 2
10406
10715
  },
10407
10716
  totalsBreakdownValue: {
10408
- fontSize: 11,
10717
+ fontSize: 9,
10409
10718
  fontFamily: FONT_FAMILY_BOLD
10410
10719
  },
10411
10720
  totalsBreakdownValueItalic: {
10412
- fontSize: 11,
10721
+ fontSize: 9,
10413
10722
  fontFamily: FONT_FAMILY_OBLIQUE,
10414
10723
  color: "#9ca3af"
10415
10724
  },
10416
10725
  grandTotalContainer: {
10417
10726
  alignItems: "flex-end",
10418
- marginTop: 16
10727
+ marginTop: 10
10419
10728
  },
10420
10729
  grandTotalLabel: {
10421
- fontSize: 8,
10730
+ fontSize: 7,
10422
10731
  fontFamily: FONT_FAMILY_BOLD,
10423
10732
  color: "#9ca3af",
10424
10733
  textTransform: "uppercase",
10425
10734
  letterSpacing: 3,
10426
- marginBottom: 4,
10735
+ marginBottom: 2,
10427
10736
  textAlign: "right"
10428
10737
  },
10429
10738
  grandTotalValue: {
10430
- fontSize: 28,
10739
+ fontSize: 22,
10431
10740
  fontFamily: FONT_FAMILY_BOLD_OBLIQUE,
10432
10741
  letterSpacing: -0.5,
10433
10742
  textAlign: "right"
@@ -10435,42 +10744,42 @@ var styles = renderer.StyleSheet.create({
10435
10744
  // Footer - Editorial Style
10436
10745
  footer: {
10437
10746
  position: "absolute",
10438
- bottom: 30,
10439
- left: 48,
10440
- right: 48
10747
+ bottom: 24,
10748
+ left: 36,
10749
+ right: 36
10441
10750
  },
10442
10751
  dietaryLegend: {
10443
10752
  flexDirection: "row",
10444
10753
  flexWrap: "wrap",
10445
- marginBottom: 6
10754
+ marginBottom: 4
10446
10755
  },
10447
10756
  footerDivider: {
10448
10757
  height: 0.5,
10449
10758
  backgroundColor: "#d1d5db",
10450
- marginBottom: 10
10759
+ marginBottom: 6
10451
10760
  },
10452
10761
  dietaryLegendItem: {
10453
10762
  flexDirection: "row",
10454
10763
  alignItems: "center",
10455
- marginRight: 16,
10456
- marginBottom: 4
10764
+ marginRight: 10,
10765
+ marginBottom: 2
10457
10766
  },
10458
10767
  dietaryLegendBadge: {
10459
- width: 14,
10460
- height: 14,
10768
+ width: 12,
10769
+ height: 12,
10461
10770
  borderRadius: 2,
10462
10771
  alignItems: "center",
10463
10772
  justifyContent: "center",
10464
- marginRight: 4
10773
+ marginRight: 3
10465
10774
  },
10466
10775
  dietaryLegendText: {
10467
- fontSize: 8,
10776
+ fontSize: 7,
10468
10777
  fontFamily: FONT_FAMILY_BOLD,
10469
10778
  textTransform: "uppercase",
10470
10779
  letterSpacing: 1
10471
10780
  },
10472
10781
  footerText: {
10473
- fontSize: 8,
10782
+ fontSize: 7,
10474
10783
  fontFamily: FONT_FAMILY_OBLIQUE,
10475
10784
  color: "#666"
10476
10785
  }
@@ -10953,7 +11262,7 @@ function mapToMenuItem(item) {
10953
11262
  discountPrice: item.discountPrice?.toString(),
10954
11263
  allergens: item.allergens,
10955
11264
  isDiscount: item.isDiscount || false,
10956
- image: item.image,
11265
+ images: item.images ?? (item.image ? [item.image] : []),
10957
11266
  averageRating: item.averageRating,
10958
11267
  restaurantId: item.restaurantId,
10959
11268
  restaurantName: item.restaurant?.restaurant_name,
@@ -22014,10 +22323,10 @@ function MenuItemCard({
22014
22323
  ] })
22015
22324
  ] })
22016
22325
  ] }) }),
22017
- item.image && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[130px] h-full bg-gray-200 flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
22326
+ item.images?.[0] && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-[130px] h-full bg-gray-200 flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
22018
22327
  "img",
22019
22328
  {
22020
- src: item.image,
22329
+ src: item.images?.[0],
22021
22330
  alt: item.menuItemName,
22022
22331
  className: "w-full h-full object-cover"
22023
22332
  }
@@ -23164,8 +23473,8 @@ function RestaurantMenuBrowser({
23164
23473
  const orderA = a.itemDisplayOrder ?? 999;
23165
23474
  const orderB = b.itemDisplayOrder ?? 999;
23166
23475
  if (orderA !== orderB) return orderA - orderB;
23167
- const aHasImage = a.image && a.image.trim() !== "" ? 0 : 1;
23168
- const bHasImage = b.image && b.image.trim() !== "" ? 0 : 1;
23476
+ const aHasImage = (a.images?.[0] ?? "").trim() !== "" ? 0 : 1;
23477
+ const bHasImage = (b.images?.[0] ?? "").trim() !== "" ? 0 : 1;
23169
23478
  if (aHasImage !== bHasImage) return aHasImage - bHasImage;
23170
23479
  return getDisplayPrice(a) - getDisplayPrice(b);
23171
23480
  });
@@ -23425,7 +23734,15 @@ function RestaurantMenuBrowser({
23425
23734
  ]
23426
23735
  }
23427
23736
  ),
23428
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1 p-3 flex flex-col", children: [
23737
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1 p-3 flex flex-col relative", children: [
23738
+ restaurant.logoImageUrl && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-1/2 right-2 -translate-y-1/2 w-12 h-12 rounded-full overflow-hidden border-2 border-white shadow-md", children: /* @__PURE__ */ jsxRuntime.jsx(
23739
+ "img",
23740
+ {
23741
+ src: restaurant.logoImageUrl,
23742
+ alt: "",
23743
+ className: "w-full h-full object-cover"
23744
+ }
23745
+ ) }),
23429
23746
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "line-clamp-2 text-sm font-semibold leading-tight text-gray-900", children: restaurant.restaurant_name }),
23430
23747
  restaurant.minCateringOrderQuantity && restaurant.minCateringOrderQuantity > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1.5 flex flex-wrap gap-1.5", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center rounded-full bg-primary/10 px-2 py-1 text-[10px] font-semibold text-primary", children: [
23431
23748
  "Min ",
@@ -23638,7 +23955,7 @@ function RestaurantMenuBrowser({
23638
23955
  onClick: () => setSelectedCategoryId(
23639
23956
  selectedCategoryId === category.id ? null : category.id
23640
23957
  ),
23641
- className: `flex-shrink-0 px-3 py-1.5 rounded-xl text-sm font-medium transition-all border flex flex-col items-center justify-center gap-0.5 leading-none ${category.images || category.icon ? "min-h-16" : ""} ${selectedCategoryId === category.id ? "border-primary text-primary" : "border-transparent text-gray-700 hover:text-primary"}`,
23958
+ className: `w-20 flex-shrink-0 py-1.5 rounded-xl text-sm font-medium transition-all border flex flex-col items-center justify-center gap-0.5 leading-none ${category.images || category.icon ? "min-h-16" : ""} ${selectedCategoryId === category.id ? "border-primary text-primary" : "border-transparent text-gray-700 hover:text-primary"}`,
23642
23959
  children: [
23643
23960
  category.images ? /* @__PURE__ */ jsxRuntime.jsx(
23644
23961
  "img",
@@ -25042,7 +25359,8 @@ function AddressAutocomplete({
25042
25359
  onPlaceSelect,
25043
25360
  onClearAddress,
25044
25361
  error,
25045
- hasValidAddress
25362
+ hasValidAddress,
25363
+ hideChangeButton
25046
25364
  }) {
25047
25365
  const {
25048
25366
  inputRef,
@@ -25082,7 +25400,7 @@ function AddressAutocomplete({
25082
25400
  className: `address-search-input w-full bg-gray-50 border rounded-lg px-4 py-2.5 text-base text-base-content placeholder:text-base-content/50 focus:outline-none focus:ring-2 focus:ring-dark-pink/20 focus:border-dark-pink transition-all ${shownError ? "border-error" : hasValidAddress ? "border-success" : "border-base-300"}`
25083
25401
  }
25084
25402
  ),
25085
- hasValidAddress && /* @__PURE__ */ jsxRuntime.jsx(
25403
+ hasValidAddress && !hideChangeButton && /* @__PURE__ */ jsxRuntime.jsx(
25086
25404
  "button",
25087
25405
  {
25088
25406
  type: "button",
@@ -26493,7 +26811,7 @@ function CheckoutScreen() {
26493
26811
  price: orderItem.item.price,
26494
26812
  discountPrice: orderItem.item.discountPrice,
26495
26813
  isDiscount: orderItem.item.isDiscount,
26496
- image: orderItem.item.image,
26814
+ image: orderItem.item.images?.[0] ?? orderItem.item.image,
26497
26815
  restaurantId: orderItem.item.restaurantId,
26498
26816
  cateringQuantityUnit: orderItem.item.cateringQuantityUnit,
26499
26817
  feedsPerUnit: orderItem.item.feedsPerUnit,
@@ -27183,6 +27501,75 @@ function CheckoutScreen() {
27183
27501
  ] })
27184
27502
  ] });
27185
27503
  }
27504
+ function ShareCartButton({ className = "" }) {
27505
+ const { mealSessions, eventDetails } = useCateringState();
27506
+ const [status, setStatus] = react.useState(
27507
+ "idle"
27508
+ );
27509
+ const hasItems = mealSessions.some((s) => s.orderItems.length > 0);
27510
+ if (!hasItems) return null;
27511
+ const handleShare = async () => {
27512
+ if (status === "loading") return;
27513
+ setStatus("loading");
27514
+ try {
27515
+ const snapshot = serializeCartToSnapshot(
27516
+ mealSessions,
27517
+ eventDetails ? {
27518
+ eventType: eventDetails.eventType,
27519
+ eventDate: eventDetails.eventDate,
27520
+ eventTime: eventDetails.eventTime,
27521
+ guestCount: eventDetails.guestCount
27522
+ } : void 0
27523
+ );
27524
+ const { id } = await cateringService.createSharedCart(snapshot);
27525
+ const shareUrl = `${window.location.origin}${window.location.pathname}?sharedCart=${id}`;
27526
+ try {
27527
+ await navigator.clipboard.writeText(shareUrl);
27528
+ } catch {
27529
+ window.prompt("Copy your cart link:", shareUrl);
27530
+ }
27531
+ setStatus("done");
27532
+ setTimeout(() => setStatus("idle"), 2500);
27533
+ } catch (err) {
27534
+ console.error("[catering] failed to create share link", err);
27535
+ setStatus("error");
27536
+ setTimeout(() => setStatus("idle"), 2500);
27537
+ }
27538
+ };
27539
+ const label = status === "loading" ? "Creating link\u2026" : status === "done" ? "Link copied \u2713" : status === "error" ? "Try again" : "Share cart";
27540
+ return /* @__PURE__ */ jsxRuntime.jsxs(
27541
+ "button",
27542
+ {
27543
+ type: "button",
27544
+ onClick: handleShare,
27545
+ disabled: status === "loading",
27546
+ title: "Create a link to share this cart",
27547
+ className: `inline-flex items-center justify-center gap-1.5 rounded-lg border border-primary px-3 py-3 text-sm font-semibold text-primary transition-colors hover:bg-primary/5 disabled:cursor-not-allowed disabled:opacity-60 ${className}`,
27548
+ children: [
27549
+ /* @__PURE__ */ jsxRuntime.jsx(
27550
+ "svg",
27551
+ {
27552
+ xmlns: "http://www.w3.org/2000/svg",
27553
+ className: "h-4 w-4",
27554
+ fill: "none",
27555
+ viewBox: "0 0 24 24",
27556
+ stroke: "currentColor",
27557
+ strokeWidth: 2,
27558
+ children: /* @__PURE__ */ jsxRuntime.jsx(
27559
+ "path",
27560
+ {
27561
+ strokeLinecap: "round",
27562
+ strokeLinejoin: "round",
27563
+ d: "M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z"
27564
+ }
27565
+ )
27566
+ }
27567
+ ),
27568
+ label
27569
+ ]
27570
+ }
27571
+ );
27572
+ }
27186
27573
  function EmptySessionWarningModal({
27187
27574
  sessionName,
27188
27575
  onRemove,
@@ -27446,10 +27833,10 @@ function SwapItemModal({
27446
27833
  onClick: () => setSelectedAlternative(alt),
27447
27834
  className: "w-full flex items-center gap-3 p-3 rounded-xl border border-base-200 hover:border-primary/40 hover:bg-primary/5 transition-all text-left",
27448
27835
  children: [
27449
- alt.image ? /* @__PURE__ */ jsxRuntime.jsx(
27836
+ alt.images?.[0] ? /* @__PURE__ */ jsxRuntime.jsx(
27450
27837
  "img",
27451
27838
  {
27452
- src: alt.image,
27839
+ src: alt.images?.[0],
27453
27840
  alt: alt.menuItemName,
27454
27841
  className: "w-14 h-14 rounded-lg object-cover flex-shrink-0"
27455
27842
  }
@@ -27549,6 +27936,182 @@ function ValidationAlertModal({
27549
27936
  )
27550
27937
  ] }) });
27551
27938
  }
27939
+ function parseHHMM2(value) {
27940
+ if (!value) return null;
27941
+ const parts = value.split(":");
27942
+ if (parts.length !== 2) return null;
27943
+ const h = Number(parts[0]);
27944
+ const m = Number(parts[1]);
27945
+ if (!Number.isFinite(h) || !Number.isFinite(m)) return null;
27946
+ return h * 60 + m;
27947
+ }
27948
+ function WelcomeModal({ onComplete }) {
27949
+ const { contactInfo, setContactInfo, updateMealSession, mealSessions } = useCateringState();
27950
+ const { initialData, allowedCateringTimes } = useCateringConfig();
27951
+ const [addressUpdate, setAddressUpdate] = react.useState(null);
27952
+ const [sessionDate, setSessionDate] = react.useState("");
27953
+ const [selectedTimeSlot, setSelectedTimeSlot] = react.useState("");
27954
+ react.useEffect(() => {
27955
+ const first = mealSessions[0];
27956
+ if (!first) return;
27957
+ if (first.sessionDate) setSessionDate((prev) => prev || first.sessionDate);
27958
+ if (first.eventTime) setSelectedTimeSlot((prev) => prev || first.eventTime);
27959
+ }, [mealSessions]);
27960
+ const allowedStartMin = parseHHMM2(allowedCateringTimes?.start);
27961
+ const allowedEndMin = parseHHMM2(allowedCateringTimes?.end);
27962
+ const eventStartDate = initialData?.eventStartDate ?? "";
27963
+ const eventEndDate = initialData?.eventEndDate ?? "";
27964
+ const eventStartMin = parseHHMM2(initialData?.eventStartTime);
27965
+ const eventEndMin = parseHHMM2(initialData?.eventEndTime);
27966
+ const lowerBoundMin = (() => {
27967
+ let lo = allowedStartMin ?? null;
27968
+ if (sessionDate && eventStartDate && sessionDate === eventStartDate && eventStartMin != null) {
27969
+ lo = lo == null ? eventStartMin : Math.max(lo, eventStartMin);
27970
+ }
27971
+ return lo;
27972
+ })();
27973
+ const upperBoundMin = (() => {
27974
+ let hi = allowedEndMin ?? null;
27975
+ if (sessionDate && eventEndDate && sessionDate === eventEndDate && eventEndMin != null) {
27976
+ hi = hi == null ? eventEndMin : Math.min(hi, eventEndMin);
27977
+ }
27978
+ return hi;
27979
+ })();
27980
+ const SLOT_DURATION_MIN = 30;
27981
+ const availableSlots = TIME_SLOT_OPTIONS.filter((o) => {
27982
+ const slotStart = parseHHMM2(o.value);
27983
+ if (slotStart == null) return false;
27984
+ const slotEnd = slotStart + SLOT_DURATION_MIN;
27985
+ if (lowerBoundMin != null && slotStart < lowerBoundMin) return false;
27986
+ if (upperBoundMin != null && slotEnd > upperBoundMin) return false;
27987
+ return true;
27988
+ });
27989
+ const dateMin = eventStartDate || getMinDate();
27990
+ const dateMax = eventEndDate || getMaxDate();
27991
+ const handlePlaceSelect = (place) => {
27992
+ const parsed = parsePlaceResult(place);
27993
+ if (!parsed) return;
27994
+ setAddressUpdate(parsed.contactInfo);
27995
+ };
27996
+ const handleClearAddress = () => {
27997
+ setAddressUpdate(null);
27998
+ };
27999
+ const applyAndClose = () => {
28000
+ if (addressUpdate) {
28001
+ setContactInfo({
28002
+ ...contactInfo ?? {},
28003
+ ...addressUpdate
28004
+ });
28005
+ }
28006
+ if (sessionDate || selectedTimeSlot) {
28007
+ updateMealSession(0, {
28008
+ ...sessionDate && { sessionDate },
28009
+ ...selectedTimeSlot && { eventTime: selectedTimeSlot }
28010
+ });
28011
+ }
28012
+ onComplete();
28013
+ };
28014
+ const hasAnyDetail = !!addressUpdate || !!sessionDate || !!selectedTimeSlot;
28015
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-[100] p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-2xl max-w-md w-full max-h-[90vh] overflow-y-auto shadow-xl animate-in zoom-in-95 duration-200", children: [
28016
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 pt-6 pb-5", children: [
28017
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12 h-12 rounded-2xl bg-primary flex items-center justify-center shadow-md mb-3", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-6 w-6 text-white" }) }),
28018
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-semibold uppercase tracking-widest text-primary", children: "Welcome" }),
28019
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "mt-1 text-xl font-bold text-gray-900 leading-tight", children: "Let's tailor your order" })
28020
+ ] }),
28021
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 pb-6", children: [
28022
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 mb-6 space-y-3", children: [
28023
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
28024
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-7 h-7 flex-shrink-0 rounded-lg bg-primary/10 flex items-center justify-center mt-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MapPin, { className: "h-4 w-4 text-primary" }) }),
28025
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-600 leading-snug", children: [
28026
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-gray-800", children: "Delivery address" }),
28027
+ " ",
28028
+ "\u2014 so we surface the restaurants nearest to you."
28029
+ ] })
28030
+ ] }),
28031
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
28032
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-7 h-7 flex-shrink-0 rounded-lg bg-primary/10 flex items-center justify-center mt-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "h-4 w-4 text-primary" }) }),
28033
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-600 leading-snug", children: [
28034
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-gray-800", children: "Event date & time" }),
28035
+ " ",
28036
+ "\u2014 so we respect each restaurant's opening hours and minimum order notice."
28037
+ ] })
28038
+ ] })
28039
+ ] }),
28040
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
28041
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1", children: /* @__PURE__ */ jsxRuntime.jsx(
28042
+ AddressAutocomplete,
28043
+ {
28044
+ onPlaceSelect: handlePlaceSelect,
28045
+ onClearAddress: handleClearAddress,
28046
+ hasValidAddress: !!addressUpdate,
28047
+ hideChangeButton: true
28048
+ }
28049
+ ) }),
28050
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
28051
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-[10px] font-bold uppercase tracking-widest text-base-content/60 mb-1.5", children: "Event date" }),
28052
+ /* @__PURE__ */ jsxRuntime.jsx(
28053
+ DatePickerField,
28054
+ {
28055
+ value: sessionDate,
28056
+ onChange: setSessionDate,
28057
+ min: dateMin,
28058
+ max: dateMax,
28059
+ ariaLabel: "Event date"
28060
+ }
28061
+ )
28062
+ ] }),
28063
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
28064
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-[10px] font-bold uppercase tracking-widest text-base-content/60 mb-1.5", children: "Event time" }),
28065
+ /* @__PURE__ */ jsxRuntime.jsx(
28066
+ TimeSlotDropdown,
28067
+ {
28068
+ value: selectedTimeSlot,
28069
+ onChange: setSelectedTimeSlot,
28070
+ slots: availableSlots
28071
+ }
28072
+ ),
28073
+ lowerBoundMin != null && upperBoundMin != null && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-1.5 text-xs text-base-content/60", children: [
28074
+ "Available between",
28075
+ " ",
28076
+ formatTime(
28077
+ Math.floor(lowerBoundMin / 60),
28078
+ lowerBoundMin % 60
28079
+ ),
28080
+ " ",
28081
+ "and",
28082
+ " ",
28083
+ formatTime(
28084
+ Math.floor(upperBoundMin / 60),
28085
+ upperBoundMin % 60
28086
+ ),
28087
+ "."
28088
+ ] })
28089
+ ] })
28090
+ ] }),
28091
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 mt-6", children: [
28092
+ /* @__PURE__ */ jsxRuntime.jsx(
28093
+ "button",
28094
+ {
28095
+ type: "button",
28096
+ onClick: onComplete,
28097
+ className: "px-4 py-3 text-sm font-medium text-gray-500 hover:text-gray-800 transition-colors",
28098
+ children: "Skip for now"
28099
+ }
28100
+ ),
28101
+ /* @__PURE__ */ jsxRuntime.jsx(
28102
+ "button",
28103
+ {
28104
+ type: "button",
28105
+ onClick: applyAndClose,
28106
+ disabled: !hasAnyDetail,
28107
+ className: "flex-1 px-4 py-3 bg-primary text-white rounded-xl shadow-md hover:bg-primary/90 transition-colors font-semibold disabled:opacity-40 disabled:cursor-not-allowed disabled:shadow-none",
28108
+ children: "Continue"
28109
+ }
28110
+ )
28111
+ ] })
28112
+ ] })
28113
+ ] }) });
28114
+ }
27552
28115
  var TUTORIAL_STORAGE_KEY = "catering_tutorial_completed";
27553
28116
  function useCateringTutorial({
27554
28117
  mealSessions,
@@ -27840,10 +28403,10 @@ function useCateringData({ expandedSessionIndex }) {
27840
28403
  }
27841
28404
  const mappedItems = data.map(mapToMenuItem);
27842
28405
  const itemsWithImage = mappedItems.filter(
27843
- (item) => item.image && item.image.trim() !== ""
28406
+ (item) => (item.images?.[0] ?? "").trim() !== ""
27844
28407
  );
27845
28408
  const itemsWithoutImage = mappedItems.filter(
27846
- (item) => !item.image || item.image.trim() === ""
28409
+ (item) => (item.images?.[0] ?? "").trim() === ""
27847
28410
  );
27848
28411
  const sortedItems = [...itemsWithImage, ...itemsWithoutImage];
27849
28412
  setMenuItems(sortedItems);
@@ -27995,6 +28558,17 @@ function CateringOrderBuilder() {
27995
28558
  },
27996
28559
  [storage]
27997
28560
  );
28561
+ const WELCOME_SEEN_KEY = "catering_welcome_seen";
28562
+ const [showWelcomeModal, setShowWelcomeModal] = react.useState(() => {
28563
+ if (storage.getItem(WELCOME_SEEN_KEY) === "true") return false;
28564
+ if (contactInfo?.addressLine1) return false;
28565
+ if (mealSessions[0]?.sessionDate) return false;
28566
+ return true;
28567
+ });
28568
+ const handleWelcomeComplete = react.useCallback(() => {
28569
+ storage.setItem(WELCOME_SEEN_KEY, "true");
28570
+ setShowWelcomeModal(false);
28571
+ }, [storage]);
27998
28572
  const [isMobileAIChatOpen, setIsMobileAIChatOpen] = react.useState(false);
27999
28573
  const [mobileChatView, setMobileChatView] = react.useState(
28000
28574
  "chat"
@@ -28277,7 +28851,7 @@ function CateringOrderBuilder() {
28277
28851
  allergens: item.allergens,
28278
28852
  dietaryFilters: item.dietaryFilters,
28279
28853
  isDiscount: item.isDiscount,
28280
- image: item.image,
28854
+ image: item.images?.[0],
28281
28855
  restaurantId: item.restaurantId,
28282
28856
  restaurantName: item.restaurantName,
28283
28857
  groupTitle: item.groupTitle,
@@ -28954,6 +29528,8 @@ function CateringOrderBuilder() {
28954
29528
  setActiveSessionIndex(0);
28955
29529
  setIsClearAllConfirmOpen(false);
28956
29530
  setIsMobileCartMenuOpen(false);
29531
+ storage.removeItem(WELCOME_SEEN_KEY);
29532
+ setShowWelcomeModal(true);
28957
29533
  };
28958
29534
  const handlePdfDownload = async (withPrices) => {
28959
29535
  if (generatingPdf) return;
@@ -29007,7 +29583,7 @@ function CateringOrderBuilder() {
29007
29583
  price: orderItem.item.price,
29008
29584
  discountPrice: orderItem.item.discountPrice,
29009
29585
  isDiscount: orderItem.item.isDiscount,
29010
- image: orderItem.item.image,
29586
+ image: orderItem.item.images?.[0] ?? orderItem.item.image,
29011
29587
  restaurantId: orderItem.item.restaurantId,
29012
29588
  cateringQuantityUnit: orderItem.item.cateringQuantityUnit,
29013
29589
  feedsPerUnit: orderItem.item.feedsPerUnit,
@@ -29112,6 +29688,7 @@ function CateringOrderBuilder() {
29112
29688
  },
29113
29689
  children: [
29114
29690
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-h-screen bg-base-100", children: [
29691
+ showWelcomeModal && /* @__PURE__ */ jsxRuntime.jsx(WelcomeModal, { onComplete: handleWelcomeComplete }),
29115
29692
  editingSessionIndex !== null && /* @__PURE__ */ jsxRuntime.jsx(
29116
29693
  SessionEditor,
29117
29694
  {
@@ -29352,6 +29929,7 @@ function CateringOrderBuilder() {
29352
29929
  )
29353
29930
  ] })
29354
29931
  ] }),
29932
+ /* @__PURE__ */ jsxRuntime.jsx(ShareCartButton, {}),
29355
29933
  /* @__PURE__ */ jsxRuntime.jsx(
29356
29934
  "button",
29357
29935
  {
@@ -30385,7 +30963,10 @@ function CateringWidget(props) {
30385
30963
  );
30386
30964
  }
30387
30965
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "swift-catering-widget", style, children: [
30388
- /* @__PURE__ */ jsxRuntime.jsx(CateringConfigProvider, { value: config, children: /* @__PURE__ */ jsxRuntime.jsx(CateringStateProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(CateringFilterProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(CateringOrderBuilder, {}) }) }) }),
30966
+ /* @__PURE__ */ jsxRuntime.jsx(CateringConfigProvider, { value: config, children: /* @__PURE__ */ jsxRuntime.jsxs(CateringStateProvider, { children: [
30967
+ /* @__PURE__ */ jsxRuntime.jsx(SharedCartLoader, {}),
30968
+ /* @__PURE__ */ jsxRuntime.jsx(CateringFilterProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(CateringOrderBuilder, {}) })
30969
+ ] }) }),
30389
30970
  /* @__PURE__ */ jsxRuntime.jsx("div", { "data-swift-overlay-root": true, className: "swift-chat-design" })
30390
30971
  ] });
30391
30972
  }