@burdenoff/microfe-ggnomad 2026.801.1 → 2026.827.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/dist/ggnomad/components/AvailabilityPanel.d.ts +15 -0
  2. package/dist/ggnomad/components/AvailabilityPanel.d.ts.map +1 -0
  3. package/dist/ggnomad/components/AvailabilityPanel.js +91 -0
  4. package/dist/ggnomad/components/AvailabilityPanel.js.map +1 -0
  5. package/dist/ggnomad/components/BookingPanel.d.ts +1 -3
  6. package/dist/ggnomad/components/BookingPanel.d.ts.map +1 -1
  7. package/dist/ggnomad/components/BookingPanel.js +91 -82
  8. package/dist/ggnomad/components/BookingPanel.js.map +1 -1
  9. package/dist/ggnomad/components/EcoAccessPanel.d.ts +17 -0
  10. package/dist/ggnomad/components/EcoAccessPanel.d.ts.map +1 -0
  11. package/dist/ggnomad/components/EcoAccessPanel.js +68 -0
  12. package/dist/ggnomad/components/EcoAccessPanel.js.map +1 -0
  13. package/dist/ggnomad/components/FactGrid.d.ts +18 -0
  14. package/dist/ggnomad/components/FactGrid.d.ts.map +1 -0
  15. package/dist/ggnomad/components/FactGrid.js +29 -0
  16. package/dist/ggnomad/components/FactGrid.js.map +1 -0
  17. package/dist/ggnomad/components/GroupTripPanel.d.ts +22 -0
  18. package/dist/ggnomad/components/GroupTripPanel.d.ts.map +1 -0
  19. package/dist/ggnomad/components/GroupTripPanel.js +350 -0
  20. package/dist/ggnomad/components/GroupTripPanel.js.map +1 -0
  21. package/dist/ggnomad/components/ListingFilters.d.ts +29 -0
  22. package/dist/ggnomad/components/ListingFilters.d.ts.map +1 -0
  23. package/dist/ggnomad/components/ListingFilters.js +164 -0
  24. package/dist/ggnomad/components/ListingFilters.js.map +1 -0
  25. package/dist/ggnomad/components/PhotoGallery.d.ts +15 -0
  26. package/dist/ggnomad/components/PhotoGallery.d.ts.map +1 -0
  27. package/dist/ggnomad/components/PhotoGallery.js +54 -0
  28. package/dist/ggnomad/components/PhotoGallery.js.map +1 -0
  29. package/dist/ggnomad/components/ProviderCard.d.ts +19 -0
  30. package/dist/ggnomad/components/ProviderCard.d.ts.map +1 -0
  31. package/dist/ggnomad/components/ProviderCard.js +66 -0
  32. package/dist/ggnomad/components/ProviderCard.js.map +1 -0
  33. package/dist/ggnomad/components/RatingSummary.d.ts +14 -0
  34. package/dist/ggnomad/components/RatingSummary.d.ts.map +1 -0
  35. package/dist/ggnomad/components/RatingSummary.js +32 -0
  36. package/dist/ggnomad/components/RatingSummary.js.map +1 -0
  37. package/dist/ggnomad/components/TagChips.d.ts +16 -0
  38. package/dist/ggnomad/components/TagChips.d.ts.map +1 -0
  39. package/dist/ggnomad/components/TagChips.js +20 -0
  40. package/dist/ggnomad/components/TagChips.js.map +1 -0
  41. package/dist/ggnomad/components/index.d.ts +13 -0
  42. package/dist/ggnomad/components/index.d.ts.map +1 -1
  43. package/dist/ggnomad/components/index.js +9 -0
  44. package/dist/ggnomad/graphql.d.ts +10 -0
  45. package/dist/ggnomad/graphql.d.ts.map +1 -1
  46. package/dist/ggnomad/graphql.js +308 -20
  47. package/dist/ggnomad/graphql.js.map +1 -1
  48. package/dist/ggnomad/pages/ActivityDetailsPage.d.ts.map +1 -1
  49. package/dist/ggnomad/pages/ActivityDetailsPage.js +174 -86
  50. package/dist/ggnomad/pages/ActivityDetailsPage.js.map +1 -1
  51. package/dist/ggnomad/pages/AnalyticsPage.d.ts.map +1 -1
  52. package/dist/ggnomad/pages/AnalyticsPage.js +109 -77
  53. package/dist/ggnomad/pages/AnalyticsPage.js.map +1 -1
  54. package/dist/ggnomad/pages/BookingsPage.d.ts.map +1 -1
  55. package/dist/ggnomad/pages/BookingsPage.js +188 -137
  56. package/dist/ggnomad/pages/BookingsPage.js.map +1 -1
  57. package/dist/ggnomad/pages/DashboardPage.d.ts.map +1 -1
  58. package/dist/ggnomad/pages/DashboardPage.js +245 -128
  59. package/dist/ggnomad/pages/DashboardPage.js.map +1 -1
  60. package/dist/ggnomad/pages/EntertainmentPage.d.ts.map +1 -1
  61. package/dist/ggnomad/pages/EntertainmentPage.js +115 -53
  62. package/dist/ggnomad/pages/EntertainmentPage.js.map +1 -1
  63. package/dist/ggnomad/pages/EventDetailsPage.d.ts.map +1 -1
  64. package/dist/ggnomad/pages/EventDetailsPage.js +170 -87
  65. package/dist/ggnomad/pages/EventDetailsPage.js.map +1 -1
  66. package/dist/ggnomad/pages/FavoritesPage.d.ts.map +1 -1
  67. package/dist/ggnomad/pages/FavoritesPage.js +201 -84
  68. package/dist/ggnomad/pages/FavoritesPage.js.map +1 -1
  69. package/dist/ggnomad/pages/HospitalityPage.d.ts.map +1 -1
  70. package/dist/ggnomad/pages/HospitalityPage.js +99 -56
  71. package/dist/ggnomad/pages/HospitalityPage.js.map +1 -1
  72. package/dist/ggnomad/pages/PropertyDetailsPage.d.ts.map +1 -1
  73. package/dist/ggnomad/pages/PropertyDetailsPage.js +177 -93
  74. package/dist/ggnomad/pages/PropertyDetailsPage.js.map +1 -1
  75. package/dist/ggnomad/pages/ProviderPage.d.ts.map +1 -1
  76. package/dist/ggnomad/pages/ProviderPage.js +112 -63
  77. package/dist/ggnomad/pages/ProviderPage.js.map +1 -1
  78. package/dist/ggnomad/pages/SearchPage.d.ts.map +1 -1
  79. package/dist/ggnomad/pages/SearchPage.js +236 -65
  80. package/dist/ggnomad/pages/SearchPage.js.map +1 -1
  81. package/dist/ggnomad/pages/TourDetailsPage.d.ts.map +1 -1
  82. package/dist/ggnomad/pages/TourDetailsPage.js +171 -86
  83. package/dist/ggnomad/pages/TourDetailsPage.js.map +1 -1
  84. package/dist/ggnomad/pages/TourismPage.d.ts.map +1 -1
  85. package/dist/ggnomad/pages/TourismPage.js +108 -54
  86. package/dist/ggnomad/pages/TourismPage.js.map +1 -1
  87. package/dist/ggnomad/pages/TravelPage.d.ts.map +1 -1
  88. package/dist/ggnomad/pages/TravelPage.js +406 -43
  89. package/dist/ggnomad/pages/TravelPage.js.map +1 -1
  90. package/dist/ggnomad/pages/TripPlanDetailPage.d.ts.map +1 -1
  91. package/dist/ggnomad/pages/TripPlanDetailPage.js +93 -70
  92. package/dist/ggnomad/pages/TripPlanDetailPage.js.map +1 -1
  93. package/dist/ggnomad/utils/format.d.ts +47 -0
  94. package/dist/ggnomad/utils/format.d.ts.map +1 -0
  95. package/dist/ggnomad/utils/format.js +125 -0
  96. package/dist/ggnomad/utils/format.js.map +1 -0
  97. package/dist/stories/BookingPanel.stories.d.ts.map +1 -1
  98. package/package.json +2 -2
@@ -1,140 +1,225 @@
1
1
  import { GGNOMAD_TOUR_QUERY as e } from "../graphql.js";
2
- import { PageShell as t } from "./PageShell.js";
3
- import { SectionCard as n } from "../components/SectionCard.js";
4
- import { DetailRow as r } from "../components/DetailRow.js";
5
- import { DetailHero as i } from "../components/DetailHero.js";
6
- import { useGGNomad as a } from "../providers/GGNomadProvider.js";
7
- import { joinPath as o } from "../utils/navigation.js";
8
- import { BookingPanel as s } from "../components/BookingPanel.js";
9
- import { ReviewsSection as c } from "../components/ReviewsSection.js";
10
- import { ListingEditDialog as l } from "../components/ListingEditDialog.js";
2
+ import { humanizeEnum as t, jsonLabel as n } from "../utils/format.js";
3
+ import { PageShell as r } from "./PageShell.js";
4
+ import { StatusBadge as i } from "../components/StatusBadge.js";
5
+ import { SectionCard as a } from "../components/SectionCard.js";
6
+ import { DetailRow as o } from "../components/DetailRow.js";
7
+ import { DetailHero as s } from "../components/DetailHero.js";
8
+ import { useGGNomad as c } from "../providers/GGNomadProvider.js";
9
+ import { joinPath as l } from "../utils/navigation.js";
10
+ import { BookingPanel as u } from "../components/BookingPanel.js";
11
+ import { ReviewsSection as d } from "../components/ReviewsSection.js";
12
+ import { ListingEditDialog as f } from "../components/ListingEditDialog.js";
13
+ import { PhotoGallery as p } from "../components/PhotoGallery.js";
14
+ import { TagChips as m } from "../components/TagChips.js";
15
+ import { FactGrid as h } from "../components/FactGrid.js";
16
+ import { RatingSummary as g } from "../components/RatingSummary.js";
17
+ import { EcoAccessPanel as _ } from "../components/EcoAccessPanel.js";
18
+ import { ProviderCard as v } from "../components/ProviderCard.js";
19
+ import { AvailabilityPanel as y } from "../components/AvailabilityPanel.js";
11
20
  import "../components/index.js";
