@burdenoff/microfe-ggnomad 2026.705.2 → 2026.705.3
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/ggnomad/GGNomadRoot.js +14 -14
- package/dist/ggnomad/components/BookingPanel.js +219 -0
- package/dist/ggnomad/components/BookingPanel.js.map +1 -0
- package/dist/ggnomad/components/index.js +1 -0
- package/dist/ggnomad/graphql.js +12 -1
- package/dist/ggnomad/graphql.js.map +1 -1
- package/dist/ggnomad/pages/ActivityDetailsPage.js +51 -47
- package/dist/ggnomad/pages/ActivityDetailsPage.js.map +1 -1
- package/dist/ggnomad/pages/BookingsPage.js +1 -1
- package/dist/ggnomad/pages/EventDetailsPage.js +54 -49
- package/dist/ggnomad/pages/EventDetailsPage.js.map +1 -1
- package/dist/ggnomad/pages/FavoritesPage.js +1 -1
- package/dist/ggnomad/pages/PropertyDetailsPage.js +56 -51
- package/dist/ggnomad/pages/PropertyDetailsPage.js.map +1 -1
- package/dist/ggnomad/pages/TourDetailsPage.js +53 -49
- package/dist/ggnomad/pages/TourDetailsPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { GGNomadProvider as e } from "./providers/GGNomadProvider.js";
|
|
2
|
+
import { joinPath as t } from "./utils/navigation.js";
|
|
3
|
+
import { GGNomadRoutes as n } from "./GGNomadRoutes.js";
|
|
4
4
|
import { useEffect as r } from "react";
|
|
5
5
|
import { Activity as i, BarChart3 as a, Building as o, CalendarCheck as s, Compass as c, LayoutDashboard as l, MapPinned as u, Search as d, Star as f, Tickets as p } from "lucide-react";
|
|
6
6
|
import { useI18n as m } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
@@ -28,63 +28,63 @@ var _ = (_) => {
|
|
|
28
28
|
{
|
|
29
29
|
id: "ggnomad-search",
|
|
30
30
|
label: x("ggnomad.nav.search", "Search"),
|
|
31
|
-
path:
|
|
31
|
+
path: t(b, "search"),
|
|
32
32
|
icon: /* @__PURE__ */ h(d, { size: 16 }),
|
|
33
33
|
order: 5
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
id: "ggnomad-travel",
|
|
37
37
|
label: x("ggnomad.nav.travel", "Travel"),
|
|
38
|
-
path:
|
|
38
|
+
path: t(b, "travel"),
|
|
39
39
|
icon: /* @__PURE__ */ h(c, { size: 16 }),
|
|
40
40
|
order: 10
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
id: "ggnomad-hospitality",
|
|
44
44
|
label: x("ggnomad.nav.hospitality", "Hospitality"),
|
|
45
|
-
path:
|
|
45
|
+
path: t(b, "hospitality"),
|
|
46
46
|
icon: /* @__PURE__ */ h(o, { size: 16 }),
|
|
47
47
|
order: 20
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
id: "ggnomad-tourism",
|
|
51
51
|
label: x("ggnomad.nav.tourism", "Tourism"),
|
|
52
|
-
path:
|
|
52
|
+
path: t(b, "tourism"),
|
|
53
53
|
icon: /* @__PURE__ */ h(u, { size: 16 }),
|
|
54
54
|
order: 30
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
57
|
id: "ggnomad-entertainment",
|
|
58
58
|
label: x("ggnomad.nav.entertainment", "Entertainment"),
|
|
59
|
-
path:
|
|
59
|
+
path: t(b, "entertainment"),
|
|
60
60
|
icon: /* @__PURE__ */ h(i, { size: 16 }),
|
|
61
61
|
order: 40
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
64
|
id: "ggnomad-bookings",
|
|
65
65
|
label: x("ggnomad.nav.bookings", "Bookings"),
|
|
66
|
-
path:
|
|
66
|
+
path: t(b, "bookings"),
|
|
67
67
|
icon: /* @__PURE__ */ h(s, { size: 16 }),
|
|
68
68
|
order: 50
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
id: "ggnomad-favorites",
|
|
72
72
|
label: x("ggnomad.nav.favorites", "Favorites"),
|
|
73
|
-
path:
|
|
73
|
+
path: t(b, "favorites"),
|
|
74
74
|
icon: /* @__PURE__ */ h(f, { size: 16 }),
|
|
75
75
|
order: 60
|
|
76
76
|
},
|
|
77
77
|
{
|
|
78
78
|
id: "ggnomad-provider",
|
|
79
79
|
label: x("ggnomad.nav.providers", "Providers"),
|
|
80
|
-
path:
|
|
80
|
+
path: t(b, "provider"),
|
|
81
81
|
icon: /* @__PURE__ */ h(p, { size: 16 }),
|
|
82
82
|
order: 70
|
|
83
83
|
},
|
|
84
84
|
{
|
|
85
85
|
id: "ggnomad-analytics",
|
|
86
86
|
label: x("ggnomad.nav.analytics", "Analytics"),
|
|
87
|
-
path:
|
|
87
|
+
path: t(b, "analytics"),
|
|
88
88
|
icon: /* @__PURE__ */ h(a, { size: 16 }),
|
|
89
89
|
order: 80
|
|
90
90
|
}
|
|
@@ -106,9 +106,9 @@ var _ = (_) => {
|
|
|
106
106
|
workspaceId: null,
|
|
107
107
|
gateway: "global",
|
|
108
108
|
defaultEnabled: !0,
|
|
109
|
-
children: /* @__PURE__ */ h(
|
|
109
|
+
children: /* @__PURE__ */ h(e, {
|
|
110
110
|
..._,
|
|
111
|
-
children: /* @__PURE__ */ h(
|
|
111
|
+
children: /* @__PURE__ */ h(n, {})
|
|
112
112
|
})
|
|
113
113
|
});
|
|
114
114
|
};
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { CREATE_GGNOMAD_BOOKING_MUTATION as e } from "../graphql.js";
|
|
2
|
+
import { cn as t } from "../utils/cn.js";
|
|
3
|
+
import { useGGNomad as n } from "../providers/GGNomadProvider.js";
|
|
4
|
+
import { joinPath as r } from "../utils/navigation.js";
|
|
5
|
+
import { notify as i } from "../utils/notify.js";
|
|
6
|
+
import { useState as a } from "react";
|
|
7
|
+
import { Minus as o, Plus as s } from "lucide-react";
|
|
8
|
+
import { useI18n as c } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
9
|
+
import { useNavigate as l } from "react-router-dom";
|
|
10
|
+
import { useMutation as u } from "@apollo/client/react";
|
|
11
|
+
import { Button as d, GlassCard as f, Input as p } from "@burdenoff/fe-libs/ui";
|
|
12
|
+
import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
13
|
+
//#region src/ggnomad/components/BookingPanel.tsx
|
|
14
|
+
function _({ bookingType: _, itemId: v, itemName: y, unitPrice: b, currency: x, nights: S, eventDate: C }) {
|
|
15
|
+
let { t: w } = c(), T = l(), { basePath: E = "/" } = n(), [D, O] = a(""), [k, A] = a(""), [j, M] = a(""), [N, P] = a(1), [F, { loading: I }] = u(e), L = b * (_ === "PROPERTY" && S ? S : N), R = L * .1, z = L + R, B = async () => {
|
|
16
|
+
if (_ === "PROPERTY") {
|
|
17
|
+
if (!k || !j) {
|
|
18
|
+
i.warning(w("ggnomad.booking.validation.missingDates", "Missing dates"), w("ggnomad.booking.validation.propertyDatesRequired", "Please select both check-in and check-out dates."));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
} else if (_ === "EVENT") {
|
|
22
|
+
if (!C) {
|
|
23
|
+
i.warning(w("ggnomad.booking.validation.missingDate", "Missing date"), w("ggnomad.booking.validation.eventDateRequired", "Event date is required for booking."));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
} else if (!D) {
|
|
27
|
+
i.warning(w("ggnomad.booking.validation.missingDate", "Missing date"), w("ggnomad.booking.validation.dateRequired", "Please select a date for your booking."));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
let e = {
|
|
32
|
+
bookingType: _,
|
|
33
|
+
itemId: v,
|
|
34
|
+
itemName: y,
|
|
35
|
+
guestName: w("ggnomad.booking.defaultGuestName", "Demo Guest"),
|
|
36
|
+
guestEmail: "demo@burdenoff.com",
|
|
37
|
+
guests: N,
|
|
38
|
+
totalPrice: Math.round(z * 100) / 100,
|
|
39
|
+
currency: x,
|
|
40
|
+
paymentMethod: "card"
|
|
41
|
+
}, t = await F({ variables: { input: _ === "PROPERTY" ? {
|
|
42
|
+
...e,
|
|
43
|
+
checkIn: k,
|
|
44
|
+
checkOut: j
|
|
45
|
+
} : _ === "EVENT" ? {
|
|
46
|
+
...e,
|
|
47
|
+
eventDate: C
|
|
48
|
+
} : {
|
|
49
|
+
...e,
|
|
50
|
+
eventDate: D
|
|
51
|
+
} } });
|
|
52
|
+
if (t.error) {
|
|
53
|
+
i.error(w("ggnomad.booking.toast.createErrorTitle", "Could not create booking"), t.error.message);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
let n = t.data?.createGgnomadBooking;
|
|
57
|
+
i.success(w("ggnomad.booking.toast.createSuccessTitle", "Booking confirmed"), n ? w("ggnomad.booking.toast.createSuccessBody", "{{ref}} · {{item}}").replace("{{ref}}", n.referenceCode).replace("{{item}}", n.itemName) : y), T(r(E, "bookings"));
|
|
58
|
+
} catch (e) {
|
|
59
|
+
i.error(w("ggnomad.booking.toast.createErrorTitle", "Could not create booking"), e instanceof Error ? e.message : String(e));
|
|
60
|
+
}
|
|
61
|
+
}, V = "text-sm font-medium text-text-primary", H = "w-full";
|
|
62
|
+
return /* @__PURE__ */ g(f, {
|
|
63
|
+
treatment: "glass",
|
|
64
|
+
glow: !0,
|
|
65
|
+
className: "border-border-seam p-5 sticky top-6",
|
|
66
|
+
children: [
|
|
67
|
+
/* @__PURE__ */ h("h2", {
|
|
68
|
+
className: "mb-4 text-lg font-medium tracking-tight text-text-primary",
|
|
69
|
+
children: _ === "PROPERTY" ? w("ggnomad.booking.title.property", "Book this stay") : _ === "EVENT" ? w("ggnomad.booking.title.event", "Book tickets") : _ === "TOUR" ? w("ggnomad.booking.title.tour", "Book this tour") : w("ggnomad.booking.title.activity", "Book this activity")
|
|
70
|
+
}),
|
|
71
|
+
/* @__PURE__ */ g("div", {
|
|
72
|
+
className: "space-y-4 mb-6",
|
|
73
|
+
children: [_ === "PROPERTY" ? /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
|
|
74
|
+
htmlFor: "check-in",
|
|
75
|
+
className: V,
|
|
76
|
+
children: w("ggnomad.booking.checkIn", "Check-in")
|
|
77
|
+
}), /* @__PURE__ */ h(p, {
|
|
78
|
+
id: "check-in",
|
|
79
|
+
type: "date",
|
|
80
|
+
value: k,
|
|
81
|
+
onChange: (e) => A(e.target.value),
|
|
82
|
+
className: t(H, "mt-2"),
|
|
83
|
+
"aria-label": w("ggnomad.booking.checkIn", "Check-in")
|
|
84
|
+
})] }), /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
|
|
85
|
+
htmlFor: "check-out",
|
|
86
|
+
className: V,
|
|
87
|
+
children: w("ggnomad.booking.checkOut", "Check-out")
|
|
88
|
+
}), /* @__PURE__ */ h(p, {
|
|
89
|
+
id: "check-out",
|
|
90
|
+
type: "date",
|
|
91
|
+
value: j,
|
|
92
|
+
onChange: (e) => M(e.target.value),
|
|
93
|
+
className: t(H, "mt-2"),
|
|
94
|
+
"aria-label": w("ggnomad.booking.checkOut", "Check-out")
|
|
95
|
+
})] })] }) : _ === "EVENT" ? /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
|
|
96
|
+
htmlFor: "event-date",
|
|
97
|
+
className: V,
|
|
98
|
+
children: w("ggnomad.booking.date", "Date")
|
|
99
|
+
}), /* @__PURE__ */ h(p, {
|
|
100
|
+
id: "event-date",
|
|
101
|
+
type: "date",
|
|
102
|
+
value: C ? C.split("T")[0] : "",
|
|
103
|
+
disabled: !0,
|
|
104
|
+
className: t(H, "mt-2"),
|
|
105
|
+
"aria-label": w("ggnomad.booking.date", "Date")
|
|
106
|
+
})] }) : /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
|
|
107
|
+
htmlFor: "booking-date",
|
|
108
|
+
className: V,
|
|
109
|
+
children: w("ggnomad.booking.date", "Date")
|
|
110
|
+
}), /* @__PURE__ */ h(p, {
|
|
111
|
+
id: "booking-date",
|
|
112
|
+
type: "date",
|
|
113
|
+
value: D,
|
|
114
|
+
onChange: (e) => O(e.target.value),
|
|
115
|
+
className: t(H, "mt-2"),
|
|
116
|
+
"aria-label": w("ggnomad.booking.date", "Date")
|
|
117
|
+
})] }), /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("label", {
|
|
118
|
+
className: V,
|
|
119
|
+
children: _ === "PROPERTY" ? w("ggnomad.booking.guests", "Guests") : _ === "EVENT" ? w("ggnomad.booking.tickets", "Tickets") : w("ggnomad.booking.participants", "Participants")
|
|
120
|
+
}), /* @__PURE__ */ g("div", {
|
|
121
|
+
className: "flex items-center gap-2 mt-2",
|
|
122
|
+
children: [
|
|
123
|
+
/* @__PURE__ */ h(d, {
|
|
124
|
+
variant: "outline",
|
|
125
|
+
size: "sm",
|
|
126
|
+
onClick: () => P(Math.max(1, N - 1)),
|
|
127
|
+
disabled: N <= 1 || I,
|
|
128
|
+
"aria-label": w("ggnomad.booking.decreaseQuantity", "Decrease quantity"),
|
|
129
|
+
className: "flex-shrink-0",
|
|
130
|
+
children: /* @__PURE__ */ h(o, { className: "size-4" })
|
|
131
|
+
}),
|
|
132
|
+
/* @__PURE__ */ h("input", {
|
|
133
|
+
type: "number",
|
|
134
|
+
min: 1,
|
|
135
|
+
value: N,
|
|
136
|
+
onChange: (e) => P(Math.max(1, parseInt(e.target.value) || 1)),
|
|
137
|
+
className: "flex-1 h-9 rounded-input border border-border-default bg-bg-surface px-3 py-1 text-center text-sm text-text-primary",
|
|
138
|
+
"aria-label": _ === "PROPERTY" ? w("ggnomad.booking.guests", "Guests") : _ === "EVENT" ? w("ggnomad.booking.tickets", "Tickets") : w("ggnomad.booking.participants", "Participants")
|
|
139
|
+
}),
|
|
140
|
+
/* @__PURE__ */ h(d, {
|
|
141
|
+
variant: "outline",
|
|
142
|
+
size: "sm",
|
|
143
|
+
onClick: () => P(N + 1),
|
|
144
|
+
disabled: I,
|
|
145
|
+
"aria-label": w("ggnomad.booking.increaseQuantity", "Increase quantity"),
|
|
146
|
+
className: "flex-shrink-0",
|
|
147
|
+
children: /* @__PURE__ */ h(s, { className: "size-4" })
|
|
148
|
+
})
|
|
149
|
+
]
|
|
150
|
+
})] })]
|
|
151
|
+
}),
|
|
152
|
+
/* @__PURE__ */ g("div", {
|
|
153
|
+
className: "space-y-2 mb-6 p-3 rounded-md bg-bg-sunken",
|
|
154
|
+
children: [
|
|
155
|
+
/* @__PURE__ */ g("div", {
|
|
156
|
+
className: "flex justify-between text-sm",
|
|
157
|
+
children: [/* @__PURE__ */ g("span", {
|
|
158
|
+
className: "text-text-secondary",
|
|
159
|
+
children: [
|
|
160
|
+
x,
|
|
161
|
+
" ",
|
|
162
|
+
b.toFixed(2),
|
|
163
|
+
" ×",
|
|
164
|
+
" ",
|
|
165
|
+
_ === "PROPERTY" ? `${S ?? 1} ${w("ggnomad.booking.nights", "nights")}` : `${N} ${w("ggnomad.booking.item", "item")}`
|
|
166
|
+
]
|
|
167
|
+
}), /* @__PURE__ */ g("span", {
|
|
168
|
+
className: "text-text-primary font-medium",
|
|
169
|
+
children: [
|
|
170
|
+
x,
|
|
171
|
+
" ",
|
|
172
|
+
L.toFixed(2)
|
|
173
|
+
]
|
|
174
|
+
})]
|
|
175
|
+
}),
|
|
176
|
+
/* @__PURE__ */ g("div", {
|
|
177
|
+
className: "flex justify-between text-sm",
|
|
178
|
+
children: [/* @__PURE__ */ h("span", {
|
|
179
|
+
className: "text-text-secondary",
|
|
180
|
+
children: w("ggnomad.booking.tax", "Tax (10%)")
|
|
181
|
+
}), /* @__PURE__ */ g("span", {
|
|
182
|
+
className: "text-text-primary",
|
|
183
|
+
children: [
|
|
184
|
+
x,
|
|
185
|
+
" ",
|
|
186
|
+
R.toFixed(2)
|
|
187
|
+
]
|
|
188
|
+
})]
|
|
189
|
+
}),
|
|
190
|
+
/* @__PURE__ */ g("div", {
|
|
191
|
+
className: "border-t border-border-seam pt-2 flex justify-between",
|
|
192
|
+
children: [/* @__PURE__ */ h("span", {
|
|
193
|
+
className: "font-semibold text-text-primary",
|
|
194
|
+
children: w("ggnomad.booking.total", "Total")
|
|
195
|
+
}), /* @__PURE__ */ g("span", {
|
|
196
|
+
className: "font-bold text-lg text-text-primary",
|
|
197
|
+
children: [
|
|
198
|
+
x,
|
|
199
|
+
" ",
|
|
200
|
+
z.toFixed(2)
|
|
201
|
+
]
|
|
202
|
+
})]
|
|
203
|
+
})
|
|
204
|
+
]
|
|
205
|
+
}),
|
|
206
|
+
/* @__PURE__ */ h(d, {
|
|
207
|
+
onClick: () => void B(),
|
|
208
|
+
disabled: I,
|
|
209
|
+
className: "w-full bg-gradient-to-r from-action-primary-bg to-action-success-bg text-white font-semibold",
|
|
210
|
+
size: "lg",
|
|
211
|
+
children: I ? w("ggnomad.booking.button.creating", "Creating booking…") : _ === "PROPERTY" ? w("ggnomad.booking.button.property", "Book this stay") : _ === "EVENT" ? w("ggnomad.booking.button.event", "Book tickets") : _ === "TOUR" ? w("ggnomad.booking.button.tour", "Book this tour") : w("ggnomad.booking.button.activity", "Book this activity")
|
|
212
|
+
})
|
|
213
|
+
]
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
//#endregion
|
|
217
|
+
export { _ as BookingPanel };
|
|
218
|
+
|
|
219
|
+
//# sourceMappingURL=BookingPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BookingPanel.js","names":[],"sources":["../../../src/ggnomad/components/BookingPanel.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useMutation } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useNavigate } from 'react-router-dom';\nimport { Minus, Plus } from 'lucide-react';\nimport { Button, GlassCard, Input } from '@burdenoff/fe-libs/ui';\n\nimport { CREATE_GGNOMAD_BOOKING_MUTATION } from '../graphql';\nimport { useGGNomad } from '../providers/GGNomadProvider';\nimport { joinPath } from '../utils/navigation';\nimport { notify } from '../utils/notify';\nimport { cn } from '../utils/cn';\n\ntype BookingType = 'PROPERTY' | 'TOUR' | 'EVENT' | 'ACTIVITY';\n\ntype BookingPanelProps = {\n bookingType: BookingType;\n itemId: string;\n itemName: string;\n unitPrice: number;\n currency: string;\n /** For PROPERTY bookings, the number of nights to calculate price */\n nights?: number;\n /** For EVENT bookings, the event date (ISO string) */\n eventDate?: string;\n};\n\n/** Frosted glass booking panel with type-specific inputs and real createGgnomadBooking mutation. */\nexport function BookingPanel({\n bookingType,\n itemId,\n itemName,\n unitPrice,\n currency,\n nights,\n eventDate,\n}: BookingPanelProps) {\n const { t } = useI18n();\n const navigate = useNavigate();\n const { basePath = '/' } = useGGNomad();\n\n // For properties: check-in and check-out dates\n // For events/tours/activities: a single date\n const [selectedDate, setSelectedDate] = useState<string>('');\n const [checkInDate, setCheckInDate] = useState<string>('');\n const [checkOutDate, setCheckOutDate] = useState<string>('');\n\n // Quantity: guests (property), participants (tour/activity), tickets (event)\n const [quantity, setQuantity] = useState(1);\n\n type BookingInput = {\n bookingType: BookingType;\n itemId: string;\n itemName: string;\n guestName: string;\n guestEmail: string;\n guests: number;\n totalPrice: number;\n currency: string;\n paymentMethod: string;\n checkIn?: string;\n checkOut?: string;\n eventDate?: string;\n };\n\n const [createBooking, { loading: creating }] = useMutation(\n CREATE_GGNOMAD_BOOKING_MUTATION as TypedDocumentNode<\n { createGgnomadBooking: { id: string; referenceCode: string; itemName: string } },\n { input: BookingInput }\n >\n );\n\n // Calculate total: for properties, multiply by nights; for others, multiply by quantity\n const multiplier = bookingType === 'PROPERTY' && nights ? nights : quantity;\n const subtotal = unitPrice * multiplier;\n const taxAmount = subtotal * 0.1; // 10% tax\n const total = subtotal + taxAmount;\n\n const handleBooking = async () => {\n // Validate required fields\n if (bookingType === 'PROPERTY') {\n if (!checkInDate || !checkOutDate) {\n notify.warning(\n t('ggnomad.booking.validation.missingDates', 'Missing dates'),\n t(\n 'ggnomad.booking.validation.propertyDatesRequired',\n 'Please select both check-in and check-out dates.'\n )\n );\n return;\n }\n } else if (bookingType === 'EVENT') {\n if (!eventDate) {\n notify.warning(\n t('ggnomad.booking.validation.missingDate', 'Missing date'),\n t('ggnomad.booking.validation.eventDateRequired', 'Event date is required for booking.')\n );\n return;\n }\n } else {\n if (!selectedDate) {\n notify.warning(\n t('ggnomad.booking.validation.missingDate', 'Missing date'),\n t('ggnomad.booking.validation.dateRequired', 'Please select a date for your booking.')\n );\n return;\n }\n }\n\n try {\n const baseInput = {\n bookingType,\n itemId,\n itemName,\n guestName: t('ggnomad.booking.defaultGuestName', 'Demo Guest'),\n guestEmail: 'demo@burdenoff.com',\n guests: quantity,\n totalPrice: Math.round(total * 100) / 100,\n currency,\n paymentMethod: 'card',\n };\n\n const input: BookingInput =\n bookingType === 'PROPERTY'\n ? { ...baseInput, checkIn: checkInDate, checkOut: checkOutDate }\n : bookingType === 'EVENT'\n ? { ...baseInput, eventDate: eventDate }\n : { ...baseInput, eventDate: selectedDate };\n\n const result = await createBooking({\n variables: { input },\n });\n\n if (result.error) {\n notify.error(\n t('ggnomad.booking.toast.createErrorTitle', 'Could not create booking'),\n result.error.message\n );\n return;\n }\n\n const created = result.data?.createGgnomadBooking;\n notify.success(\n t('ggnomad.booking.toast.createSuccessTitle', 'Booking confirmed'),\n created\n ? t('ggnomad.booking.toast.createSuccessBody', '{{ref}} · {{item}}')\n .replace('{{ref}}', created.referenceCode)\n .replace('{{item}}', created.itemName)\n : itemName\n );\n\n // Navigate to bookings list\n navigate(joinPath(basePath, 'bookings'));\n } catch (err) {\n notify.error(\n t('ggnomad.booking.toast.createErrorTitle', 'Could not create booking'),\n err instanceof Error ? err.message : String(err)\n );\n }\n };\n\n const labelClass = 'text-sm font-medium text-text-primary';\n const inputClass = 'w-full';\n\n return (\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam p-5 sticky top-6\">\n <h2 className=\"mb-4 text-lg font-medium tracking-tight text-text-primary\">\n {bookingType === 'PROPERTY'\n ? t('ggnomad.booking.title.property', 'Book this stay')\n : bookingType === 'EVENT'\n ? t('ggnomad.booking.title.event', 'Book tickets')\n : bookingType === 'TOUR'\n ? t('ggnomad.booking.title.tour', 'Book this tour')\n : t('ggnomad.booking.title.activity', 'Book this activity')}\n </h2>\n\n <div className=\"space-y-4 mb-6\">\n {/* Dates section */}\n {bookingType === 'PROPERTY' ? (\n <>\n <div>\n <label htmlFor=\"check-in\" className={labelClass}>\n {t('ggnomad.booking.checkIn', 'Check-in')}\n </label>\n <Input\n id=\"check-in\"\n type=\"date\"\n value={checkInDate}\n onChange={(e) => setCheckInDate(e.target.value)}\n className={cn(inputClass, 'mt-2')}\n aria-label={t('ggnomad.booking.checkIn', 'Check-in')}\n />\n </div>\n <div>\n <label htmlFor=\"check-out\" className={labelClass}>\n {t('ggnomad.booking.checkOut', 'Check-out')}\n </label>\n <Input\n id=\"check-out\"\n type=\"date\"\n value={checkOutDate}\n onChange={(e) => setCheckOutDate(e.target.value)}\n className={cn(inputClass, 'mt-2')}\n aria-label={t('ggnomad.booking.checkOut', 'Check-out')}\n />\n </div>\n </>\n ) : bookingType === 'EVENT' ? (\n <div>\n <label htmlFor=\"event-date\" className={labelClass}>\n {t('ggnomad.booking.date', 'Date')}\n </label>\n <Input\n id=\"event-date\"\n type=\"date\"\n value={eventDate ? eventDate.split('T')[0] : ''}\n disabled\n className={cn(inputClass, 'mt-2')}\n aria-label={t('ggnomad.booking.date', 'Date')}\n />\n </div>\n ) : (\n <div>\n <label htmlFor=\"booking-date\" className={labelClass}>\n {t('ggnomad.booking.date', 'Date')}\n </label>\n <Input\n id=\"booking-date\"\n type=\"date\"\n value={selectedDate}\n onChange={(e) => setSelectedDate(e.target.value)}\n className={cn(inputClass, 'mt-2')}\n aria-label={t('ggnomad.booking.date', 'Date')}\n />\n </div>\n )}\n\n {/* Quantity section */}\n <div>\n <label className={labelClass}>\n {bookingType === 'PROPERTY'\n ? t('ggnomad.booking.guests', 'Guests')\n : bookingType === 'EVENT'\n ? t('ggnomad.booking.tickets', 'Tickets')\n : t('ggnomad.booking.participants', 'Participants')}\n </label>\n <div className=\"flex items-center gap-2 mt-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setQuantity(Math.max(1, quantity - 1))}\n disabled={quantity <= 1 || creating}\n aria-label={t('ggnomad.booking.decreaseQuantity', 'Decrease quantity')}\n className=\"flex-shrink-0\"\n >\n <Minus className=\"size-4\" />\n </Button>\n <input\n type=\"number\"\n min={1}\n value={quantity}\n onChange={(e) => setQuantity(Math.max(1, parseInt(e.target.value) || 1))}\n className=\"flex-1 h-9 rounded-input border border-border-default bg-bg-surface px-3 py-1 text-center text-sm text-text-primary\"\n aria-label={\n bookingType === 'PROPERTY'\n ? t('ggnomad.booking.guests', 'Guests')\n : bookingType === 'EVENT'\n ? t('ggnomad.booking.tickets', 'Tickets')\n : t('ggnomad.booking.participants', 'Participants')\n }\n />\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setQuantity(quantity + 1)}\n disabled={creating}\n aria-label={t('ggnomad.booking.increaseQuantity', 'Increase quantity')}\n className=\"flex-shrink-0\"\n >\n <Plus className=\"size-4\" />\n </Button>\n </div>\n </div>\n </div>\n\n {/* Pricing breakdown */}\n <div className=\"space-y-2 mb-6 p-3 rounded-md bg-bg-sunken\">\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">\n {currency} {unitPrice.toFixed(2)} ×{' '}\n {bookingType === 'PROPERTY'\n ? `${nights ?? 1} ${t('ggnomad.booking.nights', 'nights')}`\n : `${quantity} ${t('ggnomad.booking.item', 'item')}`}\n </span>\n <span className=\"text-text-primary font-medium\">\n {currency} {subtotal.toFixed(2)}\n </span>\n </div>\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">{t('ggnomad.booking.tax', 'Tax (10%)')}</span>\n <span className=\"text-text-primary\">\n {currency} {taxAmount.toFixed(2)}\n </span>\n </div>\n <div className=\"border-t border-border-seam pt-2 flex justify-between\">\n <span className=\"font-semibold text-text-primary\">\n {t('ggnomad.booking.total', 'Total')}\n </span>\n <span className=\"font-bold text-lg text-text-primary\">\n {currency} {total.toFixed(2)}\n </span>\n </div>\n </div>\n\n {/* Book button */}\n <Button\n onClick={() => void handleBooking()}\n disabled={creating}\n className=\"w-full bg-gradient-to-r from-action-primary-bg to-action-success-bg text-white font-semibold\"\n size=\"lg\"\n >\n {creating\n ? t('ggnomad.booking.button.creating', 'Creating booking…')\n : bookingType === 'PROPERTY'\n ? t('ggnomad.booking.button.property', 'Book this stay')\n : bookingType === 'EVENT'\n ? t('ggnomad.booking.button.event', 'Book tickets')\n : bookingType === 'TOUR'\n ? t('ggnomad.booking.button.tour', 'Book this tour')\n : t('ggnomad.booking.button.activity', 'Book this activity')}\n </Button>\n </GlassCard>\n );\n}\n"],"mappings":"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"}
|
package/dist/ggnomad/graphql.js
CHANGED
|
@@ -123,7 +123,18 @@ var t = e`
|
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
-
|
|
126
|
+
`;
|
|
127
|
+
e`
|
|
128
|
+
query GGNomadPropertyForBooking($id: ID!) {
|
|
129
|
+
ggnomadProperty(id: $id) {
|
|
130
|
+
id
|
|
131
|
+
name
|
|
132
|
+
pricePerNight
|
|
133
|
+
currency
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
`;
|
|
137
|
+
var s = e`
|
|
127
138
|
query GGNomadTours($first: Int, $skip: Int) {
|
|
128
139
|
ggnomadTours(pagination: { first: $first, skip: $skip }) {
|
|
129
140
|
id
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graphql.js","names":[],"sources":["../../src/ggnomad/graphql.ts"],"sourcesContent":["import { gql } from '@apollo/client/core';\n\nexport const GGNOMAD_OVERVIEW_QUERY = gql`\n query GGNomadOverview {\n ggnomadOverviewStats {\n users\n listings\n bookings\n monthlyRevenue\n }\n ggnomadAnalytics {\n totalRevenue\n totalBookings\n totalUsers\n conversionRate\n revenueByCategory\n }\n }\n`;\n\n/**\n * One bookable item of each type (properties are priced per night, the rest\n * carry a flat price). Used to seed the Bookings \"create demo booking\" action\n * with a REAL listing id so the mutation passes the backend's\n * assertTargetInWorkspace check instead of failing on a synthetic id.\n */\nexport const GGNOMAD_BOOKABLE_SAMPLE_QUERY = gql`\n query GGNomadBookableSample {\n ggnomadProperties(pagination: { first: 1, skip: 0 }) {\n id\n name\n pricePerNight\n currency\n }\n ggnomadTours(pagination: { first: 1, skip: 0 }) {\n id\n name\n price\n currency\n }\n ggnomadEvents(pagination: { first: 1, skip: 0 }) {\n id\n name\n price\n currency\n }\n ggnomadActivities(pagination: { first: 1, skip: 0 }) {\n id\n name\n price\n currency\n }\n }\n`;\n\n/**\n * id + name for every favouritable listing type, used to (a) resolve the real\n * entity name for a saved favorite (which the backend only exposes as\n * targetType + targetId) and (b) seed the \"toggle demo favorite\" action with a\n * real target id.\n */\nexport const GGNOMAD_FAVORITE_TARGETS_QUERY = gql`\n query GGNomadFavoriteTargets {\n ggnomadProperties(pagination: { first: 100, skip: 0 }) {\n id\n name\n }\n ggnomadTours(pagination: { first: 100, skip: 0 }) {\n id\n name\n }\n ggnomadEvents(pagination: { first: 100, skip: 0 }) {\n id\n name\n }\n ggnomadActivities(pagination: { first: 100, skip: 0 }) {\n id\n name\n }\n }\n`;\n\nexport const GGNOMAD_PROVIDERS_QUERY = gql`\n query GGNomadProviders($first: Int, $skip: Int) {\n ggnomadProviders(pagination: { first: $first, skip: $skip }) {\n id\n name\n type\n status\n listingCount\n totalRevenue\n rating\n reviewCount\n contactEmail\n website\n }\n }\n`;\n\nexport const GGNOMAD_PROPERTIES_QUERY = gql`\n query GGNomadProperties($first: Int, $skip: Int) {\n ggnomadProperties(pagination: { first: $first, skip: $skip }) {\n id\n name\n type\n status\n description\n pricePerNight\n currency\n rating\n reviewCount\n maxGuests\n amenities\n images\n providerId\n }\n }\n`;\n\nexport const GGNOMAD_PROPERTY_QUERY = gql`\n query GGNomadProperty($id: ID!) {\n ggnomadProperty(id: $id) {\n id\n name\n type\n status\n description\n address\n pricePerNight\n currency\n rating\n reviewCount\n bedrooms\n bathrooms\n maxGuests\n checkInTime\n checkOutTime\n amenities\n images\n provider {\n id\n name\n type\n rating\n }\n }\n }\n`;\n\nexport const GGNOMAD_TOURS_QUERY = gql`\n query GGNomadTours($first: Int, $skip: Int) {\n ggnomadTours(pagination: { first: $first, skip: $skip }) {\n id\n name\n description\n type\n status\n duration\n difficulty\n price\n currency\n rating\n reviewCount\n highlights\n images\n }\n }\n`;\n\nexport const GGNOMAD_TOUR_QUERY = gql`\n query GGNomadTour($id: ID!) {\n ggnomadTour(id: $id) {\n id\n name\n description\n type\n status\n duration\n difficulty\n price\n currency\n rating\n reviewCount\n highlights\n images\n languages\n guideName\n provider {\n id\n name\n }\n }\n }\n`;\n\nexport const GGNOMAD_EVENTS_QUERY = gql`\n query GGNomadEvents($first: Int, $skip: Int) {\n ggnomadEvents(pagination: { first: $first, skip: $skip }) {\n id\n name\n description\n category\n status\n startsAt\n price\n currency\n rating\n reviewCount\n performers\n images\n }\n }\n`;\n\nexport const GGNOMAD_EVENT_QUERY = gql`\n query GGNomadEvent($id: ID!) {\n ggnomadEvent(id: $id) {\n id\n name\n description\n category\n status\n startsAt\n endsAt\n venue\n price\n currency\n rating\n reviewCount\n performers\n images\n provider {\n id\n name\n }\n }\n }\n`;\n\nexport const GGNOMAD_ACTIVITIES_QUERY = gql`\n query GGNomadActivities($first: Int, $skip: Int) {\n ggnomadActivities(pagination: { first: $first, skip: $skip }) {\n id\n name\n description\n category\n status\n duration\n difficulty\n price\n currency\n rating\n reviewCount\n maxParticipants\n includes\n requirements\n images\n }\n }\n`;\n\nexport const GGNOMAD_ACTIVITY_QUERY = gql`\n query GGNomadActivity($id: ID!) {\n ggnomadActivity(id: $id) {\n id\n name\n description\n category\n status\n location\n duration\n difficulty\n price\n currency\n rating\n reviewCount\n maxParticipants\n includes\n requirements\n safetyInfo\n images\n provider {\n id\n name\n }\n }\n }\n`;\n\nexport const GGNOMAD_TRIPS_QUERY = gql`\n query GGNomadTrips($first: Int, $skip: Int) {\n ggnomadTrips(pagination: { first: $first, skip: $skip }) {\n id\n name\n transportMode\n status\n origin\n destination\n departureAt\n arrivalAt\n isRoundTrip\n carrier\n class\n price\n currency\n passengers\n ecoFriendly\n }\n }\n`;\n\nexport const GGNOMAD_BOOKINGS_QUERY = gql`\n query GGNomadBookings($first: Int, $skip: Int) {\n ggnomadBookings(pagination: { first: $first, skip: $skip }) {\n id\n referenceCode\n bookingType\n status\n itemId\n itemName\n guestName\n guestEmail\n guestPhone\n guests\n checkIn\n checkOut\n eventDate\n totalPrice\n currency\n paymentStatus\n paymentMethod\n specialRequests\n createdAt\n }\n }\n`;\n\nexport const GGNOMAD_FAVORITES_QUERY = gql`\n query GGNomadFavorites {\n ggnomadFavorites\n }\n`;\n\nexport const CREATE_GGNOMAD_BOOKING_MUTATION = gql`\n mutation CreateGGNomadBooking($input: CreateGgnomadBookingInput!) {\n createGgnomadBooking(input: $input) {\n id\n referenceCode\n bookingType\n status\n itemId\n itemName\n guestName\n totalPrice\n currency\n createdAt\n }\n }\n`;\n\nexport const TOGGLE_GGNOMAD_FAVORITE_MUTATION = gql`\n mutation ToggleGGNomadFavorite($input: ToggleGgnomadFavoriteInput!) {\n toggleGgnomadFavorite(input: $input)\n }\n`;\n\nexport const CANCEL_GGNOMAD_BOOKING_MUTATION = gql`\n mutation CancelGGNomadBooking($id: ID!, $reason: String) {\n cancelGgnomadBooking(id: $id, reason: $reason) {\n id\n status\n }\n }\n`;\n"],"mappings":";;AAEA,IAAa,IAAyB,CAAG;;;;;;;;;;;;;;;;GAwB5B,IAAgC,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCnC,IAAiC,CAAG;;;;;;;;;;;;;;;;;;;GAqBpC,IAA0B,CAAG;;;;;;;;;;;;;;;GAiB7B,IAA2B,CAAG;;;;;;;;;;;;;;;;;;GAoB9B,IAAyB,CAAG
|
|
1
|
+
{"version":3,"file":"graphql.js","names":[],"sources":["../../src/ggnomad/graphql.ts"],"sourcesContent":["import { gql } from '@apollo/client/core';\n\nexport const GGNOMAD_OVERVIEW_QUERY = gql`\n query GGNomadOverview {\n ggnomadOverviewStats {\n users\n listings\n bookings\n monthlyRevenue\n }\n ggnomadAnalytics {\n totalRevenue\n totalBookings\n totalUsers\n conversionRate\n revenueByCategory\n }\n }\n`;\n\n/**\n * One bookable item of each type (properties are priced per night, the rest\n * carry a flat price). Used to seed the Bookings \"create demo booking\" action\n * with a REAL listing id so the mutation passes the backend's\n * assertTargetInWorkspace check instead of failing on a synthetic id.\n */\nexport const GGNOMAD_BOOKABLE_SAMPLE_QUERY = gql`\n query GGNomadBookableSample {\n ggnomadProperties(pagination: { first: 1, skip: 0 }) {\n id\n name\n pricePerNight\n currency\n }\n ggnomadTours(pagination: { first: 1, skip: 0 }) {\n id\n name\n price\n currency\n }\n ggnomadEvents(pagination: { first: 1, skip: 0 }) {\n id\n name\n price\n currency\n }\n ggnomadActivities(pagination: { first: 1, skip: 0 }) {\n id\n name\n price\n currency\n }\n }\n`;\n\n/**\n * id + name for every favouritable listing type, used to (a) resolve the real\n * entity name for a saved favorite (which the backend only exposes as\n * targetType + targetId) and (b) seed the \"toggle demo favorite\" action with a\n * real target id.\n */\nexport const GGNOMAD_FAVORITE_TARGETS_QUERY = gql`\n query GGNomadFavoriteTargets {\n ggnomadProperties(pagination: { first: 100, skip: 0 }) {\n id\n name\n }\n ggnomadTours(pagination: { first: 100, skip: 0 }) {\n id\n name\n }\n ggnomadEvents(pagination: { first: 100, skip: 0 }) {\n id\n name\n }\n ggnomadActivities(pagination: { first: 100, skip: 0 }) {\n id\n name\n }\n }\n`;\n\nexport const GGNOMAD_PROVIDERS_QUERY = gql`\n query GGNomadProviders($first: Int, $skip: Int) {\n ggnomadProviders(pagination: { first: $first, skip: $skip }) {\n id\n name\n type\n status\n listingCount\n totalRevenue\n rating\n reviewCount\n contactEmail\n website\n }\n }\n`;\n\nexport const GGNOMAD_PROPERTIES_QUERY = gql`\n query GGNomadProperties($first: Int, $skip: Int) {\n ggnomadProperties(pagination: { first: $first, skip: $skip }) {\n id\n name\n type\n status\n description\n pricePerNight\n currency\n rating\n reviewCount\n maxGuests\n amenities\n images\n providerId\n }\n }\n`;\n\nexport const GGNOMAD_PROPERTY_QUERY = gql`\n query GGNomadProperty($id: ID!) {\n ggnomadProperty(id: $id) {\n id\n name\n type\n status\n description\n address\n pricePerNight\n currency\n rating\n reviewCount\n bedrooms\n bathrooms\n maxGuests\n checkInTime\n checkOutTime\n amenities\n images\n provider {\n id\n name\n type\n rating\n }\n }\n }\n`;\n\n// Query to get property details for booking - ensures id is included\nexport const GGNOMAD_PROPERTY_FOR_BOOKING_QUERY = gql`\n query GGNomadPropertyForBooking($id: ID!) {\n ggnomadProperty(id: $id) {\n id\n name\n pricePerNight\n currency\n }\n }\n`;\n\nexport const GGNOMAD_TOURS_QUERY = gql`\n query GGNomadTours($first: Int, $skip: Int) {\n ggnomadTours(pagination: { first: $first, skip: $skip }) {\n id\n name\n description\n type\n status\n duration\n difficulty\n price\n currency\n rating\n reviewCount\n highlights\n images\n }\n }\n`;\n\nexport const GGNOMAD_TOUR_QUERY = gql`\n query GGNomadTour($id: ID!) {\n ggnomadTour(id: $id) {\n id\n name\n description\n type\n status\n duration\n difficulty\n price\n currency\n rating\n reviewCount\n highlights\n images\n languages\n guideName\n provider {\n id\n name\n }\n }\n }\n`;\n\nexport const GGNOMAD_EVENTS_QUERY = gql`\n query GGNomadEvents($first: Int, $skip: Int) {\n ggnomadEvents(pagination: { first: $first, skip: $skip }) {\n id\n name\n description\n category\n status\n startsAt\n price\n currency\n rating\n reviewCount\n performers\n images\n }\n }\n`;\n\nexport const GGNOMAD_EVENT_QUERY = gql`\n query GGNomadEvent($id: ID!) {\n ggnomadEvent(id: $id) {\n id\n name\n description\n category\n status\n startsAt\n endsAt\n venue\n price\n currency\n rating\n reviewCount\n performers\n images\n provider {\n id\n name\n }\n }\n }\n`;\n\nexport const GGNOMAD_ACTIVITIES_QUERY = gql`\n query GGNomadActivities($first: Int, $skip: Int) {\n ggnomadActivities(pagination: { first: $first, skip: $skip }) {\n id\n name\n description\n category\n status\n duration\n difficulty\n price\n currency\n rating\n reviewCount\n maxParticipants\n includes\n requirements\n images\n }\n }\n`;\n\nexport const GGNOMAD_ACTIVITY_QUERY = gql`\n query GGNomadActivity($id: ID!) {\n ggnomadActivity(id: $id) {\n id\n name\n description\n category\n status\n location\n duration\n difficulty\n price\n currency\n rating\n reviewCount\n maxParticipants\n includes\n requirements\n safetyInfo\n images\n provider {\n id\n name\n }\n }\n }\n`;\n\nexport const GGNOMAD_TRIPS_QUERY = gql`\n query GGNomadTrips($first: Int, $skip: Int) {\n ggnomadTrips(pagination: { first: $first, skip: $skip }) {\n id\n name\n transportMode\n status\n origin\n destination\n departureAt\n arrivalAt\n isRoundTrip\n carrier\n class\n price\n currency\n passengers\n ecoFriendly\n }\n }\n`;\n\nexport const GGNOMAD_BOOKINGS_QUERY = gql`\n query GGNomadBookings($first: Int, $skip: Int) {\n ggnomadBookings(pagination: { first: $first, skip: $skip }) {\n id\n referenceCode\n bookingType\n status\n itemId\n itemName\n guestName\n guestEmail\n guestPhone\n guests\n checkIn\n checkOut\n eventDate\n totalPrice\n currency\n paymentStatus\n paymentMethod\n specialRequests\n createdAt\n }\n }\n`;\n\nexport const GGNOMAD_FAVORITES_QUERY = gql`\n query GGNomadFavorites {\n ggnomadFavorites\n }\n`;\n\nexport const CREATE_GGNOMAD_BOOKING_MUTATION = gql`\n mutation CreateGGNomadBooking($input: CreateGgnomadBookingInput!) {\n createGgnomadBooking(input: $input) {\n id\n referenceCode\n bookingType\n status\n itemId\n itemName\n guestName\n totalPrice\n currency\n createdAt\n }\n }\n`;\n\nexport const TOGGLE_GGNOMAD_FAVORITE_MUTATION = gql`\n mutation ToggleGGNomadFavorite($input: ToggleGgnomadFavoriteInput!) {\n toggleGgnomadFavorite(input: $input)\n }\n`;\n\nexport const CANCEL_GGNOMAD_BOOKING_MUTATION = gql`\n mutation CancelGGNomadBooking($id: ID!, $reason: String) {\n cancelGgnomadBooking(id: $id, reason: $reason) {\n id\n status\n }\n }\n`;\n"],"mappings":";;AAEA,IAAa,IAAyB,CAAG;;;;;;;;;;;;;;;;GAwB5B,IAAgC,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCnC,IAAiC,CAAG;;;;;;;;;;;;;;;;;;;GAqBpC,IAA0B,CAAG;;;;;;;;;;;;;;;GAiB7B,IAA2B,CAAG;;;;;;;;;;;;;;;;;;GAoB9B,IAAyB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BS,CAAG;;;;;;;;;;AAWrD,IAAa,IAAsB,CAAG;;;;;;;;;;;;;;;;;;GAoBzB,IAAqB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;GA0BxB,IAAuB,CAAG;;;;;;;;;;;;;;;;;GAmB1B,IAAsB,CAAG;;;;;;;;;;;;;;;;;;;;;;;GAyBzB,IAA2B,CAAG;;;;;;;;;;;;;;;;;;;;GAsB9B,IAAyB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;GA4B5B,IAAsB,CAAG;;;;;;;;;;;;;;;;;;;;GAsBzB,IAAyB,CAAG;;;;;;;;;;;;;;;;;;;;;;;;GA0B5B,IAA0B,CAAG;;;;GAM7B,IAAkC,CAAG;;;;;;;;;;;;;;;GAiBrC,IAAmC,CAAG;;;;GAMtC,IAAkC,CAAG"}
|
|
@@ -3,10 +3,11 @@ import { PageShell as t } from "./PageShell.js";
|
|
|
3
3
|
import { SectionCard as n } from "../components/SectionCard.js";
|
|
4
4
|
import { DetailRow as r } from "../components/DetailRow.js";
|
|
5
5
|
import { DetailHero as i } from "../components/DetailHero.js";
|
|
6
|
-
import "../components/index.js";
|
|
7
6
|
import { useGGNomad as a } from "../providers/GGNomadProvider.js";
|
|
8
7
|
import { joinPath as o } from "../utils/navigation.js";
|
|
9
|
-
import {
|
|
8
|
+
import { BookingPanel as s } from "../components/BookingPanel.js";
|
|
9
|
+
import "../components/index.js";
|
|
10
|
+
import { Activity as c, Compass as l, ShieldCheck as u } from "lucide-react";
|
|
10
11
|
import { useI18n as d } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
11
12
|
import { useNavigate as f, useParams as p } from "react-router-dom";
|
|
12
13
|
import { useQuery as m } from "@apollo/client/react";
|
|
@@ -27,18 +28,12 @@ function S() {
|
|
|
27
28
|
alt: D.name
|
|
28
29
|
}),
|
|
29
30
|
/* @__PURE__ */ b(v, {
|
|
30
|
-
icon: /* @__PURE__ */ b(
|
|
31
|
+
icon: /* @__PURE__ */ b(c, { className: "size-4" }),
|
|
31
32
|
children: S("ggnomad.activity.purpose", "Everything you need to know before joining this activity — its category, duration, group size, price and the safety policy that applies — so you can be confident it fits your group before you book.")
|
|
32
33
|
}),
|
|
33
34
|
/* @__PURE__ */ b(_, {
|
|
34
35
|
storageKey: "ggnomad-activity-detail",
|
|
35
36
|
steps: [{
|
|
36
|
-
id: "book",
|
|
37
|
-
label: S("ggnomad.activity.next.book", "Book this activity"),
|
|
38
|
-
description: S("ggnomad.activity.next.bookDesc", "Add it to your itinerary and track it under Bookings."),
|
|
39
|
-
icon: /* @__PURE__ */ b(c, { className: "size-4" }),
|
|
40
|
-
onClick: () => C(o(w, "bookings"))
|
|
41
|
-
}, {
|
|
42
37
|
id: "browse",
|
|
43
38
|
label: S("ggnomad.activity.next.browse", "Explore more experiences"),
|
|
44
39
|
description: S("ggnomad.activity.next.browseDesc", "Return to Tourism to compare tours and activities."),
|
|
@@ -47,45 +42,54 @@ function S() {
|
|
|
47
42
|
}]
|
|
48
43
|
}),
|
|
49
44
|
/* @__PURE__ */ x("div", {
|
|
50
|
-
className: "grid gap-4 lg:grid-cols-
|
|
51
|
-
children: [/* @__PURE__ */ x(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
className: "
|
|
57
|
-
children:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
45
|
+
className: "grid gap-4 lg:grid-cols-3",
|
|
46
|
+
children: [/* @__PURE__ */ x("div", {
|
|
47
|
+
className: "lg:col-span-2 space-y-4",
|
|
48
|
+
children: [/* @__PURE__ */ x(h, {
|
|
49
|
+
treatment: "glass",
|
|
50
|
+
glow: !0,
|
|
51
|
+
className: "border-border-seam p-5",
|
|
52
|
+
children: [/* @__PURE__ */ b("h2", {
|
|
53
|
+
className: "mb-4 text-lg font-medium tracking-tight text-text-primary",
|
|
54
|
+
children: S("ggnomad.activity.details", "Details")
|
|
55
|
+
}), /* @__PURE__ */ x("dl", {
|
|
56
|
+
className: "space-y-2 text-sm",
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ b(r, {
|
|
59
|
+
label: S("ggnomad.activity.category", "Category"),
|
|
60
|
+
value: D.category
|
|
61
|
+
}),
|
|
62
|
+
/* @__PURE__ */ b(r, {
|
|
63
|
+
label: S("ggnomad.activity.duration", "Duration"),
|
|
64
|
+
value: D.duration
|
|
65
|
+
}),
|
|
66
|
+
/* @__PURE__ */ b(r, {
|
|
67
|
+
label: S("ggnomad.activity.maxParticipants", "Max participants"),
|
|
68
|
+
value: String(D.maxParticipants)
|
|
69
|
+
}),
|
|
70
|
+
/* @__PURE__ */ b(r, {
|
|
71
|
+
label: S("ggnomad.activity.price", "Price"),
|
|
72
|
+
value: `${D.currency} ${Number(D.price).toFixed(2)}`
|
|
73
|
+
})
|
|
74
|
+
]
|
|
75
|
+
})]
|
|
76
|
+
}), /* @__PURE__ */ b(n, {
|
|
77
|
+
title: S("ggnomad.activity.safety", "Safety information"),
|
|
78
|
+
children: /* @__PURE__ */ x("div", {
|
|
79
|
+
className: "flex items-start gap-2 text-sm text-text-primary",
|
|
80
|
+
children: [/* @__PURE__ */ b(u, {
|
|
81
|
+
className: "mt-0.5 size-4 flex-shrink-0 text-status-success-text",
|
|
82
|
+
"aria-hidden": "true"
|
|
83
|
+
}), /* @__PURE__ */ b("p", { children: D.safetyInfo ?? S("ggnomad.activity.defaultSafety", "Standard provider safety policy applies.") })]
|
|
84
|
+
})
|
|
78
85
|
})]
|
|
79
|
-
}), /* @__PURE__ */ b(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}), /* @__PURE__ */ b("p", { children: D.safetyInfo ?? S("ggnomad.activity.defaultSafety", "Standard provider safety policy applies.") })]
|
|
87
|
-
})
|
|
88
|
-
})]
|
|
86
|
+
}), /* @__PURE__ */ b("div", { children: /* @__PURE__ */ b(s, {
|
|
87
|
+
bookingType: "ACTIVITY",
|
|
88
|
+
itemId: D.id ?? T,
|
|
89
|
+
itemName: D.name,
|
|
90
|
+
unitPrice: D.price ?? 0,
|
|
91
|
+
currency: D.currency ?? "USD"
|
|
92
|
+
}) })]
|
|
89
93
|
})
|
|
90
94
|
] }) : /* @__PURE__ */ b(g, {
|
|
91
95
|
illustration: "empty-data",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActivityDetailsPage.js","names":[],"sources":["../../../src/ggnomad/pages/ActivityDetailsPage.tsx"],"sourcesContent":["import { useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport { Activity,
|
|
1
|
+
{"version":3,"file":"ActivityDetailsPage.js","names":[],"sources":["../../../src/ggnomad/pages/ActivityDetailsPage.tsx"],"sourcesContent":["import { useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport { Activity, Compass, ShieldCheck } from 'lucide-react';\nimport { GlassCard, IllustratedEmptyState, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';\n\nimport { GGNOMAD_ACTIVITY_QUERY } from '../graphql';\nimport { useGGNomad } from '../providers/GGNomadProvider';\nimport { joinPath } from '../utils/navigation';\nimport { PageShell } from './PageShell';\nimport { DetailRow, SectionCard, DetailHero, BookingPanel } from '../components';\n\nexport function ActivityDetailsPage() {\n const { t } = useI18n();\n const navigate = useNavigate();\n const { basePath = '/' } = useGGNomad();\n const { id = '' } = useParams();\n const { data } = useQuery(\n GGNOMAD_ACTIVITY_QUERY as TypedDocumentNode<\n {\n ggnomadActivity: {\n id: string;\n name: string;\n category: string;\n duration: string;\n maxParticipants: number;\n currency: string;\n price: number;\n safetyInfo?: string;\n images?: string[];\n } | null;\n },\n { id: string }\n >,\n { variables: { id }, skip: !id }\n );\n const activity = data?.ggnomadActivity;\n\n return (\n <PageShell\n title={activity?.name ?? t('ggnomad.activity.fallbackTitle', 'Activity details')}\n subtitle={t('ggnomad.activity.subtitle', 'Safety, inclusions and participation details')}\n >\n {!activity ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('ggnomad.activity.notFoundTitle', 'No activity found')}\n description={t(\n 'ggnomad.activity.notFoundDescription',\n 'This activity is unavailable or may have been removed.'\n )}\n />\n ) : (\n <>\n <DetailHero image={activity.images?.[0]} alt={activity.name} />\n <PagePurpose icon={<Activity className=\"size-4\" />}>\n {t(\n 'ggnomad.activity.purpose',\n 'Everything you need to know before joining this activity — its category, duration, group size, price and the safety policy that applies — so you can be confident it fits your group before you book.'\n )}\n </PagePurpose>\n\n <NextSteps\n storageKey=\"ggnomad-activity-detail\"\n steps={[\n {\n id: 'browse',\n label: t('ggnomad.activity.next.browse', 'Explore more experiences'),\n description: t(\n 'ggnomad.activity.next.browseDesc',\n 'Return to Tourism to compare tours and activities.'\n ),\n icon: <Compass className=\"size-4\" />,\n onClick: () => navigate(joinPath(basePath, 'tourism')),\n },\n ]}\n />\n\n <div className=\"grid gap-4 lg:grid-cols-3\">\n <div className=\"lg:col-span-2 space-y-4\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam p-5\">\n <h2 className=\"mb-4 text-lg font-medium tracking-tight text-text-primary\">\n {t('ggnomad.activity.details', 'Details')}\n </h2>\n <dl className=\"space-y-2 text-sm\">\n <DetailRow\n label={t('ggnomad.activity.category', 'Category')}\n value={activity.category}\n />\n <DetailRow\n label={t('ggnomad.activity.duration', 'Duration')}\n value={activity.duration}\n />\n <DetailRow\n label={t('ggnomad.activity.maxParticipants', 'Max participants')}\n value={String(activity.maxParticipants)}\n />\n <DetailRow\n label={t('ggnomad.activity.price', 'Price')}\n value={`${activity.currency} ${Number(activity.price).toFixed(2)}`}\n />\n </dl>\n </GlassCard>\n <SectionCard title={t('ggnomad.activity.safety', 'Safety information')}>\n <div className=\"flex items-start gap-2 text-sm text-text-primary\">\n <ShieldCheck\n className=\"mt-0.5 size-4 flex-shrink-0 text-status-success-text\"\n aria-hidden=\"true\"\n />\n <p>\n {activity.safetyInfo ??\n t(\n 'ggnomad.activity.defaultSafety',\n 'Standard provider safety policy applies.'\n )}\n </p>\n </div>\n </SectionCard>\n </div>\n <div>\n <BookingPanel\n bookingType=\"ACTIVITY\"\n itemId={activity.id ?? id}\n itemName={activity.name}\n unitPrice={activity.price ?? 0}\n currency={activity.currency ?? 'USD'}\n />\n </div>\n </div>\n </>\n )}\n </PageShell>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAaA,SAAgB,IAAsB;CACpC,IAAM,EAAE,SAAM,GAAS,EACjB,IAAW,GAAa,EACxB,EAAE,cAAW,QAAQ,GAAY,EACjC,EAAE,QAAK,OAAO,GAAW,EACzB,EAAE,YAAS,EACf,GAgBA;EAAE,WAAW,EAAE,OAAI;EAAE,MAAM,CAAC;EAAI,CACjC,EACK,IAAW,GAAM;AAEvB,QACE,kBAAC,GAAD;EACE,OAAO,GAAU,QAAQ,EAAE,kCAAkC,mBAAmB;EAChF,UAAU,EAAE,6BAA6B,+CAA+C;YAEtF,IAUA,kBAAA,GAAA,EAAA,UAAA;GACE,kBAAC,GAAD;IAAY,OAAO,EAAS,SAAS;IAAI,KAAK,EAAS;IAAQ,CAAA;GAC/D,kBAAC,GAAD;IAAa,MAAM,kBAAC,GAAD,EAAU,WAAU,UAAW,CAAA;cAC/C,EACC,4BACA,wMACD;IACW,CAAA;GAEd,kBAAC,GAAD;IACE,YAAW;IACX,OAAO,CACL;KACE,IAAI;KACJ,OAAO,EAAE,gCAAgC,2BAA2B;KACpE,aAAa,EACX,oCACA,qDACD;KACD,MAAM,kBAAC,GAAD,EAAS,WAAU,UAAW,CAAA;KACpC,eAAe,EAAS,EAAS,GAAU,UAAU,CAAC;KACvD,CACF;IACD,CAAA;GAEF,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MAAW,WAAU;MAAQ,MAAA;MAAK,WAAU;gBAA5C,CACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAE,4BAA4B,UAAU;OACtC,CAAA,EACL,kBAAC,MAAD;OAAI,WAAU;iBAAd;QACE,kBAAC,GAAD;SACE,OAAO,EAAE,6BAA6B,WAAW;SACjD,OAAO,EAAS;SAChB,CAAA;QACF,kBAAC,GAAD;SACE,OAAO,EAAE,6BAA6B,WAAW;SACjD,OAAO,EAAS;SAChB,CAAA;QACF,kBAAC,GAAD;SACE,OAAO,EAAE,oCAAoC,mBAAmB;SAChE,OAAO,OAAO,EAAS,gBAAgB;SACvC,CAAA;QACF,kBAAC,GAAD;SACE,OAAO,EAAE,0BAA0B,QAAQ;SAC3C,OAAO,GAAG,EAAS,SAAS,GAAG,OAAO,EAAS,MAAM,CAAC,QAAQ,EAAE;SAChE,CAAA;QACC;SACK;SACZ,kBAAC,GAAD;MAAa,OAAO,EAAE,2BAA2B,qBAAqB;gBACpE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD;QACE,WAAU;QACV,eAAY;QACZ,CAAA,EACF,kBAAC,KAAD,EAAA,UACG,EAAS,cACR,EACE,kCACA,2CACD,EACD,CAAA,CACA;;MACM,CAAA,CACV;QACN,kBAAC,OAAD,EAAA,UACE,kBAAC,GAAD;KACE,aAAY;KACZ,QAAQ,EAAS,MAAM;KACvB,UAAU,EAAS;KACnB,WAAW,EAAS,SAAS;KAC7B,UAAU,EAAS,YAAY;KAC/B,CAAA,EACE,CAAA,CACF;;GACL,EAAA,CAAA,GArFH,kBAAC,GAAD;GACE,cAAa;GACb,OAAO,EAAE,kCAAkC,oBAAoB;GAC/D,aAAa,EACX,wCACA,yDACD;GACD,CAAA;EAgFM,CAAA"}
|
|
@@ -2,8 +2,8 @@ import { CANCEL_GGNOMAD_BOOKING_MUTATION as e, CREATE_GGNOMAD_BOOKING_MUTATION a
|
|
|
2
2
|
import { PageShell as i } from "./PageShell.js";
|
|
3
3
|
import { StatusBadge as a } from "../components/StatusBadge.js";
|
|
4
4
|
import { EntityCard as o } from "../components/EntityCard.js";
|
|
5
|
-
import "../components/index.js";
|
|
6
5
|
import { notify as s } from "../utils/notify.js";
|
|
6
|
+
import "../components/index.js";
|
|
7
7
|
import { useState as c } from "react";
|
|
8
8
|
import { CalendarCheck as l, Compass as u, Hotel as d, Plus as f, Ticket as p, XCircle as m } from "lucide-react";
|
|
9
9
|
import { useI18n as h } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
@@ -3,10 +3,11 @@ import { PageShell as t } from "./PageShell.js";
|
|
|
3
3
|
import { SectionCard as n } from "../components/SectionCard.js";
|
|
4
4
|
import { DetailRow as r } from "../components/DetailRow.js";
|
|
5
5
|
import { DetailHero as i } from "../components/DetailHero.js";
|
|
6
|
-
import "../components/index.js";
|
|
7
6
|
import { useGGNomad as a } from "../providers/GGNomadProvider.js";
|
|
8
7
|
import { joinPath as o } from "../utils/navigation.js";
|
|
9
|
-
import {
|
|
8
|
+
import { BookingPanel as s } from "../components/BookingPanel.js";
|
|
9
|
+
import "../components/index.js";
|
|
10
|
+
import { Mic2 as c, Ticket as l } from "lucide-react";
|
|
10
11
|
import { useI18n as u } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
11
12
|
import { useNavigate as d, useParams as f } from "react-router-dom";
|
|
12
13
|
import { useQuery as p } from "@apollo/client/react";
|
|
@@ -33,12 +34,6 @@ function x() {
|
|
|
33
34
|
/* @__PURE__ */ y(g, {
|
|
34
35
|
storageKey: "ggnomad-event-detail",
|
|
35
36
|
steps: [{
|
|
36
|
-
id: "book",
|
|
37
|
-
label: x("ggnomad.event.next.book", "Book tickets"),
|
|
38
|
-
description: x("ggnomad.event.next.bookDesc", "Reserve seats and track them under Bookings."),
|
|
39
|
-
icon: /* @__PURE__ */ y(s, { className: "size-4" }),
|
|
40
|
-
onClick: () => S(o(C, "bookings"))
|
|
41
|
-
}, {
|
|
42
37
|
id: "browse",
|
|
43
38
|
label: x("ggnomad.event.next.browse", "See more events"),
|
|
44
39
|
description: x("ggnomad.event.next.browseDesc", "Return to Entertainment for other live experiences."),
|
|
@@ -47,48 +42,58 @@ function x() {
|
|
|
47
42
|
}]
|
|
48
43
|
}),
|
|
49
44
|
/* @__PURE__ */ b("div", {
|
|
50
|
-
className: "grid gap-4 lg:grid-cols-
|
|
51
|
-
children: [/* @__PURE__ */ b(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
className: "
|
|
57
|
-
children:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
45
|
+
className: "grid gap-4 lg:grid-cols-3",
|
|
46
|
+
children: [/* @__PURE__ */ b("div", {
|
|
47
|
+
className: "lg:col-span-2 space-y-4",
|
|
48
|
+
children: [/* @__PURE__ */ b(m, {
|
|
49
|
+
treatment: "glass",
|
|
50
|
+
glow: !0,
|
|
51
|
+
className: "border-border-seam p-5",
|
|
52
|
+
children: [/* @__PURE__ */ y("h2", {
|
|
53
|
+
className: "mb-4 text-lg font-medium tracking-tight text-text-primary",
|
|
54
|
+
children: x("ggnomad.event.details", "Details")
|
|
55
|
+
}), /* @__PURE__ */ b("dl", {
|
|
56
|
+
className: "space-y-2 text-sm",
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ y(r, {
|
|
59
|
+
label: x("ggnomad.event.category", "Category"),
|
|
60
|
+
value: E.category
|
|
61
|
+
}),
|
|
62
|
+
/* @__PURE__ */ y(r, {
|
|
63
|
+
label: x("ggnomad.event.starts", "Starts"),
|
|
64
|
+
value: new Date(E.startsAt).toLocaleString()
|
|
65
|
+
}),
|
|
66
|
+
/* @__PURE__ */ y(r, {
|
|
67
|
+
label: x("ggnomad.event.ends", "Ends"),
|
|
68
|
+
value: E.endsAt ? new Date(E.endsAt).toLocaleString() : x("ggnomad.event.na", "N/A")
|
|
69
|
+
}),
|
|
70
|
+
/* @__PURE__ */ y(r, {
|
|
71
|
+
label: x("ggnomad.event.price", "Price"),
|
|
72
|
+
value: `${E.currency} ${Number(E.price).toFixed(2)}`
|
|
73
|
+
})
|
|
74
|
+
]
|
|
75
|
+
})]
|
|
76
|
+
}), /* @__PURE__ */ y(n, {
|
|
77
|
+
title: x("ggnomad.event.performers", "Performers"),
|
|
78
|
+
children: /* @__PURE__ */ y("ul", {
|
|
79
|
+
className: "space-y-2 text-sm",
|
|
80
|
+
children: (E.performers ?? []).map((e) => /* @__PURE__ */ b("li", {
|
|
81
|
+
className: "flex items-start gap-2 text-text-primary",
|
|
82
|
+
children: [/* @__PURE__ */ y(c, {
|
|
83
|
+
className: "mt-0.5 size-4 flex-shrink-0 text-action-primary-bg",
|
|
84
|
+
"aria-hidden": "true"
|
|
85
|
+
}), e]
|
|
86
|
+
}, e))
|
|
87
|
+
})
|
|
78
88
|
})]
|
|
79
|
-
}), /* @__PURE__ */ y(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
"aria-hidden": "true"
|
|
88
|
-
}), e]
|
|
89
|
-
}, e))
|
|
90
|
-
})
|
|
91
|
-
})]
|
|
89
|
+
}), /* @__PURE__ */ y("div", { children: /* @__PURE__ */ y(s, {
|
|
90
|
+
bookingType: "EVENT",
|
|
91
|
+
itemId: E.id ?? w,
|
|
92
|
+
itemName: E.name,
|
|
93
|
+
unitPrice: E.price ?? 0,
|
|
94
|
+
currency: E.currency ?? "USD",
|
|
95
|
+
eventDate: E.startsAt
|
|
96
|
+
}) })]
|
|
92
97
|
})
|
|
93
98
|
] }) : /* @__PURE__ */ y(h, {
|
|
94
99
|
illustration: "empty-data",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EventDetailsPage.js","names":[],"sources":["../../../src/ggnomad/pages/EventDetailsPage.tsx"],"sourcesContent":["import { useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport {
|
|
1
|
+
{"version":3,"file":"EventDetailsPage.js","names":[],"sources":["../../../src/ggnomad/pages/EventDetailsPage.tsx"],"sourcesContent":["import { useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport { Mic2, Ticket } from 'lucide-react';\nimport { GlassCard, IllustratedEmptyState, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';\n\nimport { GGNOMAD_EVENT_QUERY } from '../graphql';\nimport { useGGNomad } from '../providers/GGNomadProvider';\nimport { joinPath } from '../utils/navigation';\nimport { PageShell } from './PageShell';\nimport { DetailRow, SectionCard, DetailHero, BookingPanel } from '../components';\n\nexport function EventDetailsPage() {\n const { t } = useI18n();\n const navigate = useNavigate();\n const { basePath = '/' } = useGGNomad();\n const { id = '' } = useParams();\n const { data } = useQuery(\n GGNOMAD_EVENT_QUERY as TypedDocumentNode<\n {\n ggnomadEvent: {\n id: string;\n name: string;\n category: string;\n startsAt: string;\n endsAt?: string;\n currency: string;\n price: number;\n performers: string[];\n images?: string[];\n } | null;\n },\n { id: string }\n >,\n { variables: { id }, skip: !id }\n );\n const event = data?.ggnomadEvent;\n\n return (\n <PageShell\n title={event?.name ?? t('ggnomad.event.fallbackTitle', 'Event details')}\n subtitle={t('ggnomad.event.subtitle', 'Live event details, venue and lineup')}\n >\n {!event ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('ggnomad.event.notFoundTitle', 'No event found')}\n description={t(\n 'ggnomad.event.notFoundDescription',\n 'This event is unavailable or may have been removed.'\n )}\n />\n ) : (\n <>\n <DetailHero image={event.images?.[0]} alt={event.name} />\n <PagePurpose icon={<Ticket className=\"size-4\" />}>\n {t(\n 'ggnomad.event.purpose',\n 'All the details for this live event in one place — category, start and end times, ticket price and the full lineup — so you can decide and book tickets before they sell out.'\n )}\n </PagePurpose>\n\n <NextSteps\n storageKey=\"ggnomad-event-detail\"\n steps={[\n {\n id: 'browse',\n label: t('ggnomad.event.next.browse', 'See more events'),\n description: t(\n 'ggnomad.event.next.browseDesc',\n 'Return to Entertainment for other live experiences.'\n ),\n icon: <Ticket className=\"size-4\" />,\n onClick: () => navigate(joinPath(basePath, 'entertainment')),\n },\n ]}\n />\n\n <div className=\"grid gap-4 lg:grid-cols-3\">\n <div className=\"lg:col-span-2 space-y-4\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam p-5\">\n <h2 className=\"mb-4 text-lg font-medium tracking-tight text-text-primary\">\n {t('ggnomad.event.details', 'Details')}\n </h2>\n <dl className=\"space-y-2 text-sm\">\n <DetailRow\n label={t('ggnomad.event.category', 'Category')}\n value={event.category}\n />\n <DetailRow\n label={t('ggnomad.event.starts', 'Starts')}\n value={new Date(event.startsAt).toLocaleString()}\n />\n <DetailRow\n label={t('ggnomad.event.ends', 'Ends')}\n value={\n event.endsAt\n ? new Date(event.endsAt).toLocaleString()\n : t('ggnomad.event.na', 'N/A')\n }\n />\n <DetailRow\n label={t('ggnomad.event.price', 'Price')}\n value={`${event.currency} ${Number(event.price).toFixed(2)}`}\n />\n </dl>\n </GlassCard>\n <SectionCard title={t('ggnomad.event.performers', 'Performers')}>\n <ul className=\"space-y-2 text-sm\">\n {(event.performers ?? []).map((performer) => (\n <li key={performer} className=\"flex items-start gap-2 text-text-primary\">\n <Mic2\n className=\"mt-0.5 size-4 flex-shrink-0 text-action-primary-bg\"\n aria-hidden=\"true\"\n />\n {performer}\n </li>\n ))}\n </ul>\n </SectionCard>\n </div>\n <div>\n <BookingPanel\n bookingType=\"EVENT\"\n itemId={event.id ?? id}\n itemName={event.name}\n unitPrice={event.price ?? 0}\n currency={event.currency ?? 'USD'}\n eventDate={event.startsAt}\n />\n </div>\n </div>\n </>\n )}\n </PageShell>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAaA,SAAgB,IAAmB;CACjC,IAAM,EAAE,SAAM,GAAS,EACjB,IAAW,GAAa,EACxB,EAAE,cAAW,QAAQ,GAAY,EACjC,EAAE,QAAK,OAAO,GAAW,EACzB,EAAE,YAAS,EACf,GAgBA;EAAE,WAAW,EAAE,OAAI;EAAE,MAAM,CAAC;EAAI,CACjC,EACK,IAAQ,GAAM;AAEpB,QACE,kBAAC,GAAD;EACE,OAAO,GAAO,QAAQ,EAAE,+BAA+B,gBAAgB;EACvE,UAAU,EAAE,0BAA0B,uCAAuC;YAE3E,IAUA,kBAAA,GAAA,EAAA,UAAA;GACE,kBAAC,GAAD;IAAY,OAAO,EAAM,SAAS;IAAI,KAAK,EAAM;IAAQ,CAAA;GACzD,kBAAC,GAAD;IAAa,MAAM,kBAAC,GAAD,EAAQ,WAAU,UAAW,CAAA;cAC7C,EACC,yBACA,gLACD;IACW,CAAA;GAEd,kBAAC,GAAD;IACE,YAAW;IACX,OAAO,CACL;KACE,IAAI;KACJ,OAAO,EAAE,6BAA6B,kBAAkB;KACxD,aAAa,EACX,iCACA,sDACD;KACD,MAAM,kBAAC,GAAD,EAAQ,WAAU,UAAW,CAAA;KACnC,eAAe,EAAS,EAAS,GAAU,gBAAgB,CAAC;KAC7D,CACF;IACD,CAAA;GAEF,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MAAW,WAAU;MAAQ,MAAA;MAAK,WAAU;gBAA5C,CACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAE,yBAAyB,UAAU;OACnC,CAAA,EACL,kBAAC,MAAD;OAAI,WAAU;iBAAd;QACE,kBAAC,GAAD;SACE,OAAO,EAAE,0BAA0B,WAAW;SAC9C,OAAO,EAAM;SACb,CAAA;QACF,kBAAC,GAAD;SACE,OAAO,EAAE,wBAAwB,SAAS;SAC1C,OAAO,IAAI,KAAK,EAAM,SAAS,CAAC,gBAAgB;SAChD,CAAA;QACF,kBAAC,GAAD;SACE,OAAO,EAAE,sBAAsB,OAAO;SACtC,OACE,EAAM,SACF,IAAI,KAAK,EAAM,OAAO,CAAC,gBAAgB,GACvC,EAAE,oBAAoB,MAAM;SAElC,CAAA;QACF,kBAAC,GAAD;SACE,OAAO,EAAE,uBAAuB,QAAQ;SACxC,OAAO,GAAG,EAAM,SAAS,GAAG,OAAO,EAAM,MAAM,CAAC,QAAQ,EAAE;SAC1D,CAAA;QACC;SACK;SACZ,kBAAC,GAAD;MAAa,OAAO,EAAE,4BAA4B,aAAa;gBAC7D,kBAAC,MAAD;OAAI,WAAU;kBACV,EAAM,cAAc,EAAE,EAAE,KAAK,MAC7B,kBAAC,MAAD;QAAoB,WAAU;kBAA9B,CACE,kBAAC,GAAD;SACE,WAAU;SACV,eAAY;SACZ,CAAA,EACD,EACE;UANI,EAMJ,CACL;OACC,CAAA;MACO,CAAA,CACV;QACN,kBAAC,OAAD,EAAA,UACE,kBAAC,GAAD;KACE,aAAY;KACZ,QAAQ,EAAM,MAAM;KACpB,UAAU,EAAM;KAChB,WAAW,EAAM,SAAS;KAC1B,UAAU,EAAM,YAAY;KAC5B,WAAW,EAAM;KACjB,CAAA,EACE,CAAA,CACF;;GACL,EAAA,CAAA,GAxFH,kBAAC,GAAD;GACE,cAAa;GACb,OAAO,EAAE,+BAA+B,iBAAiB;GACzD,aAAa,EACX,qCACA,sDACD;GACD,CAAA;EAmFM,CAAA"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { GGNOMAD_FAVORITES_QUERY as e, GGNOMAD_FAVORITE_TARGETS_QUERY as t, TOGGLE_GGNOMAD_FAVORITE_MUTATION as n } from "../graphql.js";
|
|
2
2
|
import { PageShell as r } from "./PageShell.js";
|
|
3
3
|
import { EntityCard as i } from "../components/EntityCard.js";
|
|
4
|
-
import "../components/index.js";
|
|
5
4
|
import { notify as a } from "../utils/notify.js";
|
|
5
|
+
import "../components/index.js";
|
|
6
6
|
import { useMemo as o } from "react";
|
|
7
7
|
import { Heart as s } from "lucide-react";
|
|
8
8
|
import { useI18n as c } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
@@ -3,10 +3,11 @@ import { PageShell as t } from "./PageShell.js";
|
|
|
3
3
|
import { SectionCard as n } from "../components/SectionCard.js";
|
|
4
4
|
import { DetailRow as r } from "../components/DetailRow.js";
|
|
5
5
|
import { DetailHero as i } from "../components/DetailHero.js";
|
|
6
|
-
import "../components/index.js";
|
|
7
6
|
import { useGGNomad as a } from "../providers/GGNomadProvider.js";
|
|
8
7
|
import { joinPath as o } from "../utils/navigation.js";
|
|
9
|
-
import {
|
|
8
|
+
import { BookingPanel as s } from "../components/BookingPanel.js";
|
|
9
|
+
import "../components/index.js";
|
|
10
|
+
import { Hotel as c } from "lucide-react";
|
|
10
11
|
import { useI18n as l } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
11
12
|
import { useNavigate as u, useParams as d } from "react-router-dom";
|
|
12
13
|
import { useQuery as f } from "@apollo/client/react";
|
|
@@ -33,12 +34,6 @@ function b() {
|
|
|
33
34
|
/* @__PURE__ */ v(h, {
|
|
34
35
|
storageKey: "ggnomad-property-detail",
|
|
35
36
|
steps: [{
|
|
36
|
-
id: "book",
|
|
37
|
-
label: b("ggnomad.property.next.book", "Book this stay"),
|
|
38
|
-
description: b("ggnomad.property.next.bookDesc", "Reserve these dates and track it under Bookings."),
|
|
39
|
-
icon: /* @__PURE__ */ v(s, { className: "size-4" }),
|
|
40
|
-
onClick: () => x(o(S, "bookings"))
|
|
41
|
-
}, {
|
|
42
37
|
id: "browse",
|
|
43
38
|
label: b("ggnomad.property.next.browse", "Compare other stays"),
|
|
44
39
|
description: b("ggnomad.property.next.browseDesc", "Go back to hospitality listings to compare options."),
|
|
@@ -47,56 +42,66 @@ function b() {
|
|
|
47
42
|
}]
|
|
48
43
|
}),
|
|
49
44
|
/* @__PURE__ */ y("div", {
|
|
50
|
-
className: "grid gap-4 lg:grid-cols-
|
|
51
|
-
children: [/* @__PURE__ */ y(
|
|
52
|
-
|
|
53
|
-
children: [
|
|
54
|
-
|
|
55
|
-
className: "text-sm text-text-secondary",
|
|
56
|
-
children: b("ggnomad.property.type", "Type")
|
|
57
|
-
}),
|
|
58
|
-
/* @__PURE__ */ v("p", {
|
|
59
|
-
className: "text-text-primary",
|
|
60
|
-
children: T.type
|
|
61
|
-
}),
|
|
62
|
-
/* @__PURE__ */ v("p", {
|
|
63
|
-
className: "mt-3 text-sm text-text-secondary",
|
|
64
|
-
children: b("ggnomad.property.description", "Description")
|
|
65
|
-
}),
|
|
66
|
-
/* @__PURE__ */ v("p", {
|
|
67
|
-
className: "text-text-primary",
|
|
68
|
-
children: T.description ?? b("ggnomad.property.noDescription", "No description")
|
|
69
|
-
})
|
|
70
|
-
]
|
|
71
|
-
}), /* @__PURE__ */ y(p, {
|
|
72
|
-
treatment: "glass",
|
|
73
|
-
glow: !0,
|
|
74
|
-
className: "border-border-seam p-5",
|
|
75
|
-
children: [/* @__PURE__ */ v("h2", {
|
|
76
|
-
className: "mb-4 text-lg font-medium tracking-tight text-text-primary",
|
|
77
|
-
children: b("ggnomad.property.details", "Details")
|
|
78
|
-
}), /* @__PURE__ */ y("dl", {
|
|
79
|
-
className: "space-y-2 text-sm",
|
|
45
|
+
className: "grid gap-4 lg:grid-cols-3",
|
|
46
|
+
children: [/* @__PURE__ */ y("div", {
|
|
47
|
+
className: "lg:col-span-2 space-y-4",
|
|
48
|
+
children: [/* @__PURE__ */ y(n, {
|
|
49
|
+
title: b("ggnomad.property.about", "About"),
|
|
80
50
|
children: [
|
|
81
|
-
/* @__PURE__ */ v(
|
|
82
|
-
|
|
83
|
-
|
|
51
|
+
/* @__PURE__ */ v("p", {
|
|
52
|
+
className: "text-sm text-text-secondary",
|
|
53
|
+
children: b("ggnomad.property.type", "Type")
|
|
84
54
|
}),
|
|
85
|
-
/* @__PURE__ */ v(
|
|
86
|
-
|
|
87
|
-
|
|
55
|
+
/* @__PURE__ */ v("p", {
|
|
56
|
+
className: "text-text-primary",
|
|
57
|
+
children: T.type
|
|
88
58
|
}),
|
|
89
|
-
/* @__PURE__ */ v(
|
|
90
|
-
|
|
91
|
-
|
|
59
|
+
/* @__PURE__ */ v("p", {
|
|
60
|
+
className: "mt-3 text-sm text-text-secondary",
|
|
61
|
+
children: b("ggnomad.property.description", "Description")
|
|
92
62
|
}),
|
|
93
|
-
/* @__PURE__ */ v(
|
|
94
|
-
|
|
95
|
-
|
|
63
|
+
/* @__PURE__ */ v("p", {
|
|
64
|
+
className: "text-text-primary",
|
|
65
|
+
children: T.description ?? b("ggnomad.property.noDescription", "No description")
|
|
96
66
|
})
|
|
97
67
|
]
|
|
68
|
+
}), /* @__PURE__ */ y(p, {
|
|
69
|
+
treatment: "glass",
|
|
70
|
+
glow: !0,
|
|
71
|
+
className: "border-border-seam p-5",
|
|
72
|
+
children: [/* @__PURE__ */ v("h2", {
|
|
73
|
+
className: "mb-4 text-lg font-medium tracking-tight text-text-primary",
|
|
74
|
+
children: b("ggnomad.property.details", "Details")
|
|
75
|
+
}), /* @__PURE__ */ y("dl", {
|
|
76
|
+
className: "space-y-2 text-sm",
|
|
77
|
+
children: [
|
|
78
|
+
/* @__PURE__ */ v(r, {
|
|
79
|
+
label: b("ggnomad.property.price", "Price"),
|
|
80
|
+
value: `${T.currency} ${Number(T.pricePerNight).toFixed(2)}`
|
|
81
|
+
}),
|
|
82
|
+
/* @__PURE__ */ v(r, {
|
|
83
|
+
label: b("ggnomad.property.guests", "Guests"),
|
|
84
|
+
value: String(T.maxGuests)
|
|
85
|
+
}),
|
|
86
|
+
/* @__PURE__ */ v(r, {
|
|
87
|
+
label: b("ggnomad.property.rating", "Rating"),
|
|
88
|
+
value: String(T.rating ?? b("ggnomad.property.noRating", "N/A"))
|
|
89
|
+
}),
|
|
90
|
+
/* @__PURE__ */ v(r, {
|
|
91
|
+
label: b("ggnomad.property.provider", "Provider"),
|
|
92
|
+
value: T.provider?.name ?? b("ggnomad.property.unassigned", "Unassigned")
|
|
93
|
+
})
|
|
94
|
+
]
|
|
95
|
+
})]
|
|
98
96
|
})]
|
|
99
|
-
})
|
|
97
|
+
}), /* @__PURE__ */ v("div", { children: /* @__PURE__ */ v(s, {
|
|
98
|
+
bookingType: "PROPERTY",
|
|
99
|
+
itemId: T.id ?? C,
|
|
100
|
+
itemName: T.name,
|
|
101
|
+
unitPrice: T.pricePerNight ?? 0,
|
|
102
|
+
currency: T.currency ?? "USD",
|
|
103
|
+
nights: 1
|
|
104
|
+
}) })]
|
|
100
105
|
})
|
|
101
106
|
] }) : /* @__PURE__ */ v(m, {
|
|
102
107
|
illustration: "empty-data",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PropertyDetailsPage.js","names":[],"sources":["../../../src/ggnomad/pages/PropertyDetailsPage.tsx"],"sourcesContent":["import { useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport {
|
|
1
|
+
{"version":3,"file":"PropertyDetailsPage.js","names":[],"sources":["../../../src/ggnomad/pages/PropertyDetailsPage.tsx"],"sourcesContent":["import { useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport { Hotel } from 'lucide-react';\nimport { GlassCard, IllustratedEmptyState, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';\n\nimport { GGNOMAD_PROPERTY_QUERY } from '../graphql';\nimport { useGGNomad } from '../providers/GGNomadProvider';\nimport { joinPath } from '../utils/navigation';\nimport { PageShell } from './PageShell';\nimport { DetailRow, SectionCard, DetailHero, BookingPanel } from '../components';\n\nexport function PropertyDetailsPage() {\n const { t } = useI18n();\n const navigate = useNavigate();\n const { basePath = '/' } = useGGNomad();\n const { id = '' } = useParams();\n const { data } = useQuery(\n GGNOMAD_PROPERTY_QUERY as TypedDocumentNode<\n {\n ggnomadProperty: {\n id: string;\n name: string;\n type: string;\n description?: string;\n currency: string;\n pricePerNight: number;\n maxGuests: number;\n rating?: number;\n provider?: { name: string };\n images?: string[];\n } | null;\n },\n { id: string }\n >,\n { variables: { id }, skip: !id }\n );\n const property = data?.ggnomadProperty;\n\n return (\n <PageShell\n title={property?.name ?? t('ggnomad.property.fallbackTitle', 'Property details')}\n subtitle={t('ggnomad.property.subtitle', 'Detailed hospitality listing view')}\n >\n {!property ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('ggnomad.property.notFoundTitle', 'No property found')}\n description={t(\n 'ggnomad.property.notFoundDescription',\n 'This property is unavailable or may have been removed.'\n )}\n />\n ) : (\n <>\n <DetailHero image={property.images?.[0]} alt={property.name} />\n <PagePurpose icon={<Hotel className=\"size-4\" />}>\n {t(\n 'ggnomad.property.purpose',\n 'Everything you need to decide on this stay — its type, description, nightly price, guest capacity, rating and the provider behind it — before you reserve it.'\n )}\n </PagePurpose>\n\n <NextSteps\n storageKey=\"ggnomad-property-detail\"\n steps={[\n {\n id: 'browse',\n label: t('ggnomad.property.next.browse', 'Compare other stays'),\n description: t(\n 'ggnomad.property.next.browseDesc',\n 'Go back to hospitality listings to compare options.'\n ),\n icon: <Hotel className=\"size-4\" />,\n onClick: () => navigate(joinPath(basePath, 'hospitality')),\n },\n ]}\n />\n\n <div className=\"grid gap-4 lg:grid-cols-3\">\n <div className=\"lg:col-span-2 space-y-4\">\n <SectionCard title={t('ggnomad.property.about', 'About')}>\n <p className=\"text-sm text-text-secondary\">{t('ggnomad.property.type', 'Type')}</p>\n <p className=\"text-text-primary\">{property.type}</p>\n <p className=\"mt-3 text-sm text-text-secondary\">\n {t('ggnomad.property.description', 'Description')}\n </p>\n <p className=\"text-text-primary\">\n {property.description ?? t('ggnomad.property.noDescription', 'No description')}\n </p>\n </SectionCard>\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam p-5\">\n <h2 className=\"mb-4 text-lg font-medium tracking-tight text-text-primary\">\n {t('ggnomad.property.details', 'Details')}\n </h2>\n <dl className=\"space-y-2 text-sm\">\n <DetailRow\n label={t('ggnomad.property.price', 'Price')}\n value={`${property.currency} ${Number(property.pricePerNight).toFixed(2)}`}\n />\n <DetailRow\n label={t('ggnomad.property.guests', 'Guests')}\n value={String(property.maxGuests)}\n />\n <DetailRow\n label={t('ggnomad.property.rating', 'Rating')}\n value={String(property.rating ?? t('ggnomad.property.noRating', 'N/A'))}\n />\n <DetailRow\n label={t('ggnomad.property.provider', 'Provider')}\n value={\n property.provider?.name ?? t('ggnomad.property.unassigned', 'Unassigned')\n }\n />\n </dl>\n </GlassCard>\n </div>\n <div>\n <BookingPanel\n bookingType=\"PROPERTY\"\n itemId={property.id ?? id}\n itemName={property.name}\n unitPrice={property.pricePerNight ?? 0}\n currency={property.currency ?? 'USD'}\n nights={1}\n />\n </div>\n </div>\n </>\n )}\n </PageShell>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAaA,SAAgB,IAAsB;CACpC,IAAM,EAAE,SAAM,GAAS,EACjB,IAAW,GAAa,EACxB,EAAE,cAAW,QAAQ,GAAY,EACjC,EAAE,QAAK,OAAO,GAAW,EACzB,EAAE,YAAS,EACf,GAiBA;EAAE,WAAW,EAAE,OAAI;EAAE,MAAM,CAAC;EAAI,CACjC,EACK,IAAW,GAAM;AAEvB,QACE,kBAAC,GAAD;EACE,OAAO,GAAU,QAAQ,EAAE,kCAAkC,mBAAmB;EAChF,UAAU,EAAE,6BAA6B,oCAAoC;YAE3E,IAUA,kBAAA,GAAA,EAAA,UAAA;GACE,kBAAC,GAAD;IAAY,OAAO,EAAS,SAAS;IAAI,KAAK,EAAS;IAAQ,CAAA;GAC/D,kBAAC,GAAD;IAAa,MAAM,kBAAC,GAAD,EAAO,WAAU,UAAW,CAAA;cAC5C,EACC,4BACA,gKACD;IACW,CAAA;GAEd,kBAAC,GAAD;IACE,YAAW;IACX,OAAO,CACL;KACE,IAAI;KACJ,OAAO,EAAE,gCAAgC,sBAAsB;KAC/D,aAAa,EACX,oCACA,sDACD;KACD,MAAM,kBAAC,GAAD,EAAO,WAAU,UAAW,CAAA;KAClC,eAAe,EAAS,EAAS,GAAU,cAAc,CAAC;KAC3D,CACF;IACD,CAAA;GAEF,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MAAa,OAAO,EAAE,0BAA0B,QAAQ;gBAAxD;OACE,kBAAC,KAAD;QAAG,WAAU;kBAA+B,EAAE,yBAAyB,OAAO;QAAK,CAAA;OACnF,kBAAC,KAAD;QAAG,WAAU;kBAAqB,EAAS;QAAS,CAAA;OACpD,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAE,gCAAgC,cAAc;QAC/C,CAAA;OACJ,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAS,eAAe,EAAE,kCAAkC,iBAAiB;QAC5E,CAAA;OACQ;SACd,kBAAC,GAAD;MAAW,WAAU;MAAQ,MAAA;MAAK,WAAU;gBAA5C,CACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAE,4BAA4B,UAAU;OACtC,CAAA,EACL,kBAAC,MAAD;OAAI,WAAU;iBAAd;QACE,kBAAC,GAAD;SACE,OAAO,EAAE,0BAA0B,QAAQ;SAC3C,OAAO,GAAG,EAAS,SAAS,GAAG,OAAO,EAAS,cAAc,CAAC,QAAQ,EAAE;SACxE,CAAA;QACF,kBAAC,GAAD;SACE,OAAO,EAAE,2BAA2B,SAAS;SAC7C,OAAO,OAAO,EAAS,UAAU;SACjC,CAAA;QACF,kBAAC,GAAD;SACE,OAAO,EAAE,2BAA2B,SAAS;SAC7C,OAAO,OAAO,EAAS,UAAU,EAAE,6BAA6B,MAAM,CAAC;SACvE,CAAA;QACF,kBAAC,GAAD;SACE,OAAO,EAAE,6BAA6B,WAAW;SACjD,OACE,EAAS,UAAU,QAAQ,EAAE,+BAA+B,aAAa;SAE3E,CAAA;QACC;SACK;QACR;QACN,kBAAC,OAAD,EAAA,UACE,kBAAC,GAAD;KACE,aAAY;KACZ,QAAQ,EAAS,MAAM;KACvB,UAAU,EAAS;KACnB,WAAW,EAAS,iBAAiB;KACrC,UAAU,EAAS,YAAY;KAC/B,QAAQ;KACR,CAAA,EACE,CAAA,CACF;;GACL,EAAA,CAAA,GAnFH,kBAAC,GAAD;GACE,cAAa;GACb,OAAO,EAAE,kCAAkC,oBAAoB;GAC/D,aAAa,EACX,wCACA,yDACD;GACD,CAAA;EA8EM,CAAA"}
|
|
@@ -3,10 +3,11 @@ import { PageShell as t } from "./PageShell.js";
|
|
|
3
3
|
import { SectionCard as n } from "../components/SectionCard.js";
|
|
4
4
|
import { DetailRow as r } from "../components/DetailRow.js";
|
|
5
5
|
import { DetailHero as i } from "../components/DetailHero.js";
|
|
6
|
-
import "../components/index.js";
|
|
7
6
|
import { useGGNomad as a } from "../providers/GGNomadProvider.js";
|
|
8
7
|
import { joinPath as o } from "../utils/navigation.js";
|
|
9
|
-
import {
|
|
8
|
+
import { BookingPanel as s } from "../components/BookingPanel.js";
|
|
9
|
+
import "../components/index.js";
|
|
10
|
+
import { CheckCircle2 as c, Compass as l } from "lucide-react";
|
|
10
11
|
import { useI18n as u } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
11
12
|
import { useNavigate as d, useParams as f } from "react-router-dom";
|
|
12
13
|
import { useQuery as p } from "@apollo/client/react";
|
|
@@ -33,12 +34,6 @@ function x() {
|
|
|
33
34
|
/* @__PURE__ */ y(g, {
|
|
34
35
|
storageKey: "ggnomad-tour-detail",
|
|
35
36
|
steps: [{
|
|
36
|
-
id: "book",
|
|
37
|
-
label: x("ggnomad.tour.next.book", "Book this tour"),
|
|
38
|
-
description: x("ggnomad.tour.next.bookDesc", "Add it to your itinerary and track it under Bookings."),
|
|
39
|
-
icon: /* @__PURE__ */ y(s, { className: "size-4" }),
|
|
40
|
-
onClick: () => S(o(C, "bookings"))
|
|
41
|
-
}, {
|
|
42
37
|
id: "browse",
|
|
43
38
|
label: x("ggnomad.tour.next.browse", "Explore more experiences"),
|
|
44
39
|
description: x("ggnomad.tour.next.browseDesc", "Return to Tourism to compare tours and activities."),
|
|
@@ -47,48 +42,57 @@ function x() {
|
|
|
47
42
|
}]
|
|
48
43
|
}),
|
|
49
44
|
/* @__PURE__ */ b("div", {
|
|
50
|
-
className: "grid gap-4 lg:grid-cols-
|
|
51
|
-
children: [/* @__PURE__ */ b(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
className: "
|
|
57
|
-
children:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
45
|
+
className: "grid gap-4 lg:grid-cols-3",
|
|
46
|
+
children: [/* @__PURE__ */ b("div", {
|
|
47
|
+
className: "lg:col-span-2 space-y-4",
|
|
48
|
+
children: [/* @__PURE__ */ b(m, {
|
|
49
|
+
treatment: "glass",
|
|
50
|
+
glow: !0,
|
|
51
|
+
className: "border-border-seam p-5",
|
|
52
|
+
children: [/* @__PURE__ */ y("h2", {
|
|
53
|
+
className: "mb-4 text-lg font-medium tracking-tight text-text-primary",
|
|
54
|
+
children: x("ggnomad.tour.details", "Details")
|
|
55
|
+
}), /* @__PURE__ */ b("dl", {
|
|
56
|
+
className: "space-y-2 text-sm",
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ y(r, {
|
|
59
|
+
label: x("ggnomad.tour.duration", "Duration"),
|
|
60
|
+
value: E.duration
|
|
61
|
+
}),
|
|
62
|
+
/* @__PURE__ */ y(r, {
|
|
63
|
+
label: x("ggnomad.tour.difficulty", "Difficulty"),
|
|
64
|
+
value: E.difficulty ?? x("ggnomad.tour.na", "N/A")
|
|
65
|
+
}),
|
|
66
|
+
/* @__PURE__ */ y(r, {
|
|
67
|
+
label: x("ggnomad.tour.guide", "Guide"),
|
|
68
|
+
value: E.guideName ?? x("ggnomad.tour.na", "N/A")
|
|
69
|
+
}),
|
|
70
|
+
/* @__PURE__ */ y(r, {
|
|
71
|
+
label: x("ggnomad.tour.price", "Price"),
|
|
72
|
+
value: `${E.currency} ${Number(E.price).toFixed(2)}`
|
|
73
|
+
})
|
|
74
|
+
]
|
|
75
|
+
})]
|
|
76
|
+
}), /* @__PURE__ */ y(n, {
|
|
77
|
+
title: x("ggnomad.tour.highlights", "Highlights"),
|
|
78
|
+
children: /* @__PURE__ */ y("ul", {
|
|
79
|
+
className: "space-y-2 text-sm",
|
|
80
|
+
children: (E.highlights ?? []).map((e) => /* @__PURE__ */ b("li", {
|
|
81
|
+
className: "flex items-start gap-2 text-text-primary",
|
|
82
|
+
children: [/* @__PURE__ */ y(c, {
|
|
83
|
+
className: "mt-0.5 size-4 flex-shrink-0 text-status-success-text",
|
|
84
|
+
"aria-hidden": "true"
|
|
85
|
+
}), e]
|
|
86
|
+
}, e))
|
|
87
|
+
})
|
|
78
88
|
})]
|
|
79
|
-
}), /* @__PURE__ */ y(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
className: "mt-0.5 size-4 flex-shrink-0 text-status-success-text",
|
|
87
|
-
"aria-hidden": "true"
|
|
88
|
-
}), e]
|
|
89
|
-
}, e))
|
|
90
|
-
})
|
|
91
|
-
})]
|
|
89
|
+
}), /* @__PURE__ */ y("div", { children: /* @__PURE__ */ y(s, {
|
|
90
|
+
bookingType: "TOUR",
|
|
91
|
+
itemId: E.id ?? w,
|
|
92
|
+
itemName: E.name,
|
|
93
|
+
unitPrice: E.price ?? 0,
|
|
94
|
+
currency: E.currency ?? "USD"
|
|
95
|
+
}) })]
|
|
92
96
|
})
|
|
93
97
|
] }) : /* @__PURE__ */ y(h, {
|
|
94
98
|
illustration: "empty-data",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TourDetailsPage.js","names":[],"sources":["../../../src/ggnomad/pages/TourDetailsPage.tsx"],"sourcesContent":["import { useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport {
|
|
1
|
+
{"version":3,"file":"TourDetailsPage.js","names":[],"sources":["../../../src/ggnomad/pages/TourDetailsPage.tsx"],"sourcesContent":["import { useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport { CheckCircle2, Compass } from 'lucide-react';\nimport { GlassCard, IllustratedEmptyState, NextSteps, PagePurpose } from '@burdenoff/fe-libs/ui';\n\nimport { GGNOMAD_TOUR_QUERY } from '../graphql';\nimport { useGGNomad } from '../providers/GGNomadProvider';\nimport { joinPath } from '../utils/navigation';\nimport { PageShell } from './PageShell';\nimport { DetailRow, SectionCard, DetailHero, BookingPanel } from '../components';\n\nexport function TourDetailsPage() {\n const { t } = useI18n();\n const navigate = useNavigate();\n const { basePath = '/' } = useGGNomad();\n const { id = '' } = useParams();\n const { data } = useQuery(\n GGNOMAD_TOUR_QUERY as TypedDocumentNode<\n {\n ggnomadTour: {\n id: string;\n name: string;\n duration: string;\n difficulty?: string;\n guideName?: string;\n currency: string;\n price: number;\n highlights: string[];\n images?: string[];\n } | null;\n },\n { id: string }\n >,\n { variables: { id }, skip: !id }\n );\n const tour = data?.ggnomadTour;\n\n return (\n <PageShell\n title={tour?.name ?? t('ggnomad.tour.fallbackTitle', 'Tour details')}\n subtitle={t('ggnomad.tour.subtitle', 'Tour package details and booking context')}\n >\n {!tour ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('ggnomad.tour.notFoundTitle', 'No tour found')}\n description={t(\n 'ggnomad.tour.notFoundDescription',\n 'This tour is unavailable or may have been removed.'\n )}\n />\n ) : (\n <>\n <DetailHero image={tour.images?.[0]} alt={tour.name} />\n <PagePurpose icon={<Compass className=\"size-4\" />}>\n {t(\n 'ggnomad.tour.purpose',\n 'See exactly what this tour involves — duration, difficulty, your guide, price and the highlights you’ll experience — so you can confirm it fits your trip before booking.'\n )}\n </PagePurpose>\n\n <NextSteps\n storageKey=\"ggnomad-tour-detail\"\n steps={[\n {\n id: 'browse',\n label: t('ggnomad.tour.next.browse', 'Explore more experiences'),\n description: t(\n 'ggnomad.tour.next.browseDesc',\n 'Return to Tourism to compare tours and activities.'\n ),\n icon: <Compass className=\"size-4\" />,\n onClick: () => navigate(joinPath(basePath, 'tourism')),\n },\n ]}\n />\n\n <div className=\"grid gap-4 lg:grid-cols-3\">\n <div className=\"lg:col-span-2 space-y-4\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam p-5\">\n <h2 className=\"mb-4 text-lg font-medium tracking-tight text-text-primary\">\n {t('ggnomad.tour.details', 'Details')}\n </h2>\n <dl className=\"space-y-2 text-sm\">\n <DetailRow label={t('ggnomad.tour.duration', 'Duration')} value={tour.duration} />\n <DetailRow\n label={t('ggnomad.tour.difficulty', 'Difficulty')}\n value={tour.difficulty ?? t('ggnomad.tour.na', 'N/A')}\n />\n <DetailRow\n label={t('ggnomad.tour.guide', 'Guide')}\n value={tour.guideName ?? t('ggnomad.tour.na', 'N/A')}\n />\n <DetailRow\n label={t('ggnomad.tour.price', 'Price')}\n value={`${tour.currency} ${Number(tour.price).toFixed(2)}`}\n />\n </dl>\n </GlassCard>\n <SectionCard title={t('ggnomad.tour.highlights', 'Highlights')}>\n <ul className=\"space-y-2 text-sm\">\n {(tour.highlights ?? []).map((highlight) => (\n <li key={highlight} className=\"flex items-start gap-2 text-text-primary\">\n <CheckCircle2\n className=\"mt-0.5 size-4 flex-shrink-0 text-status-success-text\"\n aria-hidden=\"true\"\n />\n {highlight}\n </li>\n ))}\n </ul>\n </SectionCard>\n </div>\n <div>\n <BookingPanel\n bookingType=\"TOUR\"\n itemId={tour.id ?? id}\n itemName={tour.name}\n unitPrice={tour.price ?? 0}\n currency={tour.currency ?? 'USD'}\n />\n </div>\n </div>\n </>\n )}\n </PageShell>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAaA,SAAgB,IAAkB;CAChC,IAAM,EAAE,SAAM,GAAS,EACjB,IAAW,GAAa,EACxB,EAAE,cAAW,QAAQ,GAAY,EACjC,EAAE,QAAK,OAAO,GAAW,EACzB,EAAE,YAAS,EACf,GAgBA;EAAE,WAAW,EAAE,OAAI;EAAE,MAAM,CAAC;EAAI,CACjC,EACK,IAAO,GAAM;AAEnB,QACE,kBAAC,GAAD;EACE,OAAO,GAAM,QAAQ,EAAE,8BAA8B,eAAe;EACpE,UAAU,EAAE,yBAAyB,2CAA2C;YAE9E,IAUA,kBAAA,GAAA,EAAA,UAAA;GACE,kBAAC,GAAD;IAAY,OAAO,EAAK,SAAS;IAAI,KAAK,EAAK;IAAQ,CAAA;GACvD,kBAAC,GAAD;IAAa,MAAM,kBAAC,GAAD,EAAS,WAAU,UAAW,CAAA;cAC9C,EACC,wBACA,4KACD;IACW,CAAA;GAEd,kBAAC,GAAD;IACE,YAAW;IACX,OAAO,CACL;KACE,IAAI;KACJ,OAAO,EAAE,4BAA4B,2BAA2B;KAChE,aAAa,EACX,gCACA,qDACD;KACD,MAAM,kBAAC,GAAD,EAAS,WAAU,UAAW,CAAA;KACpC,eAAe,EAAS,EAAS,GAAU,UAAU,CAAC;KACvD,CACF;IACD,CAAA;GAEF,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MAAW,WAAU;MAAQ,MAAA;MAAK,WAAU;gBAA5C,CACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAE,wBAAwB,UAAU;OAClC,CAAA,EACL,kBAAC,MAAD;OAAI,WAAU;iBAAd;QACE,kBAAC,GAAD;SAAW,OAAO,EAAE,yBAAyB,WAAW;SAAE,OAAO,EAAK;SAAY,CAAA;QAClF,kBAAC,GAAD;SACE,OAAO,EAAE,2BAA2B,aAAa;SACjD,OAAO,EAAK,cAAc,EAAE,mBAAmB,MAAM;SACrD,CAAA;QACF,kBAAC,GAAD;SACE,OAAO,EAAE,sBAAsB,QAAQ;SACvC,OAAO,EAAK,aAAa,EAAE,mBAAmB,MAAM;SACpD,CAAA;QACF,kBAAC,GAAD;SACE,OAAO,EAAE,sBAAsB,QAAQ;SACvC,OAAO,GAAG,EAAK,SAAS,GAAG,OAAO,EAAK,MAAM,CAAC,QAAQ,EAAE;SACxD,CAAA;QACC;SACK;SACZ,kBAAC,GAAD;MAAa,OAAO,EAAE,2BAA2B,aAAa;gBAC5D,kBAAC,MAAD;OAAI,WAAU;kBACV,EAAK,cAAc,EAAE,EAAE,KAAK,MAC5B,kBAAC,MAAD;QAAoB,WAAU;kBAA9B,CACE,kBAAC,GAAD;SACE,WAAU;SACV,eAAY;SACZ,CAAA,EACD,EACE;UANI,EAMJ,CACL;OACC,CAAA;MACO,CAAA,CACV;QACN,kBAAC,OAAD,EAAA,UACE,kBAAC,GAAD;KACE,aAAY;KACZ,QAAQ,EAAK,MAAM;KACnB,UAAU,EAAK;KACf,WAAW,EAAK,SAAS;KACzB,UAAU,EAAK,YAAY;KAC3B,CAAA,EACE,CAAA,CACF;;GACL,EAAA,CAAA,GAhFH,kBAAC,GAAD;GACE,cAAa;GACb,OAAO,EAAE,8BAA8B,gBAAgB;GACvD,aAAa,EACX,oCACA,qDACD;GACD,CAAA;EA2EM,CAAA"}
|