@swift-food-services/catering-widget 0.2.0-beta.4 → 0.2.0-beta.6
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 +1660 -1114
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1662 -1116
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +2 -2
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -33,7 +33,7 @@ function styleInject(css, { insertAt } = {}) {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
// src/styles/generated.css
|
|
36
|
-
styleInject(`/*! tailwindcss v4.
|
|
36
|
+
styleInject(`/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
|
|
37
37
|
@layer properties {
|
|
38
38
|
@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))) {
|
|
39
39
|
.swift-catering-widget *,
|
|
@@ -667,19 +667,17 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
667
667
|
--depth:1;
|
|
668
668
|
--noise:0;
|
|
669
669
|
}
|
|
670
|
-
.swift-catering-widget {
|
|
671
|
-
--fx-noise:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E");
|
|
672
|
-
scrollbar-color: currentColor #0000;
|
|
673
|
-
}
|
|
674
|
-
@supports (color:color-mix(in lab, red, red)) {
|
|
675
|
-
.swift-catering-widget {
|
|
676
|
-
scrollbar-color: color-mix(in oklch, currentColor 35%, #0000) #0000;
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
@property --radialprogress { syntax:"<percentage>";inherits:true;initial-value:0% }
|
|
680
670
|
.swift-catering-widget :root:not(span) {
|
|
681
671
|
overflow: var(--page-overflow);
|
|
682
672
|
}
|
|
673
|
+
.swift-catering-widget,
|
|
674
|
+
.swift-catering-widget [data-theme] {
|
|
675
|
+
background: var(--page-scroll-bg,var(--root-bg));
|
|
676
|
+
color: var(--color-base-content);
|
|
677
|
+
}
|
|
678
|
+
.swift-catering-widget :where(:root, [data-theme]) {
|
|
679
|
+
--root-bg:var(--color-base-100);
|
|
680
|
+
}
|
|
683
681
|
.swift-catering-widget {
|
|
684
682
|
background: var(--page-scroll-bg,var(--root-bg));
|
|
685
683
|
--page-scroll-bg-on:linear-gradient(var(--root-bg,#0000), var(--root-bg,#0000)) var(--root-bg,#0000);
|
|
@@ -700,14 +698,16 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
700
698
|
--page-has-scroll:1;
|
|
701
699
|
}
|
|
702
700
|
}
|
|
703
|
-
.swift-catering-widget
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
color: var(--color-base-content);
|
|
701
|
+
.swift-catering-widget {
|
|
702
|
+
--fx-noise:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.34' numOctaves='4' stitchTiles='stitch'%3E%3C/feTurbulence%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23a)' opacity='0.2'%3E%3C/rect%3E%3C/svg%3E");
|
|
703
|
+
scrollbar-color: currentColor #0000;
|
|
707
704
|
}
|
|
708
|
-
|
|
709
|
-
|
|
705
|
+
@supports (color:color-mix(in lab, red, red)) {
|
|
706
|
+
.swift-catering-widget {
|
|
707
|
+
scrollbar-color: color-mix(in oklch, currentColor 35%, #0000) #0000;
|
|
708
|
+
}
|
|
710
709
|
}
|
|
710
|
+
@property --radialprogress { syntax:"<percentage>";inherits:true;initial-value:0% }
|
|
711
711
|
}
|
|
712
712
|
@layer components {
|
|
713
713
|
.swift-catering-widget .swift-btn-primary {
|
|
@@ -1323,7 +1323,8 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
1323
1323
|
transition-property:
|
|
1324
1324
|
opacity,
|
|
1325
1325
|
scale,
|
|
1326
|
-
display
|
|
1326
|
+
display,
|
|
1327
|
+
overlay;
|
|
1327
1328
|
transition-duration: .2s;
|
|
1328
1329
|
transition-timing-function: cubic-bezier(.4, 0, .2, 1);
|
|
1329
1330
|
animation: .2s dropdown;
|
|
@@ -3543,12 +3544,6 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
3543
3544
|
.swift-catering-widget .inset-x-4 {
|
|
3544
3545
|
inset-inline: calc(var(--spacing) * 4);
|
|
3545
3546
|
}
|
|
3546
|
-
.swift-catering-widget .start {
|
|
3547
|
-
inset-inline-start: var(--spacing);
|
|
3548
|
-
}
|
|
3549
|
-
.swift-catering-widget .end {
|
|
3550
|
-
inset-inline-end: var(--spacing);
|
|
3551
|
-
}
|
|
3552
3547
|
.swift-catering-widget .-top-14 {
|
|
3553
3548
|
top: calc(var(--spacing) * -14);
|
|
3554
3549
|
}
|
|
@@ -3854,6 +3849,9 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
3854
3849
|
.swift-catering-widget .mb-2 {
|
|
3855
3850
|
margin-bottom: calc(var(--spacing) * 2);
|
|
3856
3851
|
}
|
|
3852
|
+
.swift-catering-widget .mb-2\\.5 {
|
|
3853
|
+
margin-bottom: calc(var(--spacing) * 2.5);
|
|
3854
|
+
}
|
|
3857
3855
|
.swift-catering-widget .mb-3 {
|
|
3858
3856
|
margin-bottom: calc(var(--spacing) * 3);
|
|
3859
3857
|
}
|
|
@@ -4053,8 +4051,8 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
4053
4051
|
.swift-catering-widget .min-h-16 {
|
|
4054
4052
|
min-height: calc(var(--spacing) * 16);
|
|
4055
4053
|
}
|
|
4056
|
-
.swift-catering-widget .min-h-\\[
|
|
4057
|
-
min-height:
|
|
4054
|
+
.swift-catering-widget .min-h-\\[18px\\] {
|
|
4055
|
+
min-height: 18px;
|
|
4058
4056
|
}
|
|
4059
4057
|
.swift-catering-widget .min-h-\\[100px\\] {
|
|
4060
4058
|
min-height: 100px;
|
|
@@ -5352,6 +5350,9 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
5352
5350
|
.swift-catering-widget .pl-4 {
|
|
5353
5351
|
padding-left: calc(var(--spacing) * 4);
|
|
5354
5352
|
}
|
|
5353
|
+
.swift-catering-widget .pl-6 {
|
|
5354
|
+
padding-left: calc(var(--spacing) * 6);
|
|
5355
|
+
}
|
|
5355
5356
|
.swift-catering-widget .pl-9 {
|
|
5356
5357
|
padding-left: calc(var(--spacing) * 9);
|
|
5357
5358
|
}
|
|
@@ -6963,10 +6964,9 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
6963
6964
|
transform: translate(100%);
|
|
6964
6965
|
}
|
|
6965
6966
|
}
|
|
6966
|
-
@keyframes
|
|
6967
|
-
0
|
|
6968
|
-
|
|
6969
|
-
scale: 1.1;
|
|
6967
|
+
@keyframes menu {
|
|
6968
|
+
0% {
|
|
6969
|
+
opacity: 0;
|
|
6970
6970
|
}
|
|
6971
6971
|
}
|
|
6972
6972
|
@keyframes dropdown {
|
|
@@ -6974,12 +6974,23 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
6974
6974
|
opacity: 0;
|
|
6975
6975
|
}
|
|
6976
6976
|
}
|
|
6977
|
-
@keyframes
|
|
6977
|
+
@keyframes skeleton {
|
|
6978
6978
|
0% {
|
|
6979
|
-
|
|
6979
|
+
background-position: 150%;
|
|
6980
|
+
}
|
|
6981
|
+
to {
|
|
6982
|
+
background-position: -50%;
|
|
6983
|
+
}
|
|
6984
|
+
}
|
|
6985
|
+
@keyframes rating {
|
|
6986
|
+
0%, 40% {
|
|
6987
|
+
filter: brightness(1.05)contrast(1.05);
|
|
6988
|
+
scale: 1.1;
|
|
6980
6989
|
}
|
|
6990
|
+
}
|
|
6991
|
+
@keyframes progress {
|
|
6981
6992
|
50% {
|
|
6982
|
-
|
|
6993
|
+
background-position-x: -115%;
|
|
6983
6994
|
}
|
|
6984
6995
|
}
|
|
6985
6996
|
@keyframes toast {
|
|
@@ -7003,22 +7014,12 @@ styleInject(`/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
|
|
|
7003
7014
|
translate: 0 -100%;
|
|
7004
7015
|
}
|
|
7005
7016
|
}
|
|
7006
|
-
@keyframes
|
|
7007
|
-
0% {
|
|
7008
|
-
background-position: 150%;
|
|
7009
|
-
}
|
|
7010
|
-
to {
|
|
7011
|
-
background-position: -50%;
|
|
7012
|
-
}
|
|
7013
|
-
}
|
|
7014
|
-
@keyframes menu {
|
|
7017
|
+
@keyframes radio {
|
|
7015
7018
|
0% {
|
|
7016
|
-
|
|
7019
|
+
padding: 5px;
|
|
7017
7020
|
}
|
|
7018
|
-
}
|
|
7019
|
-
@keyframes progress {
|
|
7020
7021
|
50% {
|
|
7021
|
-
|
|
7022
|
+
padding: 3px;
|
|
7022
7023
|
}
|
|
7023
7024
|
}
|
|
7024
7025
|
@property --tw-translate-x { syntax:"*";inherits:false;initial-value:0 }
|
|
@@ -7120,6 +7121,9 @@ function useCateringConfig() {
|
|
|
7120
7121
|
}
|
|
7121
7122
|
return ctx;
|
|
7122
7123
|
}
|
|
7124
|
+
function useApiClient() {
|
|
7125
|
+
return useCateringConfig().api;
|
|
7126
|
+
}
|
|
7123
7127
|
function useStorage() {
|
|
7124
7128
|
return useCateringConfig().storage;
|
|
7125
7129
|
}
|
|
@@ -7559,6 +7563,15 @@ function createChatEndpoints(client) {
|
|
|
7559
7563
|
if (!res.ok) throw new ChatApiError(`HTTP ${res.status}`, res.status);
|
|
7560
7564
|
return res.json();
|
|
7561
7565
|
},
|
|
7566
|
+
detectFields: async (message, signal) => {
|
|
7567
|
+
const res = await client.request("/catering-chat/detect-fields", {
|
|
7568
|
+
method: "POST",
|
|
7569
|
+
body: JSON.stringify({ message }),
|
|
7570
|
+
signal
|
|
7571
|
+
});
|
|
7572
|
+
if (!res.ok) throw new ChatApiError(`HTTP ${res.status}`, res.status);
|
|
7573
|
+
return res.json();
|
|
7574
|
+
},
|
|
7562
7575
|
submitFeedback: async (sid, body) => {
|
|
7563
7576
|
const payload = { rating: body.rating };
|
|
7564
7577
|
if (body.note && body.note.trim()) payload.note = body.note.trim();
|
|
@@ -8136,7 +8149,8 @@ var STORAGE_KEY = "catering_filters";
|
|
|
8136
8149
|
var defaultFilters = {
|
|
8137
8150
|
dietaryRestrictions: [],
|
|
8138
8151
|
allergens: [],
|
|
8139
|
-
pricePerPersonRange: null
|
|
8152
|
+
pricePerPersonRange: null,
|
|
8153
|
+
restaurantPriceRange: null
|
|
8140
8154
|
};
|
|
8141
8155
|
function CateringFilterProvider({ children }) {
|
|
8142
8156
|
const storage = useStorage();
|
|
@@ -8166,6 +8180,15 @@ function CateringFilterProvider({ children }) {
|
|
|
8166
8180
|
const clearFilters = () => setFiltersState(defaultFilters);
|
|
8167
8181
|
return /* @__PURE__ */ jsxRuntime.jsx(FilterContext.Provider, { value: { filters, setFilters, clearFilters }, children });
|
|
8168
8182
|
}
|
|
8183
|
+
function useCateringFilters() {
|
|
8184
|
+
const context = react.useContext(FilterContext);
|
|
8185
|
+
if (context === void 0) {
|
|
8186
|
+
throw new Error(
|
|
8187
|
+
"useCateringFilters must be used within a CateringFilterProvider"
|
|
8188
|
+
);
|
|
8189
|
+
}
|
|
8190
|
+
return context;
|
|
8191
|
+
}
|
|
8169
8192
|
function useSearchParams() {
|
|
8170
8193
|
return new URLSearchParams();
|
|
8171
8194
|
}
|
|
@@ -9452,7 +9475,7 @@ function MenuItemModal({
|
|
|
9452
9475
|
onClick: () => handleSaveAiPick(true),
|
|
9453
9476
|
disabled: isMinSelectionsUnmet,
|
|
9454
9477
|
className: `w-full py-3 rounded-lg font-medium transition-all text-sm ${isMinSelectionsUnmet ? "bg-base-300 text-base-content/50 cursor-not-allowed" : "bg-primary hover:opacity-90 text-white"}`,
|
|
9455
|
-
children: isPickedInAiMenu ? "Save selections" : "Pick \xB7 Save selections"
|
|
9478
|
+
children: addButtonLabel ?? (isPickedInAiMenu ? "Save selections" : "Pick \xB7 Save selections")
|
|
9456
9479
|
}
|
|
9457
9480
|
),
|
|
9458
9481
|
isPickedInAiMenu && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -11267,7 +11290,8 @@ function SessionEditor({
|
|
|
11267
11290
|
onUpdate,
|
|
11268
11291
|
onClose,
|
|
11269
11292
|
restaurants,
|
|
11270
|
-
existingDates = []
|
|
11293
|
+
existingDates = [],
|
|
11294
|
+
existingSessions = []
|
|
11271
11295
|
}) {
|
|
11272
11296
|
const [sessionName, setSessionName] = react.useState(session.sessionName);
|
|
11273
11297
|
const [sessionDate, setSessionDate] = react.useState(session.sessionDate);
|
|
@@ -11347,6 +11371,10 @@ function SessionEditor({
|
|
|
11347
11371
|
);
|
|
11348
11372
|
return;
|
|
11349
11373
|
}
|
|
11374
|
+
if (existingSessions.some((s) => s.date === sessionDate && s.time === eventTime)) {
|
|
11375
|
+
setValidationError("A session with the same date and time already exists.");
|
|
11376
|
+
return;
|
|
11377
|
+
}
|
|
11350
11378
|
if (eventStartDate && sessionDate < eventStartDate) {
|
|
11351
11379
|
setValidationError("Session date is before the event starts.");
|
|
11352
11380
|
return;
|
|
@@ -11460,7 +11488,7 @@ function SessionEditor({
|
|
|
11460
11488
|
] }),
|
|
11461
11489
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
11462
11490
|
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Date" }),
|
|
11463
|
-
existingDates.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-2 overflow-x-auto scrollbar-hide pb-2 mb-2", children: existingDates.map((d) => {
|
|
11491
|
+
existingDates.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-2 overflow-x-auto scrollbar-hide pb-2 mb-2", children: [...existingDates].sort((a, b) => a.date.localeCompare(b.date)).map((d) => {
|
|
11464
11492
|
const isActive = sessionDate === d.date;
|
|
11465
11493
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11466
11494
|
"button",
|
|
@@ -13514,6 +13542,10 @@ function ChatSessionProvider({
|
|
|
13514
13542
|
setFeedbackTarget({ messageId, up, eventId });
|
|
13515
13543
|
setFeedbackRating(0);
|
|
13516
13544
|
},
|
|
13545
|
+
startGeneralFeedback: () => {
|
|
13546
|
+
setFeedbackTarget({ messageId: "__general__", up: false });
|
|
13547
|
+
setFeedbackRating(0);
|
|
13548
|
+
},
|
|
13517
13549
|
cancelFeedback: () => {
|
|
13518
13550
|
setFeedbackTarget(null);
|
|
13519
13551
|
setFeedbackRating(0);
|
|
@@ -13735,21 +13767,23 @@ function DraftItemRow({
|
|
|
13735
13767
|
}
|
|
13736
13768
|
),
|
|
13737
13769
|
item.reason && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: 4 }, children: /* @__PURE__ */ jsxRuntime.jsx(Reason, { children: item.reason }) }),
|
|
13738
|
-
|
|
13739
|
-
|
|
13740
|
-
|
|
13741
|
-
|
|
13742
|
-
"
|
|
13770
|
+
dietary.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", alignItems: "center", gap: 3, marginTop: 6 }, children: dietary.map((d) => {
|
|
13771
|
+
const iconInfo = DIETARY_ICON_MAP[d.toLowerCase()];
|
|
13772
|
+
if (!iconInfo) return null;
|
|
13773
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
13774
|
+
"img",
|
|
13743
13775
|
{
|
|
13744
|
-
|
|
13745
|
-
|
|
13746
|
-
|
|
13747
|
-
|
|
13748
|
-
|
|
13749
|
-
|
|
13750
|
-
|
|
13751
|
-
|
|
13752
|
-
|
|
13776
|
+
src: iconInfo.src,
|
|
13777
|
+
alt: iconInfo.label,
|
|
13778
|
+
title: iconInfo.label,
|
|
13779
|
+
style: { width: 16, height: 16, objectFit: "contain" }
|
|
13780
|
+
},
|
|
13781
|
+
d
|
|
13782
|
+
);
|
|
13783
|
+
}) }),
|
|
13784
|
+
allergens.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { fontSize: "0.65rem", color: "#b0b0b0", margin: "4px 0 0", lineHeight: 1.4 }, children: [
|
|
13785
|
+
"Contains: ",
|
|
13786
|
+
allergens.map((a) => a.toLowerCase().replace(/_/g, " ")).join(", ")
|
|
13753
13787
|
] })
|
|
13754
13788
|
] }),
|
|
13755
13789
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -13819,19 +13853,6 @@ function DraftItemRow({
|
|
|
13819
13853
|
children: "Swap"
|
|
13820
13854
|
}
|
|
13821
13855
|
),
|
|
13822
|
-
onRemove && /* @__PURE__ */ jsxRuntime.jsx(
|
|
13823
|
-
"button",
|
|
13824
|
-
{
|
|
13825
|
-
type: "button",
|
|
13826
|
-
className: "chip",
|
|
13827
|
-
onClick: (e) => {
|
|
13828
|
-
e.stopPropagation();
|
|
13829
|
-
onRemove();
|
|
13830
|
-
},
|
|
13831
|
-
style: { height: 26, fontSize: "0.75rem" },
|
|
13832
|
-
children: "Remove"
|
|
13833
|
-
}
|
|
13834
|
-
),
|
|
13835
13856
|
(addonSummary || addonState) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
13836
13857
|
"button",
|
|
13837
13858
|
{
|
|
@@ -14902,16 +14923,21 @@ function PreviewItemCard({
|
|
|
14902
14923
|
dietary.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
14903
14924
|
"div",
|
|
14904
14925
|
{
|
|
14905
|
-
style: { display: "flex",
|
|
14906
|
-
children: dietary.map((d) =>
|
|
14907
|
-
|
|
14908
|
-
|
|
14909
|
-
|
|
14910
|
-
|
|
14911
|
-
|
|
14912
|
-
|
|
14913
|
-
|
|
14914
|
-
|
|
14926
|
+
style: { display: "flex", alignItems: "center", gap: 3, marginTop: 4 },
|
|
14927
|
+
children: dietary.map((d) => {
|
|
14928
|
+
const iconInfo = DIETARY_ICON_MAP[d.toLowerCase()];
|
|
14929
|
+
if (!iconInfo) return null;
|
|
14930
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
14931
|
+
"img",
|
|
14932
|
+
{
|
|
14933
|
+
src: iconInfo.src,
|
|
14934
|
+
alt: iconInfo.label,
|
|
14935
|
+
title: iconInfo.label,
|
|
14936
|
+
style: { width: 14, height: 14, objectFit: "contain" }
|
|
14937
|
+
},
|
|
14938
|
+
d
|
|
14939
|
+
);
|
|
14940
|
+
})
|
|
14915
14941
|
}
|
|
14916
14942
|
)
|
|
14917
14943
|
]
|
|
@@ -16324,6 +16350,26 @@ function getOverlayRoot() {
|
|
|
16324
16350
|
}
|
|
16325
16351
|
return document.querySelector("[data-swift-overlay-root]") ?? document.body;
|
|
16326
16352
|
}
|
|
16353
|
+
function swapOptionToMenuItem(o, restaurantId) {
|
|
16354
|
+
return {
|
|
16355
|
+
id: o.menuItemId,
|
|
16356
|
+
menuItemName: o.name,
|
|
16357
|
+
description: o.description ?? void 0,
|
|
16358
|
+
price: String(o.unitPrice),
|
|
16359
|
+
discountPrice: o.discountPrice != null ? String(o.discountPrice) : void 0,
|
|
16360
|
+
isDiscount: o.isDiscount,
|
|
16361
|
+
image: o.imageUrl ?? void 0,
|
|
16362
|
+
allergens: o.allergens,
|
|
16363
|
+
dietaryFilters: o.dietaryFilters,
|
|
16364
|
+
cateringQuantityUnit: o.cateringQuantityUnit,
|
|
16365
|
+
feedsPerUnit: o.feedsPerUnit,
|
|
16366
|
+
minOrderQuantity: o.minOrderQuantity,
|
|
16367
|
+
restaurantId,
|
|
16368
|
+
groupTitle: o.groupTitle ?? void 0,
|
|
16369
|
+
itemDisplayOrder: 0,
|
|
16370
|
+
addons: o.addons ?? []
|
|
16371
|
+
};
|
|
16372
|
+
}
|
|
16327
16373
|
function SwapModal({
|
|
16328
16374
|
open,
|
|
16329
16375
|
sessionId,
|
|
@@ -16341,10 +16387,12 @@ function SwapModal({
|
|
|
16341
16387
|
const [options, setOptions] = react.useState(null);
|
|
16342
16388
|
const [loading, setLoading] = react.useState(false);
|
|
16343
16389
|
const [error, setError] = react.useState(null);
|
|
16390
|
+
const [selected, setSelected] = react.useState(null);
|
|
16344
16391
|
react.useEffect(() => {
|
|
16345
16392
|
if (!open || !restaurantId || !category) {
|
|
16346
16393
|
setOptions(null);
|
|
16347
16394
|
setError(null);
|
|
16395
|
+
setSelected(null);
|
|
16348
16396
|
return;
|
|
16349
16397
|
}
|
|
16350
16398
|
let cancelled = false;
|
|
@@ -16369,6 +16417,24 @@ function SwapModal({
|
|
|
16369
16417
|
};
|
|
16370
16418
|
}, [open, sessionId, restaurantId, category, excludeIds.join(","), intentPhrase]);
|
|
16371
16419
|
if (typeof document === "undefined") return null;
|
|
16420
|
+
if (selected && restaurantId) {
|
|
16421
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16422
|
+
MenuItemModal,
|
|
16423
|
+
{
|
|
16424
|
+
item: swapOptionToMenuItem(selected, restaurantId),
|
|
16425
|
+
isOpen: true,
|
|
16426
|
+
onClose: () => setSelected(null),
|
|
16427
|
+
viewOnly: true,
|
|
16428
|
+
aiAddonMode: true,
|
|
16429
|
+
addButtonLabel: "Confirm Swap",
|
|
16430
|
+
isPickedInAiMenu: false,
|
|
16431
|
+
onSaveAiPickAddons: (selections) => {
|
|
16432
|
+
onPick(selected, selections);
|
|
16433
|
+
setSelected(null);
|
|
16434
|
+
}
|
|
16435
|
+
}
|
|
16436
|
+
);
|
|
16437
|
+
}
|
|
16372
16438
|
const modal = /* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { children: open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
16373
16439
|
react$1.motion.div,
|
|
16374
16440
|
{
|
|
@@ -16377,7 +16443,16 @@ function SwapModal({
|
|
|
16377
16443
|
exit: { opacity: 0 },
|
|
16378
16444
|
transition: { duration: 0.18 },
|
|
16379
16445
|
onClick: onClose,
|
|
16380
|
-
style:
|
|
16446
|
+
style: {
|
|
16447
|
+
position: "fixed",
|
|
16448
|
+
inset: 0,
|
|
16449
|
+
background: "rgba(20, 18, 16, 0.45)",
|
|
16450
|
+
display: "flex",
|
|
16451
|
+
alignItems: "center",
|
|
16452
|
+
justifyContent: "center",
|
|
16453
|
+
padding: 24,
|
|
16454
|
+
zIndex: 60
|
|
16455
|
+
},
|
|
16381
16456
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
16382
16457
|
react$1.motion.div,
|
|
16383
16458
|
{
|
|
@@ -16386,44 +16461,65 @@ function SwapModal({
|
|
|
16386
16461
|
exit: prefersReducedMotion ? void 0 : { opacity: 0, y: 6, scale: 0.98 },
|
|
16387
16462
|
transition: { duration: 0.22, ease: [0.22, 1, 0.36, 1] },
|
|
16388
16463
|
onClick: (e) => e.stopPropagation(),
|
|
16389
|
-
style:
|
|
16464
|
+
style: {
|
|
16465
|
+
background: "#fff",
|
|
16466
|
+
borderRadius: 16,
|
|
16467
|
+
boxShadow: "0 20px 60px rgba(0,0,0,0.15)",
|
|
16468
|
+
border: "1px solid #e5e7eb",
|
|
16469
|
+
width: "100%",
|
|
16470
|
+
maxWidth: 480,
|
|
16471
|
+
maxHeight: "80vh",
|
|
16472
|
+
overflow: "hidden",
|
|
16473
|
+
display: "flex",
|
|
16474
|
+
flexDirection: "column",
|
|
16475
|
+
padding: 24
|
|
16476
|
+
},
|
|
16390
16477
|
children: [
|
|
16391
|
-
/* @__PURE__ */ jsxRuntime.
|
|
16392
|
-
|
|
16393
|
-
|
|
16394
|
-
|
|
16395
|
-
|
|
16396
|
-
|
|
16397
|
-
|
|
16398
|
-
|
|
16399
|
-
|
|
16400
|
-
|
|
16401
|
-
|
|
16402
|
-
|
|
16403
|
-
|
|
16404
|
-
|
|
16405
|
-
|
|
16406
|
-
|
|
16407
|
-
|
|
16408
|
-
|
|
16409
|
-
|
|
16410
|
-
|
|
16411
|
-
|
|
16412
|
-
|
|
16413
|
-
|
|
16414
|
-
|
|
16415
|
-
|
|
16416
|
-
|
|
16417
|
-
|
|
16418
|
-
|
|
16419
|
-
|
|
16420
|
-
|
|
16421
|
-
|
|
16422
|
-
|
|
16423
|
-
|
|
16424
|
-
|
|
16425
|
-
|
|
16426
|
-
|
|
16478
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "flex-start", justifyContent: "space-between", marginBottom: 16 }, children: [
|
|
16479
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
16480
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: 11, fontWeight: 600, textTransform: "uppercase", letterSpacing: "0.06em", color: "#9ca3af", margin: 0 }, children: "Swap this for" }),
|
|
16481
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: 16, fontWeight: 600, color: "#1f2937", margin: "4px 0 0" }, children: itemName })
|
|
16482
|
+
] }),
|
|
16483
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16484
|
+
"button",
|
|
16485
|
+
{
|
|
16486
|
+
type: "button",
|
|
16487
|
+
onClick: onClose,
|
|
16488
|
+
style: {
|
|
16489
|
+
display: "flex",
|
|
16490
|
+
alignItems: "center",
|
|
16491
|
+
justifyContent: "center",
|
|
16492
|
+
width: 32,
|
|
16493
|
+
height: 32,
|
|
16494
|
+
borderRadius: 8,
|
|
16495
|
+
border: "none",
|
|
16496
|
+
background: "transparent",
|
|
16497
|
+
color: "#9ca3af",
|
|
16498
|
+
cursor: "pointer",
|
|
16499
|
+
flexShrink: 0
|
|
16500
|
+
},
|
|
16501
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { style: { width: 16, height: 16 } })
|
|
16502
|
+
}
|
|
16503
|
+
)
|
|
16504
|
+
] }),
|
|
16505
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minHeight: 0, overflowY: "auto", margin: "0 -24px", padding: "0 24px" }, children: [
|
|
16506
|
+
loading && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "48px 0", textAlign: "center", color: "#9ca3af", fontSize: 14 }, children: "Finding alternatives\u2026" }),
|
|
16507
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { borderRadius: 10, background: "#fef2f2", border: "1px solid #fecaca", padding: "8px 12px", fontSize: 14, color: "#dc2626", marginBottom: 12 }, children: error }),
|
|
16508
|
+
options && options.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "48px 0", textAlign: "center", color: "#9ca3af", fontSize: 14 }, children: "No other options available in this category." }),
|
|
16509
|
+
options && options.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
16510
|
+
react$1.motion.div,
|
|
16511
|
+
{
|
|
16512
|
+
initial: "hidden",
|
|
16513
|
+
animate: "visible",
|
|
16514
|
+
variants: {
|
|
16515
|
+
hidden: {},
|
|
16516
|
+
visible: { transition: { staggerChildren: 0.04, delayChildren: 0.02 } }
|
|
16517
|
+
},
|
|
16518
|
+
style: { display: "flex", flexDirection: "column" },
|
|
16519
|
+
children: options.map((opt, i) => /* @__PURE__ */ jsxRuntime.jsx(SwapCard, { option: opt, onPick: () => setSelected(opt), showDivider: i < options.length - 1 }, opt.menuItemId))
|
|
16520
|
+
}
|
|
16521
|
+
)
|
|
16522
|
+
] })
|
|
16427
16523
|
]
|
|
16428
16524
|
}
|
|
16429
16525
|
)
|
|
@@ -16433,112 +16529,118 @@ function SwapModal({
|
|
|
16433
16529
|
}
|
|
16434
16530
|
function SwapCard({
|
|
16435
16531
|
option,
|
|
16436
|
-
onPick
|
|
16532
|
+
onPick,
|
|
16533
|
+
showDivider
|
|
16437
16534
|
}) {
|
|
16438
16535
|
const prefersReducedMotion = react$1.useReducedMotion();
|
|
16439
16536
|
const dietary = (option.dietaryFilters ?? []).filter(Boolean);
|
|
16440
|
-
const
|
|
16441
|
-
|
|
16442
|
-
);
|
|
16537
|
+
const description = option.description ?? "";
|
|
16538
|
+
const [hovered, setHovered] = react.useState(false);
|
|
16443
16539
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
16444
|
-
react$1.motion.
|
|
16540
|
+
react$1.motion.button,
|
|
16445
16541
|
{
|
|
16542
|
+
type: "button",
|
|
16446
16543
|
variants: {
|
|
16447
|
-
hidden: { opacity: 0, y:
|
|
16448
|
-
visible: { opacity: 1, y: 0, transition: { duration: 0.
|
|
16544
|
+
hidden: { opacity: 0, y: 6 },
|
|
16545
|
+
visible: { opacity: 1, y: 0, transition: { duration: 0.2, ease: "easeOut" } }
|
|
16449
16546
|
},
|
|
16450
16547
|
whileHover: prefersReducedMotion ? void 0 : { y: -1 },
|
|
16451
16548
|
whileTap: { scale: 0.99 },
|
|
16452
16549
|
onClick: onPick,
|
|
16550
|
+
onMouseEnter: () => setHovered(true),
|
|
16551
|
+
onMouseLeave: () => setHovered(false),
|
|
16453
16552
|
style: {
|
|
16454
16553
|
display: "flex",
|
|
16455
|
-
gap:
|
|
16456
|
-
padding: "
|
|
16457
|
-
borderRadius:
|
|
16458
|
-
border: "
|
|
16459
|
-
|
|
16554
|
+
gap: 12,
|
|
16555
|
+
padding: "12px 4px",
|
|
16556
|
+
borderRadius: 8,
|
|
16557
|
+
border: "none",
|
|
16558
|
+
borderBottom: showDivider ? "1px solid #f0f0f0" : "none",
|
|
16559
|
+
background: hovered ? "#f9fafb" : "transparent",
|
|
16460
16560
|
cursor: "pointer",
|
|
16461
|
-
|
|
16561
|
+
textAlign: "left",
|
|
16562
|
+
width: "100%",
|
|
16563
|
+
transition: "background 0.15s"
|
|
16462
16564
|
},
|
|
16463
16565
|
children: [
|
|
16464
16566
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
16465
16567
|
"div",
|
|
16466
16568
|
{
|
|
16467
16569
|
style: {
|
|
16468
|
-
width:
|
|
16469
|
-
height:
|
|
16470
|
-
borderRadius:
|
|
16471
|
-
|
|
16570
|
+
width: 80,
|
|
16571
|
+
height: 80,
|
|
16572
|
+
borderRadius: 10,
|
|
16573
|
+
overflow: "hidden",
|
|
16472
16574
|
flexShrink: 0,
|
|
16473
|
-
|
|
16474
|
-
position: "relative"
|
|
16575
|
+
background: "#f3f4f6"
|
|
16475
16576
|
},
|
|
16476
|
-
children:
|
|
16477
|
-
"
|
|
16577
|
+
children: option.imageUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
16578
|
+
"img",
|
|
16579
|
+
{
|
|
16580
|
+
src: option.imageUrl,
|
|
16581
|
+
alt: option.name,
|
|
16582
|
+
style: { width: "100%", height: "100%", objectFit: "cover", display: "block" }
|
|
16583
|
+
}
|
|
16584
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
16585
|
+
"div",
|
|
16478
16586
|
{
|
|
16479
|
-
className: "display-italic",
|
|
16480
16587
|
style: {
|
|
16481
|
-
|
|
16482
|
-
|
|
16588
|
+
width: "100%",
|
|
16589
|
+
height: "100%",
|
|
16483
16590
|
display: "flex",
|
|
16484
16591
|
alignItems: "center",
|
|
16485
16592
|
justifyContent: "center",
|
|
16486
|
-
color: "
|
|
16487
|
-
fontSize:
|
|
16593
|
+
color: "#d1d5db",
|
|
16594
|
+
fontSize: 22,
|
|
16595
|
+
fontWeight: 600,
|
|
16596
|
+
fontStyle: "italic"
|
|
16488
16597
|
},
|
|
16489
16598
|
children: option.name.trim()[0]?.toUpperCase() ?? "?"
|
|
16490
16599
|
}
|
|
16491
16600
|
)
|
|
16492
16601
|
}
|
|
16493
16602
|
),
|
|
16494
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
16495
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
16496
|
-
|
|
16497
|
-
|
|
16498
|
-
|
|
16499
|
-
|
|
16500
|
-
|
|
16501
|
-
|
|
16502
|
-
|
|
16503
|
-
|
|
16504
|
-
|
|
16603
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", justifyContent: "center" }, children: [
|
|
16604
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: 14, fontWeight: 600, color: "#1f2937", margin: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: option.name }),
|
|
16605
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: {
|
|
16606
|
+
fontSize: 12,
|
|
16607
|
+
color: "#9ca3af",
|
|
16608
|
+
margin: "2px 0 0",
|
|
16609
|
+
lineHeight: 1.5,
|
|
16610
|
+
overflow: "hidden",
|
|
16611
|
+
display: "-webkit-box",
|
|
16612
|
+
WebkitLineClamp: 2,
|
|
16613
|
+
WebkitBoxOrient: "vertical"
|
|
16614
|
+
}, children: description }),
|
|
16615
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginTop: 6 }, children: [
|
|
16616
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: 14, fontWeight: 600, color: "var(--primary, #b91c1c)", fontVariantNumeric: "tabular-nums" }, children: [
|
|
16617
|
+
"\xA3",
|
|
16618
|
+
option.unitPrice.toFixed(2)
|
|
16619
|
+
] }),
|
|
16620
|
+
option.feedsPerUnit > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { fontSize: 11, color: "#9ca3af" }, children: [
|
|
16621
|
+
"feeds ",
|
|
16622
|
+
option.feedsPerUnit
|
|
16623
|
+
] })
|
|
16505
16624
|
] }),
|
|
16506
|
-
/* @__PURE__ */ jsxRuntime.
|
|
16507
|
-
|
|
16508
|
-
|
|
16509
|
-
|
|
16625
|
+
dietary.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", alignItems: "center", gap: 4, marginTop: 6 }, children: dietary.map((d) => {
|
|
16626
|
+
const iconInfo = DIETARY_ICON_MAP[d.toLowerCase()];
|
|
16627
|
+
if (!iconInfo) return null;
|
|
16628
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
16629
|
+
"img",
|
|
16630
|
+
{
|
|
16631
|
+
src: iconInfo.src,
|
|
16632
|
+
alt: iconInfo.label,
|
|
16633
|
+
title: iconInfo.label,
|
|
16634
|
+
style: { width: 16, height: 16, objectFit: "contain" }
|
|
16635
|
+
},
|
|
16636
|
+
d
|
|
16637
|
+
);
|
|
16638
|
+
}) })
|
|
16510
16639
|
] })
|
|
16511
16640
|
]
|
|
16512
16641
|
}
|
|
16513
16642
|
);
|
|
16514
16643
|
}
|
|
16515
|
-
var overlayStyle = {
|
|
16516
|
-
position: "fixed",
|
|
16517
|
-
inset: 0,
|
|
16518
|
-
background: "rgba(20, 18, 16, 0.45)",
|
|
16519
|
-
display: "flex",
|
|
16520
|
-
alignItems: "center",
|
|
16521
|
-
justifyContent: "center",
|
|
16522
|
-
padding: 16,
|
|
16523
|
-
zIndex: 60
|
|
16524
|
-
};
|
|
16525
|
-
var panelStyle = {
|
|
16526
|
-
background: "var(--paper)",
|
|
16527
|
-
borderRadius: 16,
|
|
16528
|
-
padding: 18,
|
|
16529
|
-
width: "100%",
|
|
16530
|
-
maxWidth: 360,
|
|
16531
|
-
boxShadow: "var(--shadow-lift)",
|
|
16532
|
-
border: "1px solid var(--rule)"
|
|
16533
|
-
};
|
|
16534
|
-
var errorStyle = {
|
|
16535
|
-
fontSize: "0.85rem",
|
|
16536
|
-
color: "var(--ember)",
|
|
16537
|
-
background: "var(--ember-soft)",
|
|
16538
|
-
border: "1px solid var(--ember)",
|
|
16539
|
-
borderRadius: 10,
|
|
16540
|
-
padding: "8px 12px"
|
|
16541
|
-
};
|
|
16542
16644
|
|
|
16543
16645
|
// src/utils/parsePlaceResult.ts
|
|
16544
16646
|
function parsePlaceResult(place) {
|
|
@@ -16606,6 +16708,15 @@ var GOOGLE_MAPS_CONFIG = {
|
|
|
16606
16708
|
"name"
|
|
16607
16709
|
]
|
|
16608
16710
|
};
|
|
16711
|
+
var LONDON_DELIVERY_BOUNDS = {
|
|
16712
|
+
north: 51.75,
|
|
16713
|
+
south: 51.2,
|
|
16714
|
+
east: 0.35,
|
|
16715
|
+
west: -0.55
|
|
16716
|
+
};
|
|
16717
|
+
function isWithinLondonBounds(lat, lng) {
|
|
16718
|
+
return lat >= LONDON_DELIVERY_BOUNDS.south && lat <= LONDON_DELIVERY_BOUNDS.north && lng >= LONDON_DELIVERY_BOUNDS.west && lng <= LONDON_DELIVERY_BOUNDS.east;
|
|
16719
|
+
}
|
|
16609
16720
|
|
|
16610
16721
|
// src/utils/google-maps-loader.ts
|
|
16611
16722
|
var isLoading = false;
|
|
@@ -16650,8 +16761,10 @@ function loadGoogleMapsScript(apiKey) {
|
|
|
16650
16761
|
}
|
|
16651
16762
|
|
|
16652
16763
|
// src/hooks/useAddressAutocomplete.ts
|
|
16764
|
+
var OUT_OF_ZONE_MESSAGE = "We only deliver inside London right now \u2014 please pick a London address.";
|
|
16653
16765
|
function useAddressAutocomplete(onPlaceSelect, options = {}) {
|
|
16654
16766
|
const countryRestriction = options.countryRestriction === void 0 ? GOOGLE_MAPS_CONFIG.COUNTRY_RESTRICTION : options.countryRestriction;
|
|
16767
|
+
const restrictToDeliveryZone = options.restrictToDeliveryZone ?? true;
|
|
16655
16768
|
const { googleMapsApiKey } = useCateringConfig();
|
|
16656
16769
|
const inputRef = react.useRef(null);
|
|
16657
16770
|
const containerRef = react.useRef(null);
|
|
@@ -16663,6 +16776,7 @@ function useAddressAutocomplete(onPlaceSelect, options = {}) {
|
|
|
16663
16776
|
const [predictions, setPredictions] = react.useState([]);
|
|
16664
16777
|
const [open, setOpen] = react.useState(false);
|
|
16665
16778
|
const [activeIndex, setActiveIndex] = react.useState(-1);
|
|
16779
|
+
const [outOfZoneError, setOutOfZoneError] = react.useState(null);
|
|
16666
16780
|
react.useEffect(() => {
|
|
16667
16781
|
loadGoogleMapsScript(googleMapsApiKey).then(() => {
|
|
16668
16782
|
if (!window.google?.maps?.places) return;
|
|
@@ -16673,6 +16787,7 @@ function useAddressAutocomplete(onPlaceSelect, options = {}) {
|
|
|
16673
16787
|
}, [googleMapsApiKey]);
|
|
16674
16788
|
react.useEffect(() => {
|
|
16675
16789
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
16790
|
+
setOutOfZoneError(null);
|
|
16676
16791
|
if (justSelectedRef.current) {
|
|
16677
16792
|
justSelectedRef.current = false;
|
|
16678
16793
|
return;
|
|
@@ -16687,7 +16802,10 @@ function useAddressAutocomplete(onPlaceSelect, options = {}) {
|
|
|
16687
16802
|
autocompleteServiceRef.current.getPlacePredictions(
|
|
16688
16803
|
{
|
|
16689
16804
|
input: query,
|
|
16690
|
-
...countryRestriction ? { componentRestrictions: { country: countryRestriction } } : {}
|
|
16805
|
+
...countryRestriction ? { componentRestrictions: { country: countryRestriction } } : {},
|
|
16806
|
+
// Delivery pickers hard-restrict predictions to the London box,
|
|
16807
|
+
// so out-of-zone places (e.g. Edinburgh) never appear.
|
|
16808
|
+
...restrictToDeliveryZone ? { locationRestriction: LONDON_DELIVERY_BOUNDS } : {}
|
|
16691
16809
|
},
|
|
16692
16810
|
(results, status) => {
|
|
16693
16811
|
if (status === google.maps.places.PlacesServiceStatus.OK && results) {
|
|
@@ -16716,6 +16834,13 @@ function useAddressAutocomplete(onPlaceSelect, options = {}) {
|
|
|
16716
16834
|
{ placeId: prediction.place_id, fields: GOOGLE_MAPS_CONFIG.FIELDS },
|
|
16717
16835
|
(place, status) => {
|
|
16718
16836
|
if (status === google.maps.places.PlacesServiceStatus.OK && place?.geometry) {
|
|
16837
|
+
const lat = place.geometry.location?.lat();
|
|
16838
|
+
const lng = place.geometry.location?.lng();
|
|
16839
|
+
if (restrictToDeliveryZone && typeof lat === "number" && typeof lng === "number" && !isWithinLondonBounds(lat, lng)) {
|
|
16840
|
+
setOutOfZoneError(OUT_OF_ZONE_MESSAGE);
|
|
16841
|
+
return;
|
|
16842
|
+
}
|
|
16843
|
+
setOutOfZoneError(null);
|
|
16719
16844
|
onPlaceSelect(place);
|
|
16720
16845
|
}
|
|
16721
16846
|
}
|
|
@@ -16753,6 +16878,7 @@ function useAddressAutocomplete(onPlaceSelect, options = {}) {
|
|
|
16753
16878
|
setPredictions([]);
|
|
16754
16879
|
setActiveIndex(-1);
|
|
16755
16880
|
setOpen(false);
|
|
16881
|
+
setOutOfZoneError(null);
|
|
16756
16882
|
};
|
|
16757
16883
|
return {
|
|
16758
16884
|
inputRef,
|
|
@@ -16765,7 +16891,8 @@ function useAddressAutocomplete(onPlaceSelect, options = {}) {
|
|
|
16765
16891
|
setActiveIndex,
|
|
16766
16892
|
handleSelect,
|
|
16767
16893
|
handleKeyDown,
|
|
16768
|
-
clear
|
|
16894
|
+
clear,
|
|
16895
|
+
outOfZoneError
|
|
16769
16896
|
};
|
|
16770
16897
|
}
|
|
16771
16898
|
function ChatAddressInput({
|
|
@@ -16787,7 +16914,8 @@ function ChatAddressInput({
|
|
|
16787
16914
|
activeIndex,
|
|
16788
16915
|
setActiveIndex,
|
|
16789
16916
|
handleSelect,
|
|
16790
|
-
handleKeyDown
|
|
16917
|
+
handleKeyDown,
|
|
16918
|
+
outOfZoneError
|
|
16791
16919
|
} = useAddressAutocomplete(onPlaceSelect);
|
|
16792
16920
|
react.useEffect(() => {
|
|
16793
16921
|
if (initialQuery) setQuery(initialQuery);
|
|
@@ -16866,6 +16994,7 @@ function ChatAddressInput({
|
|
|
16866
16994
|
}
|
|
16867
16995
|
)
|
|
16868
16996
|
] }),
|
|
16997
|
+
outOfZoneError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 pl-6 text-xs text-red-500", children: outOfZoneError }),
|
|
16869
16998
|
open && predictions.length > 0 && dropdownRect && typeof document !== "undefined" && reactDom.createPortal(
|
|
16870
16999
|
/* Portal to the widget's shared overlay root so the
|
|
16871
17000
|
dropdown escapes the bar pill's overflow-hidden +
|
|
@@ -17046,6 +17175,32 @@ function useBetaUnlock() {
|
|
|
17046
17175
|
}, []);
|
|
17047
17176
|
return { unlocked, tryUnlock };
|
|
17048
17177
|
}
|
|
17178
|
+
var FIELDS = [
|
|
17179
|
+
["guestCount", "Number of guests"],
|
|
17180
|
+
["sessionDate", "Date"],
|
|
17181
|
+
["eventTime", "Event time"],
|
|
17182
|
+
["deliveryLocation", "Delivery location"],
|
|
17183
|
+
["budget", "Budget"]
|
|
17184
|
+
];
|
|
17185
|
+
function PreSendChecklist({ ticks }) {
|
|
17186
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 py-1", children: FIELDS.map(([field, label]) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17187
|
+
"span",
|
|
17188
|
+
{
|
|
17189
|
+
className: `flex items-center gap-1 text-xs transition-colors ${ticks[field] ? "text-gray-700" : "text-gray-400"}`,
|
|
17190
|
+
children: [
|
|
17191
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17192
|
+
"span",
|
|
17193
|
+
{
|
|
17194
|
+
className: `flex h-3.5 w-3.5 flex-shrink-0 items-center justify-center rounded-full border transition-colors ${ticks[field] ? "border-primary bg-primary" : "border-gray-300 bg-transparent"}`,
|
|
17195
|
+
children: ticks[field] && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-2 w-2 text-white", strokeWidth: 3 })
|
|
17196
|
+
}
|
|
17197
|
+
),
|
|
17198
|
+
label
|
|
17199
|
+
]
|
|
17200
|
+
},
|
|
17201
|
+
field
|
|
17202
|
+
)) });
|
|
17203
|
+
}
|
|
17049
17204
|
var MAX_INPUT_HEIGHT = 140;
|
|
17050
17205
|
function AIChat() {
|
|
17051
17206
|
const { unlocked, tryUnlock } = useBetaUnlock();
|
|
@@ -17057,6 +17212,7 @@ function AIChat() {
|
|
|
17057
17212
|
function AIChatBody() {
|
|
17058
17213
|
const {
|
|
17059
17214
|
chat: {
|
|
17215
|
+
messages,
|
|
17060
17216
|
sending,
|
|
17061
17217
|
bootstrapping,
|
|
17062
17218
|
sessionId,
|
|
@@ -17081,15 +17237,27 @@ function AIChatBody() {
|
|
|
17081
17237
|
feedbackTarget,
|
|
17082
17238
|
feedbackRating,
|
|
17083
17239
|
setFeedbackRating,
|
|
17240
|
+
startGeneralFeedback,
|
|
17084
17241
|
cancelFeedback
|
|
17085
17242
|
} = useChatSessionContext();
|
|
17086
17243
|
const buildChatAddress = useChatAddressFromContext();
|
|
17087
17244
|
const { contactInfo, setContactInfo } = useCateringState();
|
|
17245
|
+
const api = useApiClient();
|
|
17088
17246
|
const hasAddress = !!(contactInfo?.addressLine1 && contactInfo.latitude !== void 0 && contactInfo.longitude !== void 0);
|
|
17089
17247
|
const gateActive = !hasAddress;
|
|
17090
17248
|
const [pillEditing, setPillEditing] = react.useState(false);
|
|
17249
|
+
const [headerMenuOpen, setHeaderMenuOpen] = react.useState(false);
|
|
17091
17250
|
const textareaRef = react.useRef(null);
|
|
17092
17251
|
const [input, setInput] = react.useState("");
|
|
17252
|
+
const [fieldTicks, setFieldTicks] = react.useState({
|
|
17253
|
+
guestCount: false,
|
|
17254
|
+
sessionDate: false,
|
|
17255
|
+
eventTime: false,
|
|
17256
|
+
deliveryLocation: false,
|
|
17257
|
+
budget: false
|
|
17258
|
+
});
|
|
17259
|
+
const detectDebounceRef = react.useRef(null);
|
|
17260
|
+
const detectAbortRef = react.useRef(null);
|
|
17093
17261
|
const [feedbackHover, setFeedbackHover] = react.useState(0);
|
|
17094
17262
|
const [feedbackState, setFeedbackState] = react.useState("idle");
|
|
17095
17263
|
const [feedbackNote, setFeedbackNote] = react.useState("");
|
|
@@ -17118,7 +17286,7 @@ function AIChatBody() {
|
|
|
17118
17286
|
};
|
|
17119
17287
|
react.useEffect(() => {
|
|
17120
17288
|
handleInput();
|
|
17121
|
-
}, [input, gateActive]);
|
|
17289
|
+
}, [input, feedbackNote, gateActive]);
|
|
17122
17290
|
react.useEffect(() => {
|
|
17123
17291
|
if (!pendingInputFocus) return;
|
|
17124
17292
|
if (gateActive || pillEditing) return;
|
|
@@ -17128,6 +17296,10 @@ function AIChatBody() {
|
|
|
17128
17296
|
setPendingInputFocus(false);
|
|
17129
17297
|
}, [pendingInputFocus, gateActive, pillEditing, bootstrapping, sessionId]);
|
|
17130
17298
|
const inFeedbackMode = feedbackTarget !== null;
|
|
17299
|
+
const hasUserReply = messages.some((m) => m.sender === "user");
|
|
17300
|
+
console.log("[AIChat] messages", messages, "hasUserReply", hasUserReply);
|
|
17301
|
+
const showChecklist = !inFeedbackMode && !gateActive && !hasUserReply;
|
|
17302
|
+
const allTicked = Object.values(fieldTicks).every(Boolean);
|
|
17131
17303
|
const RATING_LABELS = ["Terrible", "Poor", "Okay", "Good", "Great"];
|
|
17132
17304
|
react.useEffect(() => {
|
|
17133
17305
|
if (!feedbackTarget) return;
|
|
@@ -17135,6 +17307,25 @@ function AIChatBody() {
|
|
|
17135
17307
|
setFeedbackNote("");
|
|
17136
17308
|
setFeedbackState("idle");
|
|
17137
17309
|
}, [feedbackTarget]);
|
|
17310
|
+
react.useEffect(() => {
|
|
17311
|
+
if (!showChecklist || !input.trim()) return;
|
|
17312
|
+
if (detectDebounceRef.current) clearTimeout(detectDebounceRef.current);
|
|
17313
|
+
detectDebounceRef.current = setTimeout(async () => {
|
|
17314
|
+
detectAbortRef.current?.abort();
|
|
17315
|
+
detectAbortRef.current = new AbortController();
|
|
17316
|
+
const { signal } = detectAbortRef.current;
|
|
17317
|
+
try {
|
|
17318
|
+
const msg = hasAddress && contactInfo?.addressLine1 ? `${input.trim()} ${contactInfo.addressLine1}` : input.trim();
|
|
17319
|
+
const result = await api.chat.detectFields(msg, signal);
|
|
17320
|
+
if (!signal.aborted) setFieldTicks(result);
|
|
17321
|
+
} catch {
|
|
17322
|
+
}
|
|
17323
|
+
}, 400);
|
|
17324
|
+
return () => {
|
|
17325
|
+
if (detectDebounceRef.current) clearTimeout(detectDebounceRef.current);
|
|
17326
|
+
detectAbortRef.current?.abort();
|
|
17327
|
+
};
|
|
17328
|
+
}, [input, showChecklist]);
|
|
17138
17329
|
function closeFeedback() {
|
|
17139
17330
|
cancelFeedback();
|
|
17140
17331
|
setFeedbackHover(0);
|
|
@@ -17205,7 +17396,9 @@ function AIChatBody() {
|
|
|
17205
17396
|
}
|
|
17206
17397
|
if (sending || bootstrapping || !sessionId || !input.trim()) return;
|
|
17207
17398
|
if (gateActive && !hasAddress) return;
|
|
17208
|
-
|
|
17399
|
+
const addr = buildChatAddress();
|
|
17400
|
+
console.log("[AIChat] submitText address", addr, "contactInfo", contactInfo);
|
|
17401
|
+
void sendText(input, addr);
|
|
17209
17402
|
setInput("");
|
|
17210
17403
|
}
|
|
17211
17404
|
function handleSubmit(e) {
|
|
@@ -17230,7 +17423,7 @@ function AIChatBody() {
|
|
|
17230
17423
|
setEditingMealSessionIndex(void 0);
|
|
17231
17424
|
await applyEditField(field, value, idx);
|
|
17232
17425
|
}
|
|
17233
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "swift-chat-design bg-white rounded-xl shadow-sm border border-base-200 flex h-full min-h-0 flex-col overflow-hidden", children: [
|
|
17426
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react$1.LayoutGroup, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "swift-chat-design bg-white rounded-xl shadow-sm border border-base-200 flex h-full min-h-0 flex-col overflow-hidden", children: [
|
|
17234
17427
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-shrink-0 px-3 py-2.5 flex items-center gap-3 border-b border-base-200", children: [
|
|
17235
17428
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-9 h-9 rounded-full bg-primary flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "w-4 h-4 text-white" }) }),
|
|
17236
17429
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
@@ -17261,16 +17454,55 @@ function AIChatBody() {
|
|
|
17261
17454
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: "New chat" })
|
|
17262
17455
|
]
|
|
17263
17456
|
}
|
|
17264
|
-
)
|
|
17265
|
-
|
|
17266
|
-
|
|
17267
|
-
!gateActive && !inFeedbackMode && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute left-0 right-0 z-10 px-3 pt-1.5 flex justify-center pointer-events-none", children: [
|
|
17268
|
-
hasAddress && !pillEditing && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17457
|
+
),
|
|
17458
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
17459
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17269
17460
|
"button",
|
|
17270
17461
|
{
|
|
17271
17462
|
type: "button",
|
|
17272
|
-
onClick: () =>
|
|
17273
|
-
className: "
|
|
17463
|
+
onClick: () => setHeaderMenuOpen((v) => !v),
|
|
17464
|
+
className: "flex items-center justify-center w-7 h-7 rounded-md text-gray-400 hover:text-gray-600 hover:bg-base-100 transition-colors",
|
|
17465
|
+
title: "More options",
|
|
17466
|
+
"aria-label": "More options",
|
|
17467
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontal, { className: "w-4 h-4" })
|
|
17468
|
+
}
|
|
17469
|
+
),
|
|
17470
|
+
headerMenuOpen && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
17471
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17472
|
+
"div",
|
|
17473
|
+
{
|
|
17474
|
+
className: "fixed inset-0 z-40",
|
|
17475
|
+
onClick: () => setHeaderMenuOpen(false)
|
|
17476
|
+
}
|
|
17477
|
+
),
|
|
17478
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-0 top-full z-50 mt-1 w-44 overflow-hidden rounded-xl border border-base-200 bg-white shadow-lg", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17479
|
+
"button",
|
|
17480
|
+
{
|
|
17481
|
+
type: "button",
|
|
17482
|
+
onClick: () => {
|
|
17483
|
+
setHeaderMenuOpen(false);
|
|
17484
|
+
startGeneralFeedback();
|
|
17485
|
+
},
|
|
17486
|
+
className: "flex w-full items-center gap-2 px-3 py-2.5 text-left text-sm text-gray-700 transition-colors hover:bg-base-100",
|
|
17487
|
+
children: [
|
|
17488
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.MessageSquarePlus, { className: "h-4 w-4" }),
|
|
17489
|
+
"Give Feedback"
|
|
17490
|
+
]
|
|
17491
|
+
}
|
|
17492
|
+
) })
|
|
17493
|
+
] })
|
|
17494
|
+
] })
|
|
17495
|
+
] }),
|
|
17496
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1 min-h-0", children: [
|
|
17497
|
+
!gateActive && !inFeedbackMode && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute left-0 right-0 z-10 px-3 pt-1.5 flex justify-center pointer-events-none", children: [
|
|
17498
|
+
hasAddress && !pillEditing && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17499
|
+
react$1.motion.button,
|
|
17500
|
+
{
|
|
17501
|
+
type: "button",
|
|
17502
|
+
layoutId: "desktop-address-region",
|
|
17503
|
+
transition: { duration: 0.35, ease: "easeOut" },
|
|
17504
|
+
onClick: () => setPillEditing(true),
|
|
17505
|
+
className: "pointer-events-auto inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-black/50 backdrop-blur-sm text-white/90 hover:bg-black/60 transition-colors text-xs max-w-full shadow-sm",
|
|
17274
17506
|
children: [
|
|
17275
17507
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17276
17508
|
lucideReact.MapPin,
|
|
@@ -17304,13 +17536,16 @@ function AIChatBody() {
|
|
|
17304
17536
|
}
|
|
17305
17537
|
)
|
|
17306
17538
|
] }),
|
|
17307
|
-
/* @__PURE__ */ jsxRuntime.
|
|
17539
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
17308
17540
|
"div",
|
|
17309
17541
|
{
|
|
17310
17542
|
ref: messagesScrollRef,
|
|
17311
17543
|
onScroll: handleMessagesScroll,
|
|
17312
17544
|
className: "absolute inset-0 overflow-y-auto overscroll-contain p-3",
|
|
17313
|
-
children:
|
|
17545
|
+
children: [
|
|
17546
|
+
!gateActive && !inFeedbackMode && hasAddress && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-7", "aria-hidden": true }),
|
|
17547
|
+
/* @__PURE__ */ jsxRuntime.jsx(ChatMessagesView, {})
|
|
17548
|
+
]
|
|
17314
17549
|
}
|
|
17315
17550
|
),
|
|
17316
17551
|
/* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { children: showScrollDown && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -17374,7 +17609,10 @@ function AIChatBody() {
|
|
|
17374
17609
|
"aria-label": `${n} star${n > 1 ? "s" : ""}`,
|
|
17375
17610
|
onMouseEnter: () => setFeedbackHover(n),
|
|
17376
17611
|
onMouseLeave: () => setFeedbackHover(0),
|
|
17377
|
-
onClick: () =>
|
|
17612
|
+
onClick: () => {
|
|
17613
|
+
setFeedbackRating(n);
|
|
17614
|
+
textareaRef.current?.focus();
|
|
17615
|
+
},
|
|
17378
17616
|
className: "p-0.5 transition-transform hover:scale-110",
|
|
17379
17617
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17380
17618
|
lucideReact.Star,
|
|
@@ -17421,9 +17659,11 @@ function AIChatBody() {
|
|
|
17421
17659
|
exit: { opacity: 0, y: -8 },
|
|
17422
17660
|
transition: { duration: 0.18, ease: "easeOut" },
|
|
17423
17661
|
children: gateActive ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17424
|
-
|
|
17662
|
+
react$1.motion.form,
|
|
17425
17663
|
{
|
|
17426
17664
|
onSubmit: handleSubmit,
|
|
17665
|
+
layoutId: "desktop-address-region",
|
|
17666
|
+
transition: { duration: 0.35, ease: "easeOut" },
|
|
17427
17667
|
className: "flex flex-col rounded-xl border border-base-300 bg-white px-3 py-2 focus-within:border-primary transition-colors",
|
|
17428
17668
|
children: [
|
|
17429
17669
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pb-2 border-b border-base-200", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -17465,31 +17705,45 @@ function AIChatBody() {
|
|
|
17465
17705
|
"form",
|
|
17466
17706
|
{
|
|
17467
17707
|
onSubmit: handleSubmit,
|
|
17468
|
-
className: "flex
|
|
17708
|
+
className: "flex flex-col rounded-xl border border-base-300 bg-white px-3 py-2 focus-within:border-primary transition-colors",
|
|
17469
17709
|
children: [
|
|
17470
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17471
|
-
|
|
17472
|
-
{
|
|
17473
|
-
ref: textareaRef,
|
|
17474
|
-
rows: 1,
|
|
17475
|
-
value: inFeedbackMode ? feedbackNote : input,
|
|
17476
|
-
onChange: (e) => inFeedbackMode ? setFeedbackNote(e.target.value) : setInput(e.target.value),
|
|
17477
|
-
onKeyDown: handleKeyDown,
|
|
17478
|
-
placeholder: inFeedbackMode ? feedbackRating <= 2 ? "What went wrong? (optional)" : "Add a note (optional)" : "Ask for menu suggestions...",
|
|
17479
|
-
disabled: inFeedbackMode ? feedbackState === "sending" : bootstrapping || !sessionId,
|
|
17480
|
-
className: "flex-1 bg-transparent text-sm text-gray-800 placeholder:text-gray-400 outline-none resize-none leading-snug py-1 overflow-hidden"
|
|
17481
|
-
}
|
|
17482
|
-
),
|
|
17483
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17484
|
-
"button",
|
|
17710
|
+
/* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { children: showChecklist && /* @__PURE__ */ jsxRuntime.jsx(
|
|
17711
|
+
react$1.motion.div,
|
|
17485
17712
|
{
|
|
17486
|
-
|
|
17487
|
-
|
|
17488
|
-
|
|
17489
|
-
|
|
17490
|
-
|
|
17491
|
-
|
|
17492
|
-
|
|
17713
|
+
initial: { opacity: 0, height: 0 },
|
|
17714
|
+
animate: { opacity: 1, height: "auto" },
|
|
17715
|
+
exit: { opacity: 0, height: 0 },
|
|
17716
|
+
transition: { duration: 0.18, ease: "easeOut" },
|
|
17717
|
+
className: "overflow-hidden border-b border-base-200 pb-1.5 mb-1.5",
|
|
17718
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(PreSendChecklist, { ticks: fieldTicks })
|
|
17719
|
+
},
|
|
17720
|
+
"checklist"
|
|
17721
|
+
) }),
|
|
17722
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end gap-2", children: [
|
|
17723
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17724
|
+
"textarea",
|
|
17725
|
+
{
|
|
17726
|
+
ref: textareaRef,
|
|
17727
|
+
rows: 1,
|
|
17728
|
+
value: inFeedbackMode ? feedbackNote : input,
|
|
17729
|
+
onChange: (e) => inFeedbackMode ? setFeedbackNote(e.target.value) : setInput(e.target.value),
|
|
17730
|
+
onKeyDown: handleKeyDown,
|
|
17731
|
+
placeholder: inFeedbackMode ? feedbackRating <= 2 ? "What went wrong? (optional)" : "Add a note (optional)" : "Ask for menu suggestions...",
|
|
17732
|
+
disabled: inFeedbackMode ? feedbackState === "sending" : bootstrapping || !sessionId,
|
|
17733
|
+
className: "flex-1 bg-transparent text-sm text-gray-800 placeholder:text-gray-400 outline-none resize-none leading-snug py-1 overflow-hidden"
|
|
17734
|
+
}
|
|
17735
|
+
),
|
|
17736
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17737
|
+
"button",
|
|
17738
|
+
{
|
|
17739
|
+
type: "submit",
|
|
17740
|
+
disabled: inFeedbackMode ? feedbackRating < 1 || feedbackState === "sending" : sending || bootstrapping || !input.trim() || !sessionId || showChecklist && !allTicked,
|
|
17741
|
+
className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-full bg-primary text-white transition-colors hover:bg-primary/90 disabled:opacity-50",
|
|
17742
|
+
title: inFeedbackMode ? "Submit feedback" : "Send",
|
|
17743
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "w-3.5 h-3.5" })
|
|
17744
|
+
}
|
|
17745
|
+
)
|
|
17746
|
+
] })
|
|
17493
17747
|
]
|
|
17494
17748
|
}
|
|
17495
17749
|
) })
|
|
@@ -17509,7 +17763,7 @@ function AIChatBody() {
|
|
|
17509
17763
|
intentExcludes: swapTarget?.intentExcludes ?? null,
|
|
17510
17764
|
itemName: swapTarget?.itemName ?? "",
|
|
17511
17765
|
onClose: () => setSwapTarget(null),
|
|
17512
|
-
onPick: (replacement) => {
|
|
17766
|
+
onPick: (replacement, addonSelections) => {
|
|
17513
17767
|
const target = swapTarget;
|
|
17514
17768
|
if (!target) return;
|
|
17515
17769
|
setSwapTarget(null);
|
|
@@ -17526,14 +17780,19 @@ function AIChatBody() {
|
|
|
17526
17780
|
allergens: replacement.allergens,
|
|
17527
17781
|
dietaryFilters: replacement.dietaryFilters,
|
|
17528
17782
|
feedsPerUnit: replacement.feedsPerUnit,
|
|
17529
|
-
cateringQuantityUnit:
|
|
17530
|
-
minOrderQuantity:
|
|
17531
|
-
addons:
|
|
17783
|
+
cateringQuantityUnit: replacement.cateringQuantityUnit,
|
|
17784
|
+
minOrderQuantity: replacement.minOrderQuantity,
|
|
17785
|
+
addons: replacement.addons
|
|
17532
17786
|
});
|
|
17787
|
+
cart.setAddonSelections(
|
|
17788
|
+
target.intentId,
|
|
17789
|
+
replacement.menuItemId,
|
|
17790
|
+
addonSelections
|
|
17791
|
+
);
|
|
17533
17792
|
}
|
|
17534
17793
|
}
|
|
17535
17794
|
)
|
|
17536
|
-
] });
|
|
17795
|
+
] }) });
|
|
17537
17796
|
}
|
|
17538
17797
|
function MobileAddressPickerSurface({
|
|
17539
17798
|
onPlaceSelect,
|
|
@@ -17552,7 +17811,8 @@ function MobileAddressPickerSurface({
|
|
|
17552
17811
|
activeIndex,
|
|
17553
17812
|
setActiveIndex,
|
|
17554
17813
|
handleSelect,
|
|
17555
|
-
handleKeyDown
|
|
17814
|
+
handleKeyDown,
|
|
17815
|
+
outOfZoneError
|
|
17556
17816
|
} = useAddressAutocomplete(onPlaceSelect);
|
|
17557
17817
|
react.useEffect(() => {
|
|
17558
17818
|
if (initialQuery) setQuery(initialQuery);
|
|
@@ -17649,7 +17909,7 @@ function MobileAddressPickerSurface({
|
|
|
17649
17909
|
"input",
|
|
17650
17910
|
{
|
|
17651
17911
|
ref: inputRef,
|
|
17652
|
-
type: "
|
|
17912
|
+
type: "text",
|
|
17653
17913
|
value: query,
|
|
17654
17914
|
onChange: (e) => setQuery(e.target.value),
|
|
17655
17915
|
onKeyDown: handleSearchKeyDown,
|
|
@@ -17678,6 +17938,7 @@ function MobileAddressPickerSurface({
|
|
|
17678
17938
|
] })
|
|
17679
17939
|
}
|
|
17680
17940
|
),
|
|
17941
|
+
outOfZoneError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 flex-shrink-0 text-center text-xs text-red-600", children: outOfZoneError }),
|
|
17681
17942
|
predictions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
17682
17943
|
react$1.motion.div,
|
|
17683
17944
|
{
|
|
@@ -20298,15 +20559,73 @@ function AISuggestionsPanel() {
|
|
|
20298
20559
|
mealSessions: widgetMealSessions,
|
|
20299
20560
|
addMealSession,
|
|
20300
20561
|
addMenuItem,
|
|
20562
|
+
updateMealSession,
|
|
20301
20563
|
setActiveSessionIndex
|
|
20302
20564
|
} = useCateringState();
|
|
20565
|
+
const [mergeConfirm, setMergeConfirm] = react.useState(null);
|
|
20303
20566
|
function handleSwap(target) {
|
|
20304
20567
|
setSwapTarget(target);
|
|
20305
20568
|
}
|
|
20569
|
+
function findConflictingSessions() {
|
|
20570
|
+
const conflicts = [];
|
|
20571
|
+
const seen = /* @__PURE__ */ new Set();
|
|
20572
|
+
for (const part of latestMealSessionParts) {
|
|
20573
|
+
const aiMeal = latestMealSessions[part.mealSessionIndex];
|
|
20574
|
+
const isoDate = aiMeal?.isoSessionDate ?? "";
|
|
20575
|
+
const aiTime = convertAiTime(aiMeal?.isoEventTime ?? "");
|
|
20576
|
+
if (!isoDate) continue;
|
|
20577
|
+
const matchIdx = widgetMealSessions.findIndex(
|
|
20578
|
+
(s) => s.sessionDate === isoDate && s.eventTime === aiTime
|
|
20579
|
+
);
|
|
20580
|
+
if (matchIdx < 0 || seen.has(matchIdx)) continue;
|
|
20581
|
+
seen.add(matchIdx);
|
|
20582
|
+
const existing = widgetMealSessions[matchIdx];
|
|
20583
|
+
if (existing.orderItems.length > 0) {
|
|
20584
|
+
conflicts.push({
|
|
20585
|
+
idx: matchIdx,
|
|
20586
|
+
name: existing.sessionName || `Session ${matchIdx + 1}`,
|
|
20587
|
+
itemCount: existing.orderItems.length
|
|
20588
|
+
});
|
|
20589
|
+
}
|
|
20590
|
+
}
|
|
20591
|
+
return conflicts;
|
|
20592
|
+
}
|
|
20306
20593
|
function handleAddToBasket() {
|
|
20594
|
+
const conflicts = findConflictingSessions();
|
|
20595
|
+
if (conflicts.length > 0) {
|
|
20596
|
+
setMergeConfirm({ conflictingSessions: conflicts });
|
|
20597
|
+
return;
|
|
20598
|
+
}
|
|
20599
|
+
commitToBasket(false);
|
|
20600
|
+
}
|
|
20601
|
+
function commitToBasket(replace) {
|
|
20602
|
+
setMergeConfirm(null);
|
|
20307
20603
|
const preBatchCount = widgetMealSessions.length;
|
|
20308
20604
|
let working = widgetMealSessions;
|
|
20309
20605
|
let firstTargetIdx = -1;
|
|
20606
|
+
if (replace) {
|
|
20607
|
+
for (const part of latestMealSessionParts) {
|
|
20608
|
+
const aiMeal = latestMealSessions[part.mealSessionIndex];
|
|
20609
|
+
const isoDate = aiMeal?.isoSessionDate ?? "";
|
|
20610
|
+
const aiTime = convertAiTime(aiMeal?.isoEventTime ?? "");
|
|
20611
|
+
if (!isoDate) continue;
|
|
20612
|
+
const matchIdx = widgetMealSessions.findIndex(
|
|
20613
|
+
(s) => s.sessionDate === isoDate && s.eventTime === aiTime
|
|
20614
|
+
);
|
|
20615
|
+
if (matchIdx >= 0) {
|
|
20616
|
+
updateMealSession(matchIdx, { orderItems: [] });
|
|
20617
|
+
}
|
|
20618
|
+
}
|
|
20619
|
+
working = widgetMealSessions.map((s) => {
|
|
20620
|
+
const shouldClear = latestMealSessionParts.some((part) => {
|
|
20621
|
+
const aiMeal = latestMealSessions[part.mealSessionIndex];
|
|
20622
|
+
const isoDate = aiMeal?.isoSessionDate ?? "";
|
|
20623
|
+
const aiTime = convertAiTime(aiMeal?.isoEventTime ?? "");
|
|
20624
|
+
return isoDate && s.sessionDate === isoDate && s.eventTime === aiTime;
|
|
20625
|
+
});
|
|
20626
|
+
return shouldClear ? { ...s, orderItems: [] } : s;
|
|
20627
|
+
});
|
|
20628
|
+
}
|
|
20310
20629
|
for (const part of latestMealSessionParts) {
|
|
20311
20630
|
const resolvedItems = resolveDraftItems(
|
|
20312
20631
|
latestMealSessionParts,
|
|
@@ -20338,7 +20657,7 @@ function AISuggestionsPanel() {
|
|
|
20338
20657
|
});
|
|
20339
20658
|
}
|
|
20340
20659
|
working.forEach((s, idx) => {
|
|
20341
|
-
const original = widgetMealSessions[idx];
|
|
20660
|
+
const original = replace ? { orderItems: [] } : widgetMealSessions[idx];
|
|
20342
20661
|
const originalIds = new Set(
|
|
20343
20662
|
(original?.orderItems ?? []).map((oi) => oi.item.id)
|
|
20344
20663
|
);
|
|
@@ -20348,7 +20667,6 @@ function AISuggestionsPanel() {
|
|
|
20348
20667
|
}
|
|
20349
20668
|
});
|
|
20350
20669
|
setActiveSessionIndex(firstTargetIdx);
|
|
20351
|
-
dismissSuggestionsOverlay();
|
|
20352
20670
|
onAddedToBasket();
|
|
20353
20671
|
}
|
|
20354
20672
|
const showPreview = activeViewedPreview !== null;
|
|
@@ -20458,6 +20776,63 @@ function AISuggestionsPanel() {
|
|
|
20458
20776
|
}
|
|
20459
20777
|
) })
|
|
20460
20778
|
}
|
|
20779
|
+
) }),
|
|
20780
|
+
/* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { children: mergeConfirm && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
20781
|
+
react$1.motion.div,
|
|
20782
|
+
{
|
|
20783
|
+
initial: { opacity: 0 },
|
|
20784
|
+
animate: { opacity: 1 },
|
|
20785
|
+
exit: { opacity: 0 },
|
|
20786
|
+
transition: { duration: 0.15 },
|
|
20787
|
+
className: "fixed inset-0 z-[60] flex items-center justify-center",
|
|
20788
|
+
children: [
|
|
20789
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20790
|
+
"div",
|
|
20791
|
+
{
|
|
20792
|
+
className: "absolute inset-0 bg-black/40",
|
|
20793
|
+
onClick: () => setMergeConfirm(null)
|
|
20794
|
+
}
|
|
20795
|
+
),
|
|
20796
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
20797
|
+
react$1.motion.div,
|
|
20798
|
+
{
|
|
20799
|
+
initial: { scale: 0.95, opacity: 0 },
|
|
20800
|
+
animate: { scale: 1, opacity: 1 },
|
|
20801
|
+
exit: { scale: 0.95, opacity: 0 },
|
|
20802
|
+
transition: { duration: 0.15 },
|
|
20803
|
+
className: "relative w-full max-w-sm rounded-2xl bg-white p-6 shadow-xl mx-4",
|
|
20804
|
+
children: [
|
|
20805
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-900", children: "Session already has items" }),
|
|
20806
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-2 text-sm text-gray-600", children: [
|
|
20807
|
+
mergeConfirm.conflictingSessions.length === 1 ? `"${mergeConfirm.conflictingSessions[0].name}" already has ${mergeConfirm.conflictingSessions[0].itemCount} item${mergeConfirm.conflictingSessions[0].itemCount === 1 ? "" : "s"}.` : `${mergeConfirm.conflictingSessions.length} sessions already have items.`,
|
|
20808
|
+
" ",
|
|
20809
|
+
"Would you like to replace the existing items or add to them?"
|
|
20810
|
+
] }),
|
|
20811
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-5 flex gap-3", children: [
|
|
20812
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20813
|
+
"button",
|
|
20814
|
+
{
|
|
20815
|
+
type: "button",
|
|
20816
|
+
onClick: () => commitToBasket(true),
|
|
20817
|
+
className: "flex-1 rounded-xl border border-base-300 px-4 py-2.5 text-sm font-medium text-gray-700 transition-colors hover:bg-base-100",
|
|
20818
|
+
children: "Replace"
|
|
20819
|
+
}
|
|
20820
|
+
),
|
|
20821
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20822
|
+
"button",
|
|
20823
|
+
{
|
|
20824
|
+
type: "button",
|
|
20825
|
+
onClick: () => commitToBasket(false),
|
|
20826
|
+
className: "flex-1 rounded-xl bg-primary px-4 py-2.5 text-sm font-medium text-white transition-colors hover:bg-primary/90",
|
|
20827
|
+
children: "Add to existing"
|
|
20828
|
+
}
|
|
20829
|
+
)
|
|
20830
|
+
] })
|
|
20831
|
+
]
|
|
20832
|
+
}
|
|
20833
|
+
)
|
|
20834
|
+
]
|
|
20835
|
+
}
|
|
20461
20836
|
) })
|
|
20462
20837
|
]
|
|
20463
20838
|
}
|
|
@@ -20665,8 +21040,19 @@ function resolveDraftItems(mealSessionParts, aiMealSessions, activeMealSessionIn
|
|
|
20665
21040
|
}
|
|
20666
21041
|
return out;
|
|
20667
21042
|
}
|
|
20668
|
-
function SuggestionsOverlay({ onClose }) {
|
|
21043
|
+
function SuggestionsOverlay({ onClose, flyToCart }) {
|
|
20669
21044
|
const { stickyTopOffset = 0 } = useCateringConfig();
|
|
21045
|
+
const cardRef = react.useRef(null);
|
|
21046
|
+
const controls = react$1.useAnimation();
|
|
21047
|
+
const flying = !!flyToCart;
|
|
21048
|
+
react.useEffect(() => {
|
|
21049
|
+
if (!flyToCart) return;
|
|
21050
|
+
void controls.start({
|
|
21051
|
+
scale: 0.1,
|
|
21052
|
+
opacity: 0,
|
|
21053
|
+
transition: { duration: 0.4, ease: [0.4, 0, 0.2, 1] }
|
|
21054
|
+
});
|
|
21055
|
+
}, [flyToCart, controls]);
|
|
20670
21056
|
react.useEffect(() => {
|
|
20671
21057
|
const body = document.body;
|
|
20672
21058
|
const scrollY = window.scrollY;
|
|
@@ -20703,14 +21089,25 @@ function SuggestionsOverlay({ onClose }) {
|
|
|
20703
21089
|
transition: { duration: 0.2, ease: "easeOut" },
|
|
20704
21090
|
children: [
|
|
20705
21091
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
20706
|
-
|
|
21092
|
+
react$1.motion.div,
|
|
20707
21093
|
{
|
|
20708
21094
|
className: "absolute inset-0 bg-gray-900/30 backdrop-blur-lg",
|
|
20709
21095
|
"aria-hidden": "true",
|
|
20710
|
-
onClick: onClose
|
|
21096
|
+
onClick: onClose,
|
|
21097
|
+
animate: { opacity: flying ? 0 : 1 },
|
|
21098
|
+
transition: { duration: 0.3, ease: "easeOut" }
|
|
20711
21099
|
}
|
|
20712
21100
|
),
|
|
20713
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21101
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21102
|
+
react$1.motion.div,
|
|
21103
|
+
{
|
|
21104
|
+
ref: cardRef,
|
|
21105
|
+
animate: controls,
|
|
21106
|
+
className: "relative h-full overflow-hidden pt-6",
|
|
21107
|
+
style: { transformOrigin: "center center" },
|
|
21108
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-6xl mx-auto w-full px-2 md:px-6", children: /* @__PURE__ */ jsxRuntime.jsx(AISuggestionsPanel, {}) })
|
|
21109
|
+
}
|
|
21110
|
+
)
|
|
20714
21111
|
]
|
|
20715
21112
|
}
|
|
20716
21113
|
);
|
|
@@ -20850,7 +21247,8 @@ function InlineAddressInput({
|
|
|
20850
21247
|
activeIndex,
|
|
20851
21248
|
setActiveIndex,
|
|
20852
21249
|
handleSelect,
|
|
20853
|
-
handleKeyDown
|
|
21250
|
+
handleKeyDown,
|
|
21251
|
+
outOfZoneError
|
|
20854
21252
|
} = useAddressAutocomplete(onPlaceSelect);
|
|
20855
21253
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "relative mt-1.5 pt-1.5 border-t border-base-200", children: [
|
|
20856
21254
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
@@ -20888,7 +21286,8 @@ function InlineAddressInput({
|
|
|
20888
21286
|
]
|
|
20889
21287
|
},
|
|
20890
21288
|
p.place_id
|
|
20891
|
-
)) })
|
|
21289
|
+
)) }),
|
|
21290
|
+
outOfZoneError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-[10px] text-red-500", children: outOfZoneError })
|
|
20892
21291
|
] });
|
|
20893
21292
|
}
|
|
20894
21293
|
function PricingSummary({
|
|
@@ -22088,6 +22487,7 @@ function RestaurantMenuBrowser({
|
|
|
22088
22487
|
}) {
|
|
22089
22488
|
const { addMenuItem, mealSessions, restaurantPromotions, contactInfo } = useCateringState();
|
|
22090
22489
|
const { stickyTopOffset: hostStickyTopOffset = 0 } = useCateringConfig();
|
|
22490
|
+
const { filters, setFilters } = useCateringFilters();
|
|
22091
22491
|
const activeSession = mealSessions[sessionIndex];
|
|
22092
22492
|
const [selectedRestaurantId, setSelectedRestaurantIdState] = react.useState(() => {
|
|
22093
22493
|
if (typeof window === "undefined") return null;
|
|
@@ -22300,6 +22700,8 @@ function RestaurantMenuBrowser({
|
|
|
22300
22700
|
const [isMobileViewport, setIsMobileViewport] = react.useState(false);
|
|
22301
22701
|
const [apiSearchResults, setApiSearchResults] = react.useState(null);
|
|
22302
22702
|
const [searchLoading, setSearchLoading] = react.useState(false);
|
|
22703
|
+
const [priceFilterOpen, setPriceFilterOpen] = react.useState(false);
|
|
22704
|
+
const priceFilterRef = react.useRef(null);
|
|
22303
22705
|
const sectionRefs = react.useRef(/* @__PURE__ */ new Map());
|
|
22304
22706
|
const groupButtonRefs = react.useRef(/* @__PURE__ */ new Map());
|
|
22305
22707
|
const isProgrammaticScroll = react.useRef(false);
|
|
@@ -22499,6 +22901,16 @@ function RestaurantMenuBrowser({
|
|
|
22499
22901
|
}, 300);
|
|
22500
22902
|
return () => clearTimeout(timer);
|
|
22501
22903
|
}, [isSearchActive, searchQuery, selectedDietaryFilters]);
|
|
22904
|
+
react.useEffect(() => {
|
|
22905
|
+
if (!priceFilterOpen) return;
|
|
22906
|
+
const handleClickOutside = (e) => {
|
|
22907
|
+
if (priceFilterRef.current && !priceFilterRef.current.contains(e.target)) {
|
|
22908
|
+
setPriceFilterOpen(false);
|
|
22909
|
+
}
|
|
22910
|
+
};
|
|
22911
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
22912
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
22913
|
+
}, [priceFilterOpen]);
|
|
22502
22914
|
const filteredRestaurants = react.useMemo(() => {
|
|
22503
22915
|
return availableRestaurants.filter((restaurant) => {
|
|
22504
22916
|
const matchesCategory = !selectedCategoryId || (restaurant.categories ?? []).some(
|
|
@@ -22507,12 +22919,14 @@ function RestaurantMenuBrowser({
|
|
|
22507
22919
|
const matchesDiet = selectedDietaryFilters.length === 0 || selectedDietaryFilters.every(
|
|
22508
22920
|
(filter) => (restaurant.dietaryFilters ?? []).includes(filter)
|
|
22509
22921
|
);
|
|
22510
|
-
|
|
22922
|
+
const matchesPriceRange = !filters.restaurantPriceRange || restaurant.priceRange === filters.restaurantPriceRange;
|
|
22923
|
+
return matchesCategory && matchesDiet && matchesPriceRange;
|
|
22511
22924
|
}).sort(compareRestaurantsByAvailability);
|
|
22512
22925
|
}, [
|
|
22513
22926
|
availableRestaurants,
|
|
22514
22927
|
selectedCategoryId,
|
|
22515
22928
|
selectedDietaryFilters,
|
|
22929
|
+
filters.restaurantPriceRange,
|
|
22516
22930
|
compareRestaurantsByAvailability
|
|
22517
22931
|
]);
|
|
22518
22932
|
const selectedRestaurant = react.useMemo(
|
|
@@ -22909,16 +23323,23 @@ function RestaurantMenuBrowser({
|
|
|
22909
23323
|
const userLoc = contactInfo?.latitude && contactInfo?.longitude ? { latitude: contactInfo.latitude, longitude: contactInfo.longitude } : null;
|
|
22910
23324
|
const distance = userLoc && restaurantLoc ? haversineDistanceMiles(userLoc.latitude, userLoc.longitude, restaurantLoc.latitude, restaurantLoc.longitude) : null;
|
|
22911
23325
|
const rating = restaurant.averageRating && parseFloat(restaurant.averageRating) > 0 ? parseFloat(restaurant.averageRating) : null;
|
|
22912
|
-
|
|
22913
|
-
|
|
22914
|
-
|
|
22915
|
-
|
|
23326
|
+
const priceRange = restaurant.priceRange;
|
|
23327
|
+
const tags = restaurant.tags?.filter(Boolean) ?? [];
|
|
23328
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-auto pt-2 flex flex-col gap-1.5", children: [
|
|
23329
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-h-[18px] flex items-center gap-2", children: [
|
|
23330
|
+
rating !== null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-0.5 text-[11px] text-gray-500", children: [
|
|
23331
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-yellow-400", children: "\u2605" }),
|
|
23332
|
+
rating.toFixed(1)
|
|
23333
|
+
] }),
|
|
23334
|
+
rating !== null && distance !== null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-300 text-[11px]", children: "\xB7" }),
|
|
23335
|
+
distance !== null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] text-gray-500", children: [
|
|
23336
|
+
distance.toFixed(1),
|
|
23337
|
+
" mi"
|
|
23338
|
+
] }),
|
|
23339
|
+
priceRange && (rating !== null || distance !== null) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-300 text-[11px]", children: "\xB7" }),
|
|
23340
|
+
priceRange && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] text-gray-500", children: priceRange })
|
|
22916
23341
|
] }),
|
|
22917
|
-
|
|
22918
|
-
distance !== null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[11px] text-gray-500", children: [
|
|
22919
|
-
distance.toFixed(1),
|
|
22920
|
-
" mi"
|
|
22921
|
-
] })
|
|
23342
|
+
tags.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] text-gray-500 leading-tight", children: tags.slice(0, 3).join(" - ") })
|
|
22922
23343
|
] });
|
|
22923
23344
|
})()
|
|
22924
23345
|
] })
|
|
@@ -23081,24 +23502,31 @@ function RestaurantMenuBrowser({
|
|
|
23081
23502
|
const rating = selectedRestaurant.averageRating && parseFloat(selectedRestaurant.averageRating) > 0 ? parseFloat(selectedRestaurant.averageRating) : null;
|
|
23082
23503
|
const advanceNoticeText = getRestaurantAdvanceNoticeText(selectedRestaurant);
|
|
23083
23504
|
const noticeMet = isRestaurantAdvanceNoticeMet(selectedRestaurant, activeSession?.sessionDate, activeSession?.eventTime);
|
|
23084
|
-
|
|
23085
|
-
|
|
23086
|
-
|
|
23087
|
-
|
|
23088
|
-
|
|
23089
|
-
|
|
23090
|
-
|
|
23091
|
-
|
|
23092
|
-
|
|
23093
|
-
"
|
|
23094
|
-
|
|
23095
|
-
|
|
23096
|
-
|
|
23097
|
-
|
|
23098
|
-
|
|
23099
|
-
|
|
23505
|
+
const priceRange = selectedRestaurant.priceRange;
|
|
23506
|
+
const tags = selectedRestaurant.tags?.filter(Boolean).slice(0, 3) ?? [];
|
|
23507
|
+
if (!rating && !distance && !advanceNoticeText && !priceRange && tags.length === 0) return null;
|
|
23508
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 mb-1 flex flex-col gap-1", children: [
|
|
23509
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1", children: [
|
|
23510
|
+
rating !== null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1 text-sm text-gray-500 whitespace-nowrap", children: [
|
|
23511
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-yellow-400", children: "\u2605" }),
|
|
23512
|
+
rating.toFixed(1)
|
|
23513
|
+
] }),
|
|
23514
|
+
rating !== null && distance !== null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-300", children: "\xB7" }),
|
|
23515
|
+
distance !== null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm text-gray-500 whitespace-nowrap", children: [
|
|
23516
|
+
distance.toFixed(1),
|
|
23517
|
+
" mi away"
|
|
23518
|
+
] }),
|
|
23519
|
+
priceRange && (rating !== null || distance !== null) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-300", children: "\xB7" }),
|
|
23520
|
+
priceRange && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-gray-500 whitespace-nowrap", children: priceRange }),
|
|
23521
|
+
advanceNoticeText && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
23522
|
+
(rating !== null || distance !== null || priceRange) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-300", children: "\xB7" }),
|
|
23523
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: `flex items-center gap-1 text-sm whitespace-nowrap ${noticeMet ? "text-gray-500" : "text-gray-500"}`, children: [
|
|
23524
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock3, { className: `h-3.5 w-3.5 flex-shrink-0 ${noticeMet ? "text-gray-400" : "text-red-500"}` }),
|
|
23525
|
+
advanceNoticeText
|
|
23526
|
+
] })
|
|
23100
23527
|
] })
|
|
23101
|
-
] })
|
|
23528
|
+
] }),
|
|
23529
|
+
tags.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: tags.join(" - ") })
|
|
23102
23530
|
] });
|
|
23103
23531
|
})(),
|
|
23104
23532
|
selectedRestaurant.restaurant_description && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -23360,26 +23788,72 @@ function RestaurantMenuBrowser({
|
|
|
23360
23788
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pb-6 md:pb-8", style: { contain: "inline-size" }, children: [
|
|
23361
23789
|
hoursInfoTooltip,
|
|
23362
23790
|
mobileHoursInfoSheet,
|
|
23363
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
23364
|
-
/* @__PURE__ */ jsxRuntime.
|
|
23365
|
-
|
|
23366
|
-
|
|
23367
|
-
|
|
23368
|
-
|
|
23369
|
-
|
|
23370
|
-
|
|
23371
|
-
|
|
23372
|
-
|
|
23373
|
-
|
|
23374
|
-
|
|
23375
|
-
|
|
23376
|
-
|
|
23377
|
-
|
|
23378
|
-
|
|
23379
|
-
|
|
23380
|
-
|
|
23381
|
-
|
|
23382
|
-
|
|
23791
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 mb-2 hidden md:flex items-center gap-2", children: [
|
|
23792
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1", children: [
|
|
23793
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" }),
|
|
23794
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23795
|
+
"input",
|
|
23796
|
+
{
|
|
23797
|
+
type: "text",
|
|
23798
|
+
value: searchQuery,
|
|
23799
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
23800
|
+
placeholder: "Search restaurants and menu items...",
|
|
23801
|
+
className: "w-full pl-9 pr-9 py-2.5 rounded-xl border border-base-300 bg-white text-base focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary transition-colors"
|
|
23802
|
+
}
|
|
23803
|
+
),
|
|
23804
|
+
searchQuery && /* @__PURE__ */ jsxRuntime.jsx(
|
|
23805
|
+
"button",
|
|
23806
|
+
{
|
|
23807
|
+
onClick: () => setSearchQuery(""),
|
|
23808
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600",
|
|
23809
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4" })
|
|
23810
|
+
}
|
|
23811
|
+
)
|
|
23812
|
+
] }),
|
|
23813
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-shrink-0", ref: priceFilterRef, children: [
|
|
23814
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
23815
|
+
"button",
|
|
23816
|
+
{
|
|
23817
|
+
onClick: () => setPriceFilterOpen((v) => !v),
|
|
23818
|
+
className: `flex items-center gap-2 h-full px-3 py-2.5 rounded-xl border transition-colors ${filters.restaurantPriceRange ? "bg-primary border-primary text-white" : "bg-white border-base-300 text-gray-600 hover:border-primary hover:text-primary"}`,
|
|
23819
|
+
children: [
|
|
23820
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.SlidersHorizontal, { className: "w-4 h-4 flex-shrink-0" }),
|
|
23821
|
+
filters.restaurantPriceRange ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium", children: filters.restaurantPriceRange }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm", children: "Filters" })
|
|
23822
|
+
]
|
|
23823
|
+
}
|
|
23824
|
+
),
|
|
23825
|
+
priceFilterOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute right-0 top-full mt-2 bg-white rounded-xl border border-base-300 shadow-lg p-3 z-20 min-w-[180px]", children: [
|
|
23826
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2.5", children: [
|
|
23827
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-gray-700", children: "Price Range" }),
|
|
23828
|
+
filters.restaurantPriceRange && /* @__PURE__ */ jsxRuntime.jsx(
|
|
23829
|
+
"button",
|
|
23830
|
+
{
|
|
23831
|
+
onClick: () => {
|
|
23832
|
+
setFilters({ ...filters, restaurantPriceRange: null });
|
|
23833
|
+
setPriceFilterOpen(false);
|
|
23834
|
+
},
|
|
23835
|
+
className: "text-xs text-primary hover:text-primary/80 font-medium",
|
|
23836
|
+
children: "Clear"
|
|
23837
|
+
}
|
|
23838
|
+
)
|
|
23839
|
+
] }),
|
|
23840
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: ["~\xA3", "\xA3-\xA3\xA3", "\xA3\xA3-\xA3\xA3\xA3", "\xA3\xA3\xA3~"].map((range) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
23841
|
+
"button",
|
|
23842
|
+
{
|
|
23843
|
+
onClick: () => {
|
|
23844
|
+
setFilters({
|
|
23845
|
+
...filters,
|
|
23846
|
+
restaurantPriceRange: filters.restaurantPriceRange === range ? null : range
|
|
23847
|
+
});
|
|
23848
|
+
setPriceFilterOpen(false);
|
|
23849
|
+
},
|
|
23850
|
+
className: `px-3 py-1.5 rounded-full text-xs font-medium transition-colors ${filters.restaurantPriceRange === range ? "bg-primary text-white" : "bg-gray-100 text-gray-700 hover:bg-gray-200"}`,
|
|
23851
|
+
children: range
|
|
23852
|
+
},
|
|
23853
|
+
range
|
|
23854
|
+
)) })
|
|
23855
|
+
] })
|
|
23856
|
+
] })
|
|
23383
23857
|
] }),
|
|
23384
23858
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
23385
23859
|
!isSearchActive && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -24393,8 +24867,10 @@ function AddressAutocomplete({
|
|
|
24393
24867
|
setActiveIndex,
|
|
24394
24868
|
handleSelect,
|
|
24395
24869
|
handleKeyDown,
|
|
24396
|
-
clear
|
|
24870
|
+
clear,
|
|
24871
|
+
outOfZoneError
|
|
24397
24872
|
} = useAddressAutocomplete(onPlaceSelect);
|
|
24873
|
+
const shownError = error || outOfZoneError || void 0;
|
|
24398
24874
|
const handleClear = () => {
|
|
24399
24875
|
clear();
|
|
24400
24876
|
if (onClearAddress) onClearAddress();
|
|
@@ -24415,7 +24891,7 @@ function AddressAutocomplete({
|
|
|
24415
24891
|
onKeyDown: handleKeyDown,
|
|
24416
24892
|
placeholder: "Start typing an address...",
|
|
24417
24893
|
autoComplete: "new-password",
|
|
24418
|
-
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 ${
|
|
24894
|
+
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"}`
|
|
24419
24895
|
}
|
|
24420
24896
|
),
|
|
24421
24897
|
hasValidAddress && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -24448,9 +24924,9 @@ function AddressAutocomplete({
|
|
|
24448
24924
|
p.place_id
|
|
24449
24925
|
)) })
|
|
24450
24926
|
] }),
|
|
24451
|
-
|
|
24452
|
-
hasValidAddress && !
|
|
24453
|
-
!hasValidAddress && !
|
|
24927
|
+
shownError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-error", children: shownError }),
|
|
24928
|
+
hasValidAddress && !shownError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-success", children: "Address selected" }),
|
|
24929
|
+
!hasValidAddress && !shownError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-base-content/60", children: "Please select an address from the dropdown" })
|
|
24454
24930
|
] });
|
|
24455
24931
|
}
|
|
24456
24932
|
function DeliveryAddressForm({
|
|
@@ -24588,7 +25064,11 @@ function BillingAddressAutocomplete({
|
|
|
24588
25064
|
setActiveIndex,
|
|
24589
25065
|
handleSelect,
|
|
24590
25066
|
handleKeyDown
|
|
24591
|
-
} = useAddressAutocomplete(onPlaceSelect, {
|
|
25067
|
+
} = useAddressAutocomplete(onPlaceSelect, {
|
|
25068
|
+
countryRestriction: null,
|
|
25069
|
+
// Billing can be anywhere — only delivery is London-restricted.
|
|
25070
|
+
restrictToDeliveryZone: false
|
|
25071
|
+
});
|
|
24592
25072
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-full", ref: containerRef, children: [
|
|
24593
25073
|
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "block text-[10px] font-bold text-base-content/60 uppercase tracking-widest mb-1.5", children: [
|
|
24594
25074
|
"Search Address",
|
|
@@ -27325,6 +27805,10 @@ function CateringOrderBuilder() {
|
|
|
27325
27805
|
setMobileChatView("chat");
|
|
27326
27806
|
setMobileAddressPillEditing(false);
|
|
27327
27807
|
setIsMobileChatMenuOpen(false);
|
|
27808
|
+
} else {
|
|
27809
|
+
requestAnimationFrame(() => {
|
|
27810
|
+
mobileAIInputRef.current?.blur();
|
|
27811
|
+
});
|
|
27328
27812
|
}
|
|
27329
27813
|
}, [isMobileAIChatOpen]);
|
|
27330
27814
|
const [mobileAIInput, setMobileAIInput] = react.useState("");
|
|
@@ -27352,6 +27836,9 @@ function CateringOrderBuilder() {
|
|
|
27352
27836
|
mobileAIInputRef.current.style.overflowY = "hidden";
|
|
27353
27837
|
}
|
|
27354
27838
|
};
|
|
27839
|
+
const cartTabRef = react.useRef(null);
|
|
27840
|
+
const [flyToCart, setFlyToCart] = react.useState(null);
|
|
27841
|
+
const [flyGhost, setFlyGhost] = react.useState(null);
|
|
27355
27842
|
const [isMobileSearchOpen, setIsMobileSearchOpen] = react.useState(false);
|
|
27356
27843
|
const [isMobileSearchActive, setIsMobileSearchActive] = react.useState(false);
|
|
27357
27844
|
const [mobileSearchState, setMobileSearchState] = react.useState({ mode: "list", query: "" });
|
|
@@ -27510,9 +27997,6 @@ function CateringOrderBuilder() {
|
|
|
27510
27997
|
...parsed.contactInfo
|
|
27511
27998
|
});
|
|
27512
27999
|
setMobileAddressPillEditing(false);
|
|
27513
|
-
requestAnimationFrame(() => {
|
|
27514
|
-
mobileAIInputRef.current?.focus();
|
|
27515
|
-
});
|
|
27516
28000
|
};
|
|
27517
28001
|
const handleMobileAddressClear = () => {
|
|
27518
28002
|
setContactInfo({
|
|
@@ -27918,37 +28402,45 @@ function CateringOrderBuilder() {
|
|
|
27918
28402
|
longitude: void 0
|
|
27919
28403
|
});
|
|
27920
28404
|
}, [contactInfo, setContactInfo]);
|
|
27921
|
-
const
|
|
27922
|
-
|
|
27923
|
-
|
|
27924
|
-
|
|
28405
|
+
const pricingCancelRef = react.useRef(0);
|
|
28406
|
+
const pricingRetryRef = react.useRef(null);
|
|
28407
|
+
react.useEffect(() => {
|
|
28408
|
+
if (pricingDebounceRef.current) clearTimeout(pricingDebounceRef.current);
|
|
28409
|
+
if (pricingRetryRef.current) clearTimeout(pricingRetryRef.current);
|
|
28410
|
+
const gen = ++pricingCancelRef.current;
|
|
28411
|
+
function fire() {
|
|
28412
|
+
if (gen !== pricingCancelRef.current) return;
|
|
28413
|
+
if (totalItems === 0) {
|
|
27925
28414
|
setPricing(null);
|
|
27926
28415
|
return;
|
|
27927
28416
|
}
|
|
27928
28417
|
setCalculatingPricing(true);
|
|
27929
|
-
|
|
27930
|
-
|
|
27931
|
-
|
|
27932
|
-
|
|
27933
|
-
|
|
27934
|
-
);
|
|
27935
|
-
if (result.isValid)
|
|
27936
|
-
|
|
27937
|
-
|
|
28418
|
+
cateringService.calculateCateringPricingWithMealSessions(
|
|
28419
|
+
mealSessions,
|
|
28420
|
+
[],
|
|
28421
|
+
deliveryLocation ?? void 0
|
|
28422
|
+
).then((result) => {
|
|
28423
|
+
if (gen !== pricingCancelRef.current) return;
|
|
28424
|
+
if (result.isValid) {
|
|
28425
|
+
setPricing(result);
|
|
28426
|
+
} else {
|
|
28427
|
+
setPricing(null);
|
|
28428
|
+
pricingRetryRef.current = setTimeout(fire, 2e3);
|
|
28429
|
+
}
|
|
28430
|
+
}).catch(() => {
|
|
28431
|
+
if (gen !== pricingCancelRef.current) return;
|
|
28432
|
+
pricingRetryRef.current = setTimeout(fire, 2e3);
|
|
28433
|
+
}).finally(() => {
|
|
28434
|
+
if (gen !== pricingCancelRef.current) return;
|
|
27938
28435
|
setCalculatingPricing(false);
|
|
27939
|
-
}
|
|
27940
|
-
}
|
|
27941
|
-
|
|
27942
|
-
);
|
|
27943
|
-
react.useEffect(() => {
|
|
27944
|
-
if (pricingDebounceRef.current) clearTimeout(pricingDebounceRef.current);
|
|
27945
|
-
pricingDebounceRef.current = setTimeout(() => {
|
|
27946
|
-
fetchPricing(mealSessions);
|
|
27947
|
-
}, 600);
|
|
28436
|
+
});
|
|
28437
|
+
}
|
|
28438
|
+
pricingDebounceRef.current = setTimeout(fire, 600);
|
|
27948
28439
|
return () => {
|
|
27949
28440
|
if (pricingDebounceRef.current) clearTimeout(pricingDebounceRef.current);
|
|
28441
|
+
if (pricingRetryRef.current) clearTimeout(pricingRetryRef.current);
|
|
27950
28442
|
};
|
|
27951
|
-
}, [mealSessions,
|
|
28443
|
+
}, [totalItems, mealSessions, deliveryLocation]);
|
|
27952
28444
|
const handleEditorClose = (cancelled) => {
|
|
27953
28445
|
const sessionIndex = editingSessionIndex;
|
|
27954
28446
|
const wasNewSession = isNewSession;
|
|
@@ -28388,7 +28880,7 @@ function CateringOrderBuilder() {
|
|
|
28388
28880
|
if (currentStep === 2) {
|
|
28389
28881
|
return /* @__PURE__ */ jsxRuntime.jsx(CheckoutScreen, {});
|
|
28390
28882
|
}
|
|
28391
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
28883
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
28392
28884
|
ChatSessionProvider,
|
|
28393
28885
|
{
|
|
28394
28886
|
enabled: aiEnabled && (rightPanelTab === "ai" || isMobileAIChatOpen),
|
|
@@ -28400,854 +28892,903 @@ function CateringOrderBuilder() {
|
|
|
28400
28892
|
setPendingItem(previewItemToMenuItem(previewItem));
|
|
28401
28893
|
},
|
|
28402
28894
|
onAddedToBasket: () => {
|
|
28403
|
-
|
|
28404
|
-
|
|
28405
|
-
|
|
28406
|
-
|
|
28407
|
-
|
|
28408
|
-
|
|
28409
|
-
|
|
28410
|
-
|
|
28411
|
-
|
|
28412
|
-
|
|
28413
|
-
|
|
28414
|
-
|
|
28415
|
-
|
|
28416
|
-
|
|
28417
|
-
dayName: d.dayName,
|
|
28418
|
-
displayDate: d.displayDate
|
|
28419
|
-
}))
|
|
28895
|
+
const basketRect = basketColumnRef.current?.getBoundingClientRect();
|
|
28896
|
+
const overlayLeft = 8;
|
|
28897
|
+
const overlayRight = window.innerWidth - 384;
|
|
28898
|
+
const fromX = (overlayLeft + overlayRight) / 2;
|
|
28899
|
+
const fromY = window.innerHeight / 2;
|
|
28900
|
+
setFlyToCart({ x: 0, y: 0 });
|
|
28901
|
+
setTimeout(() => {
|
|
28902
|
+
if (basketRect) {
|
|
28903
|
+
setFlyGhost({
|
|
28904
|
+
fromX,
|
|
28905
|
+
fromY,
|
|
28906
|
+
toX: basketRect.left + basketRect.width / 2,
|
|
28907
|
+
toY: basketRect.top + basketRect.height / 2
|
|
28908
|
+
});
|
|
28420
28909
|
}
|
|
28421
|
-
)
|
|
28422
|
-
|
|
28423
|
-
|
|
28424
|
-
|
|
28425
|
-
|
|
28426
|
-
|
|
28427
|
-
|
|
28428
|
-
|
|
28429
|
-
|
|
28430
|
-
|
|
28431
|
-
|
|
28432
|
-
|
|
28433
|
-
|
|
28434
|
-
|
|
28435
|
-
|
|
28436
|
-
|
|
28910
|
+
}, 350);
|
|
28911
|
+
setTimeout(() => {
|
|
28912
|
+
setFlyToCart(null);
|
|
28913
|
+
setRightPanelTab("cart");
|
|
28914
|
+
setMobileChatView("chat");
|
|
28915
|
+
}, 550);
|
|
28916
|
+
setTimeout(() => setFlyGhost(null), 1200);
|
|
28917
|
+
},
|
|
28918
|
+
children: [
|
|
28919
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-h-screen bg-base-100", children: [
|
|
28920
|
+
editingSessionIndex !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
28921
|
+
SessionEditor,
|
|
28922
|
+
{
|
|
28923
|
+
session: mealSessions[editingSessionIndex],
|
|
28924
|
+
sessionIndex: editingSessionIndex,
|
|
28925
|
+
onUpdate: updateMealSession,
|
|
28926
|
+
onClose: handleEditorClose,
|
|
28927
|
+
restaurants,
|
|
28928
|
+
existingDates: dayGroups.filter((d) => d.date !== "unscheduled").map((d) => ({
|
|
28929
|
+
date: d.date,
|
|
28930
|
+
dayName: d.dayName,
|
|
28931
|
+
displayDate: d.displayDate
|
|
28932
|
+
})),
|
|
28933
|
+
existingSessions: mealSessions.filter((_, i) => i !== editingSessionIndex).filter((s) => s.sessionDate && s.eventTime).map((s) => ({ date: s.sessionDate, time: s.eventTime }))
|
|
28934
|
+
}
|
|
28935
|
+
),
|
|
28936
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col md:flex-row px-2${isMobileAIChatOpen ? " hidden md:flex" : ""}`, children: [
|
|
28937
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 flex flex-col", children: [
|
|
28437
28938
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28438
|
-
|
|
28939
|
+
SessionPickerDropdown,
|
|
28439
28940
|
{
|
|
28440
|
-
|
|
28441
|
-
onToggleBundleBrowser: setShowBundleBrowser,
|
|
28442
|
-
sessionIndex: activeSessionIndex,
|
|
28443
|
-
defaultGuestCount: mealSessions[activeSessionIndex]?.guestCount ?? 1,
|
|
28444
|
-
restaurants,
|
|
28445
|
-
restaurantsLoading,
|
|
28446
|
-
onAddItem: handleAddItem,
|
|
28447
|
-
onUpdateQuantity: handleUpdateQuantity,
|
|
28448
|
-
onAddOrderPress: handleAddOrderPress,
|
|
28449
|
-
getItemQuantity,
|
|
28450
|
-
expandedItemId,
|
|
28451
|
-
setExpandedItemId,
|
|
28452
|
-
selectedDietaryFilters,
|
|
28453
|
-
toggleDietaryFilter,
|
|
28454
|
-
restaurantListRef,
|
|
28455
|
-
firstMenuItemRef,
|
|
28456
|
-
categoriesRowRef,
|
|
28941
|
+
dayGroups,
|
|
28457
28942
|
expandedSessionIndex: activeSessionIndex,
|
|
28458
|
-
|
|
28459
|
-
|
|
28460
|
-
|
|
28461
|
-
|
|
28462
|
-
|
|
28943
|
+
onSessionPillClick: handleSessionPillClick,
|
|
28944
|
+
onEditSession: (index) => setEditingSessionIndex(index),
|
|
28945
|
+
onDeleteSession: (index) => setSessionToRemove(index),
|
|
28946
|
+
onAddDay: handleAddDay,
|
|
28947
|
+
formatTimeDisplay
|
|
28463
28948
|
}
|
|
28464
28949
|
),
|
|
28465
|
-
/* @__PURE__ */ jsxRuntime.
|
|
28466
|
-
|
|
28467
|
-
|
|
28468
|
-
active: effectiveRightPanelTab === "ai",
|
|
28469
|
-
onVisibleChange: setOverlayVisible
|
|
28470
|
-
}
|
|
28471
|
-
)
|
|
28472
|
-
] })
|
|
28473
|
-
] }),
|
|
28474
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28475
|
-
"div",
|
|
28476
|
-
{
|
|
28477
|
-
ref: basketColumnRef,
|
|
28478
|
-
className: `hidden md:flex md:w-96 flex-shrink-0 flex-col overflow-hidden py-2 px-1 ${overlayVisible ? "fixed z-50 bg-base-100" : "sticky"}`,
|
|
28479
|
-
style: {
|
|
28480
|
-
top: stickyTopOffset,
|
|
28481
|
-
right: overlayVisible ? 0 : void 0,
|
|
28482
|
-
height: overlayVisible ? `calc(100dvh - ${stickyTopOffset}px)` : basketHeight,
|
|
28483
|
-
alignSelf: "flex-start"
|
|
28484
|
-
},
|
|
28485
|
-
children: mealSessions[activeSessionIndex] && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col gap-2 overflow-hidden", children: [
|
|
28486
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-shrink-0 flex rounded-xl bg-base-200 p-1", children: [
|
|
28487
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28488
|
-
"button",
|
|
28489
|
-
{
|
|
28490
|
-
type: "button",
|
|
28491
|
-
onClick: () => setRightPanelTab("cart"),
|
|
28492
|
-
className: `flex-1 rounded-lg px-3 py-1.5 text-sm font-semibold transition-colors ${effectiveRightPanelTab === "cart" ? "bg-white text-gray-800 shadow-sm" : "text-gray-500 hover:text-gray-700"}`,
|
|
28493
|
-
children: "Cart"
|
|
28494
|
-
}
|
|
28495
|
-
),
|
|
28496
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
28497
|
-
"button",
|
|
28498
|
-
{
|
|
28499
|
-
type: "button",
|
|
28500
|
-
onClick: () => {
|
|
28501
|
-
if (!aiEnabled) return;
|
|
28502
|
-
setRightPanelTab("ai");
|
|
28503
|
-
},
|
|
28504
|
-
disabled: !aiEnabled,
|
|
28505
|
-
"aria-disabled": !aiEnabled,
|
|
28506
|
-
title: aiEnabled ? void 0 : "Coming Soon",
|
|
28507
|
-
className: `flex-1 rounded-lg px-3 py-1.5 text-sm font-semibold transition-colors flex items-center justify-center gap-1.5 ${!aiEnabled ? "text-gray-400 cursor-not-allowed" : effectiveRightPanelTab === "ai" ? "bg-white text-gray-800 shadow-sm" : "text-gray-500 hover:text-gray-700"}`,
|
|
28508
|
-
children: [
|
|
28509
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "w-3.5 h-3.5" }),
|
|
28510
|
-
"AI Chat",
|
|
28511
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full bg-primary px-1.5 py-0.5 text-[8px] font-bold uppercase tracking-wider text-white shadow-sm whitespace-nowrap", children: aiEnabled ? "Beta" : "Soon" })
|
|
28512
|
-
]
|
|
28513
|
-
}
|
|
28514
|
-
)
|
|
28515
|
-
] }),
|
|
28516
|
-
effectiveRightPanelTab === "cart" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
28517
|
-
ActiveSessionPanel,
|
|
28950
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative max-w-6xl mx-auto w-full px-2 md:px-6", children: [
|
|
28951
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28952
|
+
MenuBrowserColumn,
|
|
28518
28953
|
{
|
|
28519
|
-
|
|
28954
|
+
showBundleBrowser,
|
|
28955
|
+
onToggleBundleBrowser: setShowBundleBrowser,
|
|
28520
28956
|
sessionIndex: activeSessionIndex,
|
|
28521
|
-
|
|
28522
|
-
|
|
28523
|
-
|
|
28524
|
-
|
|
28525
|
-
|
|
28526
|
-
|
|
28527
|
-
|
|
28528
|
-
|
|
28529
|
-
|
|
28530
|
-
|
|
28531
|
-
|
|
28532
|
-
|
|
28533
|
-
|
|
28534
|
-
|
|
28535
|
-
|
|
28536
|
-
|
|
28537
|
-
|
|
28538
|
-
|
|
28539
|
-
|
|
28957
|
+
defaultGuestCount: mealSessions[activeSessionIndex]?.guestCount ?? 1,
|
|
28958
|
+
restaurants,
|
|
28959
|
+
restaurantsLoading,
|
|
28960
|
+
onAddItem: handleAddItem,
|
|
28961
|
+
onUpdateQuantity: handleUpdateQuantity,
|
|
28962
|
+
onAddOrderPress: handleAddOrderPress,
|
|
28963
|
+
getItemQuantity,
|
|
28964
|
+
expandedItemId,
|
|
28965
|
+
setExpandedItemId,
|
|
28966
|
+
selectedDietaryFilters,
|
|
28967
|
+
toggleDietaryFilter,
|
|
28968
|
+
restaurantListRef,
|
|
28969
|
+
firstMenuItemRef,
|
|
28970
|
+
categoriesRowRef,
|
|
28971
|
+
expandedSessionIndex: activeSessionIndex,
|
|
28972
|
+
onRegisterResetToList: (fn) => {
|
|
28973
|
+
resetRestaurantListRef.current = fn;
|
|
28974
|
+
},
|
|
28975
|
+
onMobileSearchStateChange: setMobileSearchState,
|
|
28976
|
+
onRegisterMobileSearchSetter: handleRegisterMobileSearchSetter
|
|
28540
28977
|
}
|
|
28541
|
-
)
|
|
28542
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28543
|
-
|
|
28544
|
-
|
|
28545
|
-
|
|
28546
|
-
|
|
28547
|
-
|
|
28548
|
-
|
|
28549
|
-
|
|
28550
|
-
onClearAddress: handleClearDeliveryAddress
|
|
28551
|
-
}
|
|
28552
|
-
) }),
|
|
28553
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-stretch gap-2", children: [
|
|
28554
|
-
mealSessions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-shrink-0", children: [
|
|
28555
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28556
|
-
"button",
|
|
28557
|
-
{
|
|
28558
|
-
ref: desktopMenuBtnRef,
|
|
28559
|
-
onClick: () => {
|
|
28560
|
-
if (!isDesktopCartMenuOpen && desktopMenuBtnRef.current) {
|
|
28561
|
-
const rect = desktopMenuBtnRef.current.getBoundingClientRect();
|
|
28562
|
-
setDesktopMenuPos({
|
|
28563
|
-
bottom: window.innerHeight - rect.top + 8,
|
|
28564
|
-
left: rect.left
|
|
28565
|
-
});
|
|
28566
|
-
}
|
|
28567
|
-
setIsDesktopCartMenuOpen((v) => !v);
|
|
28568
|
-
},
|
|
28569
|
-
className: "flex h-full items-center justify-center rounded-lg border border-base-300 px-3 text-base-content/60 transition-colors hover:bg-base-200",
|
|
28570
|
-
title: "More options",
|
|
28571
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontal, { className: "h-4 w-4" })
|
|
28572
|
-
}
|
|
28573
|
-
),
|
|
28574
|
-
isDesktopCartMenuOpen && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
28575
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28576
|
-
"div",
|
|
28577
|
-
{
|
|
28578
|
-
className: "fixed inset-0 z-40",
|
|
28579
|
-
onClick: () => setIsDesktopCartMenuOpen(false)
|
|
28580
|
-
}
|
|
28581
|
-
),
|
|
28582
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
28583
|
-
"div",
|
|
28584
|
-
{
|
|
28585
|
-
className: "fixed z-50 w-44 overflow-hidden rounded-xl border border-base-200 bg-white shadow-lg",
|
|
28586
|
-
style: {
|
|
28587
|
-
bottom: desktopMenuPos.bottom,
|
|
28588
|
-
left: desktopMenuPos.left
|
|
28589
|
-
},
|
|
28590
|
-
children: [
|
|
28591
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
28592
|
-
"button",
|
|
28593
|
-
{
|
|
28594
|
-
onClick: () => {
|
|
28595
|
-
setIsDesktopCartMenuOpen(false);
|
|
28596
|
-
handleViewMenu();
|
|
28597
|
-
},
|
|
28598
|
-
disabled: generatingPdf || totalItems === 0,
|
|
28599
|
-
className: "flex w-full items-center gap-2 px-3 py-2.5 text-left text-sm text-gray-700 transition-colors hover:bg-base-100 disabled:cursor-not-allowed disabled:opacity-50",
|
|
28600
|
-
children: [
|
|
28601
|
-
generatingPdf ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "loading loading-spinner loading-xs" }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
28602
|
-
"svg",
|
|
28603
|
-
{
|
|
28604
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
28605
|
-
className: "h-4 w-4",
|
|
28606
|
-
fill: "none",
|
|
28607
|
-
viewBox: "0 0 24 24",
|
|
28608
|
-
stroke: "currentColor",
|
|
28609
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
28610
|
-
"path",
|
|
28611
|
-
{
|
|
28612
|
-
strokeLinecap: "round",
|
|
28613
|
-
strokeLinejoin: "round",
|
|
28614
|
-
strokeWidth: 2,
|
|
28615
|
-
d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
|
|
28616
|
-
}
|
|
28617
|
-
)
|
|
28618
|
-
}
|
|
28619
|
-
),
|
|
28620
|
-
"Download Menu"
|
|
28621
|
-
]
|
|
28622
|
-
}
|
|
28623
|
-
),
|
|
28624
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
28625
|
-
"button",
|
|
28626
|
-
{
|
|
28627
|
-
onClick: () => {
|
|
28628
|
-
setIsDesktopCartMenuOpen(false);
|
|
28629
|
-
setIsClearAllConfirmOpen(true);
|
|
28630
|
-
},
|
|
28631
|
-
className: "flex w-full items-center gap-2 border-t border-base-200 px-3 py-2.5 text-left text-sm text-red-600 transition-colors hover:bg-red-50",
|
|
28632
|
-
children: [
|
|
28633
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-4 w-4" }),
|
|
28634
|
-
"Clear Cart"
|
|
28635
|
-
]
|
|
28636
|
-
}
|
|
28637
|
-
)
|
|
28638
|
-
]
|
|
28639
|
-
}
|
|
28640
|
-
)
|
|
28641
|
-
] })
|
|
28642
|
-
] }),
|
|
28643
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28644
|
-
"button",
|
|
28645
|
-
{
|
|
28646
|
-
onClick: handleCheckout,
|
|
28647
|
-
disabled: totalItems === 0,
|
|
28648
|
-
className: `flex flex-1 items-center justify-center rounded-lg px-3 py-3 text-sm font-semibold text-white transition-colors disabled:cursor-not-allowed disabled:opacity-50 ${isCurrentSessionValid ? "bg-primary hover:bg-primary/90" : "bg-warning hover:bg-warning/90"}`,
|
|
28649
|
-
children: totalItems === 0 ? "Cart Empty" : isCurrentSessionValid ? "Checkout" : "Min. Order Not Met"
|
|
28650
|
-
}
|
|
28651
|
-
)
|
|
28652
|
-
] })
|
|
28653
|
-
] }) })
|
|
28978
|
+
),
|
|
28979
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28980
|
+
SuggestionsOverlayBridge,
|
|
28981
|
+
{
|
|
28982
|
+
active: effectiveRightPanelTab === "ai",
|
|
28983
|
+
onVisibleChange: setOverlayVisible,
|
|
28984
|
+
flyToCart
|
|
28985
|
+
}
|
|
28986
|
+
)
|
|
28654
28987
|
] })
|
|
28655
|
-
}
|
|
28656
|
-
|
|
28657
|
-
|
|
28658
|
-
|
|
28659
|
-
|
|
28660
|
-
|
|
28661
|
-
|
|
28662
|
-
|
|
28663
|
-
|
|
28664
|
-
|
|
28665
|
-
|
|
28666
|
-
|
|
28667
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28668
|
-
"div",
|
|
28669
|
-
{
|
|
28670
|
-
className: "absolute inset-0 bg-white",
|
|
28671
|
-
"aria-hidden": "true"
|
|
28672
|
-
}
|
|
28673
|
-
),
|
|
28674
|
-
/* @__PURE__ */ jsxRuntime.jsx(react$1.LayoutGroup, { children: /* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { initial: false, mode: "popLayout", children: mobileAddressEditorOpen ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
28675
|
-
MobileAddressPickerSurface,
|
|
28676
|
-
{
|
|
28677
|
-
hasAddress: hasChatAddress,
|
|
28678
|
-
initialQuery: mobileAddressPillEditing ? contactInfo?.addressLine1 ?? "" : "",
|
|
28679
|
-
onPlaceSelect: handleMobileAddressPick,
|
|
28680
|
-
onBack: () => setMobileAddressPillEditing(false),
|
|
28681
|
-
onRemove: handleMobileAddressClear,
|
|
28682
|
-
onClose: closeMobileAIChat
|
|
28988
|
+
] }),
|
|
28989
|
+
overlayVisible && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden md:block md:w-96 flex-shrink-0", "aria-hidden": true }),
|
|
28990
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28991
|
+
"div",
|
|
28992
|
+
{
|
|
28993
|
+
ref: basketColumnRef,
|
|
28994
|
+
className: `hidden md:flex md:w-96 flex-shrink-0 flex-col overflow-hidden py-2 px-1 ${overlayVisible ? "fixed z-50 bg-base-100" : "sticky"}`,
|
|
28995
|
+
style: {
|
|
28996
|
+
top: stickyTopOffset,
|
|
28997
|
+
right: overlayVisible ? 0 : void 0,
|
|
28998
|
+
height: overlayVisible ? `calc(100dvh - ${stickyTopOffset}px)` : basketHeight,
|
|
28999
|
+
alignSelf: "flex-start"
|
|
28683
29000
|
},
|
|
28684
|
-
"
|
|
28685
|
-
|
|
28686
|
-
|
|
28687
|
-
|
|
28688
|
-
initial: { opacity: 0 },
|
|
28689
|
-
animate: { opacity: 1 },
|
|
28690
|
-
exit: { opacity: 0 },
|
|
28691
|
-
transition: { duration: 0.18, ease: "easeOut" },
|
|
28692
|
-
className: "absolute inset-0",
|
|
28693
|
-
children: [
|
|
28694
|
-
aiBetaUnlocked && hasChatAddress && mobileChatView === "chat" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
28695
|
-
react$1.motion.button,
|
|
29001
|
+
children: mealSessions[activeSessionIndex] && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full flex-col gap-2 overflow-hidden", children: [
|
|
29002
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-shrink-0 flex rounded-xl bg-base-200 p-1", children: [
|
|
29003
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29004
|
+
"button",
|
|
28696
29005
|
{
|
|
29006
|
+
ref: cartTabRef,
|
|
28697
29007
|
type: "button",
|
|
28698
|
-
|
|
28699
|
-
|
|
28700
|
-
|
|
28701
|
-
className: "absolute top-3 left-3 z-10 inline-flex max-w-[60%] items-center gap-1.5 rounded-xl bg-black/60 backdrop-blur-sm px-3 py-2 text-xs text-white",
|
|
28702
|
-
children: [
|
|
28703
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28704
|
-
lucideReact.MapPin,
|
|
28705
|
-
{
|
|
28706
|
-
className: "h-3.5 w-3.5 flex-shrink-0 text-white/80",
|
|
28707
|
-
"aria-hidden": true
|
|
28708
|
-
}
|
|
28709
|
-
),
|
|
28710
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: contactInfo?.addressLine1 }),
|
|
28711
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-white/50", children: "\xB7" }),
|
|
28712
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-white", children: "change" })
|
|
28713
|
-
]
|
|
29008
|
+
onClick: () => setRightPanelTab("cart"),
|
|
29009
|
+
className: `flex-1 rounded-lg px-3 py-1.5 text-sm font-semibold transition-colors ${effectiveRightPanelTab === "cart" ? "bg-white text-gray-800 shadow-sm" : "text-gray-500 hover:text-gray-700"}`,
|
|
29010
|
+
children: "Cart"
|
|
28714
29011
|
}
|
|
28715
29012
|
),
|
|
28716
|
-
|
|
29013
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
28717
29014
|
"button",
|
|
28718
29015
|
{
|
|
28719
29016
|
type: "button",
|
|
28720
|
-
onClick:
|
|
28721
|
-
|
|
28722
|
-
|
|
28723
|
-
|
|
28724
|
-
|
|
29017
|
+
onClick: () => {
|
|
29018
|
+
if (!aiEnabled) return;
|
|
29019
|
+
setRightPanelTab("ai");
|
|
29020
|
+
},
|
|
29021
|
+
disabled: !aiEnabled,
|
|
29022
|
+
"aria-disabled": !aiEnabled,
|
|
29023
|
+
title: aiEnabled ? void 0 : "Coming Soon",
|
|
29024
|
+
className: `flex-1 rounded-lg px-3 py-1.5 text-sm font-semibold transition-colors flex items-center justify-center gap-1.5 ${!aiEnabled ? "text-gray-400 cursor-not-allowed" : effectiveRightPanelTab === "ai" ? "bg-white text-gray-800 shadow-sm" : "text-gray-500 hover:text-gray-700"}`,
|
|
29025
|
+
children: [
|
|
29026
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "w-3.5 h-3.5" }),
|
|
29027
|
+
"AI Chat",
|
|
29028
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full bg-primary px-1.5 py-0.5 text-[8px] font-bold uppercase tracking-wider text-white shadow-sm whitespace-nowrap", children: aiEnabled ? "Beta" : "Soon" })
|
|
29029
|
+
]
|
|
28725
29030
|
}
|
|
28726
|
-
)
|
|
28727
|
-
|
|
28728
|
-
|
|
29031
|
+
)
|
|
29032
|
+
] }),
|
|
29033
|
+
effectiveRightPanelTab === "cart" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
29034
|
+
ActiveSessionPanel,
|
|
29035
|
+
{
|
|
29036
|
+
session: mealSessions[activeSessionIndex],
|
|
29037
|
+
sessionIndex: activeSessionIndex,
|
|
29038
|
+
sessionTotal: getSessionTotal(activeSessionIndex),
|
|
29039
|
+
sessionPromotions: getSessionDiscount(activeSessionIndex).promotions,
|
|
29040
|
+
validationError: sessionValidationErrors[activeSessionIndex] || null,
|
|
29041
|
+
isUnscheduled: !mealSessions[activeSessionIndex].sessionDate,
|
|
29042
|
+
canRemove: true,
|
|
29043
|
+
onEditSession: () => setEditingSessionIndex(activeSessionIndex),
|
|
29044
|
+
onRemoveSession: (e) => handleRemoveSession(activeSessionIndex, e),
|
|
29045
|
+
onEditItem: handleEditItem,
|
|
29046
|
+
onRemoveItem: handleRemoveItem,
|
|
29047
|
+
onSwapItem: handleSwapItem,
|
|
29048
|
+
onRemoveBundle: handleRemoveBundle,
|
|
29049
|
+
collapsedCategories,
|
|
29050
|
+
onToggleCategory: handleToggleCategory,
|
|
29051
|
+
onViewMenu: handleViewMenu,
|
|
29052
|
+
isCurrentSessionValid,
|
|
29053
|
+
totalPrice: getTotalPrice(),
|
|
29054
|
+
onCheckout: handleCheckout,
|
|
29055
|
+
showCheckoutButton: false,
|
|
29056
|
+
restaurants
|
|
29057
|
+
}
|
|
29058
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(AIChat, {}),
|
|
29059
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex-shrink-0 flex flex-col gap-1.5", children: effectiveRightPanelTab === "ai" ? /* @__PURE__ */ jsxRuntime.jsx(AISuggestionsBottomButton, {}) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
29060
|
+
totalItems > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 pb-1 border-t border-base-300 pt-3", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
29061
|
+
PricingSummary,
|
|
28729
29062
|
{
|
|
28730
|
-
|
|
28731
|
-
|
|
28732
|
-
|
|
28733
|
-
|
|
28734
|
-
|
|
28735
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28736
|
-
TextBubble,
|
|
28737
|
-
{
|
|
28738
|
-
sender: "bot",
|
|
28739
|
-
text: "What is the code to use the AI chat and test our beta version?"
|
|
28740
|
-
}
|
|
28741
|
-
),
|
|
28742
|
-
mobileGateError && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "text-xs text-red-600", children: mobileGateError })
|
|
28743
|
-
] }) : mobileChatView === "results" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
28744
|
-
MobileResultsView,
|
|
28745
|
-
{
|
|
28746
|
-
onBack: () => setMobileChatView("chat")
|
|
28747
|
-
}
|
|
28748
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
28749
|
-
MobileChatThread,
|
|
28750
|
-
{
|
|
28751
|
-
hasAddressTopPill: hasChatAddress && aiBetaUnlocked
|
|
28752
|
-
}
|
|
28753
|
-
)
|
|
29063
|
+
pricing,
|
|
29064
|
+
calculatingPricing,
|
|
29065
|
+
compact: true,
|
|
29066
|
+
onPlaceSelect: handleDeliveryPlaceSelect,
|
|
29067
|
+
onClearAddress: handleClearDeliveryAddress
|
|
28754
29068
|
}
|
|
28755
|
-
),
|
|
28756
|
-
|
|
28757
|
-
|
|
28758
|
-
},
|
|
28759
|
-
"chat-surface"
|
|
28760
|
-
) }) })
|
|
28761
|
-
]
|
|
28762
|
-
}
|
|
28763
|
-
),
|
|
28764
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
28765
|
-
"div",
|
|
28766
|
-
{
|
|
28767
|
-
className: `fixed left-0 right-0 md:hidden z-50 ${mobileAddressEditorOpen || keyboardOffset > 100 && !isMobileAIChatOpen && !isMobileSearchActive ? "hidden" : ""}`,
|
|
28768
|
-
style: { bottom: keyboardOffset },
|
|
28769
|
-
"aria-hidden": mobileAddressEditorOpen,
|
|
28770
|
-
children: [
|
|
28771
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28772
|
-
"div",
|
|
28773
|
-
{
|
|
28774
|
-
ref: mobileBarRowRef,
|
|
28775
|
-
className: "relative px-3 pt-1 pb-2",
|
|
28776
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-end gap-2", children: [
|
|
28777
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
28778
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28779
|
-
"button",
|
|
28780
|
-
{
|
|
28781
|
-
onMouseDown: (e) => {
|
|
28782
|
-
if (chatInputFocused) e.preventDefault();
|
|
28783
|
-
},
|
|
28784
|
-
onClick: isMobileAIChatOpen ? chatInputFocused ? () => mobileAIInputRef.current?.blur() : () => setIsMobileChatMenuOpen((v) => !v) : () => setIsMobileCartMenuOpen((v) => !v),
|
|
28785
|
-
className: "flex h-11 w-11 items-center justify-center rounded-full border border-base-200 bg-white/70 text-gray-700 shadow-sm backdrop-blur-sm transition-colors hover:bg-white",
|
|
28786
|
-
title: isMobileAIChatOpen ? chatInputFocused ? "Hide keyboard" : "Chat actions" : "More actions",
|
|
28787
|
-
"aria-label": isMobileAIChatOpen ? chatInputFocused ? "Hide keyboard" : "Chat actions" : "More actions",
|
|
28788
|
-
children: isMobileAIChatOpen && chatInputFocused ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontal, { className: "h-4 w-4" })
|
|
28789
|
-
}
|
|
28790
|
-
),
|
|
28791
|
-
isMobileAIChatOpen && isMobileChatMenuOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
28792
|
-
MobileChatActionsMenu,
|
|
28793
|
-
{
|
|
28794
|
-
onClose: () => setIsMobileChatMenuOpen(false)
|
|
28795
|
-
}
|
|
28796
|
-
),
|
|
28797
|
-
isMobileCartMenuOpen && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
29069
|
+
) }),
|
|
29070
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-stretch gap-2", children: [
|
|
29071
|
+
mealSessions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-shrink-0", children: [
|
|
28798
29072
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28799
|
-
"
|
|
29073
|
+
"button",
|
|
28800
29074
|
{
|
|
28801
|
-
|
|
28802
|
-
onClick: () =>
|
|
29075
|
+
ref: desktopMenuBtnRef,
|
|
29076
|
+
onClick: () => {
|
|
29077
|
+
if (!isDesktopCartMenuOpen && desktopMenuBtnRef.current) {
|
|
29078
|
+
const rect = desktopMenuBtnRef.current.getBoundingClientRect();
|
|
29079
|
+
setDesktopMenuPos({
|
|
29080
|
+
bottom: window.innerHeight - rect.top + 8,
|
|
29081
|
+
left: rect.left
|
|
29082
|
+
});
|
|
29083
|
+
}
|
|
29084
|
+
setIsDesktopCartMenuOpen((v) => !v);
|
|
29085
|
+
},
|
|
29086
|
+
className: "flex h-full items-center justify-center rounded-lg border border-base-300 px-3 text-base-content/60 transition-colors hover:bg-base-200",
|
|
29087
|
+
title: "More options",
|
|
29088
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontal, { className: "h-4 w-4" })
|
|
28803
29089
|
}
|
|
28804
29090
|
),
|
|
28805
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
28806
|
-
/* @__PURE__ */ jsxRuntime.
|
|
28807
|
-
"
|
|
29091
|
+
isDesktopCartMenuOpen && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
29092
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29093
|
+
"div",
|
|
28808
29094
|
{
|
|
28809
|
-
|
|
28810
|
-
|
|
28811
|
-
handleViewMenu();
|
|
28812
|
-
},
|
|
28813
|
-
disabled: generatingPdf || totalItems === 0,
|
|
28814
|
-
className: "flex w-full items-center gap-2 px-3 py-2.5 text-left text-sm text-gray-700 transition-colors hover:bg-base-100 disabled:cursor-not-allowed disabled:opacity-50",
|
|
28815
|
-
children: [
|
|
28816
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28817
|
-
"svg",
|
|
28818
|
-
{
|
|
28819
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
28820
|
-
className: "h-4 w-4",
|
|
28821
|
-
fill: "none",
|
|
28822
|
-
viewBox: "0 0 24 24",
|
|
28823
|
-
stroke: "currentColor",
|
|
28824
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
28825
|
-
"path",
|
|
28826
|
-
{
|
|
28827
|
-
strokeLinecap: "round",
|
|
28828
|
-
strokeLinejoin: "round",
|
|
28829
|
-
strokeWidth: 2,
|
|
28830
|
-
d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
|
|
28831
|
-
}
|
|
28832
|
-
)
|
|
28833
|
-
}
|
|
28834
|
-
),
|
|
28835
|
-
"Download Menu"
|
|
28836
|
-
]
|
|
29095
|
+
className: "fixed inset-0 z-40",
|
|
29096
|
+
onClick: () => setIsDesktopCartMenuOpen(false)
|
|
28837
29097
|
}
|
|
28838
29098
|
),
|
|
28839
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-3 border-t border-base-200" }),
|
|
28840
29099
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
28841
|
-
"
|
|
29100
|
+
"div",
|
|
28842
29101
|
{
|
|
28843
|
-
|
|
28844
|
-
|
|
28845
|
-
|
|
29102
|
+
className: "fixed z-50 w-44 overflow-hidden rounded-xl border border-base-200 bg-white shadow-lg",
|
|
29103
|
+
style: {
|
|
29104
|
+
bottom: desktopMenuPos.bottom,
|
|
29105
|
+
left: desktopMenuPos.left
|
|
28846
29106
|
},
|
|
28847
|
-
className: "flex w-full items-center gap-2 px-3 py-2.5 text-left text-sm text-red-600 transition-colors hover:bg-red-50",
|
|
28848
29107
|
children: [
|
|
28849
|
-
/* @__PURE__ */ jsxRuntime.
|
|
28850
|
-
|
|
29108
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
29109
|
+
"button",
|
|
29110
|
+
{
|
|
29111
|
+
onClick: () => {
|
|
29112
|
+
setIsDesktopCartMenuOpen(false);
|
|
29113
|
+
handleViewMenu();
|
|
29114
|
+
},
|
|
29115
|
+
disabled: generatingPdf || totalItems === 0,
|
|
29116
|
+
className: "flex w-full items-center gap-2 px-3 py-2.5 text-left text-sm text-gray-700 transition-colors hover:bg-base-100 disabled:cursor-not-allowed disabled:opacity-50",
|
|
29117
|
+
children: [
|
|
29118
|
+
generatingPdf ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "loading loading-spinner loading-xs" }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
29119
|
+
"svg",
|
|
29120
|
+
{
|
|
29121
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
29122
|
+
className: "h-4 w-4",
|
|
29123
|
+
fill: "none",
|
|
29124
|
+
viewBox: "0 0 24 24",
|
|
29125
|
+
stroke: "currentColor",
|
|
29126
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
29127
|
+
"path",
|
|
29128
|
+
{
|
|
29129
|
+
strokeLinecap: "round",
|
|
29130
|
+
strokeLinejoin: "round",
|
|
29131
|
+
strokeWidth: 2,
|
|
29132
|
+
d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
|
|
29133
|
+
}
|
|
29134
|
+
)
|
|
29135
|
+
}
|
|
29136
|
+
),
|
|
29137
|
+
"Download Menu"
|
|
29138
|
+
]
|
|
29139
|
+
}
|
|
29140
|
+
),
|
|
29141
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
29142
|
+
"button",
|
|
29143
|
+
{
|
|
29144
|
+
onClick: () => {
|
|
29145
|
+
setIsDesktopCartMenuOpen(false);
|
|
29146
|
+
setIsClearAllConfirmOpen(true);
|
|
29147
|
+
},
|
|
29148
|
+
className: "flex w-full items-center gap-2 border-t border-base-200 px-3 py-2.5 text-left text-sm text-red-600 transition-colors hover:bg-red-50",
|
|
29149
|
+
children: [
|
|
29150
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-4 w-4" }),
|
|
29151
|
+
"Clear Cart"
|
|
29152
|
+
]
|
|
29153
|
+
}
|
|
29154
|
+
)
|
|
28851
29155
|
]
|
|
28852
29156
|
}
|
|
28853
29157
|
)
|
|
28854
29158
|
] })
|
|
28855
|
-
] })
|
|
28856
|
-
|
|
28857
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative min-w-0 flex-1 overflow-hidden rounded-3xl border border-base-200 bg-white/70 shadow-sm backdrop-blur-sm focus-within:border-primary", children: [
|
|
28858
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
29159
|
+
] }),
|
|
29160
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28859
29161
|
"button",
|
|
29162
|
+
{
|
|
29163
|
+
onClick: handleCheckout,
|
|
29164
|
+
disabled: totalItems === 0,
|
|
29165
|
+
className: `flex flex-1 items-center justify-center rounded-lg px-3 py-3 text-sm font-semibold text-white transition-colors disabled:cursor-not-allowed disabled:opacity-50 ${isCurrentSessionValid ? "bg-primary hover:bg-primary/90" : "bg-warning hover:bg-warning/90"}`,
|
|
29166
|
+
children: totalItems === 0 ? "Cart Empty" : isCurrentSessionValid ? "Checkout" : "Min. Order Not Met"
|
|
29167
|
+
}
|
|
29168
|
+
)
|
|
29169
|
+
] })
|
|
29170
|
+
] }) })
|
|
29171
|
+
] })
|
|
29172
|
+
}
|
|
29173
|
+
)
|
|
29174
|
+
] }),
|
|
29175
|
+
isMobileAIChatOpen && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29176
|
+
"div",
|
|
29177
|
+
{
|
|
29178
|
+
className: "fixed left-0 right-0 z-40 md:hidden swift-chat-design",
|
|
29179
|
+
style: {
|
|
29180
|
+
top: vvOffsetTop,
|
|
29181
|
+
height: vvHeight ?? "100vh"
|
|
29182
|
+
},
|
|
29183
|
+
children: [
|
|
29184
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29185
|
+
"div",
|
|
29186
|
+
{
|
|
29187
|
+
className: "absolute inset-0 bg-white",
|
|
29188
|
+
"aria-hidden": "true"
|
|
29189
|
+
}
|
|
29190
|
+
),
|
|
29191
|
+
/* @__PURE__ */ jsxRuntime.jsx(react$1.LayoutGroup, { children: /* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { initial: false, mode: "popLayout", children: mobileAddressEditorOpen ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
29192
|
+
MobileAddressPickerSurface,
|
|
29193
|
+
{
|
|
29194
|
+
hasAddress: hasChatAddress,
|
|
29195
|
+
initialQuery: mobileAddressPillEditing ? contactInfo?.addressLine1 ?? "" : "",
|
|
29196
|
+
onPlaceSelect: handleMobileAddressPick,
|
|
29197
|
+
onBack: () => setMobileAddressPillEditing(false),
|
|
29198
|
+
onRemove: handleMobileAddressClear,
|
|
29199
|
+
onClose: closeMobileAIChat
|
|
29200
|
+
},
|
|
29201
|
+
"address-picker"
|
|
29202
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29203
|
+
react$1.motion.div,
|
|
29204
|
+
{
|
|
29205
|
+
initial: { opacity: 0 },
|
|
29206
|
+
animate: { opacity: 1 },
|
|
29207
|
+
exit: { opacity: 0 },
|
|
29208
|
+
transition: { duration: 0.18, ease: "easeOut" },
|
|
29209
|
+
className: "absolute inset-0",
|
|
29210
|
+
children: [
|
|
29211
|
+
aiBetaUnlocked && hasChatAddress && mobileChatView === "chat" && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29212
|
+
react$1.motion.button,
|
|
28860
29213
|
{
|
|
28861
29214
|
type: "button",
|
|
28862
|
-
|
|
28863
|
-
|
|
28864
|
-
|
|
28865
|
-
|
|
28866
|
-
setIsAIMobileUnavailableOpen(true);
|
|
28867
|
-
}
|
|
28868
|
-
},
|
|
28869
|
-
title: aiEnabled ? void 0 : "Coming Soon",
|
|
28870
|
-
className: `absolute inset-0 flex items-center justify-center gap-1.5 px-4 py-1 transition duration-[250ms] ease-out ${isMobileSearchOpen || isMobileAIChatOpen ? "pointer-events-none -translate-y-full opacity-0" : "translate-y-0 opacity-100"}`,
|
|
28871
|
-
"aria-hidden": isMobileSearchOpen || isMobileAIChatOpen,
|
|
28872
|
-
tabIndex: isMobileSearchOpen || isMobileAIChatOpen ? -1 : 0,
|
|
29215
|
+
layoutId: "catering-address-pill",
|
|
29216
|
+
transition: { duration: 0.28, ease: "easeOut" },
|
|
29217
|
+
onClick: () => setMobileAddressPillEditing(true),
|
|
29218
|
+
className: "absolute top-3 left-3 z-10 inline-flex max-w-[60%] items-center gap-1.5 rounded-xl bg-black/60 backdrop-blur-sm px-3 py-2 text-xs text-white",
|
|
28873
29219
|
children: [
|
|
28874
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28875
|
-
|
|
28876
|
-
|
|
29220
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29221
|
+
lucideReact.MapPin,
|
|
29222
|
+
{
|
|
29223
|
+
className: "h-3.5 w-3.5 flex-shrink-0 text-white/80",
|
|
29224
|
+
"aria-hidden": true
|
|
29225
|
+
}
|
|
29226
|
+
),
|
|
29227
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: contactInfo?.addressLine1 }),
|
|
29228
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-white/50", children: "\xB7" }),
|
|
29229
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-white", children: "change" })
|
|
28877
29230
|
]
|
|
28878
29231
|
}
|
|
28879
29232
|
),
|
|
28880
|
-
/* @__PURE__ */ jsxRuntime.
|
|
29233
|
+
mobileChatView === "chat" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29234
|
+
"button",
|
|
29235
|
+
{
|
|
29236
|
+
type: "button",
|
|
29237
|
+
onClick: closeMobileAIChat,
|
|
29238
|
+
className: "absolute top-3 right-3 z-10 flex h-9 w-9 items-center justify-center rounded-full bg-black/60 backdrop-blur-sm text-white",
|
|
29239
|
+
title: "Close AI chat",
|
|
29240
|
+
"aria-label": "Close AI chat",
|
|
29241
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" })
|
|
29242
|
+
}
|
|
29243
|
+
),
|
|
29244
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28881
29245
|
"div",
|
|
28882
29246
|
{
|
|
28883
|
-
|
|
28884
|
-
"
|
|
28885
|
-
|
|
28886
|
-
|
|
29247
|
+
ref: mobileChatScrollRef,
|
|
29248
|
+
"data-allow-touch": true,
|
|
29249
|
+
className: "absolute inset-x-0 top-0 overflow-y-auto overscroll-contain",
|
|
29250
|
+
style: { bottom: 64 },
|
|
29251
|
+
children: !aiBetaUnlocked ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 pt-14 pb-4 flex flex-col gap-3", children: [
|
|
28887
29252
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28888
|
-
|
|
29253
|
+
TextBubble,
|
|
29254
|
+
{
|
|
29255
|
+
sender: "bot",
|
|
29256
|
+
text: "What is the code to use the AI chat and test our beta version?"
|
|
29257
|
+
}
|
|
29258
|
+
),
|
|
29259
|
+
mobileGateError && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "text-xs text-red-600", children: mobileGateError })
|
|
29260
|
+
] }) : mobileChatView === "results" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
29261
|
+
MobileResultsView,
|
|
29262
|
+
{
|
|
29263
|
+
onBack: () => setMobileChatView("chat")
|
|
29264
|
+
}
|
|
29265
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
29266
|
+
MobileChatThread,
|
|
29267
|
+
{
|
|
29268
|
+
hasAddressTopPill: hasChatAddress && aiBetaUnlocked
|
|
29269
|
+
}
|
|
29270
|
+
)
|
|
29271
|
+
}
|
|
29272
|
+
),
|
|
29273
|
+
aiBetaUnlocked && mobileChatView === "chat" && /* @__PURE__ */ jsxRuntime.jsx(MobileChatFloatingChips, { bottomOffset: 64 + 8, inputRef: mobileAIInputRef })
|
|
29274
|
+
]
|
|
29275
|
+
},
|
|
29276
|
+
"chat-surface"
|
|
29277
|
+
) }) })
|
|
29278
|
+
]
|
|
29279
|
+
}
|
|
29280
|
+
),
|
|
29281
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
29282
|
+
"div",
|
|
29283
|
+
{
|
|
29284
|
+
className: `fixed left-0 right-0 md:hidden z-50 ${mobileAddressEditorOpen || keyboardOffset > 100 && !isMobileAIChatOpen && !isMobileSearchActive ? "hidden" : ""}`,
|
|
29285
|
+
style: { bottom: keyboardOffset },
|
|
29286
|
+
"aria-hidden": mobileAddressEditorOpen,
|
|
29287
|
+
children: [
|
|
29288
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29289
|
+
"div",
|
|
29290
|
+
{
|
|
29291
|
+
ref: mobileBarRowRef,
|
|
29292
|
+
className: "relative px-3 pt-1 pb-2",
|
|
29293
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-end gap-2", children: [
|
|
29294
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
29295
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29296
|
+
"button",
|
|
29297
|
+
{
|
|
29298
|
+
onMouseDown: (e) => {
|
|
29299
|
+
if (chatInputFocused) e.preventDefault();
|
|
29300
|
+
},
|
|
29301
|
+
onClick: isMobileAIChatOpen ? chatInputFocused ? () => mobileAIInputRef.current?.blur() : () => setIsMobileChatMenuOpen((v) => !v) : () => setIsMobileCartMenuOpen((v) => !v),
|
|
29302
|
+
className: "flex h-11 w-11 items-center justify-center rounded-full border border-base-200 bg-white/70 text-gray-700 shadow-sm backdrop-blur-sm transition-colors hover:bg-white",
|
|
29303
|
+
title: isMobileAIChatOpen ? chatInputFocused ? "Hide keyboard" : "Chat actions" : "More actions",
|
|
29304
|
+
"aria-label": isMobileAIChatOpen ? chatInputFocused ? "Hide keyboard" : "Chat actions" : "More actions",
|
|
29305
|
+
children: isMobileAIChatOpen && chatInputFocused ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreHorizontal, { className: "h-4 w-4" })
|
|
29306
|
+
}
|
|
29307
|
+
),
|
|
29308
|
+
isMobileAIChatOpen && isMobileChatMenuOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29309
|
+
MobileChatActionsMenu,
|
|
29310
|
+
{
|
|
29311
|
+
onClose: () => setIsMobileChatMenuOpen(false)
|
|
29312
|
+
}
|
|
29313
|
+
),
|
|
29314
|
+
isMobileCartMenuOpen && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
29315
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29316
|
+
"div",
|
|
29317
|
+
{
|
|
29318
|
+
className: "fixed inset-0 z-40",
|
|
29319
|
+
onClick: () => setIsMobileCartMenuOpen(false)
|
|
29320
|
+
}
|
|
29321
|
+
),
|
|
29322
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute bottom-full left-0 z-50 mb-2 w-44 overflow-hidden rounded-xl border border-base-200 bg-white shadow-lg", children: [
|
|
29323
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
29324
|
+
"button",
|
|
29325
|
+
{
|
|
29326
|
+
onClick: () => {
|
|
29327
|
+
setIsMobileCartMenuOpen(false);
|
|
29328
|
+
handleViewMenu();
|
|
29329
|
+
},
|
|
29330
|
+
disabled: generatingPdf || totalItems === 0,
|
|
29331
|
+
className: "flex w-full items-center gap-2 px-3 py-2.5 text-left text-sm text-gray-700 transition-colors hover:bg-base-100 disabled:cursor-not-allowed disabled:opacity-50",
|
|
29332
|
+
children: [
|
|
29333
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29334
|
+
"svg",
|
|
29335
|
+
{
|
|
29336
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
29337
|
+
className: "h-4 w-4",
|
|
29338
|
+
fill: "none",
|
|
29339
|
+
viewBox: "0 0 24 24",
|
|
29340
|
+
stroke: "currentColor",
|
|
29341
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
29342
|
+
"path",
|
|
29343
|
+
{
|
|
29344
|
+
strokeLinecap: "round",
|
|
29345
|
+
strokeLinejoin: "round",
|
|
29346
|
+
strokeWidth: 2,
|
|
29347
|
+
d: "M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"
|
|
29348
|
+
}
|
|
29349
|
+
)
|
|
29350
|
+
}
|
|
29351
|
+
),
|
|
29352
|
+
"Download Menu"
|
|
29353
|
+
]
|
|
29354
|
+
}
|
|
29355
|
+
),
|
|
29356
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-3 border-t border-base-200" }),
|
|
29357
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
29358
|
+
"button",
|
|
29359
|
+
{
|
|
29360
|
+
onClick: () => {
|
|
29361
|
+
setIsMobileCartMenuOpen(false);
|
|
29362
|
+
setIsClearAllConfirmOpen(true);
|
|
29363
|
+
},
|
|
29364
|
+
className: "flex w-full items-center gap-2 px-3 py-2.5 text-left text-sm text-red-600 transition-colors hover:bg-red-50",
|
|
29365
|
+
children: [
|
|
29366
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-4 w-4" }),
|
|
29367
|
+
"Clear Cart"
|
|
29368
|
+
]
|
|
29369
|
+
}
|
|
29370
|
+
)
|
|
29371
|
+
] })
|
|
29372
|
+
] })
|
|
29373
|
+
] }),
|
|
29374
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative min-w-0 flex-1 overflow-hidden rounded-3xl border border-base-200 bg-white/70 shadow-sm backdrop-blur-sm focus-within:border-primary", children: [
|
|
29375
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
29376
|
+
"button",
|
|
29377
|
+
{
|
|
29378
|
+
type: "button",
|
|
29379
|
+
onClick: () => {
|
|
29380
|
+
if (aiEnabled) {
|
|
29381
|
+
setIsMobileAIChatOpen(true);
|
|
29382
|
+
} else {
|
|
29383
|
+
setIsAIMobileUnavailableOpen(true);
|
|
29384
|
+
}
|
|
29385
|
+
},
|
|
29386
|
+
title: aiEnabled ? void 0 : "Coming Soon",
|
|
29387
|
+
className: `absolute inset-0 flex items-center justify-center gap-1.5 px-4 py-1 transition duration-[250ms] ease-out ${isMobileSearchOpen || isMobileAIChatOpen ? "pointer-events-none -translate-y-full opacity-0" : "translate-y-0 opacity-100"}`,
|
|
29388
|
+
"aria-hidden": isMobileSearchOpen || isMobileAIChatOpen,
|
|
29389
|
+
tabIndex: isMobileSearchOpen || isMobileAIChatOpen ? -1 : 0,
|
|
29390
|
+
children: [
|
|
29391
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: `h-4 w-4 ${aiEnabled ? "text-primary" : "text-gray-400"}` }),
|
|
29392
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-sm font-semibold ${aiEnabled ? "text-gray-800" : "text-gray-400"}`, children: "Ask AI" }),
|
|
29393
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 rounded-full bg-primary px-1.5 py-0.5 text-[8px] font-bold uppercase tracking-wider text-white shadow-sm whitespace-nowrap", children: aiEnabled ? "Beta" : "Soon" })
|
|
29394
|
+
]
|
|
29395
|
+
}
|
|
29396
|
+
),
|
|
29397
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
29398
|
+
"div",
|
|
29399
|
+
{
|
|
29400
|
+
className: `absolute inset-0 transition duration-300 ease-out ${isMobileSearchOpen ? "translate-y-0 opacity-100" : "pointer-events-none translate-y-full opacity-0"}`,
|
|
29401
|
+
"aria-hidden": !isMobileSearchOpen,
|
|
29402
|
+
children: [
|
|
29403
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "pointer-events-none absolute left-3 top-1/2 z-10 h-4 w-4 -translate-y-1/2 text-gray-400" }),
|
|
29404
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29405
|
+
"input",
|
|
29406
|
+
{
|
|
29407
|
+
ref: mobileSearchInputRef,
|
|
29408
|
+
type: "search",
|
|
29409
|
+
value: mobileSearchState.query,
|
|
29410
|
+
onChange: (e) => handleMobileSearchInputChange(e.target.value),
|
|
29411
|
+
placeholder: "Search Swift Food",
|
|
29412
|
+
tabIndex: isMobileSearchOpen ? 0 : -1,
|
|
29413
|
+
autoComplete: "off",
|
|
29414
|
+
autoCorrect: "off",
|
|
29415
|
+
autoCapitalize: "off",
|
|
29416
|
+
spellCheck: false,
|
|
29417
|
+
className: `h-full w-full rounded-full bg-transparent pl-9 pr-3 text-base placeholder:text-xs focus:outline-none touch-auto ${mobileSearchCaretVisible ? "" : "caret-transparent"}`
|
|
29418
|
+
}
|
|
29419
|
+
)
|
|
29420
|
+
]
|
|
29421
|
+
}
|
|
29422
|
+
),
|
|
29423
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29424
|
+
"div",
|
|
29425
|
+
{
|
|
29426
|
+
className: `relative w-full transition duration-[250ms] ease-out ${isMobileAIChatOpen ? "translate-y-0 opacity-100" : "pointer-events-none translate-y-full opacity-0"}`,
|
|
29427
|
+
style: {
|
|
29428
|
+
height: isMobileAIChatOpen ? mobileAIInputHeight : 44
|
|
29429
|
+
},
|
|
29430
|
+
"aria-hidden": !isMobileAIChatOpen,
|
|
29431
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
29432
|
+
MobileAIInput,
|
|
28889
29433
|
{
|
|
28890
|
-
|
|
28891
|
-
|
|
28892
|
-
|
|
28893
|
-
|
|
28894
|
-
|
|
28895
|
-
|
|
28896
|
-
|
|
28897
|
-
|
|
28898
|
-
|
|
28899
|
-
|
|
28900
|
-
|
|
29434
|
+
inputRef: mobileAIInputRef,
|
|
29435
|
+
value: mobileAIInput,
|
|
29436
|
+
onChange: (v) => {
|
|
29437
|
+
setMobileAIInput(v);
|
|
29438
|
+
if (mobileGateError) setMobileGateError(null);
|
|
29439
|
+
},
|
|
29440
|
+
onInputResize: handleMobileAIInput,
|
|
29441
|
+
onResetHeight: resetMobileAIInputHeight,
|
|
29442
|
+
tabbable: isMobileAIChatOpen,
|
|
29443
|
+
isOpen: isMobileAIChatOpen,
|
|
29444
|
+
onFocus: () => {
|
|
29445
|
+
setMobileChatView("chat");
|
|
29446
|
+
setChatInputFocused(true);
|
|
29447
|
+
},
|
|
29448
|
+
onBlur: () => setChatInputFocused(false),
|
|
29449
|
+
gateMode: !aiBetaUnlocked,
|
|
29450
|
+
onGateSubmit: handleMobileGateSubmit,
|
|
29451
|
+
buildAddress: buildChatAddress
|
|
28901
29452
|
}
|
|
28902
29453
|
)
|
|
28903
|
-
|
|
28904
|
-
|
|
28905
|
-
),
|
|
29454
|
+
}
|
|
29455
|
+
)
|
|
29456
|
+
] }),
|
|
28906
29457
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28907
|
-
"
|
|
29458
|
+
"button",
|
|
28908
29459
|
{
|
|
28909
|
-
|
|
28910
|
-
|
|
28911
|
-
|
|
28912
|
-
|
|
28913
|
-
"aria-hidden":
|
|
28914
|
-
|
|
28915
|
-
|
|
28916
|
-
|
|
28917
|
-
inputRef: mobileAIInputRef,
|
|
28918
|
-
value: mobileAIInput,
|
|
28919
|
-
onChange: (v) => {
|
|
28920
|
-
setMobileAIInput(v);
|
|
28921
|
-
if (mobileGateError) setMobileGateError(null);
|
|
28922
|
-
},
|
|
28923
|
-
onInputResize: handleMobileAIInput,
|
|
28924
|
-
onResetHeight: resetMobileAIInputHeight,
|
|
28925
|
-
tabbable: isMobileAIChatOpen,
|
|
28926
|
-
isOpen: isMobileAIChatOpen,
|
|
28927
|
-
onFocus: () => {
|
|
28928
|
-
setMobileChatView("chat");
|
|
28929
|
-
setChatInputFocused(true);
|
|
28930
|
-
},
|
|
28931
|
-
onBlur: () => setChatInputFocused(false),
|
|
28932
|
-
gateMode: !aiBetaUnlocked,
|
|
28933
|
-
onGateSubmit: handleMobileGateSubmit,
|
|
28934
|
-
buildAddress: buildChatAddress
|
|
28935
|
-
}
|
|
28936
|
-
)
|
|
29460
|
+
onClick: isMobileSearchOpen ? closeMobileSearch : openMobileSearch,
|
|
29461
|
+
className: `flex h-11 flex-shrink-0 items-center justify-center rounded-full border bg-white/70 text-gray-700 backdrop-blur-sm transition-all duration-[250ms] ease-out hover:bg-white ${isMobileAIChatOpen ? "pointer-events-none w-0 -ml-2 border-transparent bg-transparent opacity-0 shadow-none" : "w-11 border-base-200 opacity-100 shadow-sm"}`,
|
|
29462
|
+
title: isMobileSearchOpen ? "Close search" : "Search",
|
|
29463
|
+
"aria-label": isMobileSearchOpen ? "Close search" : "Open search",
|
|
29464
|
+
"aria-hidden": isMobileAIChatOpen,
|
|
29465
|
+
tabIndex: isMobileAIChatOpen ? -1 : 0,
|
|
29466
|
+
type: "button",
|
|
29467
|
+
children: isMobileSearchOpen ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4" })
|
|
28937
29468
|
}
|
|
28938
29469
|
)
|
|
28939
|
-
] })
|
|
28940
|
-
|
|
28941
|
-
|
|
28942
|
-
|
|
28943
|
-
|
|
28944
|
-
|
|
28945
|
-
|
|
28946
|
-
|
|
28947
|
-
|
|
28948
|
-
|
|
28949
|
-
|
|
28950
|
-
|
|
28951
|
-
}
|
|
28952
|
-
|
|
28953
|
-
|
|
29470
|
+
] })
|
|
29471
|
+
}
|
|
29472
|
+
),
|
|
29473
|
+
mealSessions.some((s) => s.orderItems.length > 0) && !isMobileAIChatOpen && !isMobileSearchOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 bg-primary", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29474
|
+
"button",
|
|
29475
|
+
{
|
|
29476
|
+
onClick: () => setIsViewOrderOpen(true),
|
|
29477
|
+
className: "w-full flex items-center justify-between text-white",
|
|
29478
|
+
children: [
|
|
29479
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
29480
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ShoppingBag, { className: "w-5 h-5" }),
|
|
29481
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: "View Order" })
|
|
29482
|
+
] }),
|
|
29483
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
29484
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-lg font-bold", children: [
|
|
29485
|
+
"\xA3",
|
|
29486
|
+
getTotalPrice().toFixed(2)
|
|
29487
|
+
] }),
|
|
29488
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm opacity-80", children: [
|
|
29489
|
+
totalItems,
|
|
29490
|
+
" items"
|
|
29491
|
+
] })
|
|
29492
|
+
] })
|
|
29493
|
+
]
|
|
29494
|
+
}
|
|
29495
|
+
) })
|
|
29496
|
+
]
|
|
29497
|
+
}
|
|
29498
|
+
),
|
|
29499
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29500
|
+
ViewOrderModal,
|
|
29501
|
+
{
|
|
29502
|
+
isOpen: isViewOrderOpen,
|
|
29503
|
+
onClose: () => setIsViewOrderOpen(false),
|
|
29504
|
+
mealSessions,
|
|
29505
|
+
activeSessionIndex,
|
|
29506
|
+
onSessionChange: setActiveSessionIndex,
|
|
29507
|
+
getSessionTotal,
|
|
29508
|
+
getSessionDiscount,
|
|
29509
|
+
validationErrors: sessionValidationErrors,
|
|
29510
|
+
onEditSession: (index) => {
|
|
29511
|
+
setIsViewOrderOpen(false);
|
|
29512
|
+
setEditingSessionIndex(index);
|
|
29513
|
+
},
|
|
29514
|
+
onRemoveSession: (index, e) => handleRemoveSession(index, e),
|
|
29515
|
+
onEditItem: handleEditItem,
|
|
29516
|
+
onRemoveItem: handleRemoveItem,
|
|
29517
|
+
onSwapItem: handleSwapItem,
|
|
29518
|
+
onRemoveBundle: handleRemoveBundle,
|
|
29519
|
+
collapsedCategories,
|
|
29520
|
+
onToggleCategory: handleToggleCategory,
|
|
29521
|
+
onViewMenu: handleViewMenu,
|
|
29522
|
+
generatingPdf,
|
|
29523
|
+
isCurrentSessionValid,
|
|
29524
|
+
totalPrice: getTotalPrice(),
|
|
29525
|
+
onCheckout: handleCheckout,
|
|
29526
|
+
canRemoveSession: () => true,
|
|
29527
|
+
formatTimeDisplay,
|
|
29528
|
+
navMode,
|
|
29529
|
+
dayGroups,
|
|
29530
|
+
selectedDayDate,
|
|
29531
|
+
currentDayGroup,
|
|
29532
|
+
onDateClick: handleDateClick,
|
|
29533
|
+
onBackToDates: handleBackToDates,
|
|
29534
|
+
onAddDay: handleAddDay,
|
|
29535
|
+
onAddSessionToDay: handleAddSessionToDay,
|
|
29536
|
+
restaurants,
|
|
29537
|
+
pricing,
|
|
29538
|
+
calculatingPricing,
|
|
29539
|
+
onPlaceSelect: handleDeliveryPlaceSelect,
|
|
29540
|
+
onClearAddress: handleClearDeliveryAddress
|
|
29541
|
+
}
|
|
29542
|
+
),
|
|
29543
|
+
isEditModalOpen && editingItemIndex !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29544
|
+
MenuItemModal,
|
|
29545
|
+
{
|
|
29546
|
+
item: mealSessions[activeSessionIndex].orderItems[editingItemIndex].item,
|
|
29547
|
+
isOpen: isEditModalOpen,
|
|
29548
|
+
onClose: () => {
|
|
29549
|
+
setIsEditModalOpen(false);
|
|
29550
|
+
setEditingItemIndex(null);
|
|
29551
|
+
},
|
|
29552
|
+
quantity: mealSessions[activeSessionIndex].orderItems[editingItemIndex].quantity,
|
|
29553
|
+
isEditMode: true,
|
|
29554
|
+
editingIndex: editingItemIndex,
|
|
29555
|
+
onAddItem: handleSaveEditedItem,
|
|
29556
|
+
onRemoveItem: (index) => {
|
|
29557
|
+
removeMenuItemByIndex(activeSessionIndex, index);
|
|
29558
|
+
setIsEditModalOpen(false);
|
|
29559
|
+
setEditingItemIndex(null);
|
|
29560
|
+
}
|
|
29561
|
+
}
|
|
29562
|
+
),
|
|
29563
|
+
pendingItem && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29564
|
+
MenuItemModal,
|
|
29565
|
+
{
|
|
29566
|
+
item: pendingItem,
|
|
29567
|
+
isOpen: true,
|
|
29568
|
+
onClose: () => setPendingItem(null),
|
|
29569
|
+
quantity: 0,
|
|
29570
|
+
onAddItem: (item) => {
|
|
29571
|
+
handleAddItem(item);
|
|
29572
|
+
setPendingItem(null);
|
|
29573
|
+
}
|
|
29574
|
+
}
|
|
29575
|
+
),
|
|
29576
|
+
emptySessionIndex !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29577
|
+
EmptySessionWarningModal,
|
|
29578
|
+
{
|
|
29579
|
+
sessionName: mealSessions[emptySessionIndex]?.sessionName || "Session",
|
|
29580
|
+
onRemove: handleRemoveEmptySession,
|
|
29581
|
+
onAddItems: handleAddItemsToEmptySession
|
|
29582
|
+
}
|
|
29583
|
+
),
|
|
29584
|
+
removeItemIndex !== null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 bg-black/50 flex items-center justify-center z-[100] p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-2xl max-w-md w-full p-6 shadow-xl", children: [
|
|
29585
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
|
|
29586
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12 h-12 rounded-full bg-red-100 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-6 w-6 text-red-600" }) }),
|
|
29587
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
29588
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-bold text-gray-900", children: "Remove Item" }),
|
|
29589
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: mealSessions[activeSessionIndex]?.orderItems[removeItemIndex]?.item.menuItemName || "Item" })
|
|
29590
|
+
] })
|
|
29591
|
+
] }),
|
|
29592
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600 mb-6", children: "Are you sure you want to remove this item from your order?" }),
|
|
29593
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
29594
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29595
|
+
"button",
|
|
29596
|
+
{
|
|
29597
|
+
onClick: () => setRemoveItemIndex(null),
|
|
29598
|
+
className: "flex-1 px-4 py-3 border border-base-300 text-gray-600 rounded-xl hover:bg-base-100 transition-colors font-medium",
|
|
29599
|
+
children: "Cancel"
|
|
28954
29600
|
}
|
|
28955
29601
|
),
|
|
28956
|
-
|
|
29602
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28957
29603
|
"button",
|
|
28958
29604
|
{
|
|
28959
|
-
onClick:
|
|
28960
|
-
className: "
|
|
29605
|
+
onClick: confirmRemoveItem,
|
|
29606
|
+
className: "flex-1 px-4 py-3 bg-red-500 text-white rounded-xl hover:bg-red-600 transition-colors font-medium",
|
|
29607
|
+
children: "Remove"
|
|
29608
|
+
}
|
|
29609
|
+
)
|
|
29610
|
+
] })
|
|
29611
|
+
] }) }),
|
|
29612
|
+
sessionToRemove !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29613
|
+
RemoveSessionConfirmModal,
|
|
29614
|
+
{
|
|
29615
|
+
sessionName: mealSessions[sessionToRemove]?.sessionName || "Session",
|
|
29616
|
+
onConfirm: confirmRemoveSession,
|
|
29617
|
+
onCancel: () => setSessionToRemove(null)
|
|
29618
|
+
}
|
|
29619
|
+
),
|
|
29620
|
+
isAIMobileUnavailableOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29621
|
+
"div",
|
|
29622
|
+
{
|
|
29623
|
+
className: "fixed inset-0 z-[100] flex items-center justify-center bg-black/50 p-4",
|
|
29624
|
+
onClick: () => setIsAIMobileUnavailableOpen(false),
|
|
29625
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29626
|
+
"div",
|
|
29627
|
+
{
|
|
29628
|
+
className: "w-full max-w-md rounded-2xl bg-white p-6 shadow-xl",
|
|
29629
|
+
onClick: (e) => e.stopPropagation(),
|
|
28961
29630
|
children: [
|
|
28962
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-
|
|
28963
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.
|
|
28964
|
-
/* @__PURE__ */ jsxRuntime.
|
|
28965
|
-
|
|
28966
|
-
|
|
28967
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-lg font-bold", children: [
|
|
28968
|
-
"\xA3",
|
|
28969
|
-
getTotalPrice().toFixed(2)
|
|
28970
|
-
] }),
|
|
28971
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm opacity-80", children: [
|
|
28972
|
-
totalItems,
|
|
28973
|
-
" items"
|
|
29631
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 flex items-center gap-3", children: [
|
|
29632
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-5 w-5 text-primary" }) }),
|
|
29633
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
29634
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-bold text-gray-900", children: "Plan your menu with AI" }),
|
|
29635
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500", children: "Coming soon" })
|
|
28974
29636
|
] })
|
|
28975
|
-
] })
|
|
29637
|
+
] }),
|
|
29638
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6 space-y-2 text-sm text-gray-600", children: [
|
|
29639
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Chat with our AI to plan the perfect menu \u2014 tell it your guest count, dietary needs, and budget." }),
|
|
29640
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500", children: "We're putting the finishing touches on it. Check back soon." })
|
|
29641
|
+
] }),
|
|
29642
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
29643
|
+
"button",
|
|
29644
|
+
{
|
|
29645
|
+
onClick: () => setIsAIMobileUnavailableOpen(false),
|
|
29646
|
+
className: "flex-1 rounded-xl bg-primary px-4 py-2.5 text-sm font-medium text-white transition-colors hover:bg-primary/90",
|
|
29647
|
+
children: "Got it"
|
|
29648
|
+
}
|
|
29649
|
+
) })
|
|
28976
29650
|
]
|
|
28977
29651
|
}
|
|
28978
|
-
)
|
|
28979
|
-
]
|
|
28980
|
-
}
|
|
28981
|
-
),
|
|
28982
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28983
|
-
ViewOrderModal,
|
|
28984
|
-
{
|
|
28985
|
-
isOpen: isViewOrderOpen,
|
|
28986
|
-
onClose: () => setIsViewOrderOpen(false),
|
|
28987
|
-
mealSessions,
|
|
28988
|
-
activeSessionIndex,
|
|
28989
|
-
onSessionChange: setActiveSessionIndex,
|
|
28990
|
-
getSessionTotal,
|
|
28991
|
-
getSessionDiscount,
|
|
28992
|
-
validationErrors: sessionValidationErrors,
|
|
28993
|
-
onEditSession: (index) => {
|
|
28994
|
-
setIsViewOrderOpen(false);
|
|
28995
|
-
setEditingSessionIndex(index);
|
|
28996
|
-
},
|
|
28997
|
-
onRemoveSession: (index, e) => handleRemoveSession(index, e),
|
|
28998
|
-
onEditItem: handleEditItem,
|
|
28999
|
-
onRemoveItem: handleRemoveItem,
|
|
29000
|
-
onSwapItem: handleSwapItem,
|
|
29001
|
-
onRemoveBundle: handleRemoveBundle,
|
|
29002
|
-
collapsedCategories,
|
|
29003
|
-
onToggleCategory: handleToggleCategory,
|
|
29004
|
-
onViewMenu: handleViewMenu,
|
|
29005
|
-
generatingPdf,
|
|
29006
|
-
isCurrentSessionValid,
|
|
29007
|
-
totalPrice: getTotalPrice(),
|
|
29008
|
-
onCheckout: handleCheckout,
|
|
29009
|
-
canRemoveSession: () => true,
|
|
29010
|
-
formatTimeDisplay,
|
|
29011
|
-
navMode,
|
|
29012
|
-
dayGroups,
|
|
29013
|
-
selectedDayDate,
|
|
29014
|
-
currentDayGroup,
|
|
29015
|
-
onDateClick: handleDateClick,
|
|
29016
|
-
onBackToDates: handleBackToDates,
|
|
29017
|
-
onAddDay: handleAddDay,
|
|
29018
|
-
onAddSessionToDay: handleAddSessionToDay,
|
|
29019
|
-
restaurants,
|
|
29020
|
-
pricing,
|
|
29021
|
-
calculatingPricing,
|
|
29022
|
-
onPlaceSelect: handleDeliveryPlaceSelect,
|
|
29023
|
-
onClearAddress: handleClearDeliveryAddress
|
|
29024
|
-
}
|
|
29025
|
-
),
|
|
29026
|
-
isEditModalOpen && editingItemIndex !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29027
|
-
MenuItemModal,
|
|
29028
|
-
{
|
|
29029
|
-
item: mealSessions[activeSessionIndex].orderItems[editingItemIndex].item,
|
|
29030
|
-
isOpen: isEditModalOpen,
|
|
29031
|
-
onClose: () => {
|
|
29032
|
-
setIsEditModalOpen(false);
|
|
29033
|
-
setEditingItemIndex(null);
|
|
29034
|
-
},
|
|
29035
|
-
quantity: mealSessions[activeSessionIndex].orderItems[editingItemIndex].quantity,
|
|
29036
|
-
isEditMode: true,
|
|
29037
|
-
editingIndex: editingItemIndex,
|
|
29038
|
-
onAddItem: handleSaveEditedItem,
|
|
29039
|
-
onRemoveItem: (index) => {
|
|
29040
|
-
removeMenuItemByIndex(activeSessionIndex, index);
|
|
29041
|
-
setIsEditModalOpen(false);
|
|
29042
|
-
setEditingItemIndex(null);
|
|
29043
|
-
}
|
|
29044
|
-
}
|
|
29045
|
-
),
|
|
29046
|
-
pendingItem && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29047
|
-
MenuItemModal,
|
|
29048
|
-
{
|
|
29049
|
-
item: pendingItem,
|
|
29050
|
-
isOpen: true,
|
|
29051
|
-
onClose: () => setPendingItem(null),
|
|
29052
|
-
quantity: 0,
|
|
29053
|
-
onAddItem: (item) => {
|
|
29054
|
-
handleAddItem(item);
|
|
29055
|
-
setPendingItem(null);
|
|
29652
|
+
)
|
|
29056
29653
|
}
|
|
29057
|
-
|
|
29058
|
-
|
|
29059
|
-
|
|
29060
|
-
|
|
29061
|
-
|
|
29062
|
-
|
|
29063
|
-
|
|
29064
|
-
|
|
29065
|
-
|
|
29066
|
-
|
|
29067
|
-
|
|
29068
|
-
|
|
29069
|
-
|
|
29070
|
-
|
|
29071
|
-
|
|
29072
|
-
|
|
29073
|
-
|
|
29074
|
-
|
|
29075
|
-
|
|
29076
|
-
|
|
29077
|
-
|
|
29078
|
-
|
|
29079
|
-
|
|
29080
|
-
|
|
29081
|
-
|
|
29082
|
-
|
|
29083
|
-
}
|
|
29084
|
-
),
|
|
29085
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29086
|
-
"button",
|
|
29087
|
-
{
|
|
29088
|
-
onClick: confirmRemoveItem,
|
|
29089
|
-
className: "flex-1 px-4 py-3 bg-red-500 text-white rounded-xl hover:bg-red-600 transition-colors font-medium",
|
|
29090
|
-
children: "Remove"
|
|
29091
|
-
}
|
|
29092
|
-
)
|
|
29093
|
-
] })
|
|
29094
|
-
] }) }),
|
|
29095
|
-
sessionToRemove !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29096
|
-
RemoveSessionConfirmModal,
|
|
29097
|
-
{
|
|
29098
|
-
sessionName: mealSessions[sessionToRemove]?.sessionName || "Session",
|
|
29099
|
-
onConfirm: confirmRemoveSession,
|
|
29100
|
-
onCancel: () => setSessionToRemove(null)
|
|
29101
|
-
}
|
|
29102
|
-
),
|
|
29103
|
-
isAIMobileUnavailableOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29104
|
-
"div",
|
|
29105
|
-
{
|
|
29106
|
-
className: "fixed inset-0 z-[100] flex items-center justify-center bg-black/50 p-4",
|
|
29107
|
-
onClick: () => setIsAIMobileUnavailableOpen(false),
|
|
29108
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
29109
|
-
"div",
|
|
29110
|
-
{
|
|
29111
|
-
className: "w-full max-w-md rounded-2xl bg-white p-6 shadow-xl",
|
|
29112
|
-
onClick: (e) => e.stopPropagation(),
|
|
29113
|
-
children: [
|
|
29114
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 flex items-center gap-3", children: [
|
|
29115
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-5 w-5 text-primary" }) }),
|
|
29116
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
29117
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-bold text-gray-900", children: "Plan your menu with AI" }),
|
|
29118
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500", children: "Coming soon" })
|
|
29119
|
-
] })
|
|
29120
|
-
] }),
|
|
29121
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6 space-y-2 text-sm text-gray-600", children: [
|
|
29122
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { children: "Chat with our AI to plan the perfect menu \u2014 tell it your guest count, dietary needs, and budget." }),
|
|
29123
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500", children: "We're putting the finishing touches on it. Check back soon." })
|
|
29124
|
-
] }),
|
|
29125
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
29126
|
-
"button",
|
|
29127
|
-
{
|
|
29128
|
-
onClick: () => setIsAIMobileUnavailableOpen(false),
|
|
29129
|
-
className: "flex-1 rounded-xl bg-primary px-4 py-2.5 text-sm font-medium text-white transition-colors hover:bg-primary/90",
|
|
29130
|
-
children: "Got it"
|
|
29131
|
-
}
|
|
29132
|
-
) })
|
|
29133
|
-
]
|
|
29134
|
-
}
|
|
29135
|
-
)
|
|
29136
|
-
}
|
|
29137
|
-
),
|
|
29138
|
-
isClearAllConfirmOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-[100] flex items-center justify-center bg-black/50 p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full max-w-md rounded-2xl bg-white p-6 shadow-xl", children: [
|
|
29139
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 flex items-center gap-3", children: [
|
|
29140
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-red-100", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-6 w-6 text-red-600" }) }),
|
|
29141
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
29142
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-bold text-gray-900", children: "Clear Cart" }),
|
|
29143
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "Remove all items and sessions" })
|
|
29144
|
-
] })
|
|
29145
|
-
] }),
|
|
29146
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-6 text-gray-600", children: "This will delete every session and remove all items you've added, returning your order to a single empty session. This action cannot be undone." }),
|
|
29147
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
29148
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29149
|
-
"button",
|
|
29150
|
-
{
|
|
29151
|
-
onClick: () => setIsClearAllConfirmOpen(false),
|
|
29152
|
-
className: "flex-1 rounded-xl border border-base-300 px-4 py-3 font-medium text-gray-600 transition-colors hover:bg-base-100",
|
|
29153
|
-
children: "Cancel"
|
|
29154
|
-
}
|
|
29155
|
-
),
|
|
29156
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29157
|
-
"button",
|
|
29158
|
-
{
|
|
29159
|
-
onClick: handleClearAllItems,
|
|
29160
|
-
className: "flex-1 rounded-xl bg-red-500 px-4 py-3 font-medium text-white transition-colors hover:bg-red-600",
|
|
29161
|
-
children: "Clear All"
|
|
29162
|
-
}
|
|
29163
|
-
)
|
|
29164
|
-
] })
|
|
29165
|
-
] }) }),
|
|
29166
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29167
|
-
ValidationAlertModal,
|
|
29168
|
-
{
|
|
29169
|
-
isOpen: checkoutConflict !== null,
|
|
29170
|
-
onClose: () => setCheckoutConflict(null),
|
|
29171
|
-
title: "Can't check out yet",
|
|
29172
|
-
message: checkoutConflict ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
29173
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: checkoutConflict.restaurantName }),
|
|
29174
|
-
checkoutConflict.message.slice(
|
|
29175
|
-
checkoutConflict.restaurantName.length
|
|
29654
|
+
),
|
|
29655
|
+
isClearAllConfirmOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 z-[100] flex items-center justify-center bg-black/50 p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full max-w-md rounded-2xl bg-white p-6 shadow-xl", children: [
|
|
29656
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-4 flex items-center gap-3", children: [
|
|
29657
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-red-100", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-6 w-6 text-red-600" }) }),
|
|
29658
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
29659
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-bold text-gray-900", children: "Clear Cart" }),
|
|
29660
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "Remove all items and sessions" })
|
|
29661
|
+
] })
|
|
29662
|
+
] }),
|
|
29663
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-6 text-gray-600", children: "This will delete every session and remove all items you've added, returning your order to a single empty session. This action cannot be undone." }),
|
|
29664
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3", children: [
|
|
29665
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29666
|
+
"button",
|
|
29667
|
+
{
|
|
29668
|
+
onClick: () => setIsClearAllConfirmOpen(false),
|
|
29669
|
+
className: "flex-1 rounded-xl border border-base-300 px-4 py-3 font-medium text-gray-600 transition-colors hover:bg-base-100",
|
|
29670
|
+
children: "Cancel"
|
|
29671
|
+
}
|
|
29672
|
+
),
|
|
29673
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29674
|
+
"button",
|
|
29675
|
+
{
|
|
29676
|
+
onClick: handleClearAllItems,
|
|
29677
|
+
className: "flex-1 rounded-xl bg-red-500 px-4 py-3 font-medium text-white transition-colors hover:bg-red-600",
|
|
29678
|
+
children: "Clear All"
|
|
29679
|
+
}
|
|
29176
29680
|
)
|
|
29177
|
-
] })
|
|
29178
|
-
|
|
29179
|
-
|
|
29180
|
-
|
|
29181
|
-
|
|
29182
|
-
|
|
29183
|
-
|
|
29184
|
-
|
|
29185
|
-
|
|
29186
|
-
|
|
29187
|
-
|
|
29188
|
-
|
|
29189
|
-
|
|
29681
|
+
] })
|
|
29682
|
+
] }) }),
|
|
29683
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29684
|
+
ValidationAlertModal,
|
|
29685
|
+
{
|
|
29686
|
+
isOpen: checkoutConflict !== null,
|
|
29687
|
+
onClose: () => setCheckoutConflict(null),
|
|
29688
|
+
title: "Can't check out yet",
|
|
29689
|
+
message: checkoutConflict ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
29690
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: checkoutConflict.restaurantName }),
|
|
29691
|
+
checkoutConflict.message.slice(
|
|
29692
|
+
checkoutConflict.restaurantName.length
|
|
29693
|
+
)
|
|
29694
|
+
] }) : "",
|
|
29695
|
+
primaryAction: checkoutConflict ? {
|
|
29696
|
+
label: `Remove all ${checkoutConflict.restaurantName} items from this session`,
|
|
29697
|
+
onClick: () => {
|
|
29698
|
+
const { sessionIndex, restaurantId } = checkoutConflict;
|
|
29699
|
+
const session = mealSessions[sessionIndex];
|
|
29700
|
+
if (session) {
|
|
29701
|
+
const indices = session.orderItems.map(
|
|
29702
|
+
(oi, idx) => oi.item.restaurantId === restaurantId ? idx : -1
|
|
29703
|
+
).filter((idx) => idx !== -1).sort((a, b) => b - a);
|
|
29704
|
+
indices.forEach(
|
|
29705
|
+
(idx) => removeMenuItemByIndex(sessionIndex, idx)
|
|
29706
|
+
);
|
|
29707
|
+
}
|
|
29708
|
+
setSessionValidationErrors((prev) => {
|
|
29709
|
+
const next = { ...prev };
|
|
29710
|
+
delete next[sessionIndex];
|
|
29711
|
+
return next;
|
|
29712
|
+
});
|
|
29713
|
+
setCheckoutConflict(null);
|
|
29190
29714
|
}
|
|
29191
|
-
|
|
29192
|
-
|
|
29193
|
-
|
|
29194
|
-
|
|
29195
|
-
|
|
29196
|
-
|
|
29197
|
-
|
|
29198
|
-
|
|
29199
|
-
|
|
29200
|
-
|
|
29201
|
-
|
|
29202
|
-
|
|
29203
|
-
|
|
29204
|
-
|
|
29205
|
-
|
|
29206
|
-
|
|
29207
|
-
|
|
29208
|
-
|
|
29209
|
-
|
|
29210
|
-
{
|
|
29211
|
-
|
|
29212
|
-
|
|
29213
|
-
|
|
29214
|
-
|
|
29215
|
-
|
|
29216
|
-
|
|
29217
|
-
|
|
29218
|
-
|
|
29219
|
-
|
|
29220
|
-
|
|
29221
|
-
|
|
29222
|
-
|
|
29223
|
-
|
|
29224
|
-
|
|
29225
|
-
|
|
29226
|
-
|
|
29227
|
-
|
|
29715
|
+
} : void 0,
|
|
29716
|
+
secondaryAction: checkoutConflict ? {
|
|
29717
|
+
label: "Change session date & time",
|
|
29718
|
+
onClick: () => {
|
|
29719
|
+
setEditingSessionIndex(checkoutConflict.sessionIndex);
|
|
29720
|
+
setCheckoutConflict(null);
|
|
29721
|
+
}
|
|
29722
|
+
} : void 0
|
|
29723
|
+
}
|
|
29724
|
+
),
|
|
29725
|
+
minOrderModalSession !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29726
|
+
MinOrderModal,
|
|
29727
|
+
{
|
|
29728
|
+
sessionName: mealSessions[minOrderModalSession.index]?.sessionName || "Session",
|
|
29729
|
+
validationStatus: minOrderModalSession.validation,
|
|
29730
|
+
onClose: () => setMinOrderModalSession(null),
|
|
29731
|
+
onNavigateToSection: handleMinOrderNavigate
|
|
29732
|
+
}
|
|
29733
|
+
),
|
|
29734
|
+
showHalkinModal && /* @__PURE__ */ jsxRuntime.jsx(HalkinVenueModal, { onClose: () => setShowHalkinModal(false) }),
|
|
29735
|
+
showPdfModal && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29736
|
+
PdfDownloadModal,
|
|
29737
|
+
{
|
|
29738
|
+
onDownload: handlePdfDownload,
|
|
29739
|
+
onClose: () => setShowPdfModal(false),
|
|
29740
|
+
isGenerating: generatingPdf
|
|
29741
|
+
}
|
|
29742
|
+
),
|
|
29743
|
+
swapItemIndex !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29744
|
+
SwapItemModal,
|
|
29745
|
+
{
|
|
29746
|
+
currentItem: mealSessions[activeSessionIndex]?.orderItems[swapItemIndex]?.item,
|
|
29747
|
+
currentQuantity: mealSessions[activeSessionIndex]?.orderItems[swapItemIndex]?.quantity ?? 0,
|
|
29748
|
+
alternatives: swapAlternatives,
|
|
29749
|
+
isOpen: true,
|
|
29750
|
+
onClose: () => {
|
|
29751
|
+
setSwapItemIndex(null);
|
|
29752
|
+
setSwapAlternatives([]);
|
|
29753
|
+
},
|
|
29754
|
+
onSwap: handleConfirmSwap
|
|
29755
|
+
}
|
|
29756
|
+
),
|
|
29757
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
29758
|
+
TutorialTooltip,
|
|
29759
|
+
{
|
|
29760
|
+
step: currentTutorialStep,
|
|
29761
|
+
onNext: handleTutorialNext,
|
|
29762
|
+
onSkip: handleSkipTutorial,
|
|
29763
|
+
currentStepIndex: tutorialStep ?? 0,
|
|
29764
|
+
totalSteps: getTutorialSteps().length
|
|
29765
|
+
}
|
|
29766
|
+
)
|
|
29767
|
+
] }),
|
|
29768
|
+
/* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { children: flyGhost && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29769
|
+
react$1.motion.div,
|
|
29228
29770
|
{
|
|
29229
|
-
|
|
29230
|
-
|
|
29231
|
-
|
|
29232
|
-
|
|
29233
|
-
|
|
29234
|
-
|
|
29235
|
-
|
|
29771
|
+
initial: {
|
|
29772
|
+
position: "fixed",
|
|
29773
|
+
left: flyGhost.fromX - 24,
|
|
29774
|
+
top: flyGhost.fromY - 24,
|
|
29775
|
+
scale: 1,
|
|
29776
|
+
opacity: 1,
|
|
29777
|
+
zIndex: 9999
|
|
29236
29778
|
},
|
|
29237
|
-
|
|
29238
|
-
|
|
29239
|
-
|
|
29240
|
-
|
|
29241
|
-
|
|
29242
|
-
|
|
29243
|
-
|
|
29244
|
-
|
|
29245
|
-
|
|
29246
|
-
|
|
29247
|
-
|
|
29248
|
-
|
|
29249
|
-
|
|
29250
|
-
] })
|
|
29779
|
+
animate: {
|
|
29780
|
+
left: flyGhost.toX - 16,
|
|
29781
|
+
top: flyGhost.toY - 16,
|
|
29782
|
+
scale: 0.5,
|
|
29783
|
+
opacity: 0
|
|
29784
|
+
},
|
|
29785
|
+
transition: { duration: 0.85, ease: [0.22, 1, 0.36, 1] },
|
|
29786
|
+
className: "pointer-events-none",
|
|
29787
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-primary text-white shadow-2xl", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ShoppingBag, { className: "h-5 w-5" }) })
|
|
29788
|
+
},
|
|
29789
|
+
"fly-ghost"
|
|
29790
|
+
) })
|
|
29791
|
+
]
|
|
29251
29792
|
}
|
|
29252
29793
|
);
|
|
29253
29794
|
}
|
|
@@ -29303,7 +29844,7 @@ function MobileChatThread({
|
|
|
29303
29844
|
const paddingTop = hasAddressTopPill ? 68 : 56;
|
|
29304
29845
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4", style: { paddingTop, paddingBottom }, children: /* @__PURE__ */ jsxRuntime.jsx(ChatMessagesView, {}) });
|
|
29305
29846
|
}
|
|
29306
|
-
function MobileChatFloatingChips({ bottomOffset }) {
|
|
29847
|
+
function MobileChatFloatingChips({ bottomOffset, inputRef }) {
|
|
29307
29848
|
const {
|
|
29308
29849
|
hasResults,
|
|
29309
29850
|
onViewResults,
|
|
@@ -29352,7 +29893,10 @@ function MobileChatFloatingChips({ bottomOffset }) {
|
|
|
29352
29893
|
"aria-label": `${n} star${n > 1 ? "s" : ""}`,
|
|
29353
29894
|
onMouseEnter: () => setFeedbackHover(n),
|
|
29354
29895
|
onMouseLeave: () => setFeedbackHover(0),
|
|
29355
|
-
onClick: () =>
|
|
29896
|
+
onClick: () => {
|
|
29897
|
+
setFeedbackRating(n);
|
|
29898
|
+
inputRef?.current?.focus();
|
|
29899
|
+
},
|
|
29356
29900
|
className: "p-1 transition-transform hover:scale-110",
|
|
29357
29901
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
29358
29902
|
lucideReact.Star,
|
|
@@ -29488,7 +30032,8 @@ function MobileAIInput({
|
|
|
29488
30032
|
}
|
|
29489
30033
|
function SuggestionsOverlayBridge({
|
|
29490
30034
|
active,
|
|
29491
|
-
onVisibleChange
|
|
30035
|
+
onVisibleChange,
|
|
30036
|
+
flyToCart
|
|
29492
30037
|
}) {
|
|
29493
30038
|
const {
|
|
29494
30039
|
hasResults,
|
|
@@ -29504,7 +30049,8 @@ function SuggestionsOverlayBridge({
|
|
|
29504
30049
|
return /* @__PURE__ */ jsxRuntime.jsx(react$1.AnimatePresence, { children: visible && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29505
30050
|
SuggestionsOverlay,
|
|
29506
30051
|
{
|
|
29507
|
-
onClose: dismissSuggestionsOverlay
|
|
30052
|
+
onClose: dismissSuggestionsOverlay,
|
|
30053
|
+
flyToCart
|
|
29508
30054
|
},
|
|
29509
30055
|
"suggestions-overlay"
|
|
29510
30056
|
) });
|