12
- import { useState as u } from "react";
13
- import { CheckCircle2 as d, Compass as f, Pencil as p } from "lucide-react";
14
- import { useI18n as m } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
15
- import { useNavigate as h, useParams as g } from "react-router";
16
- import { useQuery as _ } from "@apollo/client/react";
17
- import { GlassCard as v, IllustratedEmptyState as y, NextSteps as b, PagePurpose as x } from "@burdenoff/fe-libs/ui";
18
- import { Fragment as S, jsx as C, jsxs as w } from "react/jsx-runtime";
21
+ import { useState as b } from "react";
22
+ import { CheckCircle2 as x, Clock as S, Compass as C, Gauge as w, Languages as T, MapPin as E, Pencil as D, UserRound as O, Users as k, Zap as A } from "lucide-react";
23
+ import { useI18n as j } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
24
+ import { useNavigate as M, useParams as N } from "react-router";
25
+ import { useQuery as P } from "@apollo/client/react";
26
+ import { GlassCard as F, IllustratedEmptyState as I, NextSteps as L, PagePurpose as R } from "@burdenoff/fe-libs/ui";
27
+ import { Fragment as z, jsx as B, jsxs as V } from "react/jsx-runtime";
19
28
  //#region src/ggnomad/pages/TourDetailsPage.tsx
20
- function T() {
21
- let { t: T } = m(), E = h(), { basePath: D = "/" } = a(), { id: O = "" } = g(), [k, A] = u(!1), { data: j, refetch: M } = _(e, {
22
- variables: { id: O },
23
- skip: !O
24
- }), N = j?.ggnomadTour;
25
- return /* @__PURE__ */ C(t, {
26
- title: N?.name ?? T("ggnomad.tour.fallbackTitle", "Tour details"),
27
- subtitle: T("ggnomad.tour.subtitle", "Tour package details and booking context"),
28
- children: N ? /* @__PURE__ */ w(S, { children: [
29
- /* @__PURE__ */ C(i, {
30
- image: N.images?.[0],
31
- alt: N.name
29
+ function H() {
30
+ let { t: H } = j(), U = M(), { basePath: W = "/" } = c(), { id: G = "" } = N(), [K, q] = b(!1), { data: J, refetch: Y } = P(e, {
31
+ variables: { id: G },
32
+ skip: !G
33
+ }), X = J?.ggnomadTour, Z = n(X?.location), Q = [];
34
+ return X && (Q.push({
35
+ id: "duration",
36
+ label: H("ggnomad.tour.duration", "Duration"),
37
+ value: X.duration,
38
+ icon: /* @__PURE__ */ B(S, {})
39
+ }), X.difficulty && Q.push({
40
+ id: "difficulty",
41
+ label: H("ggnomad.tour.difficulty", "Difficulty"),
42
+ value: t(X.difficulty),
43
+ icon: /* @__PURE__ */ B(w, {})
44
+ }), Q.push({
45
+ id: "group",
46
+ label: H("ggnomad.tour.maxGroupSize", "Max group size"),
47
+ value: String(X.maxGroupSize),
48
+ icon: /* @__PURE__ */ B(k, {})
49
+ }), X.languages.length > 0 && Q.push({
50
+ id: "languages",
51
+ label: H("ggnomad.tour.languages", "Languages"),
52
+ value: X.languages.join(", "),
53
+ icon: /* @__PURE__ */ B(T, {})
54
+ }), Z && Q.push({
55
+ id: "location",
56
+ label: H("ggnomad.tour.location", "Location"),
57
+ value: Z,
58
+ icon: /* @__PURE__ */ B(E, {})
59
+ }), X.guideName && Q.push({
60
+ id: "guide",
61
+ label: H("ggnomad.tour.guide", "Guide"),
62
+ value: X.guideName,
63
+ icon: /* @__PURE__ */ B(O, {})
64
+ })), /* @__PURE__ */ B(r, {
65
+ title: X?.name ?? H("ggnomad.tour.fallbackTitle", "Tour details"),
66
+ subtitle: H("ggnomad.tour.subtitle", "Tour package details and booking context"),
67
+ children: X ? /* @__PURE__ */ V(z, { children: [
68
+ X.images.length > 0 ? /* @__PURE__ */ B(p, {
69
+ images: X.images,
70
+ alt: X.name
71
+ }) : /* @__PURE__ */ B(s, { alt: X.name }),
72
+ /* @__PURE__ */ V("div", {
73
+ className: "flex flex-wrap items-center gap-3",
74
+ children: [
75
+ /* @__PURE__ */ B("span", {
76
+ className: "rounded-full border border-border-seam bg-bg-sunken px-3 py-1 text-sm text-text-primary",
77
+ children: t(X.type)
78
+ }),
79
+ X.status ? /* @__PURE__ */ B(i, { status: X.status }) : null,
80
+ /* @__PURE__ */ B(g, {
81
+ rating: X.rating,
82
+ reviewCount: X.reviewCount
83
+ }),
84
+ X.instantBook ? /* @__PURE__ */ V("span", {
85
+ className: "inline-flex items-center gap-1.5 rounded-full bg-status-success-bg-subtle px-3 py-1 text-sm font-medium text-status-success-text",
86
+ children: [/* @__PURE__ */ B(A, {
87
+ className: "size-3.5",
88
+ "aria-hidden": "true"
89
+ }), H("ggnomad.listing.instantBook", "Instant book")]
90
+ }) : null
91
+ ]
32
92
  }),
33
- /* @__PURE__ */ C(x, {
34
- icon: /* @__PURE__ */ C(f, { className: "size-4" }),
35
- children: T("ggnomad.tour.purpose", "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.")
93
+ /* @__PURE__ */ B(R, {
94
+ icon: /* @__PURE__ */ B(C, { className: "size-4" }),
95
+ children: H("ggnomad.tour.purpose", "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.")
36
96
  }),
37
- /* @__PURE__ */ C(b, {
97
+ /* @__PURE__ */ B(h, { facts: Q }),
98
+ /* @__PURE__ */ B(L, {
38
99
  storageKey: "ggnomad-tour-detail",
39
100
  steps: [{
40
101
  id: "browse",
41
- label: T("ggnomad.tour.next.browse", "Explore more experiences"),
42
- description: T("ggnomad.tour.next.browseDesc", "Return to Tourism to compare tours and activities."),
43
- icon: /* @__PURE__ */ C(f, { className: "size-4" }),
44
- onClick: () => E(o(D, "tourism"))
102
+ label: H("ggnomad.tour.next.browse", "Explore more experiences"),
103
+ description: H("ggnomad.tour.next.browseDesc", "Return to Tourism to compare tours and activities."),
104
+ icon: /* @__PURE__ */ B(C, { className: "size-4" }),
105
+ onClick: () => U(l(W, "tourism"))
45
106
  }]
46
107
  }),
47
- /* @__PURE__ */ w("div", {
108
+ /* @__PURE__ */ V("div", {
48
109
  className: "grid gap-4 lg:grid-cols-3",
49
- children: [/* @__PURE__ */ w("div", {
110
+ children: [/* @__PURE__ */ V("div", {
50
111
  className: "lg:col-span-2 space-y-4",
51
112
  children: [
52
- /* @__PURE__ */ w(v, {
113
+ X.description ? /* @__PURE__ */ B(a, {
114
+ title: H("ggnomad.tour.about", "About this tour"),
115
+ children: /* @__PURE__ */ B("p", {
116
+ className: "text-text-primary",
117
+ children: X.description
118
+ })
119
+ }) : null,
120
+ /* @__PURE__ */ V(F, {
53
121
  treatment: "glass",
54
122
  glow: !0,
55
123
  className: "border-border-seam p-5",
56
- children: [/* @__PURE__ */ w("div", {
124
+ children: [/* @__PURE__ */ V("div", {
57
125
  className: "mb-4 flex items-center justify-between gap-3",
58
- children: [/* @__PURE__ */ C("h2", {
126
+ children: [/* @__PURE__ */ B("h2", {
59
127
  className: "text-lg font-medium tracking-tight text-text-primary",
60
- children: T("ggnomad.tour.details", "Details")
61
- }), /* @__PURE__ */ C("button", {
62
- onClick: () => A(!0),
128
+ children: H("ggnomad.tour.details", "Details")
129
+ }), /* @__PURE__ */ B("button", {
130
+ onClick: () => q(!0),
63
131
  className: "rounded-md p-2 text-text-secondary hover:bg-action-primary-bg hover:text-action-primary-text",
64
- "aria-label": T("ggnomad.tour.editListing", "Edit listing"),
65
- title: T("ggnomad.tour.editListing", "Edit listing"),
66
- children: /* @__PURE__ */ C(p, { className: "size-4" })
132
+ "aria-label": H("ggnomad.tour.editListing", "Edit listing"),
133
+ title: H("ggnomad.tour.editListing", "Edit listing"),
134
+ children: /* @__PURE__ */ B(D, { className: "size-4" })
67
135
  })]
68
- }), /* @__PURE__ */ w("dl", {
136
+ }), /* @__PURE__ */ V("dl", {
69
137
  className: "space-y-2 text-sm",
70
138
  children: [
71
- /* @__PURE__ */ C(r, {
72
- label: T("ggnomad.tour.duration", "Duration"),
73
- value: N.duration
139
+ /* @__PURE__ */ B(o, {
140
+ label: H("ggnomad.tour.duration", "Duration"),
141
+ value: X.duration
74
142
  }),
75
- /* @__PURE__ */ C(r, {
76
- label: T("ggnomad.tour.difficulty", "Difficulty"),
77
- value: N.difficulty ?? T("ggnomad.tour.na", "N/A")
143
+ /* @__PURE__ */ B(o, {
144
+ label: H("ggnomad.tour.difficulty", "Difficulty"),
145
+ value: X.difficulty ? t(X.difficulty) : H("ggnomad.tour.na", "N/A")
78
146
  }),
79
- /* @__PURE__ */ C(r, {
80
- label: T("ggnomad.tour.guide", "Guide"),
81
- value: N.guideName ?? T("ggnomad.tour.na", "N/A")
147
+ /* @__PURE__ */ B(o, {
148
+ label: H("ggnomad.tour.guide", "Guide"),
149
+ value: X.guideName ?? H("ggnomad.tour.na", "N/A")
82
150
  }),
83
- /* @__PURE__ */ C(r, {
84
- label: T("ggnomad.tour.price", "Price"),
85
- value: `${N.currency} ${Number(N.price).toFixed(2)}`
151
+ /* @__PURE__ */ B(o, {
152
+ label: H("ggnomad.tour.price", "Price per person"),
153
+ value: `${X.currency} ${Number(X.price).toFixed(2)}`
86
154
  })
87
155
  ]
88
156
  })]
89
157
  }),
90
- /* @__PURE__ */ C(n, {
91
- title: T("ggnomad.tour.highlights", "Highlights"),
92
- children: /* @__PURE__ */ C("ul", {
158
+ X.highlights.length > 0 ? /* @__PURE__ */ B(a, {
159
+ title: H("ggnomad.tour.highlights", "Highlights"),
160
+ children: /* @__PURE__ */ B("ul", {
93
161
  className: "space-y-2 text-sm",
94
- children: (N.highlights ?? []).map((e) => /* @__PURE__ */ w("li", {
162
+ children: X.highlights.map((e) => /* @__PURE__ */ V("li", {
95
163
  className: "flex items-start gap-2 text-text-primary",
96
- children: [/* @__PURE__ */ C(d, {
164
+ children: [/* @__PURE__ */ B(x, {
97
165
  className: "mt-0.5 size-4 flex-shrink-0 text-status-success-text",
98
166
  "aria-hidden": "true"
99
167
  }), e]
100
168
  }, e))
101
169
  })
170
+ }) : null,
171
+ X.languages.length > 0 ? /* @__PURE__ */ B(a, {
172
+ title: H("ggnomad.tour.languagesTitle", "Guided in"),
173
+ children: /* @__PURE__ */ B(m, {
174
+ items: X.languages,
175
+ icon: /* @__PURE__ */ B(T, {})
176
+ })
177
+ }) : null,
178
+ /* @__PURE__ */ B(_, {
179
+ sustainabilityScore: X.sustainabilityScore,
180
+ sustainabilityPractices: X.sustainabilityPractices,
181
+ accessibilityFeatures: X.accessibilityFeatures
182
+ }),
183
+ /* @__PURE__ */ B(y, {
184
+ listingId: X.id ?? G,
185
+ listingType: "TOUR"
102
186
  }),
103
- /* @__PURE__ */ C(c, {
187
+ X.provider ? /* @__PURE__ */ B(v, { provider: X.provider }) : null,
188
+ /* @__PURE__ */ B(d, {
104
189
  targetType: "TOUR",
105
- targetId: N.id ?? O
190
+ targetId: X.id ?? G
106
191
  })
107
192
  ]
108
- }), /* @__PURE__ */ C("div", { children: /* @__PURE__ */ C(s, {
193
+ }), /* @__PURE__ */ B("div", { children: /* @__PURE__ */ B(u, {
109
194
  bookingType: "TOUR",
110
- itemId: N.id ?? O,
111
- itemName: N.name,
112
- unitPrice: N.price ?? 0,
113
- currency: N.currency ?? "USD"
195
+ itemId: X.id ?? G,
196
+ itemName: X.name,
197
+ unitPrice: X.price ?? 0,
198
+ currency: X.currency ?? "USD"
114
199
  }) })]
115
200
  }),
116
- /* @__PURE__ */ C(l, {
117
- open: k,
118
- onOpenChange: A,
201
+ /* @__PURE__ */ B(f, {
202
+ open: K,
203
+ onOpenChange: q,
119
204
  targetType: "TOUR",
120
- id: N.id ?? O,
205
+ id: X.id ?? G,
121
206
  initial: {
122
- name: N.name,
123
- description: N.description,
124
- price: N.price,
125
- status: N.status,
126
- images: N.images
207
+ name: X.name,
208
+ description: X.description ?? void 0,
209
+ price: X.price,
210
+ status: X.status,
211
+ images: X.images
127
212
  },
128
- onSaved: () => M()
213
+ onSaved: () => Y()
129
214
  })
130
- ] }) : /* @__PURE__ */ C(y, {
215
+ ] }) : /* @__PURE__ */ B(I, {
131
216
  illustration: "empty-data",
132
- title: T("ggnomad.tour.notFoundTitle", "No tour found"),
133
- description: T("ggnomad.tour.notFoundDescription", "This tour is unavailable or may have been removed.")
217
+ title: H("ggnomad.tour.notFoundTitle", "No tour found"),
218
+ description: H("ggnomad.tour.notFoundDescription", "This tour is unavailable or may have been removed.")
134
219
  })
135
220
  });
136
221
  }
137
222
  //#endregion
138
- export { T as TourDetailsPage };
223
+ export { H as TourDetailsPage };
139
224
 
140
225
  //# sourceMappingURL=TourDetailsPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TourDetailsPage.js","names":[],"sources":["../../../src/ggnomad/pages/TourDetailsPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { 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';\nimport { CheckCircle2, Compass, Pencil } 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 {\n DetailRow,\n SectionCard,\n DetailHero,\n BookingPanel,\n ReviewsSection,\n ListingEditDialog,\n} from '../components';\n\nexport function TourDetailsPage() {\n const { t } = useI18n();\n const navigate = useNavigate();\n const { basePath = '/' } = useGGNomad();\n const { id = '' } = useParams();\n const [editDialogOpen, setEditDialogOpen] = useState(false);\n const { data, refetch } = useQuery(\n GGNOMAD_TOUR_QUERY as TypedDocumentNode<\n {\n ggnomadTour: {\n id: string;\n name: string;\n description?: string;\n duration: string;\n difficulty?: string;\n guideName?: string;\n currency: string;\n price: number;\n status?: string;\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 <div className=\"mb-4 flex items-center justify-between gap-3\">\n <h2 className=\"text-lg font-medium tracking-tight text-text-primary\">\n {t('ggnomad.tour.details', 'Details')}\n </h2>\n <button\n onClick={() => setEditDialogOpen(true)}\n className=\"rounded-md p-2 text-text-secondary hover:bg-action-primary-bg hover:text-action-primary-text\"\n aria-label={t('ggnomad.tour.editListing', 'Edit listing')}\n title={t('ggnomad.tour.editListing', 'Edit listing')}\n >\n <Pencil className=\"size-4\" />\n </button>\n </div>\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 <ReviewsSection targetType=\"TOUR\" targetId={tour.id ?? id} />\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 <ListingEditDialog\n open={editDialogOpen}\n onOpenChange={setEditDialogOpen}\n targetType=\"TOUR\"\n id={tour.id ?? id}\n initial={{\n name: tour.name,\n description: tour.description,\n price: tour.price,\n status: tour.status,\n images: tour.images,\n }}\n onSaved={() => refetch()}\n />\n </>\n )}\n </PageShell>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"TourDetailsPage.js","names":[],"sources":["../../../src/ggnomad/pages/TourDetailsPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { 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';\nimport {\n CheckCircle2,\n Clock,\n Compass,\n Gauge,\n Languages as LanguagesIcon,\n MapPin,\n Pencil,\n UserRound,\n Users,\n Zap,\n} 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 { humanizeEnum, jsonLabel } from '../utils/format';\nimport { PageShell } from './PageShell';\nimport {\n AvailabilityPanel,\n BookingPanel,\n DetailHero,\n DetailRow,\n EcoAccessPanel,\n FactGrid,\n ListingEditDialog,\n PhotoGallery,\n ProviderCard,\n RatingSummary,\n ReviewsSection,\n SectionCard,\n StatusBadge,\n TagChips,\n} from '../components';\nimport type { Fact } from '../components';\n\ntype TourDetail = {\n id: string;\n name: string;\n description?: string | null;\n type: string;\n status?: string;\n duration: string;\n difficulty?: string | null;\n guideName?: string | null;\n currency: string;\n price: number;\n rating?: number | null;\n reviewCount: number;\n highlights: string[];\n images: string[];\n languages: string[];\n location?: unknown;\n maxGroupSize: number;\n instantBook: boolean;\n sustainabilityScore: number;\n sustainabilityPractices: string[];\n accessibilityFeatures: string[];\n provider?: {\n id: string;\n name: string;\n type?: string | null;\n rating?: number | null;\n reviewCount?: number | null;\n listingCount?: number | null;\n contactEmail?: string | null;\n website?: string | null;\n } | null;\n};\n\nexport function TourDetailsPage() {\n const { t } = useI18n();\n const navigate = useNavigate();\n const { basePath = '/' } = useGGNomad();\n const { id = '' } = useParams();\n const [editDialogOpen, setEditDialogOpen] = useState(false);\n const { data, refetch } = useQuery(\n GGNOMAD_TOUR_QUERY as TypedDocumentNode<{ ggnomadTour: TourDetail | null }, { id: string }>,\n { variables: { id }, skip: !id }\n );\n const tour = data?.ggnomadTour;\n const locationLabel = jsonLabel(tour?.location);\n\n const facts: Fact[] = [];\n if (tour) {\n facts.push({\n id: 'duration',\n label: t('ggnomad.tour.duration', 'Duration'),\n value: tour.duration,\n icon: <Clock />,\n });\n if (tour.difficulty) {\n facts.push({\n id: 'difficulty',\n label: t('ggnomad.tour.difficulty', 'Difficulty'),\n value: humanizeEnum(tour.difficulty),\n icon: <Gauge />,\n });\n }\n facts.push({\n id: 'group',\n label: t('ggnomad.tour.maxGroupSize', 'Max group size'),\n value: String(tour.maxGroupSize),\n icon: <Users />,\n });\n if (tour.languages.length > 0) {\n facts.push({\n id: 'languages',\n label: t('ggnomad.tour.languages', 'Languages'),\n value: tour.languages.join(', '),\n icon: <LanguagesIcon />,\n });\n }\n if (locationLabel) {\n facts.push({\n id: 'location',\n label: t('ggnomad.tour.location', 'Location'),\n value: locationLabel,\n icon: <MapPin />,\n });\n }\n if (tour.guideName) {\n facts.push({\n id: 'guide',\n label: t('ggnomad.tour.guide', 'Guide'),\n value: tour.guideName,\n icon: <UserRound />,\n });\n }\n }\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 {tour.images.length > 0 ? (\n <PhotoGallery images={tour.images} alt={tour.name} />\n ) : (\n <DetailHero alt={tour.name} />\n )}\n\n <div className=\"flex flex-wrap items-center gap-3\">\n <span className=\"rounded-full border border-border-seam bg-bg-sunken px-3 py-1 text-sm text-text-primary\">\n {humanizeEnum(tour.type)}\n </span>\n {tour.status ? <StatusBadge status={tour.status} /> : null}\n <RatingSummary rating={tour.rating} reviewCount={tour.reviewCount} />\n {tour.instantBook ? (\n <span className=\"inline-flex items-center gap-1.5 rounded-full bg-status-success-bg-subtle px-3 py-1 text-sm font-medium text-status-success-text\">\n <Zap className=\"size-3.5\" aria-hidden=\"true\" />\n {t('ggnomad.listing.instantBook', 'Instant book')}\n </span>\n ) : null}\n </div>\n\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 <FactGrid facts={facts} />\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 {tour.description ? (\n <SectionCard title={t('ggnomad.tour.about', 'About this tour')}>\n <p className=\"text-text-primary\">{tour.description}</p>\n </SectionCard>\n ) : null}\n\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam p-5\">\n <div className=\"mb-4 flex items-center justify-between gap-3\">\n <h2 className=\"text-lg font-medium tracking-tight text-text-primary\">\n {t('ggnomad.tour.details', 'Details')}\n </h2>\n <button\n onClick={() => setEditDialogOpen(true)}\n className=\"rounded-md p-2 text-text-secondary hover:bg-action-primary-bg hover:text-action-primary-text\"\n aria-label={t('ggnomad.tour.editListing', 'Edit listing')}\n title={t('ggnomad.tour.editListing', 'Edit listing')}\n >\n <Pencil className=\"size-4\" />\n </button>\n </div>\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={\n tour.difficulty ? humanizeEnum(tour.difficulty) : t('ggnomad.tour.na', 'N/A')\n }\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 per person')}\n value={`${tour.currency} ${Number(tour.price).toFixed(2)}`}\n />\n </dl>\n </GlassCard>\n\n {tour.highlights.length > 0 ? (\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 ) : null}\n\n {tour.languages.length > 0 ? (\n <SectionCard title={t('ggnomad.tour.languagesTitle', 'Guided in')}>\n <TagChips items={tour.languages} icon={<LanguagesIcon />} />\n </SectionCard>\n ) : null}\n\n <EcoAccessPanel\n sustainabilityScore={tour.sustainabilityScore}\n sustainabilityPractices={tour.sustainabilityPractices}\n accessibilityFeatures={tour.accessibilityFeatures}\n />\n\n <AvailabilityPanel listingId={tour.id ?? id} listingType=\"TOUR\" />\n\n {tour.provider ? <ProviderCard provider={tour.provider} /> : null}\n\n <ReviewsSection targetType=\"TOUR\" targetId={tour.id ?? id} />\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 <ListingEditDialog\n open={editDialogOpen}\n onOpenChange={setEditDialogOpen}\n targetType=\"TOUR\"\n id={tour.id ?? id}\n initial={{\n name: tour.name,\n description: tour.description ?? undefined,\n price: tour.price,\n status: tour.status,\n images: tour.images,\n }}\n onSaved={() => refetch()}\n />\n </>\n )}\n </PageShell>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4EA,SAAgB,IAAkB;CAChC,IAAM,EAAE,SAAM,EAAQ,GAChB,IAAW,EAAY,GACvB,EAAE,cAAW,QAAQ,EAAW,GAChC,EAAE,QAAK,OAAO,EAAU,GACxB,CAAC,GAAgB,KAAqB,EAAS,EAAK,GACpD,EAAE,SAAM,eAAY,EACxB,GACA;EAAE,WAAW,EAAE,MAAG;EAAG,MAAM,CAAC;CAAG,CACjC,GACM,IAAO,GAAM,aACb,IAAgB,EAAU,GAAM,QAAQ,GAExC,IAAgB,CAAC;CAgDvB,OA/CI,MACF,EAAM,KAAK;EACT,IAAI;EACJ,OAAO,EAAE,yBAAyB,UAAU;EAC5C,OAAO,EAAK;EACZ,MAAM,kBAAC,GAAD,CAAQ,CAAA;CAChB,CAAC,GACG,EAAK,cACP,EAAM,KAAK;EACT,IAAI;EACJ,OAAO,EAAE,2BAA2B,YAAY;EAChD,OAAO,EAAa,EAAK,UAAU;EACnC,MAAM,kBAAC,GAAD,CAAQ,CAAA;CAChB,CAAC,GAEH,EAAM,KAAK;EACT,IAAI;EACJ,OAAO,EAAE,6BAA6B,gBAAgB;EACtD,OAAO,OAAO,EAAK,YAAY;EAC/B,MAAM,kBAAC,GAAD,CAAQ,CAAA;CAChB,CAAC,GACG,EAAK,UAAU,SAAS,KAC1B,EAAM,KAAK;EACT,IAAI;EACJ,OAAO,EAAE,0BAA0B,WAAW;EAC9C,OAAO,EAAK,UAAU,KAAK,IAAI;EAC/B,MAAM,kBAAC,GAAD,CAAgB,CAAA;CACxB,CAAC,GAEC,KACF,EAAM,KAAK;EACT,IAAI;EACJ,OAAO,EAAE,yBAAyB,UAAU;EAC5C,OAAO;EACP,MAAM,kBAAC,GAAD,CAAS,CAAA;CACjB,CAAC,GAEC,EAAK,aACP,EAAM,KAAK;EACT,IAAI;EACJ,OAAO,EAAE,sBAAsB,OAAO;EACtC,OAAO,EAAK;EACZ,MAAM,kBAAC,GAAD,CAAY,CAAA;CACpB,CAAC,IAKH,kBAAC,GAAD;EACE,OAAO,GAAM,QAAQ,EAAE,8BAA8B,cAAc;EACnE,UAAU,EAAE,yBAAyB,0CAA0C;YAE7E,IAUA,kBAAA,GAAA,EAAA,UAAA;GACG,EAAK,OAAO,SAAS,IACpB,kBAAC,GAAD;IAAc,QAAQ,EAAK;IAAQ,KAAK,EAAK;GAAO,CAAA,IAEpD,kBAAC,GAAD,EAAY,KAAK,EAAK,KAAO,CAAA;GAG/B,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,QAAD;MAAM,WAAU;gBACb,EAAa,EAAK,IAAI;KACnB,CAAA;KACL,EAAK,SAAS,kBAAC,GAAD,EAAa,QAAQ,EAAK,OAAS,CAAA,IAAI;KACtD,kBAAC,GAAD;MAAe,QAAQ,EAAK;MAAQ,aAAa,EAAK;KAAc,CAAA;KACnE,EAAK,cACJ,kBAAC,QAAD;MAAM,WAAU;gBAAhB,CACE,kBAAC,GAAD;OAAK,WAAU;OAAW,eAAY;MAAQ,CAAA,GAC7C,EAAE,+BAA+B,cAAc,CAC5C;UACJ;IACD;;GAEL,kBAAC,GAAD;IAAa,MAAM,kBAAC,GAAD,EAAS,WAAU,SAAU,CAAA;cAC7C,EACC,wBACA,2KACF;GACW,CAAA;GAEb,kBAAC,GAAD,EAAiB,SAAQ,CAAA;GAEzB,kBAAC,GAAD;IACE,YAAW;IACX,OAAO,CACL;KACE,IAAI;KACJ,OAAO,EAAE,4BAA4B,0BAA0B;KAC/D,aAAa,EACX,gCACA,oDACF;KACA,MAAM,kBAAC,GAAD,EAAS,WAAU,SAAU,CAAA;KACnC,eAAe,EAAS,EAAS,GAAU,SAAS,CAAC;IACvD,CACF;GACD,CAAA;GAED,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf;MACG,EAAK,cACJ,kBAAC,GAAD;OAAa,OAAO,EAAE,sBAAsB,iBAAiB;iBAC3D,kBAAC,KAAD;QAAG,WAAU;kBAAqB,EAAK;OAAe,CAAA;MAC3C,CAAA,IACX;MAEJ,kBAAC,GAAD;OAAW,WAAU;OAAQ,MAAA;OAAK,WAAU;iBAA5C,CACE,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAE,wBAAwB,SAAS;QAClC,CAAA,GACJ,kBAAC,UAAD;SACE,eAAe,EAAkB,EAAI;SACrC,WAAU;SACV,cAAY,EAAE,4BAA4B,cAAc;SACxD,OAAO,EAAE,4BAA4B,cAAc;mBAEnD,kBAAC,GAAD,EAAQ,WAAU,SAAU,CAAA;QACtB,CAAA,CACL;WACL,kBAAC,MAAD;QAAI,WAAU;kBAAd;SACE,kBAAC,GAAD;UAAW,OAAO,EAAE,yBAAyB,UAAU;UAAG,OAAO,EAAK;SAAW,CAAA;SACjF,kBAAC,GAAD;UACE,OAAO,EAAE,2BAA2B,YAAY;UAChD,OACE,EAAK,aAAa,EAAa,EAAK,UAAU,IAAI,EAAE,mBAAmB,KAAK;SAE/E,CAAA;SACD,kBAAC,GAAD;UACE,OAAO,EAAE,sBAAsB,OAAO;UACtC,OAAO,EAAK,aAAa,EAAE,mBAAmB,KAAK;SACpD,CAAA;SACD,kBAAC,GAAD;UACE,OAAO,EAAE,sBAAsB,kBAAkB;UACjD,OAAO,GAAG,EAAK,SAAS,GAAG,OAAO,EAAK,KAAK,EAAE,QAAQ,CAAC;SACxD,CAAA;QACC;SACK;;MAEV,EAAK,WAAW,SAAS,IACxB,kBAAC,GAAD;OAAa,OAAO,EAAE,2BAA2B,YAAY;iBAC3D,kBAAC,MAAD;QAAI,WAAU;kBACX,EAAK,WAAW,KAAK,MACpB,kBAAC,MAAD;SAAoB,WAAU;mBAA9B,CACE,kBAAC,GAAD;UACE,WAAU;UACV,eAAY;SACb,CAAA,GACA,CACC;WANK,CAML,CACL;OACC,CAAA;MACO,CAAA,IACX;MAEH,EAAK,UAAU,SAAS,IACvB,kBAAC,GAAD;OAAa,OAAO,EAAE,+BAA+B,WAAW;iBAC9D,kBAAC,GAAD;QAAU,OAAO,EAAK;QAAW,MAAM,kBAAC,GAAD,CAAgB,CAAA;OAAI,CAAA;MAChD,CAAA,IACX;MAEJ,kBAAC,GAAD;OACE,qBAAqB,EAAK;OAC1B,yBAAyB,EAAK;OAC9B,uBAAuB,EAAK;MAC7B,CAAA;MAED,kBAAC,GAAD;OAAmB,WAAW,EAAK,MAAM;OAAI,aAAY;MAAQ,CAAA;MAEhE,EAAK,WAAW,kBAAC,GAAD,EAAc,UAAU,EAAK,SAAW,CAAA,IAAI;MAE7D,kBAAC,GAAD;OAAgB,YAAW;OAAO,UAAU,EAAK,MAAM;MAAK,CAAA;KACzD;QACL,kBAAC,OAAD,EAAA,UACE,kBAAC,GAAD;KACE,aAAY;KACZ,QAAQ,EAAK,MAAM;KACnB,UAAU,EAAK;KACf,WAAW,EAAK,SAAS;KACzB,UAAU,EAAK,YAAY;IAC5B,CAAA,EACE,CAAA,CACF;;GAEL,kBAAC,GAAD;IACE,MAAM;IACN,cAAc;IACd,YAAW;IACX,IAAI,EAAK,MAAM;IACf,SAAS;KACP,MAAM,EAAK;KACX,aAAa,EAAK,eAAe,KAAA;KACjC,OAAO,EAAK;KACZ,QAAQ,EAAK;KACb,QAAQ,EAAK;IACf;IACA,eAAe,EAAQ;GACxB,CAAA;EACD,EAAA,CAAA,IA3JF,kBAAC,GAAD;GACE,cAAa;GACb,OAAO,EAAE,8BAA8B,eAAe;GACtD,aAAa,EACX,oCACA,oDACF;EACD,CAAA;CAsJM,CAAA;AAEf"}
@@ -1 +1 @@
1
- {"version":3,"file":"TourismPage.d.ts","sourceRoot":"","sources":["../../../src/ggnomad/pages/TourismPage.tsx"],"names":[],"mappings":"AAoBA,wBAAgB,WAAW,gCAiH1B"}
1
+ {"version":3,"file":"TourismPage.d.ts","sourceRoot":"","sources":["../../../src/ggnomad/pages/TourismPage.tsx"],"names":[],"mappings":"AA8CA,wBAAgB,WAAW,gCAyK1B"}
@@ -1,79 +1,133 @@
1
1
  import { GGNOMAD_ACTIVITIES_QUERY as e, GGNOMAD_TOURS_QUERY as t } from "../graphql.js";
2
- import { PageShell as n } from "./PageShell.js";
3
- import { SectionCard as r } from "../components/SectionCard.js";
4
- import { EntityCard as i } from "../components/EntityCard.js";
5
- import { LoadMoreButton as a } from "../components/LoadMoreButton.js";
2
+ import { humanizeEnum as n } from "../utils/format.js";
3
+ import { PageShell as r } from "./PageShell.js";
4
+ import { SectionCard as i } from "../components/SectionCard.js";
5
+ import { EntityCard as a } from "../components/EntityCard.js";
6
+ import { LoadMoreButton as o } from "../components/LoadMoreButton.js";
7
+ import { RatingSummary as s } from "../components/RatingSummary.js";
8
+ import { EMPTY_LISTING_FILTERS as c, ListingFilters as l, hasActiveListingFilters as u } from "../components/ListingFilters.js";
6
9
  import "../components/index.js";
7
- import { useState as o } from "react";
8
- import { Compass as s } from "lucide-react";
9
- import { useI18n as c } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
10
- import { useQuery as l } from "@apollo/client/react";
11
- import { EmphasisPanel as u, IllustratedEmptyState as d, PagePurpose as f } from "@burdenoff/fe-libs/ui";
12
- import { jsx as p, jsxs as m } from "react/jsx-runtime";
10
+ import { useState as d } from "react";
11
+ import { Clock as f, Compass as p, Gauge as m, Leaf as h, Zap as g } from "lucide-react";
12
+ import { useI18n as _ } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
13
+ import { useQuery as v } from "@apollo/client/react";
14
+ import { EmphasisPanel as y, IllustratedEmptyState as b, PagePurpose as x } from "@burdenoff/fe-libs/ui";
15
+ import { jsx as S, jsxs as C } from "react/jsx-runtime";
13
16
  //#region src/ggnomad/pages/TourismPage.tsx
14
- function h() {
15
- let { t: h } = c(), [g, _] = o(12), [v, y] = o(12), { data: b } = l(t, { variables: {
16
- limit: g,
17
- offset: 0
18
- } }), { data: x } = l(e, { variables: {
19
- limit: v,
20
- offset: 0
21
- } }), S = b?.ggnomadTours ?? [], C = x?.ggnomadActivities ?? [], w = (e, t, n) => e.length === 0 ? /* @__PURE__ */ p(d, {
17
+ function w() {
18
+ let { t: w } = _(), [T, E] = d(12), [D, O] = d(12), [k, A] = d(c), j = {
19
+ status: k.status,
20
+ minSustainabilityScore: k.minSustainabilityScore,
21
+ hasAccessibilityFeatures: k.accessibilityFeatures.length > 0 ? k.accessibilityFeatures : void 0
22
+ }, { data: M } = v(t, { variables: {
23
+ limit: T,
24
+ offset: 0,
25
+ ...j
26
+ } }), { data: N } = v(e, { variables: {
27
+ limit: D,
28
+ offset: 0,
29
+ ...j
30
+ } }), P = M?.ggnomadTours ?? [], F = N?.ggnomadActivities ?? [], I = u(k), L = (e, t, r) => e.length === 0 ? /* @__PURE__ */ S(b, {
22
31
  illustration: "empty-data",
23
- title: n,
24
- description: h("ggnomad.tourism.emptyDescription", "Curated experiences will appear here once published.")
25
- }) : /* @__PURE__ */ p("div", {
32
+ title: I ? w("ggnomad.tourism.noMatchTitle", "Nothing matches these filters") : r,
33
+ description: I ? w("ggnomad.tourism.noMatchDescription", "Try clearing a filter — status, sustainability score and accessibility all narrow the catalogue.") : w("ggnomad.tourism.emptyDescription", "Curated experiences will appear here once published.")
34
+ }) : /* @__PURE__ */ S("div", {
26
35
  className: "grid gap-3",
27
- children: e.map((e) => /* @__PURE__ */ p(i, {
36
+ children: e.map((e) => /* @__PURE__ */ S(a, {
28
37
  to: `${t}/${e.id}`,
29
38
  image: e.images?.[0],
30
39
  imageAlt: e.name,
31
40
  title: e.name,
32
- meta: e.duration,
33
- price: `${e.currency} ${Number(e.price).toFixed(2)}`
41
+ meta: n(e.type ?? e.category ?? ""),
42
+ badge: e.instantBook ? /* @__PURE__ */ C("span", {
43
+ className: "inline-flex items-center gap-1 rounded-full bg-status-success-bg-subtle px-2.5 py-0.5 text-xs font-medium text-status-success-text",
44
+ children: [/* @__PURE__ */ S(g, {
45
+ className: "size-3",
46
+ "aria-hidden": "true"
47
+ }), w("ggnomad.listing.instantBook", "Instant book")]
48
+ }) : null,
49
+ price: `${e.currency} ${Number(e.price).toFixed(2)}`,
50
+ footer: /* @__PURE__ */ C("div", {
51
+ className: "flex flex-wrap items-center gap-x-3 gap-y-1",
52
+ children: [
53
+ /* @__PURE__ */ C("span", {
54
+ className: "inline-flex items-center gap-1",
55
+ children: [/* @__PURE__ */ S(f, {
56
+ className: "size-3.5",
57
+ "aria-hidden": "true"
58
+ }), e.duration]
59
+ }),
60
+ e.difficulty ? /* @__PURE__ */ C("span", {
61
+ className: "inline-flex items-center gap-1",
62
+ children: [/* @__PURE__ */ S(m, {
63
+ className: "size-3.5",
64
+ "aria-hidden": "true"
65
+ }), n(e.difficulty)]
66
+ }) : null,
67
+ /* @__PURE__ */ S(s, {
68
+ rating: e.rating,
69
+ reviewCount: e.reviewCount
70
+ }),
71
+ e.sustainabilityScore > 0 ? /* @__PURE__ */ C("span", {
72
+ className: "inline-flex items-center gap-1 tabular-nums text-status-success-text",
73
+ children: [/* @__PURE__ */ S(h, {
74
+ className: "size-3.5",
75
+ "aria-hidden": "true"
76
+ }), e.sustainabilityScore]
77
+ }) : null
78
+ ]
79
+ })
34
80
  }, e.id))
35
81
  });
36
- return /* @__PURE__ */ m(n, {
37
- title: h("ggnomad.tourism.title", "Tourism"),
38
- titleAccent: h("ggnomad.tourism.title.accent", "Tourism"),
39
- subtitle: h("ggnomad.tourism.subtitle", "Tours and curated activity experiences"),
82
+ return /* @__PURE__ */ C(r, {
83
+ title: w("ggnomad.tourism.title", "Tourism"),
84
+ titleAccent: w("ggnomad.tourism.title.accent", "Tourism"),
85
+ subtitle: w("ggnomad.tourism.subtitle", "Tours and curated activity experiences"),
40
86
  children: [
41
- /* @__PURE__ */ p(f, {
42
- icon: /* @__PURE__ */ p(s, { className: "size-4" }),
43
- children: h("ggnomad.tourism.purpose", "Plan what you’ll actually do at a destination — guided tours and bookable activities curated by local operators. Open any experience to review duration, price and what’s included, then add it to a booking.")
87
+ /* @__PURE__ */ S(x, {
88
+ icon: /* @__PURE__ */ S(p, { className: "size-4" }),
89
+ children: w("ggnomad.tourism.purpose", "Plan what you’ll actually do at a destination — guided tours and bookable activities curated by local operators. Open any experience to review duration, price and what’s included, then add it to a booking.")
44
90
  }),
45
- /* @__PURE__ */ m(u, { children: [/* @__PURE__ */ m("div", {
91
+ /* @__PURE__ */ C(y, { children: [/* @__PURE__ */ C("div", {
46
92
  className: "grid gap-4 sm:grid-cols-2",
47
- children: [/* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
93
+ children: [/* @__PURE__ */ C("div", { children: [/* @__PURE__ */ S("p", {
48
94
  className: "text-sm text-text-secondary",
49
- children: h("ggnomad.tourism.tours", "Tours")
50
- }), /* @__PURE__ */ p("p", {
95
+ children: w("ggnomad.tourism.tours", "Tours")
96
+ }), /* @__PURE__ */ S("p", {
51
97
  className: "mt-1 text-2xl font-semibold tabular-nums text-text-primary",
52
- children: S.length
53
- })] }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
98
+ children: P.length
99
+ })] }), /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ S("p", {
54
100
  className: "text-sm text-text-secondary",
55
- children: h("ggnomad.tourism.activities", "Activities")
56
- }), /* @__PURE__ */ p("p", {
101
+ children: w("ggnomad.tourism.activities", "Activities")
102
+ }), /* @__PURE__ */ S("p", {
57
103
  className: "mt-1 text-2xl font-semibold tabular-nums text-text-primary",
58
- children: C.length
104
+ children: F.length
59
105
  })] })]
60
- }), /* @__PURE__ */ p("p", {
106
+ }), /* @__PURE__ */ S("p", {
61
107
  className: "mt-4 text-sm text-text-secondary",
62
- children: h("ggnomad.tourism.emphasisNote", "Curated, bookable experiences across your destinations — pick a tour or activity below to see full details.")
108
+ children: w("ggnomad.tourism.emphasisNote", "Curated, bookable experiences across your destinations — pick a tour or activity below to see full details.")
63
109
  })] }),
64
- /* @__PURE__ */ m("div", {
110
+ /* @__PURE__ */ S(l, {
111
+ idPrefix: "ggnomad-tourism",
112
+ value: k,
113
+ onChange: (e) => {
114
+ E(12), O(12), A(e);
115
+ },
116
+ resultCount: P.length + F.length
117
+ }),
118
+ /* @__PURE__ */ C("div", {
65
119
  className: "grid gap-6 lg:grid-cols-2",
66
- children: [/* @__PURE__ */ m(r, {
67
- title: h("ggnomad.tourism.tours", "Tours"),
68
- children: [w(S, "tours", h("ggnomad.tourism.toursEmpty", "No tours yet")), /* @__PURE__ */ p(a, {
69
- visible: S.length >= g,
70
- onLoadMore: () => _((e) => e + 12)
120
+ children: [/* @__PURE__ */ C(i, {
121
+ title: w("ggnomad.tourism.tours", "Tours"),
122
+ children: [L(P, "tours", w("ggnomad.tourism.toursEmpty", "No tours yet")), /* @__PURE__ */ S(o, {
123
+ visible: P.length >= T,
124
+ onLoadMore: () => E((e) => e + 12)
71
125
  })]
72
- }), /* @__PURE__ */ m(r, {
73
- title: h("ggnomad.tourism.activities", "Activities"),
74
- children: [w(C, "activities", h("ggnomad.tourism.activitiesEmpty", "No activities yet")), /* @__PURE__ */ p(a, {
75
- visible: C.length >= v,
76
- onLoadMore: () => y((e) => e + 12)
126
+ }), /* @__PURE__ */ C(i, {
127
+ title: w("ggnomad.tourism.activities", "Activities"),
128
+ children: [L(F, "activities", w("ggnomad.tourism.activitiesEmpty", "No activities yet")), /* @__PURE__ */ S(o, {
129
+ visible: F.length >= D,
130
+ onLoadMore: () => O((e) => e + 12)
77
131
  })]
78
132
  })]
79
133
  })
@@ -81,6 +135,6 @@ function h() {
81
135
  });
82
136
  }
83
137
  //#endregion
84
- export { h as TourismPage };
138
+ export { w as TourismPage };
85
139
 
86
140
  //# sourceMappingURL=TourismPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TourismPage.js","names":[],"sources":["../../../src/ggnomad/pages/TourismPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Compass } from 'lucide-react';\nimport { EmphasisPanel, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\nimport { GGNOMAD_ACTIVITIES_QUERY, GGNOMAD_TOURS_QUERY } from '../graphql';\nimport { PageShell } from './PageShell';\nimport { EntityCard, SectionCard, LoadMoreButton } from '../components';\n\ntype TourismItem = {\n images?: string[];\n id: string;\n name: string;\n duration: string;\n price: number;\n currency: string;\n};\n\nexport function TourismPage() {\n const { t } = useI18n();\n const [tourLimit, setTourLimit] = useState(12);\n const [activityLimit, setActivityLimit] = useState(12);\n const { data: toursData } = useQuery(\n GGNOMAD_TOURS_QUERY as TypedDocumentNode<\n { ggnomadTours: TourismItem[] },\n { limit: number; offset: number }\n >,\n {\n variables: { limit: tourLimit, offset: 0 },\n }\n );\n const { data: activitiesData } = useQuery(\n GGNOMAD_ACTIVITIES_QUERY as TypedDocumentNode<\n { ggnomadActivities: TourismItem[] },\n { limit: number; offset: number }\n >,\n { variables: { limit: activityLimit, offset: 0 } }\n );\n const tours = toursData?.ggnomadTours ?? [];\n const activities = activitiesData?.ggnomadActivities ?? [];\n\n const renderList = (items: TourismItem[], basePath: string, emptyLabel: string) => {\n if (items.length === 0) {\n return (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={emptyLabel}\n description={t(\n 'ggnomad.tourism.emptyDescription',\n 'Curated experiences will appear here once published.'\n )}\n />\n );\n }\n return (\n <div className=\"grid gap-3\">\n {items.map((item) => (\n <EntityCard\n key={item.id}\n to={`${basePath}/${item.id}`}\n image={item.images?.[0]}\n imageAlt={item.name}\n title={item.name}\n meta={item.duration}\n price={`${item.currency} ${Number(item.price).toFixed(2)}`}\n />\n ))}\n </div>\n );\n };\n\n return (\n <PageShell\n title={t('ggnomad.tourism.title', 'Tourism')}\n titleAccent={t('ggnomad.tourism.title.accent', 'Tourism')}\n subtitle={t('ggnomad.tourism.subtitle', 'Tours and curated activity experiences')}\n >\n <PagePurpose icon={<Compass className=\"size-4\" />}>\n {t(\n 'ggnomad.tourism.purpose',\n 'Plan what you’ll actually do at a destination — guided tours and bookable activities curated by local operators. Open any experience to review duration, price and what’s included, then add it to a booking.'\n )}\n </PagePurpose>\n\n <EmphasisPanel>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div>\n <p className=\"text-sm text-text-secondary\">{t('ggnomad.tourism.tours', 'Tours')}</p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums text-text-primary\">\n {tours.length}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {t('ggnomad.tourism.activities', 'Activities')}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums text-text-primary\">\n {activities.length}\n </p>\n </div>\n </div>\n <p className=\"mt-4 text-sm text-text-secondary\">\n {t(\n 'ggnomad.tourism.emphasisNote',\n 'Curated, bookable experiences across your destinations — pick a tour or activity below to see full details.'\n )}\n </p>\n </EmphasisPanel>\n\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <SectionCard title={t('ggnomad.tourism.tours', 'Tours')}>\n {renderList(tours, 'tours', t('ggnomad.tourism.toursEmpty', 'No tours yet'))}\n <LoadMoreButton\n visible={tours.length >= tourLimit}\n onLoadMore={() => setTourLimit((l) => l + 12)}\n />\n </SectionCard>\n <SectionCard title={t('ggnomad.tourism.activities', 'Activities')}>\n {renderList(\n activities,\n 'activities',\n t('ggnomad.tourism.activitiesEmpty', 'No activities yet')\n )}\n <LoadMoreButton\n visible={activities.length >= activityLimit}\n onLoadMore={() => setActivityLimit((l) => l + 12)}\n />\n </SectionCard>\n </div>\n </PageShell>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAoBA,SAAgB,IAAc;CAC5B,IAAM,EAAE,SAAM,EAAQ,GAChB,CAAC,GAAW,KAAgB,EAAS,EAAE,GACvC,CAAC,GAAe,KAAoB,EAAS,EAAE,GAC/C,EAAE,MAAM,MAAc,EAC1B,GAIA,EACE,WAAW;EAAE,OAAO;EAAW,QAAQ;CAAE,EAC3C,CACF,GACM,EAAE,MAAM,MAAmB,EAC/B,GAIA,EAAE,WAAW;EAAE,OAAO;EAAe,QAAQ;CAAE,EAAE,CACnD,GACM,IAAQ,GAAW,gBAAgB,CAAC,GACpC,IAAa,GAAgB,qBAAqB,CAAC,GAEnD,KAAc,GAAsB,GAAkB,MACtD,EAAM,WAAW,IAEjB,kBAAC,GAAD;EACE,cAAa;EACb,OAAO;EACP,aAAa,EACX,oCACA,sDACF;CACD,CAAA,IAIH,kBAAC,OAAD;EAAK,WAAU;YACZ,EAAM,KAAK,MACV,kBAAC,GAAD;GAEE,IAAI,GAAG,EAAS,GAAG,EAAK;GACxB,OAAO,EAAK,SAAS;GACrB,UAAU,EAAK;GACf,OAAO,EAAK;GACZ,MAAM,EAAK;GACX,OAAO,GAAG,EAAK,SAAS,GAAG,OAAO,EAAK,KAAK,EAAE,QAAQ,CAAC;EACxD,GAPM,EAAK,EAOX,CACF;CACE,CAAA;CAIT,OACE,kBAAC,GAAD;EACE,OAAO,EAAE,yBAAyB,SAAS;EAC3C,aAAa,EAAE,gCAAgC,SAAS;EACxD,UAAU,EAAE,4BAA4B,wCAAwC;YAHlF;GAKE,kBAAC,GAAD;IAAa,MAAM,kBAAC,GAAD,EAAS,WAAU,SAAU,CAAA;cAC7C,EACC,2BACA,+MACF;GACW,CAAA;GAEb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;KAAG,WAAU;eAA+B,EAAE,yBAAyB,OAAO;IAAK,CAAA,GACnF,kBAAC,KAAD;KAAG,WAAU;eACV,EAAM;IACN,CAAA,CACA,EAAA,CAAA,GACL,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;KAAG,WAAU;eACV,EAAE,8BAA8B,YAAY;IAC5C,CAAA,GACH,kBAAC,KAAD;KAAG,WAAU;eACV,EAAW;IACX,CAAA,CACA,EAAA,CAAA,CACF;OACL,kBAAC,KAAD;IAAG,WAAU;cACV,EACC,gCACA,6GACF;GACC,CAAA,CACU,EAAA,CAAA;GAEf,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KAAa,OAAO,EAAE,yBAAyB,OAAO;eAAtD,CACG,EAAW,GAAO,SAAS,EAAE,8BAA8B,cAAc,CAAC,GAC3E,kBAAC,GAAD;MACE,SAAS,EAAM,UAAU;MACzB,kBAAkB,GAAc,MAAM,IAAI,EAAE;KAC7C,CAAA,CACU;QACb,kBAAC,GAAD;KAAa,OAAO,EAAE,8BAA8B,YAAY;eAAhE,CACG,EACC,GACA,cACA,EAAE,mCAAmC,mBAAmB,CAC1D,GACA,kBAAC,GAAD;MACE,SAAS,EAAW,UAAU;MAC9B,kBAAkB,GAAkB,MAAM,IAAI,EAAE;KACjD,CAAA,CACU;MACV;;EACI;;AAEf"}
1
+ {"version":3,"file":"TourismPage.js","names":[],"sources":["../../../src/ggnomad/pages/TourismPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Clock, Compass, Gauge, Leaf, Zap } from 'lucide-react';\nimport { EmphasisPanel, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\nimport { GGNOMAD_ACTIVITIES_QUERY, GGNOMAD_TOURS_QUERY } from '../graphql';\nimport { humanizeEnum } from '../utils/format';\nimport { PageShell } from './PageShell';\nimport {\n EntityCard,\n EMPTY_LISTING_FILTERS,\n ListingFilters,\n LoadMoreButton,\n RatingSummary,\n SectionCard,\n hasActiveListingFilters,\n} from '../components';\nimport type { ListingFilterState } from '../components';\n\ntype TourismItem = {\n id: string;\n name: string;\n /** Tours carry `type` (CULTURAL, ADVENTURE…), activities carry `category`. */\n type?: string;\n category?: string;\n duration: string;\n difficulty?: string | null;\n price: number;\n currency: string;\n rating?: number | null;\n reviewCount: number;\n images?: string[];\n instantBook: boolean;\n sustainabilityScore: number;\n};\n\ntype ListingVariables = {\n limit: number;\n offset: number;\n status?: string;\n minSustainabilityScore?: number;\n hasAccessibilityFeatures?: string[];\n};\n\nexport function TourismPage() {\n const { t } = useI18n();\n const [tourLimit, setTourLimit] = useState(12);\n const [activityLimit, setActivityLimit] = useState(12);\n const [filters, setFilters] = useState<ListingFilterState>(EMPTY_LISTING_FILTERS);\n\n const filterVariables = {\n status: filters.status,\n minSustainabilityScore: filters.minSustainabilityScore,\n hasAccessibilityFeatures:\n filters.accessibilityFeatures.length > 0 ? filters.accessibilityFeatures : undefined,\n };\n\n const { data: toursData } = useQuery(\n GGNOMAD_TOURS_QUERY as TypedDocumentNode<{ ggnomadTours: TourismItem[] }, ListingVariables>,\n { variables: { limit: tourLimit, offset: 0, ...filterVariables } }\n );\n const { data: activitiesData } = useQuery(\n GGNOMAD_ACTIVITIES_QUERY as TypedDocumentNode<\n { ggnomadActivities: TourismItem[] },\n ListingVariables\n >,\n { variables: { limit: activityLimit, offset: 0, ...filterVariables } }\n );\n const tours = toursData?.ggnomadTours ?? [];\n const activities = activitiesData?.ggnomadActivities ?? [];\n const filtered = hasActiveListingFilters(filters);\n\n const renderList = (items: TourismItem[], basePath: string, emptyLabel: string) => {\n if (items.length === 0) {\n return (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={\n filtered\n ? t('ggnomad.tourism.noMatchTitle', 'Nothing matches these filters')\n : emptyLabel\n }\n description={\n filtered\n ? t(\n 'ggnomad.tourism.noMatchDescription',\n 'Try clearing a filter — status, sustainability score and accessibility all narrow the catalogue.'\n )\n : t(\n 'ggnomad.tourism.emptyDescription',\n 'Curated experiences will appear here once published.'\n )\n }\n />\n );\n }\n return (\n <div className=\"grid gap-3\">\n {items.map((item) => (\n <EntityCard\n key={item.id}\n to={`${basePath}/${item.id}`}\n image={item.images?.[0]}\n imageAlt={item.name}\n title={item.name}\n meta={humanizeEnum(item.type ?? item.category ?? '')}\n badge={\n item.instantBook ? (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-status-success-bg-subtle px-2.5 py-0.5 text-xs font-medium text-status-success-text\">\n <Zap className=\"size-3\" aria-hidden=\"true\" />\n {t('ggnomad.listing.instantBook', 'Instant book')}\n </span>\n ) : null\n }\n price={`${item.currency} ${Number(item.price).toFixed(2)}`}\n footer={\n <div className=\"flex flex-wrap items-center gap-x-3 gap-y-1\">\n <span className=\"inline-flex items-center gap-1\">\n <Clock className=\"size-3.5\" aria-hidden=\"true\" />\n {item.duration}\n </span>\n {item.difficulty ? (\n <span className=\"inline-flex items-center gap-1\">\n <Gauge className=\"size-3.5\" aria-hidden=\"true\" />\n {humanizeEnum(item.difficulty)}\n </span>\n ) : null}\n <RatingSummary rating={item.rating} reviewCount={item.reviewCount} />\n {item.sustainabilityScore > 0 ? (\n <span className=\"inline-flex items-center gap-1 tabular-nums text-status-success-text\">\n <Leaf className=\"size-3.5\" aria-hidden=\"true\" />\n {item.sustainabilityScore}\n </span>\n ) : null}\n </div>\n }\n />\n ))}\n </div>\n );\n };\n\n return (\n <PageShell\n title={t('ggnomad.tourism.title', 'Tourism')}\n titleAccent={t('ggnomad.tourism.title.accent', 'Tourism')}\n subtitle={t('ggnomad.tourism.subtitle', 'Tours and curated activity experiences')}\n >\n <PagePurpose icon={<Compass className=\"size-4\" />}>\n {t(\n 'ggnomad.tourism.purpose',\n 'Plan what you’ll actually do at a destination — guided tours and bookable activities curated by local operators. Open any experience to review duration, price and what’s included, then add it to a booking.'\n )}\n </PagePurpose>\n\n <EmphasisPanel>\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <div>\n <p className=\"text-sm text-text-secondary\">{t('ggnomad.tourism.tours', 'Tours')}</p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums text-text-primary\">\n {tours.length}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {t('ggnomad.tourism.activities', 'Activities')}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums text-text-primary\">\n {activities.length}\n </p>\n </div>\n </div>\n <p className=\"mt-4 text-sm text-text-secondary\">\n {t(\n 'ggnomad.tourism.emphasisNote',\n 'Curated, bookable experiences across your destinations — pick a tour or activity below to see full details.'\n )}\n </p>\n </EmphasisPanel>\n\n <ListingFilters\n idPrefix=\"ggnomad-tourism\"\n value={filters}\n onChange={(next) => {\n setTourLimit(12);\n setActivityLimit(12);\n setFilters(next);\n }}\n resultCount={tours.length + activities.length}\n />\n\n <div className=\"grid gap-6 lg:grid-cols-2\">\n <SectionCard title={t('ggnomad.tourism.tours', 'Tours')}>\n {renderList(tours, 'tours', t('ggnomad.tourism.toursEmpty', 'No tours yet'))}\n <LoadMoreButton\n visible={tours.length >= tourLimit}\n onLoadMore={() => setTourLimit((l) => l + 12)}\n />\n </SectionCard>\n <SectionCard title={t('ggnomad.tourism.activities', 'Activities')}>\n {renderList(\n activities,\n 'activities',\n t('ggnomad.tourism.activitiesEmpty', 'No activities yet')\n )}\n <LoadMoreButton\n visible={activities.length >= activityLimit}\n onLoadMore={() => setActivityLimit((l) => l + 12)}\n />\n </SectionCard>\n </div>\n </PageShell>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA8CA,SAAgB,IAAc;CAC5B,IAAM,EAAE,SAAM,EAAQ,GAChB,CAAC,GAAW,KAAgB,EAAS,EAAE,GACvC,CAAC,GAAe,KAAoB,EAAS,EAAE,GAC/C,CAAC,GAAS,KAAc,EAA6B,CAAqB,GAE1E,IAAkB;EACtB,QAAQ,EAAQ;EAChB,wBAAwB,EAAQ;EAChC,0BACE,EAAQ,sBAAsB,SAAS,IAAI,EAAQ,wBAAwB,KAAA;CAC/E,GAEM,EAAE,MAAM,MAAc,EAC1B,GACA,EAAE,WAAW;EAAE,OAAO;EAAW,QAAQ;EAAG,GAAG;CAAgB,EAAE,CACnE,GACM,EAAE,MAAM,MAAmB,EAC/B,GAIA,EAAE,WAAW;EAAE,OAAO;EAAe,QAAQ;EAAG,GAAG;CAAgB,EAAE,CACvE,GACM,IAAQ,GAAW,gBAAgB,CAAC,GACpC,IAAa,GAAgB,qBAAqB,CAAC,GACnD,IAAW,EAAwB,CAAO,GAE1C,KAAc,GAAsB,GAAkB,MACtD,EAAM,WAAW,IAEjB,kBAAC,GAAD;EACE,cAAa;EACb,OACE,IACI,EAAE,gCAAgC,+BAA+B,IACjE;EAEN,aACE,IACI,EACE,sCACA,kGACF,IACA,EACE,oCACA,sDACF;CAEP,CAAA,IAIH,kBAAC,OAAD;EAAK,WAAU;YACZ,EAAM,KAAK,MACV,kBAAC,GAAD;GAEE,IAAI,GAAG,EAAS,GAAG,EAAK;GACxB,OAAO,EAAK,SAAS;GACrB,UAAU,EAAK;GACf,OAAO,EAAK;GACZ,MAAM,EAAa,EAAK,QAAQ,EAAK,YAAY,EAAE;GACnD,OACE,EAAK,cACH,kBAAC,QAAD;IAAM,WAAU;cAAhB,CACE,kBAAC,GAAD;KAAK,WAAU;KAAS,eAAY;IAAQ,CAAA,GAC3C,EAAE,+BAA+B,cAAc,CAC5C;QACJ;GAEN,OAAO,GAAG,EAAK,SAAS,GAAG,OAAO,EAAK,KAAK,EAAE,QAAQ,CAAC;GACvD,QACE,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,QAAD;MAAM,WAAU;gBAAhB,CACE,kBAAC,GAAD;OAAO,WAAU;OAAW,eAAY;MAAQ,CAAA,GAC/C,EAAK,QACF;;KACL,EAAK,aACJ,kBAAC,QAAD;MAAM,WAAU;gBAAhB,CACE,kBAAC,GAAD;OAAO,WAAU;OAAW,eAAY;MAAQ,CAAA,GAC/C,EAAa,EAAK,UAAU,CACzB;UACJ;KACJ,kBAAC,GAAD;MAAe,QAAQ,EAAK;MAAQ,aAAa,EAAK;KAAc,CAAA;KACnE,EAAK,sBAAsB,IAC1B,kBAAC,QAAD;MAAM,WAAU;gBAAhB,CACE,kBAAC,GAAD;OAAM,WAAU;OAAW,eAAY;MAAQ,CAAA,GAC9C,EAAK,mBACF;UACJ;IACD;;EAER,GApCM,EAAK,EAoCX,CACF;CACE,CAAA;CAIT,OACE,kBAAC,GAAD;EACE,OAAO,EAAE,yBAAyB,SAAS;EAC3C,aAAa,EAAE,gCAAgC,SAAS;EACxD,UAAU,EAAE,4BAA4B,wCAAwC;YAHlF;GAKE,kBAAC,GAAD;IAAa,MAAM,kBAAC,GAAD,EAAS,WAAU,SAAU,CAAA;cAC7C,EACC,2BACA,+MACF;GACW,CAAA;GAEb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;KAAG,WAAU;eAA+B,EAAE,yBAAyB,OAAO;IAAK,CAAA,GACnF,kBAAC,KAAD;KAAG,WAAU;eACV,EAAM;IACN,CAAA,CACA,EAAA,CAAA,GACL,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;KAAG,WAAU;eACV,EAAE,8BAA8B,YAAY;IAC5C,CAAA,GACH,kBAAC,KAAD;KAAG,WAAU;eACV,EAAW;IACX,CAAA,CACA,EAAA,CAAA,CACF;OACL,kBAAC,KAAD;IAAG,WAAU;cACV,EACC,gCACA,6GACF;GACC,CAAA,CACU,EAAA,CAAA;GAEf,kBAAC,GAAD;IACE,UAAS;IACT,OAAO;IACP,WAAW,MAAS;KAGlB,AAFA,EAAa,EAAE,GACf,EAAiB,EAAE,GACnB,EAAW,CAAI;IACjB;IACA,aAAa,EAAM,SAAS,EAAW;GACxC,CAAA;GAED,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KAAa,OAAO,EAAE,yBAAyB,OAAO;eAAtD,CACG,EAAW,GAAO,SAAS,EAAE,8BAA8B,cAAc,CAAC,GAC3E,kBAAC,GAAD;MACE,SAAS,EAAM,UAAU;MACzB,kBAAkB,GAAc,MAAM,IAAI,EAAE;KAC7C,CAAA,CACU;QACb,kBAAC,GAAD;KAAa,OAAO,EAAE,8BAA8B,YAAY;eAAhE,CACG,EACC,GACA,cACA,EAAE,mCAAmC,mBAAmB,CAC1D,GACA,kBAAC,GAAD;MACE,SAAS,EAAW,UAAU;MAC9B,kBAAkB,GAAkB,MAAM,IAAI,EAAE;KACjD,CAAA,CACU;MACV;;EACI;;AAEf"}