@burdenoff/microfe-ggnomad 2026.719.1 → 2026.719.2
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/components/ReviewsSection.js +2 -2
- package/dist/ggnomad/components/ReviewsSection.js.map +1 -1
- package/dist/ggnomad/graphql.js +27 -27
- package/dist/ggnomad/graphql.js.map +1 -1
- package/dist/ggnomad/pages/BookingsPage.js +2 -2
- package/dist/ggnomad/pages/BookingsPage.js.map +1 -1
- package/dist/ggnomad/pages/DashboardPage.js +8 -8
- package/dist/ggnomad/pages/DashboardPage.js.map +1 -1
- package/dist/ggnomad/pages/EntertainmentPage.js +2 -2
- package/dist/ggnomad/pages/EntertainmentPage.js.map +1 -1
- package/dist/ggnomad/pages/HospitalityPage.js +2 -2
- package/dist/ggnomad/pages/HospitalityPage.js.map +1 -1
- package/dist/ggnomad/pages/ProviderPage.js +2 -2
- package/dist/ggnomad/pages/ProviderPage.js.map +1 -1
- package/dist/ggnomad/pages/SearchPage.js +8 -8
- package/dist/ggnomad/pages/SearchPage.js.map +1 -1
- package/dist/ggnomad/pages/TourismPage.js +4 -4
- package/dist/ggnomad/pages/TourismPage.js.map +1 -1
- package/dist/ggnomad/pages/TravelPage.js +2 -2
- package/dist/ggnomad/pages/TravelPage.js.map +1 -1
- package/dist/ggnomad/pages/TripPlanDetailPage.js +8 -8
- package/dist/ggnomad/pages/TripPlanDetailPage.js.map +1 -1
- package/dist/ggnomad/pages/TripsPage.js +2 -2
- package/dist/ggnomad/pages/TripsPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -12,8 +12,8 @@ import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
|
12
12
|
//#region src/ggnomad/pages/HospitalityPage.tsx
|
|
13
13
|
function m() {
|
|
14
14
|
let { t: m } = s(), [h, g] = i(12), { data: _ } = c(e, { variables: {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
limit: h,
|
|
16
|
+
offset: 0
|
|
17
17
|
} }), v = _?.ggnomadProperties ?? [];
|
|
18
18
|
return /* @__PURE__ */ p(t, {
|
|
19
19
|
title: m("ggnomad.hospitality.title", "Hospitality"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HospitalityPage.js","names":[],"sources":["../../../src/ggnomad/pages/HospitalityPage.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 { Hotel, Star } from 'lucide-react';\nimport { GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\nimport { GGNOMAD_PROPERTIES_QUERY } from '../graphql';\nimport { PageShell } from './PageShell';\nimport { EntityCard, LoadMoreButton } from '../components';\n\nexport function HospitalityPage() {\n const { t } = useI18n();\n const [limit, setLimit] = useState(12);\n const { data } = useQuery(\n GGNOMAD_PROPERTIES_QUERY as TypedDocumentNode<\n {\n ggnomadProperties: Array<{\n id: string;\n name: string;\n type: string;\n pricePerNight: number;\n currency: string;\n rating?: number;\n images?: string[];\n }>;\n },\n {
|
|
1
|
+
{"version":3,"file":"HospitalityPage.js","names":[],"sources":["../../../src/ggnomad/pages/HospitalityPage.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 { Hotel, Star } from 'lucide-react';\nimport { GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\nimport { GGNOMAD_PROPERTIES_QUERY } from '../graphql';\nimport { PageShell } from './PageShell';\nimport { EntityCard, LoadMoreButton } from '../components';\n\nexport function HospitalityPage() {\n const { t } = useI18n();\n const [limit, setLimit] = useState(12);\n const { data } = useQuery(\n GGNOMAD_PROPERTIES_QUERY as TypedDocumentNode<\n {\n ggnomadProperties: Array<{\n id: string;\n name: string;\n type: string;\n pricePerNight: number;\n currency: string;\n rating?: number;\n images?: string[];\n }>;\n },\n { limit: number; offset: number }\n >,\n { variables: { limit, offset: 0 } }\n );\n const properties = data?.ggnomadProperties ?? [];\n\n return (\n <PageShell\n title={t('ggnomad.hospitality.title', 'Hospitality')}\n titleAccent={t('ggnomad.hospitality.title.accent', 'Hospitality')}\n subtitle={t(\n 'ggnomad.hospitality.subtitle',\n 'Property discovery powered by live GraphQL data'\n )}\n >\n <PagePurpose icon={<Hotel className=\"size-4\" />}>\n {t(\n 'ggnomad.hospitality.purpose',\n 'Discover places to stay — hotels, homestays and short-stay rentals. Open any property to review its nightly price, guest capacity and rating, then create a booking for the dates you need.'\n )}\n </PagePurpose>\n\n {properties.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('ggnomad.hospitality.emptyTitle', 'No properties available')}\n description={t(\n 'ggnomad.hospitality.emptyDescription',\n 'Properties published by providers will be discoverable here.'\n )}\n />\n ) : (\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.hospitality.featuredStays', 'Featured stays')}\n </h2>\n <div className=\"grid gap-3 sm:grid-cols-2 xl:grid-cols-3\">\n {properties.map((property) => (\n <EntityCard\n key={property.id}\n to={property.id}\n image={property.images?.[0]}\n imageAlt={property.name}\n title={property.name}\n meta={property.type}\n price={`${property.currency} ${Number(property.pricePerNight).toFixed(2)} ${t(\n 'ggnomad.hospitality.card.perNight',\n 'per night'\n )}`}\n footer={\n <span className=\"inline-flex items-center gap-1 tabular-nums\">\n <Star className=\"size-3.5 text-status-warning-text\" aria-hidden=\"true\" />\n {property.rating ?? t('ggnomad.hospitality.card.noRating', 'N/A')}\n </span>\n }\n />\n ))}\n </div>\n <LoadMoreButton\n visible={properties.length >= limit}\n onLoadMore={() => setLimit((l) => l + 12)}\n />\n </GlassCard>\n )}\n </PageShell>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAWA,SAAgB,IAAkB;CAChC,IAAM,EAAE,SAAM,EAAQ,GAChB,CAAC,GAAO,KAAY,EAAS,EAAE,GAC/B,EAAE,YAAS,EACf,GAcA,EAAE,WAAW;EAAE;EAAO,QAAQ;CAAE,EAAE,CACpC,GACM,IAAa,GAAM,qBAAqB,CAAC;CAE/C,OACE,kBAAC,GAAD;EACE,OAAO,EAAE,6BAA6B,aAAa;EACnD,aAAa,EAAE,oCAAoC,aAAa;EAChE,UAAU,EACR,gCACA,iDACF;YANF,CAQE,kBAAC,GAAD;GAAa,MAAM,kBAAC,GAAD,EAAO,WAAU,SAAU,CAAA;aAC3C,EACC,+BACA,6LACF;EACW,CAAA,GAEZ,EAAW,WAAW,IACrB,kBAAC,GAAD;GACE,cAAa;GACb,OAAO,EAAE,kCAAkC,yBAAyB;GACpE,aAAa,EACX,wCACA,8DACF;EACD,CAAA,IAED,kBAAC,GAAD;GAAW,WAAU;GAAQ,MAAA;GAAK,WAAU;aAA5C;IACE,kBAAC,MAAD;KAAI,WAAU;eACX,EAAE,qCAAqC,gBAAgB;IACtD,CAAA;IACJ,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAW,KAAK,MACf,kBAAC,GAAD;MAEE,IAAI,EAAS;MACb,OAAO,EAAS,SAAS;MACzB,UAAU,EAAS;MACnB,OAAO,EAAS;MAChB,MAAM,EAAS;MACf,OAAO,GAAG,EAAS,SAAS,GAAG,OAAO,EAAS,aAAa,EAAE,QAAQ,CAAC,EAAE,GAAG,EAC1E,qCACA,WACF;MACA,QACE,kBAAC,QAAD;OAAM,WAAU;iBAAhB,CACE,kBAAC,GAAD;QAAM,WAAU;QAAoC,eAAY;OAAQ,CAAA,GACvE,EAAS,UAAU,EAAE,qCAAqC,KAAK,CAC5D;;KAET,GAhBM,EAAS,EAgBf,CACF;IACE,CAAA;IACL,kBAAC,GAAD;KACE,SAAS,EAAW,UAAU;KAC9B,kBAAkB,GAAU,MAAM,IAAI,EAAE;IACzC,CAAA;GACQ;IAEJ;;AAEf"}
|
|
@@ -13,8 +13,8 @@ import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
|
13
13
|
//#region src/ggnomad/pages/ProviderPage.tsx
|
|
14
14
|
function m() {
|
|
15
15
|
let { t: m } = s(), [h, g] = a(12), { data: _ } = c(e, { variables: {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
limit: h,
|
|
17
|
+
offset: 0
|
|
18
18
|
} }), v = _?.ggnomadProviders ?? [];
|
|
19
19
|
return /* @__PURE__ */ p(t, {
|
|
20
20
|
title: m("ggnomad.provider.title", "Provider Dashboard"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProviderPage.js","names":[],"sources":["../../../src/ggnomad/pages/ProviderPage.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 { Briefcase } from 'lucide-react';\nimport { GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\nimport { GGNOMAD_PROVIDERS_QUERY } from '../graphql';\nimport { PageShell } from './PageShell';\nimport { EntityCard, LoadMoreButton, StatusBadge } from '../components';\n\nexport function ProviderPage() {\n const { t } = useI18n();\n const [limit, setLimit] = useState(12);\n const { data } = useQuery(\n GGNOMAD_PROVIDERS_QUERY as TypedDocumentNode<\n {\n ggnomadProviders: Array<{\n id: string;\n name: string;\n type: string;\n status: string;\n listingCount: number;\n totalRevenue: number;\n rating?: number;\n }>;\n },\n {
|
|
1
|
+
{"version":3,"file":"ProviderPage.js","names":[],"sources":["../../../src/ggnomad/pages/ProviderPage.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 { Briefcase } from 'lucide-react';\nimport { GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\nimport { GGNOMAD_PROVIDERS_QUERY } from '../graphql';\nimport { PageShell } from './PageShell';\nimport { EntityCard, LoadMoreButton, StatusBadge } from '../components';\n\nexport function ProviderPage() {\n const { t } = useI18n();\n const [limit, setLimit] = useState(12);\n const { data } = useQuery(\n GGNOMAD_PROVIDERS_QUERY as TypedDocumentNode<\n {\n ggnomadProviders: Array<{\n id: string;\n name: string;\n type: string;\n status: string;\n listingCount: number;\n totalRevenue: number;\n rating?: number;\n }>;\n },\n { limit: number; offset: number }\n >,\n { variables: { limit, offset: 0 } }\n );\n const providers = data?.ggnomadProviders ?? [];\n\n return (\n <PageShell\n title={t('ggnomad.provider.title', 'Provider Dashboard')}\n titleAccent={t('ggnomad.provider.title.accent', 'Provider')}\n subtitle={t('ggnomad.provider.subtitle', 'B2B provider operations and onboarding metrics')}\n >\n <PagePurpose icon={<Briefcase className=\"size-4\" />}>\n {t(\n 'ggnomad.provider.purpose',\n 'Track the supply side of the marketplace — the hotels, tour operators and venues that publish inventory. Use it to monitor each provider’s status, listing count, revenue and rating, and to spot who needs onboarding attention.'\n )}\n </PagePurpose>\n\n {providers.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-people\"\n title={t('ggnomad.provider.emptyTitle', 'No providers onboarded')}\n description={t(\n 'ggnomad.provider.emptyDescription',\n 'Onboarded B2B providers and their performance will be tracked here.'\n )}\n />\n ) : (\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.provider.onboardedProviders', 'Onboarded providers')}\n </h2>\n <div className=\"grid gap-3 sm:grid-cols-2 xl:grid-cols-3\">\n {providers.map((provider) => (\n <EntityCard\n key={provider.id}\n title={provider.name}\n meta={provider.type}\n badge={<StatusBadge status={provider.status} live={provider.status === 'ACTIVE'} />}\n footer={\n <dl className=\"grid grid-cols-3 gap-2 text-xs\">\n <div>\n <dt className=\"text-text-secondary\">\n {t('ggnomad.provider.listings', 'Listings')}\n </dt>\n <dd className=\"mt-0.5 font-medium tabular-nums text-text-primary\">\n {provider.listingCount}\n </dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {t('ggnomad.provider.revenue', 'Revenue')}\n </dt>\n <dd className=\"mt-0.5 font-medium tabular-nums text-text-primary\">\n ${Number(provider.totalRevenue).toLocaleString()}\n </dd>\n </div>\n <div>\n <dt className=\"text-text-secondary\">\n {t('ggnomad.provider.rating', 'Rating')}\n </dt>\n <dd className=\"mt-0.5 font-medium tabular-nums text-text-primary\">\n {provider.rating ?? t('ggnomad.provider.noRating', 'N/A')}\n </dd>\n </div>\n </dl>\n }\n />\n ))}\n </div>\n <LoadMoreButton\n visible={providers.length >= limit}\n onLoadMore={() => setLimit((l) => l + 12)}\n />\n </GlassCard>\n )}\n </PageShell>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAWA,SAAgB,IAAe;CAC7B,IAAM,EAAE,SAAM,EAAQ,GAChB,CAAC,GAAO,KAAY,EAAS,EAAE,GAC/B,EAAE,YAAS,EACf,GAcA,EAAE,WAAW;EAAE;EAAO,QAAQ;CAAE,EAAE,CACpC,GACM,IAAY,GAAM,oBAAoB,CAAC;CAE7C,OACE,kBAAC,GAAD;EACE,OAAO,EAAE,0BAA0B,oBAAoB;EACvD,aAAa,EAAE,iCAAiC,UAAU;EAC1D,UAAU,EAAE,6BAA6B,gDAAgD;YAH3F,CAKE,kBAAC,GAAD;GAAa,MAAM,kBAAC,GAAD,EAAW,WAAU,SAAU,CAAA;aAC/C,EACC,4BACA,mOACF;EACW,CAAA,GAEZ,EAAU,WAAW,IACpB,kBAAC,GAAD;GACE,cAAa;GACb,OAAO,EAAE,+BAA+B,wBAAwB;GAChE,aAAa,EACX,qCACA,qEACF;EACD,CAAA,IAED,kBAAC,GAAD;GAAW,WAAU;GAAQ,MAAA;GAAK,WAAU;aAA5C;IACE,kBAAC,MAAD;KAAI,WAAU;eACX,EAAE,uCAAuC,qBAAqB;IAC7D,CAAA;IACJ,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAU,KAAK,MACd,kBAAC,GAAD;MAEE,OAAO,EAAS;MAChB,MAAM,EAAS;MACf,OAAO,kBAAC,GAAD;OAAa,QAAQ,EAAS;OAAQ,MAAM,EAAS,WAAW;MAAW,CAAA;MAClF,QACE,kBAAC,MAAD;OAAI,WAAU;iBAAd;QACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAE,6BAA6B,UAAU;QACxC,CAAA,GACJ,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAS;QACR,CAAA,CACD,EAAA,CAAA;QACL,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAE,4BAA4B,SAAS;QACtC,CAAA,GACJ,kBAAC,MAAD;SAAI,WAAU;mBAAd,CAAkE,KAC9D,OAAO,EAAS,YAAY,EAAE,eAAe,CAC7C;UACD,EAAA,CAAA;QACL,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAE,2BAA2B,QAAQ;QACpC,CAAA,GACJ,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAS,UAAU,EAAE,6BAA6B,KAAK;QACtD,CAAA,CACD,EAAA,CAAA;OACH;;KAEP,GAhCM,EAAS,EAgCf,CACF;IACE,CAAA;IACL,kBAAC,GAAD;KACE,SAAS,EAAU,UAAU;KAC7B,kBAAkB,GAAU,MAAM,IAAI,EAAE;IACzC,CAAA;GACQ;IAEJ;;AAEf"}
|
|
@@ -10,17 +10,17 @@ import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
|
|
|
10
10
|
//#region src/ggnomad/pages/SearchPage.tsx
|
|
11
11
|
function y() {
|
|
12
12
|
let { t: y } = d(), b = f(n, { variables: {
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
limit: 5,
|
|
14
|
+
offset: 0
|
|
15
15
|
} }), x = f(r, { variables: {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
limit: 5,
|
|
17
|
+
offset: 0
|
|
18
18
|
} }), S = f(t, { variables: {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
limit: 5,
|
|
20
|
+
offset: 0
|
|
21
21
|
} }), C = f(e, { variables: {
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
limit: 5,
|
|
23
|
+
offset: 0
|
|
24
24
|
} }), w = b.data?.ggnomadProperties?.length ?? 0, T = x.data?.ggnomadTours?.length ?? 0, E = S.data?.ggnomadEvents?.length ?? 0, D = C.data?.ggnomadActivities?.length ?? 0, O = w + T + E + D;
|
|
25
25
|
return /* @__PURE__ */ v(i, {
|
|
26
26
|
title: y("ggnomad.search.title", "Global Search"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchPage.js","names":[],"sources":["../../../src/ggnomad/pages/SearchPage.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 { Activity, Building, Compass, Search, Ticket } from 'lucide-react';\nimport { EmphasisPanel, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\nimport {\n GGNOMAD_PROPERTIES_QUERY,\n GGNOMAD_TOURS_QUERY,\n GGNOMAD_EVENTS_QUERY,\n GGNOMAD_ACTIVITIES_QUERY,\n} from '../graphql';\nimport { PageShell } from './PageShell';\nimport { StatCard } from '../components';\n\nexport function SearchPage() {\n const { t } = useI18n();\n const properties = useQuery(\n GGNOMAD_PROPERTIES_QUERY as TypedDocumentNode<\n { ggnomadProperties: Array<{ id: string }> },\n {
|
|
1
|
+
{"version":3,"file":"SearchPage.js","names":[],"sources":["../../../src/ggnomad/pages/SearchPage.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 { Activity, Building, Compass, Search, Ticket } from 'lucide-react';\nimport { EmphasisPanel, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\nimport {\n GGNOMAD_PROPERTIES_QUERY,\n GGNOMAD_TOURS_QUERY,\n GGNOMAD_EVENTS_QUERY,\n GGNOMAD_ACTIVITIES_QUERY,\n} from '../graphql';\nimport { PageShell } from './PageShell';\nimport { StatCard } from '../components';\n\nexport function SearchPage() {\n const { t } = useI18n();\n const properties = useQuery(\n GGNOMAD_PROPERTIES_QUERY as TypedDocumentNode<\n { ggnomadProperties: Array<{ id: string }> },\n { limit: number; offset: number }\n >,\n { variables: { limit: 5, offset: 0 } }\n );\n const tours = useQuery(\n GGNOMAD_TOURS_QUERY as TypedDocumentNode<\n { ggnomadTours: Array<{ id: string }> },\n { limit: number; offset: number }\n >,\n {\n variables: { limit: 5, offset: 0 },\n }\n );\n const events = useQuery(\n GGNOMAD_EVENTS_QUERY as TypedDocumentNode<\n { ggnomadEvents: Array<{ id: string }> },\n { limit: number; offset: number }\n >,\n {\n variables: { limit: 5, offset: 0 },\n }\n );\n const activities = useQuery(\n GGNOMAD_ACTIVITIES_QUERY as TypedDocumentNode<\n { ggnomadActivities: Array<{ id: string }> },\n { limit: number; offset: number }\n >,\n { variables: { limit: 5, offset: 0 } }\n );\n\n const propertyCount = properties.data?.ggnomadProperties?.length ?? 0;\n const tourCount = tours.data?.ggnomadTours?.length ?? 0;\n const eventCount = events.data?.ggnomadEvents?.length ?? 0;\n const activityCount = activities.data?.ggnomadActivities?.length ?? 0;\n const total = propertyCount + tourCount + eventCount + activityCount;\n\n return (\n <PageShell\n title={t('ggnomad.search.title', 'Global Search')}\n titleAccent={t('ggnomad.search.title.accent', 'Search')}\n subtitle={t('ggnomad.search.subtitle', 'Cross-domain search across all GGNomad inventory')}\n >\n <PagePurpose icon={<Search className=\"size-4\" />}>\n {t(\n 'ggnomad.search.purpose',\n 'One search across the entire GGNomad catalogue — properties, tours, events and activities at once — so you can see everything available for a destination in a single view instead of checking each domain separately.'\n )}\n </PagePurpose>\n\n {total === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-search\"\n title={t('ggnomad.search.emptyTitle', 'No matching inventory')}\n description={t(\n 'ggnomad.search.emptyDescription',\n 'Nothing matched across properties, tours, events and activities yet.'\n )}\n />\n ) : (\n <>\n <EmphasisPanel>\n <p className=\"text-sm text-text-secondary\">\n {t('ggnomad.search.totalMatches', 'Total matches across all domains')}\n </p>\n <p className=\"mt-1 text-3xl font-semibold tabular-nums text-text-primary\">\n {total.toLocaleString()}\n </p>\n <p className=\"mt-2 text-sm text-text-secondary\">\n {t(\n 'ggnomad.search.totalMatchesNote',\n 'Combined inventory from properties, tours, events and activities — open a domain below to drill in.'\n )}\n </p>\n </EmphasisPanel>\n\n <section className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-4\">\n <StatCard\n label={t('ggnomad.search.results.propertiesFound', 'Properties found')}\n value={propertyCount}\n icon={<Building />}\n />\n <StatCard\n label={t('ggnomad.search.results.toursFound', 'Tours found')}\n value={tourCount}\n icon={<Compass />}\n />\n <StatCard\n label={t('ggnomad.search.results.eventsFound', 'Events found')}\n value={eventCount}\n icon={<Ticket />}\n />\n <StatCard\n label={t('ggnomad.search.results.activitiesFound', 'Activities found')}\n value={activityCount}\n icon={<Activity />}\n />\n </section>\n </>\n )}\n </PageShell>\n );\n}\n"],"mappings":";;;;;;;;;;AAeA,SAAgB,IAAa;CAC3B,IAAM,EAAE,SAAM,EAAQ,GAChB,IAAa,EACjB,GAIA,EAAE,WAAW;EAAE,OAAO;EAAG,QAAQ;CAAE,EAAE,CACvC,GACM,IAAQ,EACZ,GAIA,EACE,WAAW;EAAE,OAAO;EAAG,QAAQ;CAAE,EACnC,CACF,GACM,IAAS,EACb,GAIA,EACE,WAAW;EAAE,OAAO;EAAG,QAAQ;CAAE,EACnC,CACF,GACM,IAAa,EACjB,GAIA,EAAE,WAAW;EAAE,OAAO;EAAG,QAAQ;CAAE,EAAE,CACvC,GAEM,IAAgB,EAAW,MAAM,mBAAmB,UAAU,GAC9D,IAAY,EAAM,MAAM,cAAc,UAAU,GAChD,IAAa,EAAO,MAAM,eAAe,UAAU,GACnD,IAAgB,EAAW,MAAM,mBAAmB,UAAU,GAC9D,IAAQ,IAAgB,IAAY,IAAa;CAEvD,OACE,kBAAC,GAAD;EACE,OAAO,EAAE,wBAAwB,eAAe;EAChD,aAAa,EAAE,+BAA+B,QAAQ;EACtD,UAAU,EAAE,2BAA2B,kDAAkD;YAH3F,CAKE,kBAAC,GAAD;GAAa,MAAM,kBAAC,GAAD,EAAQ,WAAU,SAAU,CAAA;aAC5C,EACC,0BACA,wNACF;EACW,CAAA,GAEZ,MAAU,IACT,kBAAC,GAAD;GACE,cAAa;GACb,OAAO,EAAE,6BAA6B,uBAAuB;GAC7D,aAAa,EACX,mCACA,sEACF;EACD,CAAA,IAED,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA;GACE,kBAAC,KAAD;IAAG,WAAU;cACV,EAAE,+BAA+B,kCAAkC;GACnE,CAAA;GACH,kBAAC,KAAD;IAAG,WAAU;cACV,EAAM,eAAe;GACrB,CAAA;GACH,kBAAC,KAAD;IAAG,WAAU;cACV,EACC,mCACA,qGACF;GACC,CAAA;EACU,EAAA,CAAA,GAEf,kBAAC,WAAD;GAAS,WAAU;aAAnB;IACE,kBAAC,GAAD;KACE,OAAO,EAAE,0CAA0C,kBAAkB;KACrE,OAAO;KACP,MAAM,kBAAC,GAAD,CAAW,CAAA;IAClB,CAAA;IACD,kBAAC,GAAD;KACE,OAAO,EAAE,qCAAqC,aAAa;KAC3D,OAAO;KACP,MAAM,kBAAC,GAAD,CAAU,CAAA;IACjB,CAAA;IACD,kBAAC,GAAD;KACE,OAAO,EAAE,sCAAsC,cAAc;KAC7D,OAAO;KACP,MAAM,kBAAC,GAAD,CAAS,CAAA;IAChB,CAAA;IACD,kBAAC,GAAD;KACE,OAAO,EAAE,0CAA0C,kBAAkB;KACrE,OAAO;KACP,MAAM,kBAAC,GAAD,CAAW,CAAA;IAClB,CAAA;GACM;IACT,EAAA,CAAA,CAEK;;AAEf"}
|
|
@@ -13,11 +13,11 @@ import { jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
|
13
13
|
//#region src/ggnomad/pages/TourismPage.tsx
|
|
14
14
|
function h() {
|
|
15
15
|
let { t: h } = c(), [g, _] = o(12), [v, y] = o(12), { data: b } = l(t, { variables: {
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
limit: g,
|
|
17
|
+
offset: 0
|
|
18
18
|
} }), { data: x } = l(e, { variables: {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
limit: v,
|
|
20
|
+
offset: 0
|
|
21
21
|
} }), S = b?.ggnomadTours ?? [], C = x?.ggnomadActivities ?? [], w = (e, t, n) => e.length === 0 ? /* @__PURE__ */ p(d, {
|
|
22
22
|
illustration: "empty-data",
|
|
23
23
|
title: n,
|
|
@@ -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 {
|
|
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"}
|
|
@@ -11,8 +11,8 @@ import { jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
|
11
11
|
//#region src/ggnomad/pages/TravelPage.tsx
|
|
12
12
|
function f() {
|
|
13
13
|
let { t: f } = a(), { data: p } = o(e, { variables: {
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
limit: 20,
|
|
15
|
+
offset: 0
|
|
16
16
|
} }), m = p?.ggnomadTrips ?? [];
|
|
17
17
|
return /* @__PURE__ */ d(t, {
|
|
18
18
|
title: f("ggnomad.travel.title", "Travel"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TravelPage.js","names":[],"sources":["../../../src/ggnomad/pages/TravelPage.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 { Plane } from 'lucide-react';\nimport { GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\nimport { GGNOMAD_TRIPS_QUERY } from '../graphql';\nimport { PageShell } from './PageShell';\nimport { EntityCard, StatusBadge } from '../components';\n\nexport function TravelPage() {\n const { t } = useI18n();\n const { data } = useQuery(\n GGNOMAD_TRIPS_QUERY as TypedDocumentNode<\n {\n ggnomadTrips: Array<{\n id: string;\n name: string;\n transportMode: string;\n status: string;\n price: number;\n currency: string;\n }>;\n },\n {
|
|
1
|
+
{"version":3,"file":"TravelPage.js","names":[],"sources":["../../../src/ggnomad/pages/TravelPage.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 { Plane } from 'lucide-react';\nimport { GlassCard, IllustratedEmptyState, PagePurpose } from '@burdenoff/fe-libs/ui';\n\nimport { GGNOMAD_TRIPS_QUERY } from '../graphql';\nimport { PageShell } from './PageShell';\nimport { EntityCard, StatusBadge } from '../components';\n\nexport function TravelPage() {\n const { t } = useI18n();\n const { data } = useQuery(\n GGNOMAD_TRIPS_QUERY as TypedDocumentNode<\n {\n ggnomadTrips: Array<{\n id: string;\n name: string;\n transportMode: string;\n status: string;\n price: number;\n currency: string;\n }>;\n },\n { limit: number; offset: number }\n >,\n {\n variables: { limit: 20, offset: 0 },\n }\n );\n const trips = data?.ggnomadTrips ?? [];\n\n return (\n <PageShell\n title={t('ggnomad.travel.title', 'Travel')}\n titleAccent={t('ggnomad.travel.title.accent', 'Travel')}\n subtitle={t('ggnomad.travel.subtitle', 'Live trip inventory and route management')}\n >\n <PagePurpose icon={<Plane className=\"size-4\" />}>\n {t(\n 'ggnomad.travel.purpose',\n 'Browse the live trip catalogue — flights, rail and road routes published by providers — to compare transport modes, prices and availability before turning a trip into a booking.'\n )}\n </PagePurpose>\n\n {trips.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('ggnomad.travel.emptyTitle', 'No trips in inventory')}\n description={t(\n 'ggnomad.travel.emptyDescription',\n 'Routes and trips added by providers will appear here.'\n )}\n />\n ) : (\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.travel.availableTrips', 'Available trips')}\n </h2>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {trips.map((trip) => (\n <EntityCard\n key={trip.id}\n title={trip.name}\n meta={trip.transportMode}\n price={`${trip.currency} ${Number(trip.price).toFixed(2)}`}\n badge={<StatusBadge status={trip.status} live={trip.status === 'ACTIVE'} />}\n />\n ))}\n </div>\n </GlassCard>\n )}\n </PageShell>\n );\n}\n"],"mappings":";;;;;;;;;;;AAUA,SAAgB,IAAa;CAC3B,IAAM,EAAE,SAAM,EAAQ,GAChB,EAAE,YAAS,EACf,GAaA,EACE,WAAW;EAAE,OAAO;EAAI,QAAQ;CAAE,EACpC,CACF,GACM,IAAQ,GAAM,gBAAgB,CAAC;CAErC,OACE,kBAAC,GAAD;EACE,OAAO,EAAE,wBAAwB,QAAQ;EACzC,aAAa,EAAE,+BAA+B,QAAQ;EACtD,UAAU,EAAE,2BAA2B,0CAA0C;YAHnF,CAKE,kBAAC,GAAD;GAAa,MAAM,kBAAC,GAAD,EAAO,WAAU,SAAU,CAAA;aAC3C,EACC,0BACA,mLACF;EACW,CAAA,GAEZ,EAAM,WAAW,IAChB,kBAAC,GAAD;GACE,cAAa;GACb,OAAO,EAAE,6BAA6B,uBAAuB;GAC7D,aAAa,EACX,mCACA,uDACF;EACD,CAAA,IAED,kBAAC,GAAD;GAAW,WAAU;GAAQ,MAAA;GAAK,WAAU;aAA5C,CACE,kBAAC,MAAD;IAAI,WAAU;cACX,EAAE,iCAAiC,iBAAiB;GACnD,CAAA,GACJ,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAM,KAAK,MACV,kBAAC,GAAD;KAEE,OAAO,EAAK;KACZ,MAAM,EAAK;KACX,OAAO,GAAG,EAAK,SAAS,GAAG,OAAO,EAAK,KAAK,EAAE,QAAQ,CAAC;KACvD,OAAO,kBAAC,GAAD;MAAa,QAAQ,EAAK;MAAQ,MAAM,EAAK,WAAW;KAAW,CAAA;IAC3E,GALM,EAAK,EAKX,CACF;GACE,CAAA,CACI;IAEJ;;AAEf"}
|
|
@@ -16,17 +16,17 @@ function j() {
|
|
|
16
16
|
variables: { id: P },
|
|
17
17
|
skip: !P
|
|
18
18
|
}), G = U?.ggnomadTripPlan, { data: le } = h(n, { variables: {
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
limit: 20,
|
|
20
|
+
offset: 0
|
|
21
21
|
} }), { data: ue } = h(r, { variables: {
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
limit: 20,
|
|
23
|
+
offset: 0
|
|
24
24
|
} }), { data: de } = h(te, { variables: {
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
limit: 20,
|
|
26
|
+
offset: 0
|
|
27
27
|
} }), { data: fe } = h(ee, { variables: {
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
limit: 20,
|
|
29
|
+
offset: 0
|
|
30
30
|
} }), [pe, { loading: K }] = m(e), [me, { loading: q }] = m(a), [J] = m(o), [he] = m(t), ge = async () => {
|
|
31
31
|
if (!(!F || !G)) try {
|
|
32
32
|
let e = await pe({ variables: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TripPlanDetailPage.js","names":[],"sources":["../../../src/ggnomad/pages/TripPlanDetailPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { ChevronDown, Plus, Users, X } from 'lucide-react';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n GlassCard,\n IllustratedEmptyState,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@burdenoff/fe-libs/ui';\n\nimport {\n ADD_GGNOMAD_TRIP_PLAN_ITEM_MUTATION,\n CREATE_GGNOMAD_BOOKING_MUTATION,\n GGNOMAD_ACTIVITIES_QUERY,\n GGNOMAD_EVENTS_QUERY,\n GGNOMAD_PROPERTIES_QUERY,\n GGNOMAD_TOURS_QUERY,\n GGNOMAD_TRIP_PLAN_QUERY,\n REMOVE_GGNOMAD_TRIP_PLAN_ITEM_MUTATION,\n UPDATE_GGNOMAD_TRIP_PLAN_MUTATION,\n} from '../graphql';\nimport { PageShell } from './PageShell';\nimport { notify } from '../utils/notify';\nimport { useGGNomad } from '../providers/GGNomadProvider';\nimport { joinPath } from '../utils/navigation';\n\ntype ItemType = 'PROPERTY' | 'TOUR' | 'EVENT' | 'ACTIVITY';\n\ninterface TripPlanItem {\n id: string;\n itemType: ItemType;\n itemId: string;\n itemName: string;\n day?: number;\n scheduledAt?: string;\n price: number;\n currency: string;\n notes?: string;\n}\n\ninterface AddingItem {\n itemType: ItemType;\n itemId: string;\n itemName: string;\n price: number;\n currency: string;\n}\n\nexport function TripPlanDetailPage() {\n const { t } = useI18n();\n const navigate = useNavigate();\n const { basePath = '/' } = useGGNomad();\n const { id = '' } = useParams();\n const [addingItem, setAddingItem] = useState<AddingItem | null>(null);\n const [showCheckout, setShowCheckout] = useState(false);\n const [removingItemId, setRemovingItemId] = useState<string | null>(null);\n const [activeTab, setActiveTab] = useState('itinerary');\n\n const { data, refetch } = useQuery(\n GGNOMAD_TRIP_PLAN_QUERY as TypedDocumentNode<\n {\n ggnomadTripPlan: {\n id: string;\n name: string;\n description?: string;\n startDate?: string;\n endDate?: string;\n travelers: number;\n status: string;\n total: number;\n itemCount: number;\n items: TripPlanItem[];\n createdAt: string;\n updatedAt: string;\n } | null;\n },\n { id: string }\n >,\n { variables: { id }, skip: !id }\n );\n\n const tripPlan = data?.ggnomadTripPlan;\n\n const { data: propertiesData } = useQuery(\n GGNOMAD_PROPERTIES_QUERY as TypedDocumentNode<\n {\n ggnomadProperties: Array<{\n id: string;\n name: string;\n pricePerNight: number;\n currency: string;\n }>;\n },\n { first: number; skip: number }\n >,\n { variables: { first: 20, skip: 0 } }\n );\n\n const { data: toursData } = useQuery(\n GGNOMAD_TOURS_QUERY as TypedDocumentNode<\n {\n ggnomadTours: Array<{\n id: string;\n name: string;\n price: number;\n currency: string;\n }>;\n },\n { first: number; skip: number }\n >,\n { variables: { first: 20, skip: 0 } }\n );\n\n const { data: eventsData } = useQuery(\n GGNOMAD_EVENTS_QUERY as TypedDocumentNode<\n {\n ggnomadEvents: Array<{\n id: string;\n name: string;\n price: number;\n currency: string;\n }>;\n },\n { first: number; skip: number }\n >,\n { variables: { first: 20, skip: 0 } }\n );\n\n const { data: activitiesData } = useQuery(\n GGNOMAD_ACTIVITIES_QUERY as TypedDocumentNode<\n {\n ggnomadActivities: Array<{\n id: string;\n name: string;\n price: number;\n currency: string;\n }>;\n },\n { first: number; skip: number }\n >,\n { variables: { first: 20, skip: 0 } }\n );\n\n const [addItem, { loading: addingItemMutation }] = useMutation(\n ADD_GGNOMAD_TRIP_PLAN_ITEM_MUTATION as TypedDocumentNode<\n {\n addGgnomadTripPlanItem: TripPlanItem;\n },\n {\n tripPlanId: string;\n input: {\n itemType: ItemType;\n itemId: string;\n itemName: string;\n price: number;\n currency: string;\n };\n }\n >\n );\n\n const [removeItem, { loading: removingItemMutation }] = useMutation(\n REMOVE_GGNOMAD_TRIP_PLAN_ITEM_MUTATION as TypedDocumentNode<\n { removeGgnomadTripPlanItem: boolean },\n { id: string }\n >\n );\n\n const [updateStatus] = useMutation(\n UPDATE_GGNOMAD_TRIP_PLAN_MUTATION as TypedDocumentNode<\n {\n updateGgnomadTripPlan: {\n id: string;\n status: string;\n };\n },\n {\n id: string;\n input: {\n status: string;\n };\n }\n >\n );\n\n const [createBooking] = useMutation(\n CREATE_GGNOMAD_BOOKING_MUTATION as TypedDocumentNode<\n {\n createGgnomadBooking: {\n id: string;\n referenceCode: string;\n itemName: string;\n };\n },\n {\n input: {\n bookingType: ItemType;\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 };\n }\n >\n );\n\n const handleAddItem = async () => {\n if (!addingItem || !tripPlan) return;\n\n try {\n const result = await addItem({\n variables: {\n tripPlanId: tripPlan.id,\n input: {\n itemType: addingItem.itemType,\n itemId: addingItem.itemId,\n itemName: addingItem.itemName,\n price: addingItem.price,\n currency: addingItem.currency,\n },\n },\n });\n\n if (result.error) {\n notify.error(\n t('ggnomad.tripPlan.toast.addItemErrorTitle', 'Could not add item'),\n result.error.message\n );\n return;\n }\n\n notify.success(\n t('ggnomad.tripPlan.toast.addItemSuccessTitle', 'Item added'),\n addingItem.itemName\n );\n\n setAddingItem(null);\n await refetch();\n } catch (err) {\n notify.error(\n t('ggnomad.tripPlan.toast.addItemErrorTitle', 'Could not add item'),\n err instanceof Error ? err.message : String(err)\n );\n }\n };\n\n const handleRemoveItem = async () => {\n if (!removingItemId) return;\n\n try {\n const result = await removeItem({\n variables: { id: removingItemId },\n });\n\n if (result.error) {\n notify.error(\n t('ggnomad.tripPlan.toast.removeItemErrorTitle', 'Could not remove item'),\n result.error.message\n );\n return;\n }\n\n notify.success(t('ggnomad.tripPlan.toast.removeItemSuccessTitle', 'Item removed'), '');\n\n setRemovingItemId(null);\n await refetch();\n } catch (err) {\n notify.error(\n t('ggnomad.tripPlan.toast.removeItemErrorTitle', 'Could not remove item'),\n err instanceof Error ? err.message : String(err)\n );\n }\n };\n\n const handleCheckout = async () => {\n if (!tripPlan) return;\n\n try {\n for (const item of tripPlan.items) {\n await createBooking({\n variables: {\n input: {\n bookingType: item.itemType,\n itemId: item.itemId,\n itemName: item.itemName,\n guestName: 'Guest',\n guestEmail: 'guest@burdenoff.com',\n guests: tripPlan.travelers,\n totalPrice: item.price,\n currency: item.currency,\n paymentMethod: 'card',\n },\n },\n });\n }\n\n await updateStatus({\n variables: {\n id: tripPlan.id,\n input: { status: 'BOOKED' },\n },\n });\n\n notify.success(\n t('ggnomad.tripPlan.toast.checkoutSuccessTitle', 'Trip booked!'),\n t('ggnomad.tripPlan.toast.checkoutSuccessBody', 'All items have been booked')\n );\n\n await refetch();\n setShowCheckout(false);\n navigate(joinPath(basePath, 'bookings'));\n } catch (err) {\n notify.error(\n t('ggnomad.tripPlan.toast.checkoutErrorTitle', 'Booking failed'),\n err instanceof Error ? err.message : String(err)\n );\n }\n };\n\n if (!tripPlan) {\n return (\n <PageShell\n title={t('ggnomad.tripPlan.loadingTitle', 'Trip Plan')}\n subtitle={t('ggnomad.tripPlan.loadingSubtitle', 'Loading trip plan')}\n >\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('ggnomad.tripPlan.notFoundTitle', 'Trip plan not found')}\n description={t(\n 'ggnomad.tripPlan.notFoundDescription',\n 'This trip may have been deleted or is unavailable.'\n )}\n />\n </PageShell>\n );\n }\n\n const itemsByDay: Record<number, TripPlanItem[]> = {};\n tripPlan.items.forEach((item) => {\n const day = item.day ?? 0;\n if (!itemsByDay[day]) {\n itemsByDay[day] = [];\n }\n itemsByDay[day].push(item);\n });\n\n const sortedDays: number[] = Object.keys(itemsByDay)\n .map((d) => Number(d))\n .sort((a: number, b: number) => a - b);\n\n const properties = propertiesData?.ggnomadProperties ?? [];\n const tours = toursData?.ggnomadTours ?? [];\n const events = eventsData?.ggnomadEvents ?? [];\n const activities = activitiesData?.ggnomadActivities ?? [];\n\n return (\n <PageShell\n title={tripPlan.name}\n subtitle={t('ggnomad.tripPlan.subtitle', 'Build your complete itinerary')}\n >\n <Tabs value={activeTab} onValueChange={setActiveTab} className=\"w-full\">\n <TabsList className=\"mb-6 w-full justify-start\">\n <TabsTrigger value=\"itinerary\">\n {t('ggnomad.tripPlan.tabs.itinerary', 'Itinerary')}\n </TabsTrigger>\n <TabsTrigger value=\"timeline\">\n {t('ggnomad.tripPlan.tabs.timeline', 'Timeline')}\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"itinerary\" className=\"space-y-6\">\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-4\">\n {/* Left Rail - Add Items */}\n <div className=\"space-y-4\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam p-4\">\n <h3 className=\"mb-3 flex items-center gap-2 font-medium text-text-primary\">\n <Plus className=\"size-4\" />\n {t('ggnomad.tripPlan.addToTrip', 'Add to trip')}\n </h3>\n\n <div className=\"space-y-3\">\n {/* Stays */}\n <details className=\"group\">\n <summary className=\"flex cursor-pointer items-center justify-between rounded-md bg-bg-canvas-inverted p-2 text-sm font-medium text-text-primary hover:bg-opacity-80\">\n {t('ggnomad.tripPlan.stays', 'Stays')}\n <ChevronDown className=\"size-4 transition-transform group-open:rotate-180\" />\n </summary>\n <div className=\"mt-2 space-y-2\">\n {properties.length === 0 ? (\n <p className=\"text-xs text-text-secondary\">\n {t('ggnomad.tripPlan.noStaysAvailable', 'No stays available')}\n </p>\n ) : (\n properties.map((property) => (\n <button\n key={property.id}\n onClick={() =>\n setAddingItem({\n itemType: 'PROPERTY',\n itemId: property.id,\n itemName: property.name,\n price: property.pricePerNight,\n currency: property.currency,\n })\n }\n className=\"w-full rounded-md border border-border-seam bg-bg-canvas p-2 text-left text-xs text-text-primary hover:bg-action-primary-bg hover:text-action-primary-text\"\n >\n <div className=\"font-medium\">{property.name}</div>\n <div className=\"text-text-secondary\">\n {property.currency} {property.pricePerNight.toFixed(2)}\n </div>\n </button>\n ))\n )}\n </div>\n </details>\n\n {/* Tours */}\n <details className=\"group\">\n <summary className=\"flex cursor-pointer items-center justify-between rounded-md bg-bg-canvas-inverted p-2 text-sm font-medium text-text-primary hover:bg-opacity-80\">\n {t('ggnomad.tripPlan.tours', 'Tours')}\n <ChevronDown className=\"size-4 transition-transform group-open:rotate-180\" />\n </summary>\n <div className=\"mt-2 space-y-2\">\n {tours.length === 0 ? (\n <p className=\"text-xs text-text-secondary\">\n {t('ggnomad.tripPlan.noToursAvailable', 'No tours available')}\n </p>\n ) : (\n tours.map((tour) => (\n <button\n key={tour.id}\n onClick={() =>\n setAddingItem({\n itemType: 'TOUR',\n itemId: tour.id,\n itemName: tour.name,\n price: tour.price,\n currency: tour.currency,\n })\n }\n className=\"w-full rounded-md border border-border-seam bg-bg-canvas p-2 text-left text-xs text-text-primary hover:bg-action-primary-bg hover:text-action-primary-text\"\n >\n <div className=\"font-medium\">{tour.name}</div>\n <div className=\"text-text-secondary\">\n {tour.currency} {tour.price.toFixed(2)}\n </div>\n </button>\n ))\n )}\n </div>\n </details>\n\n {/* Events */}\n <details className=\"group\">\n <summary className=\"flex cursor-pointer items-center justify-between rounded-md bg-bg-canvas-inverted p-2 text-sm font-medium text-text-primary hover:bg-opacity-80\">\n {t('ggnomad.tripPlan.events', 'Events')}\n <ChevronDown className=\"size-4 transition-transform group-open:rotate-180\" />\n </summary>\n <div className=\"mt-2 space-y-2\">\n {events.length === 0 ? (\n <p className=\"text-xs text-text-secondary\">\n {t('ggnomad.tripPlan.noEventsAvailable', 'No events available')}\n </p>\n ) : (\n events.map((event) => (\n <button\n key={event.id}\n onClick={() =>\n setAddingItem({\n itemType: 'EVENT',\n itemId: event.id,\n itemName: event.name,\n price: event.price,\n currency: event.currency,\n })\n }\n className=\"w-full rounded-md border border-border-seam bg-bg-canvas p-2 text-left text-xs text-text-primary hover:bg-action-primary-bg hover:text-action-primary-text\"\n >\n <div className=\"font-medium\">{event.name}</div>\n <div className=\"text-text-secondary\">\n {event.currency} {event.price.toFixed(2)}\n </div>\n </button>\n ))\n )}\n </div>\n </details>\n\n {/* Activities */}\n <details className=\"group\">\n <summary className=\"flex cursor-pointer items-center justify-between rounded-md bg-bg-canvas-inverted p-2 text-sm font-medium text-text-primary hover:bg-opacity-80\">\n {t('ggnomad.tripPlan.activities', 'Activities')}\n <ChevronDown className=\"size-4 transition-transform group-open:rotate-180\" />\n </summary>\n <div className=\"mt-2 space-y-2\">\n {activities.length === 0 ? (\n <p className=\"text-xs text-text-secondary\">\n {t('ggnomad.tripPlan.noActivitiesAvailable', 'No activities available')}\n </p>\n ) : (\n activities.map((activity) => (\n <button\n key={activity.id}\n onClick={() =>\n setAddingItem({\n itemType: 'ACTIVITY',\n itemId: activity.id,\n itemName: activity.name,\n price: activity.price,\n currency: activity.currency,\n })\n }\n className=\"w-full rounded-md border border-border-seam bg-bg-canvas p-2 text-left text-xs text-text-primary hover:bg-action-primary-bg hover:text-action-primary-text\"\n >\n <div className=\"font-medium\">{activity.name}</div>\n <div className=\"text-text-secondary\">\n {activity.currency} {activity.price.toFixed(2)}\n </div>\n </button>\n ))\n )}\n </div>\n </details>\n </div>\n </GlassCard>\n </div>\n\n {/* Center - Itinerary Items */}\n <div className=\"space-y-4 lg:col-span-2\">\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.tripPlan.itineraryHeader', 'Your itinerary')}\n </h2>\n\n {tripPlan.items.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'ggnomad.tripPlan.noItemsYet',\n 'No items added yet. Start adding stays, tours, events and activities from the left.'\n )}\n </p>\n ) : (\n <div className=\"space-y-6\">\n {sortedDays.map((day: number) => (\n <div key={String(day)}>\n <h3 className=\"mb-2 text-sm font-medium text-text-secondary\">\n {day === 0\n ? t('ggnomad.tripPlan.unscheduled', 'Unscheduled')\n : t('ggnomad.tripPlan.day', 'Day {{day}}').replace(\n '{{day}}',\n String(day)\n )}\n </h3>\n <div className=\"space-y-2\">\n {(itemsByDay[day] || []).map((item: TripPlanItem) => (\n <div\n key={item.id}\n className=\"flex items-start justify-between rounded-md border border-border-seam bg-bg-canvas p-3\"\n >\n <div className=\"flex-1\">\n <p className=\"font-medium text-text-primary\">{item.itemName}</p>\n <p className=\"text-xs text-text-secondary\">\n {item.itemType.charAt(0) + item.itemType.slice(1).toLowerCase()}\n </p>\n <p className=\"mt-1 font-semibold text-status-success-text\">\n {item.currency} {item.price.toFixed(2)}\n </p>\n </div>\n <button\n onClick={() => setRemovingItemId(item.id)}\n className=\"ml-2 rounded-md p-1 text-text-secondary hover:bg-action-danger-bg hover:text-action-danger-text\"\n aria-label={t('ggnomad.tripPlan.removeItem', 'Remove item')}\n >\n <X className=\"size-4\" />\n </button>\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n )}\n </GlassCard>\n </div>\n\n {/* Right - Trip Summary */}\n <div className=\"space-y-4\">\n <GlassCard treatment=\"glass\" glow className=\"sticky top-6 border-border-seam p-5\">\n <h3 className=\"mb-4 font-medium text-text-primary\">\n {t('ggnomad.tripPlan.tripTotal', 'Trip total')}\n </h3>\n\n <div className=\"space-y-3 border-b border-border-seam pb-4\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-text-secondary\">\n {t('ggnomad.tripPlan.items', 'Items')}\n </span>\n <span className=\"font-medium text-text-primary\">{tripPlan.itemCount}</span>\n </div>\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-text-secondary\">\n {t('ggnomad.tripPlan.travelers', 'Travelers')}\n </span>\n <span className=\"font-medium text-text-primary flex items-center gap-1\">\n <Users className=\"size-3\" />\n {tripPlan.travelers}\n </span>\n </div>\n </div>\n\n <div className=\"my-4\">\n <div className=\"text-2xl font-bold text-text-primary\">\n USD {tripPlan.total.toFixed(2)}\n </div>\n {tripPlan.travelers > 0 && (\n <div className=\"mt-3 rounded-md border border-border-seam bg-bg-canvas/50 p-3\">\n <p className=\"text-xs font-medium text-text-secondary\">\n {t('ggnomad.tripPlan.costSplit', 'Split {{count}} ways').replace(\n '{{count}}',\n String(tripPlan.travelers)\n )}\n </p>\n <p className=\"mt-1 text-lg font-semibold text-action-primary-text\">\n USD {(tripPlan.total / tripPlan.travelers).toFixed(2)} each\n </p>\n <p className=\"mt-2 text-xs text-text-secondary\">\n {t(\n 'ggnomad.tripPlan.costSplitNote',\n 'This trip plan is shared with everyone in your workspace.'\n )}\n </p>\n </div>\n )}\n </div>\n\n <div className=\"space-y-2\">\n <button\n onClick={() => setShowCheckout(true)}\n disabled={tripPlan.items.length === 0}\n className=\"w-full rounded-md bg-action-primary-bg px-4 py-2 font-medium text-action-primary-text hover:bg-action-primary-bgHover disabled:opacity-50\"\n >\n {t('ggnomad.tripPlan.checkout', 'Checkout')}\n </button>\n\n <div className=\"flex items-center gap-2\">\n <select\n value={tripPlan.status}\n onChange={async (e) => {\n await updateStatus({\n variables: {\n id: tripPlan.id,\n input: { status: e.target.value },\n },\n });\n await refetch();\n }}\n className=\"flex-1 rounded-md border border-border-seam bg-bg-canvas px-2 py-1 text-sm text-text-primary\"\n >\n <option value=\"DRAFT\">Draft</option>\n <option value=\"PLANNED\">Planned</option>\n <option value=\"BOOKED\">Booked</option>\n <option value=\"CONFIRMED\">Confirmed</option>\n <option value=\"COMPLETED\">Completed</option>\n <option value=\"CANCELLED\">Cancelled</option>\n </select>\n </div>\n </div>\n </GlassCard>\n </div>\n </div>\n </TabsContent>\n\n <TabsContent value=\"timeline\" className=\"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.tripPlan.timeline', 'Trip timeline')}\n </h2>\n\n <div className=\"space-y-6\">\n {/* Plan Status Milestone */}\n <div className=\"flex gap-4\">\n <div className=\"flex flex-col items-center\">\n <div className=\"size-3 rounded-full bg-status-info-bg\" />\n <div className=\"my-2 h-8 w-0.5 bg-border-seam\" />\n </div>\n <div>\n <h3 className=\"font-medium text-text-primary\">\n {t('ggnomad.tripPlan.milestone.started', 'Trip started')}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {t('ggnomad.tripPlan.milestone.startedDesc', 'Created your itinerary')}\n </p>\n </div>\n </div>\n\n {/* Items Timeline */}\n {tripPlan.items.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {t('ggnomad.tripPlan.noItemsInTimeline', 'No items in your timeline yet')}\n </p>\n ) : (\n tripPlan.items.map((item, index) => (\n <div key={item.id} className=\"flex gap-4\">\n <div className=\"flex flex-col items-center\">\n <div\n className={`size-3 rounded-full ${\n tripPlan.status === 'BOOKED' || tripPlan.status === 'COMPLETED'\n ? 'bg-status-success-bg'\n : 'bg-status-warning-bg'\n }`}\n />\n {index < tripPlan.items.length - 1 && (\n <div className=\"my-2 h-8 w-0.5 bg-border-seam\" />\n )}\n </div>\n <div>\n <h3 className=\"font-medium text-text-primary\">{item.itemName}</h3>\n <p className=\"text-xs text-text-secondary\">\n {item.itemType.charAt(0) + item.itemType.slice(1).toLowerCase()}\n {item.day && ` · Day ${item.day}`}\n </p>\n <p className=\"mt-1 text-sm font-semibold text-status-success-text\">\n {item.currency} {item.price.toFixed(2)}\n </p>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {tripPlan.status === 'BOOKED' || tripPlan.status === 'COMPLETED'\n ? t('ggnomad.tripPlan.milestone.booked', 'Booked')\n : t('ggnomad.tripPlan.milestone.planned', 'Planned')}\n </p>\n </div>\n </div>\n ))\n )}\n\n {/* Final Status */}\n {tripPlan.items.length > 0 && (\n <>\n <div className=\"flex gap-4\">\n <div className=\"flex flex-col items-center\">\n <div\n className={`size-3 rounded-full ${\n tripPlan.status === 'COMPLETED'\n ? 'bg-status-success-bg'\n : 'bg-status-secondary-bg'\n }`}\n />\n </div>\n <div>\n <h3 className=\"font-medium text-text-primary\">\n {tripPlan.status === 'COMPLETED'\n ? t('ggnomad.tripPlan.milestone.completed', 'Trip completed')\n : t('ggnomad.tripPlan.milestone.confirming', 'Awaiting completion')}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {tripPlan.status === 'COMPLETED'\n ? t('ggnomad.tripPlan.milestone.completedDesc', 'Your trip is complete')\n : t(\n 'ggnomad.tripPlan.milestone.confirmingDesc',\n 'Update status as your trip progresses'\n )}\n </p>\n </div>\n </div>\n </>\n )}\n </div>\n </GlassCard>\n </TabsContent>\n </Tabs>\n\n {/* Add Item Dialog */}\n <AlertDialog open={addingItem !== null} onOpenChange={(open) => !open && setAddingItem(null)}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n {t('ggnomad.tripPlan.addItemDialog.title', 'Add to itinerary?')}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {addingItem && (\n <>\n {addingItem.itemName}\n {' · '}\n {addingItem.currency} {addingItem.price.toFixed(2)}\n </>\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={addingItemMutation}>\n {t('ggnomad.tripPlan.addItemDialog.cancel', 'Cancel')}\n </AlertDialogCancel>\n <AlertDialogAction\n disabled={addingItemMutation}\n onClick={(event) => {\n event.preventDefault();\n void handleAddItem();\n }}\n >\n {addingItemMutation\n ? t('ggnomad.tripPlan.addItemDialog.adding', 'Adding…')\n : t('ggnomad.tripPlan.addItemDialog.add', 'Add item')}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n\n {/* Remove Item Dialog */}\n <AlertDialog\n open={removingItemId !== null}\n onOpenChange={(open) => !open && setRemovingItemId(null)}\n >\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n {t('ggnomad.tripPlan.removeItemDialog.title', 'Remove item from trip?')}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {t(\n 'ggnomad.tripPlan.removeItemDialog.description',\n 'This item will be removed from your itinerary.'\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={removingItemMutation}>\n {t('ggnomad.tripPlan.removeItemDialog.cancel', 'Keep item')}\n </AlertDialogCancel>\n <AlertDialogAction\n className=\"bg-action-danger-bg text-action-danger-text hover:bg-action-danger-bgHover\"\n disabled={removingItemMutation}\n onClick={(event) => {\n event.preventDefault();\n void handleRemoveItem();\n }}\n >\n {removingItemMutation\n ? t('ggnomad.tripPlan.removeItemDialog.removing', 'Removing…')\n : t('ggnomad.tripPlan.removeItemDialog.remove', 'Remove item')}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n\n {/* Checkout Dialog */}\n <AlertDialog open={showCheckout} onOpenChange={setShowCheckout}>\n <AlertDialogContent className=\"max-w-2xl\">\n <AlertDialogHeader>\n <AlertDialogTitle>\n {t('ggnomad.tripPlan.checkoutDialog.title', 'Review and book')}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {t(\n 'ggnomad.tripPlan.checkoutDialog.description',\n 'Review your items and confirm to book everything at once.'\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n\n <div className=\"space-y-4 max-h-96 overflow-y-auto\">\n {tripPlan.items.map((item) => (\n <div\n key={item.id}\n className=\"flex items-center justify-between rounded-md border border-border-seam bg-bg-canvas p-3\"\n >\n <div>\n <p className=\"font-medium text-text-primary\">{item.itemName}</p>\n <p className=\"text-xs text-text-secondary\">\n {item.itemType.charAt(0) + item.itemType.slice(1).toLowerCase()}\n </p>\n </div>\n <p className=\"font-semibold text-text-primary\">\n {item.currency} {item.price.toFixed(2)}\n </p>\n </div>\n ))}\n\n <div className=\"space-y-2 border-t border-border-seam pt-4\">\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Subtotal</span>\n <span className=\"text-text-primary\">USD {tripPlan.total.toFixed(2)}</span>\n </div>\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Taxes (10%)</span>\n <span className=\"text-text-primary\">USD {(tripPlan.total * 0.1).toFixed(2)}</span>\n </div>\n <div className=\"flex justify-between border-t border-border-seam pt-2 text-lg font-bold\">\n <span className=\"text-text-primary\">Total</span>\n <span className=\"text-status-success-text\">\n USD {(tripPlan.total * 1.1).toFixed(2)}\n </span>\n </div>\n </div>\n </div>\n\n <AlertDialogFooter>\n <AlertDialogCancel disabled={false}>\n {t('ggnomad.tripPlan.checkoutDialog.cancel', 'Cancel')}\n </AlertDialogCancel>\n <AlertDialogAction\n onClick={(event) => {\n event.preventDefault();\n void handleCheckout();\n }}\n >\n {t('ggnomad.tripPlan.checkoutDialog.confirm', 'Confirm & book all')}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </PageShell>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TripPlanDetailPage.js","names":[],"sources":["../../../src/ggnomad/pages/TripPlanDetailPage.tsx"],"sourcesContent":["import { useState } from 'react';\nimport { useMutation, useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { ChevronDown, Plus, Users, X } from 'lucide-react';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n GlassCard,\n IllustratedEmptyState,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@burdenoff/fe-libs/ui';\n\nimport {\n ADD_GGNOMAD_TRIP_PLAN_ITEM_MUTATION,\n CREATE_GGNOMAD_BOOKING_MUTATION,\n GGNOMAD_ACTIVITIES_QUERY,\n GGNOMAD_EVENTS_QUERY,\n GGNOMAD_PROPERTIES_QUERY,\n GGNOMAD_TOURS_QUERY,\n GGNOMAD_TRIP_PLAN_QUERY,\n REMOVE_GGNOMAD_TRIP_PLAN_ITEM_MUTATION,\n UPDATE_GGNOMAD_TRIP_PLAN_MUTATION,\n} from '../graphql';\nimport { PageShell } from './PageShell';\nimport { notify } from '../utils/notify';\nimport { useGGNomad } from '../providers/GGNomadProvider';\nimport { joinPath } from '../utils/navigation';\n\ntype ItemType = 'PROPERTY' | 'TOUR' | 'EVENT' | 'ACTIVITY';\n\ninterface TripPlanItem {\n id: string;\n itemType: ItemType;\n itemId: string;\n itemName: string;\n day?: number;\n scheduledAt?: string;\n price: number;\n currency: string;\n notes?: string;\n}\n\ninterface AddingItem {\n itemType: ItemType;\n itemId: string;\n itemName: string;\n price: number;\n currency: string;\n}\n\nexport function TripPlanDetailPage() {\n const { t } = useI18n();\n const navigate = useNavigate();\n const { basePath = '/' } = useGGNomad();\n const { id = '' } = useParams();\n const [addingItem, setAddingItem] = useState<AddingItem | null>(null);\n const [showCheckout, setShowCheckout] = useState(false);\n const [removingItemId, setRemovingItemId] = useState<string | null>(null);\n const [activeTab, setActiveTab] = useState('itinerary');\n\n const { data, refetch } = useQuery(\n GGNOMAD_TRIP_PLAN_QUERY as TypedDocumentNode<\n {\n ggnomadTripPlan: {\n id: string;\n name: string;\n description?: string;\n startDate?: string;\n endDate?: string;\n travelers: number;\n status: string;\n total: number;\n itemCount: number;\n items: TripPlanItem[];\n createdAt: string;\n updatedAt: string;\n } | null;\n },\n { id: string }\n >,\n { variables: { id }, skip: !id }\n );\n\n const tripPlan = data?.ggnomadTripPlan;\n\n const { data: propertiesData } = useQuery(\n GGNOMAD_PROPERTIES_QUERY as TypedDocumentNode<\n {\n ggnomadProperties: Array<{\n id: string;\n name: string;\n pricePerNight: number;\n currency: string;\n }>;\n },\n { limit: number; offset: number }\n >,\n { variables: { limit: 20, offset: 0 } }\n );\n\n const { data: toursData } = useQuery(\n GGNOMAD_TOURS_QUERY as TypedDocumentNode<\n {\n ggnomadTours: Array<{\n id: string;\n name: string;\n price: number;\n currency: string;\n }>;\n },\n { limit: number; offset: number }\n >,\n { variables: { limit: 20, offset: 0 } }\n );\n\n const { data: eventsData } = useQuery(\n GGNOMAD_EVENTS_QUERY as TypedDocumentNode<\n {\n ggnomadEvents: Array<{\n id: string;\n name: string;\n price: number;\n currency: string;\n }>;\n },\n { limit: number; offset: number }\n >,\n { variables: { limit: 20, offset: 0 } }\n );\n\n const { data: activitiesData } = useQuery(\n GGNOMAD_ACTIVITIES_QUERY as TypedDocumentNode<\n {\n ggnomadActivities: Array<{\n id: string;\n name: string;\n price: number;\n currency: string;\n }>;\n },\n { limit: number; offset: number }\n >,\n { variables: { limit: 20, offset: 0 } }\n );\n\n const [addItem, { loading: addingItemMutation }] = useMutation(\n ADD_GGNOMAD_TRIP_PLAN_ITEM_MUTATION as TypedDocumentNode<\n {\n addGgnomadTripPlanItem: TripPlanItem;\n },\n {\n tripPlanId: string;\n input: {\n itemType: ItemType;\n itemId: string;\n itemName: string;\n price: number;\n currency: string;\n };\n }\n >\n );\n\n const [removeItem, { loading: removingItemMutation }] = useMutation(\n REMOVE_GGNOMAD_TRIP_PLAN_ITEM_MUTATION as TypedDocumentNode<\n { removeGgnomadTripPlanItem: boolean },\n { id: string }\n >\n );\n\n const [updateStatus] = useMutation(\n UPDATE_GGNOMAD_TRIP_PLAN_MUTATION as TypedDocumentNode<\n {\n updateGgnomadTripPlan: {\n id: string;\n status: string;\n };\n },\n {\n id: string;\n input: {\n status: string;\n };\n }\n >\n );\n\n const [createBooking] = useMutation(\n CREATE_GGNOMAD_BOOKING_MUTATION as TypedDocumentNode<\n {\n createGgnomadBooking: {\n id: string;\n referenceCode: string;\n itemName: string;\n };\n },\n {\n input: {\n bookingType: ItemType;\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 };\n }\n >\n );\n\n const handleAddItem = async () => {\n if (!addingItem || !tripPlan) return;\n\n try {\n const result = await addItem({\n variables: {\n tripPlanId: tripPlan.id,\n input: {\n itemType: addingItem.itemType,\n itemId: addingItem.itemId,\n itemName: addingItem.itemName,\n price: addingItem.price,\n currency: addingItem.currency,\n },\n },\n });\n\n if (result.error) {\n notify.error(\n t('ggnomad.tripPlan.toast.addItemErrorTitle', 'Could not add item'),\n result.error.message\n );\n return;\n }\n\n notify.success(\n t('ggnomad.tripPlan.toast.addItemSuccessTitle', 'Item added'),\n addingItem.itemName\n );\n\n setAddingItem(null);\n await refetch();\n } catch (err) {\n notify.error(\n t('ggnomad.tripPlan.toast.addItemErrorTitle', 'Could not add item'),\n err instanceof Error ? err.message : String(err)\n );\n }\n };\n\n const handleRemoveItem = async () => {\n if (!removingItemId) return;\n\n try {\n const result = await removeItem({\n variables: { id: removingItemId },\n });\n\n if (result.error) {\n notify.error(\n t('ggnomad.tripPlan.toast.removeItemErrorTitle', 'Could not remove item'),\n result.error.message\n );\n return;\n }\n\n notify.success(t('ggnomad.tripPlan.toast.removeItemSuccessTitle', 'Item removed'), '');\n\n setRemovingItemId(null);\n await refetch();\n } catch (err) {\n notify.error(\n t('ggnomad.tripPlan.toast.removeItemErrorTitle', 'Could not remove item'),\n err instanceof Error ? err.message : String(err)\n );\n }\n };\n\n const handleCheckout = async () => {\n if (!tripPlan) return;\n\n try {\n for (const item of tripPlan.items) {\n await createBooking({\n variables: {\n input: {\n bookingType: item.itemType,\n itemId: item.itemId,\n itemName: item.itemName,\n guestName: 'Guest',\n guestEmail: 'guest@burdenoff.com',\n guests: tripPlan.travelers,\n totalPrice: item.price,\n currency: item.currency,\n paymentMethod: 'card',\n },\n },\n });\n }\n\n await updateStatus({\n variables: {\n id: tripPlan.id,\n input: { status: 'BOOKED' },\n },\n });\n\n notify.success(\n t('ggnomad.tripPlan.toast.checkoutSuccessTitle', 'Trip booked!'),\n t('ggnomad.tripPlan.toast.checkoutSuccessBody', 'All items have been booked')\n );\n\n await refetch();\n setShowCheckout(false);\n navigate(joinPath(basePath, 'bookings'));\n } catch (err) {\n notify.error(\n t('ggnomad.tripPlan.toast.checkoutErrorTitle', 'Booking failed'),\n err instanceof Error ? err.message : String(err)\n );\n }\n };\n\n if (!tripPlan) {\n return (\n <PageShell\n title={t('ggnomad.tripPlan.loadingTitle', 'Trip Plan')}\n subtitle={t('ggnomad.tripPlan.loadingSubtitle', 'Loading trip plan')}\n >\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('ggnomad.tripPlan.notFoundTitle', 'Trip plan not found')}\n description={t(\n 'ggnomad.tripPlan.notFoundDescription',\n 'This trip may have been deleted or is unavailable.'\n )}\n />\n </PageShell>\n );\n }\n\n const itemsByDay: Record<number, TripPlanItem[]> = {};\n tripPlan.items.forEach((item) => {\n const day = item.day ?? 0;\n if (!itemsByDay[day]) {\n itemsByDay[day] = [];\n }\n itemsByDay[day].push(item);\n });\n\n const sortedDays: number[] = Object.keys(itemsByDay)\n .map((d) => Number(d))\n .sort((a: number, b: number) => a - b);\n\n const properties = propertiesData?.ggnomadProperties ?? [];\n const tours = toursData?.ggnomadTours ?? [];\n const events = eventsData?.ggnomadEvents ?? [];\n const activities = activitiesData?.ggnomadActivities ?? [];\n\n return (\n <PageShell\n title={tripPlan.name}\n subtitle={t('ggnomad.tripPlan.subtitle', 'Build your complete itinerary')}\n >\n <Tabs value={activeTab} onValueChange={setActiveTab} className=\"w-full\">\n <TabsList className=\"mb-6 w-full justify-start\">\n <TabsTrigger value=\"itinerary\">\n {t('ggnomad.tripPlan.tabs.itinerary', 'Itinerary')}\n </TabsTrigger>\n <TabsTrigger value=\"timeline\">\n {t('ggnomad.tripPlan.tabs.timeline', 'Timeline')}\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"itinerary\" className=\"space-y-6\">\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-4\">\n {/* Left Rail - Add Items */}\n <div className=\"space-y-4\">\n <GlassCard treatment=\"glass\" glow className=\"border-border-seam p-4\">\n <h3 className=\"mb-3 flex items-center gap-2 font-medium text-text-primary\">\n <Plus className=\"size-4\" />\n {t('ggnomad.tripPlan.addToTrip', 'Add to trip')}\n </h3>\n\n <div className=\"space-y-3\">\n {/* Stays */}\n <details className=\"group\">\n <summary className=\"flex cursor-pointer items-center justify-between rounded-md bg-bg-canvas-inverted p-2 text-sm font-medium text-text-primary hover:bg-opacity-80\">\n {t('ggnomad.tripPlan.stays', 'Stays')}\n <ChevronDown className=\"size-4 transition-transform group-open:rotate-180\" />\n </summary>\n <div className=\"mt-2 space-y-2\">\n {properties.length === 0 ? (\n <p className=\"text-xs text-text-secondary\">\n {t('ggnomad.tripPlan.noStaysAvailable', 'No stays available')}\n </p>\n ) : (\n properties.map((property) => (\n <button\n key={property.id}\n onClick={() =>\n setAddingItem({\n itemType: 'PROPERTY',\n itemId: property.id,\n itemName: property.name,\n price: property.pricePerNight,\n currency: property.currency,\n })\n }\n className=\"w-full rounded-md border border-border-seam bg-bg-canvas p-2 text-left text-xs text-text-primary hover:bg-action-primary-bg hover:text-action-primary-text\"\n >\n <div className=\"font-medium\">{property.name}</div>\n <div className=\"text-text-secondary\">\n {property.currency} {property.pricePerNight.toFixed(2)}\n </div>\n </button>\n ))\n )}\n </div>\n </details>\n\n {/* Tours */}\n <details className=\"group\">\n <summary className=\"flex cursor-pointer items-center justify-between rounded-md bg-bg-canvas-inverted p-2 text-sm font-medium text-text-primary hover:bg-opacity-80\">\n {t('ggnomad.tripPlan.tours', 'Tours')}\n <ChevronDown className=\"size-4 transition-transform group-open:rotate-180\" />\n </summary>\n <div className=\"mt-2 space-y-2\">\n {tours.length === 0 ? (\n <p className=\"text-xs text-text-secondary\">\n {t('ggnomad.tripPlan.noToursAvailable', 'No tours available')}\n </p>\n ) : (\n tours.map((tour) => (\n <button\n key={tour.id}\n onClick={() =>\n setAddingItem({\n itemType: 'TOUR',\n itemId: tour.id,\n itemName: tour.name,\n price: tour.price,\n currency: tour.currency,\n })\n }\n className=\"w-full rounded-md border border-border-seam bg-bg-canvas p-2 text-left text-xs text-text-primary hover:bg-action-primary-bg hover:text-action-primary-text\"\n >\n <div className=\"font-medium\">{tour.name}</div>\n <div className=\"text-text-secondary\">\n {tour.currency} {tour.price.toFixed(2)}\n </div>\n </button>\n ))\n )}\n </div>\n </details>\n\n {/* Events */}\n <details className=\"group\">\n <summary className=\"flex cursor-pointer items-center justify-between rounded-md bg-bg-canvas-inverted p-2 text-sm font-medium text-text-primary hover:bg-opacity-80\">\n {t('ggnomad.tripPlan.events', 'Events')}\n <ChevronDown className=\"size-4 transition-transform group-open:rotate-180\" />\n </summary>\n <div className=\"mt-2 space-y-2\">\n {events.length === 0 ? (\n <p className=\"text-xs text-text-secondary\">\n {t('ggnomad.tripPlan.noEventsAvailable', 'No events available')}\n </p>\n ) : (\n events.map((event) => (\n <button\n key={event.id}\n onClick={() =>\n setAddingItem({\n itemType: 'EVENT',\n itemId: event.id,\n itemName: event.name,\n price: event.price,\n currency: event.currency,\n })\n }\n className=\"w-full rounded-md border border-border-seam bg-bg-canvas p-2 text-left text-xs text-text-primary hover:bg-action-primary-bg hover:text-action-primary-text\"\n >\n <div className=\"font-medium\">{event.name}</div>\n <div className=\"text-text-secondary\">\n {event.currency} {event.price.toFixed(2)}\n </div>\n </button>\n ))\n )}\n </div>\n </details>\n\n {/* Activities */}\n <details className=\"group\">\n <summary className=\"flex cursor-pointer items-center justify-between rounded-md bg-bg-canvas-inverted p-2 text-sm font-medium text-text-primary hover:bg-opacity-80\">\n {t('ggnomad.tripPlan.activities', 'Activities')}\n <ChevronDown className=\"size-4 transition-transform group-open:rotate-180\" />\n </summary>\n <div className=\"mt-2 space-y-2\">\n {activities.length === 0 ? (\n <p className=\"text-xs text-text-secondary\">\n {t('ggnomad.tripPlan.noActivitiesAvailable', 'No activities available')}\n </p>\n ) : (\n activities.map((activity) => (\n <button\n key={activity.id}\n onClick={() =>\n setAddingItem({\n itemType: 'ACTIVITY',\n itemId: activity.id,\n itemName: activity.name,\n price: activity.price,\n currency: activity.currency,\n })\n }\n className=\"w-full rounded-md border border-border-seam bg-bg-canvas p-2 text-left text-xs text-text-primary hover:bg-action-primary-bg hover:text-action-primary-text\"\n >\n <div className=\"font-medium\">{activity.name}</div>\n <div className=\"text-text-secondary\">\n {activity.currency} {activity.price.toFixed(2)}\n </div>\n </button>\n ))\n )}\n </div>\n </details>\n </div>\n </GlassCard>\n </div>\n\n {/* Center - Itinerary Items */}\n <div className=\"space-y-4 lg:col-span-2\">\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.tripPlan.itineraryHeader', 'Your itinerary')}\n </h2>\n\n {tripPlan.items.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {t(\n 'ggnomad.tripPlan.noItemsYet',\n 'No items added yet. Start adding stays, tours, events and activities from the left.'\n )}\n </p>\n ) : (\n <div className=\"space-y-6\">\n {sortedDays.map((day: number) => (\n <div key={String(day)}>\n <h3 className=\"mb-2 text-sm font-medium text-text-secondary\">\n {day === 0\n ? t('ggnomad.tripPlan.unscheduled', 'Unscheduled')\n : t('ggnomad.tripPlan.day', 'Day {{day}}').replace(\n '{{day}}',\n String(day)\n )}\n </h3>\n <div className=\"space-y-2\">\n {(itemsByDay[day] || []).map((item: TripPlanItem) => (\n <div\n key={item.id}\n className=\"flex items-start justify-between rounded-md border border-border-seam bg-bg-canvas p-3\"\n >\n <div className=\"flex-1\">\n <p className=\"font-medium text-text-primary\">{item.itemName}</p>\n <p className=\"text-xs text-text-secondary\">\n {item.itemType.charAt(0) + item.itemType.slice(1).toLowerCase()}\n </p>\n <p className=\"mt-1 font-semibold text-status-success-text\">\n {item.currency} {item.price.toFixed(2)}\n </p>\n </div>\n <button\n onClick={() => setRemovingItemId(item.id)}\n className=\"ml-2 rounded-md p-1 text-text-secondary hover:bg-action-danger-bg hover:text-action-danger-text\"\n aria-label={t('ggnomad.tripPlan.removeItem', 'Remove item')}\n >\n <X className=\"size-4\" />\n </button>\n </div>\n ))}\n </div>\n </div>\n ))}\n </div>\n )}\n </GlassCard>\n </div>\n\n {/* Right - Trip Summary */}\n <div className=\"space-y-4\">\n <GlassCard treatment=\"glass\" glow className=\"sticky top-6 border-border-seam p-5\">\n <h3 className=\"mb-4 font-medium text-text-primary\">\n {t('ggnomad.tripPlan.tripTotal', 'Trip total')}\n </h3>\n\n <div className=\"space-y-3 border-b border-border-seam pb-4\">\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-text-secondary\">\n {t('ggnomad.tripPlan.items', 'Items')}\n </span>\n <span className=\"font-medium text-text-primary\">{tripPlan.itemCount}</span>\n </div>\n <div className=\"flex items-center justify-between text-sm\">\n <span className=\"text-text-secondary\">\n {t('ggnomad.tripPlan.travelers', 'Travelers')}\n </span>\n <span className=\"font-medium text-text-primary flex items-center gap-1\">\n <Users className=\"size-3\" />\n {tripPlan.travelers}\n </span>\n </div>\n </div>\n\n <div className=\"my-4\">\n <div className=\"text-2xl font-bold text-text-primary\">\n USD {tripPlan.total.toFixed(2)}\n </div>\n {tripPlan.travelers > 0 && (\n <div className=\"mt-3 rounded-md border border-border-seam bg-bg-canvas/50 p-3\">\n <p className=\"text-xs font-medium text-text-secondary\">\n {t('ggnomad.tripPlan.costSplit', 'Split {{count}} ways').replace(\n '{{count}}',\n String(tripPlan.travelers)\n )}\n </p>\n <p className=\"mt-1 text-lg font-semibold text-action-primary-text\">\n USD {(tripPlan.total / tripPlan.travelers).toFixed(2)} each\n </p>\n <p className=\"mt-2 text-xs text-text-secondary\">\n {t(\n 'ggnomad.tripPlan.costSplitNote',\n 'This trip plan is shared with everyone in your workspace.'\n )}\n </p>\n </div>\n )}\n </div>\n\n <div className=\"space-y-2\">\n <button\n onClick={() => setShowCheckout(true)}\n disabled={tripPlan.items.length === 0}\n className=\"w-full rounded-md bg-action-primary-bg px-4 py-2 font-medium text-action-primary-text hover:bg-action-primary-bgHover disabled:opacity-50\"\n >\n {t('ggnomad.tripPlan.checkout', 'Checkout')}\n </button>\n\n <div className=\"flex items-center gap-2\">\n <select\n value={tripPlan.status}\n onChange={async (e) => {\n await updateStatus({\n variables: {\n id: tripPlan.id,\n input: { status: e.target.value },\n },\n });\n await refetch();\n }}\n className=\"flex-1 rounded-md border border-border-seam bg-bg-canvas px-2 py-1 text-sm text-text-primary\"\n >\n <option value=\"DRAFT\">Draft</option>\n <option value=\"PLANNED\">Planned</option>\n <option value=\"BOOKED\">Booked</option>\n <option value=\"CONFIRMED\">Confirmed</option>\n <option value=\"COMPLETED\">Completed</option>\n <option value=\"CANCELLED\">Cancelled</option>\n </select>\n </div>\n </div>\n </GlassCard>\n </div>\n </div>\n </TabsContent>\n\n <TabsContent value=\"timeline\" className=\"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.tripPlan.timeline', 'Trip timeline')}\n </h2>\n\n <div className=\"space-y-6\">\n {/* Plan Status Milestone */}\n <div className=\"flex gap-4\">\n <div className=\"flex flex-col items-center\">\n <div className=\"size-3 rounded-full bg-status-info-bg\" />\n <div className=\"my-2 h-8 w-0.5 bg-border-seam\" />\n </div>\n <div>\n <h3 className=\"font-medium text-text-primary\">\n {t('ggnomad.tripPlan.milestone.started', 'Trip started')}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {t('ggnomad.tripPlan.milestone.startedDesc', 'Created your itinerary')}\n </p>\n </div>\n </div>\n\n {/* Items Timeline */}\n {tripPlan.items.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">\n {t('ggnomad.tripPlan.noItemsInTimeline', 'No items in your timeline yet')}\n </p>\n ) : (\n tripPlan.items.map((item, index) => (\n <div key={item.id} className=\"flex gap-4\">\n <div className=\"flex flex-col items-center\">\n <div\n className={`size-3 rounded-full ${\n tripPlan.status === 'BOOKED' || tripPlan.status === 'COMPLETED'\n ? 'bg-status-success-bg'\n : 'bg-status-warning-bg'\n }`}\n />\n {index < tripPlan.items.length - 1 && (\n <div className=\"my-2 h-8 w-0.5 bg-border-seam\" />\n )}\n </div>\n <div>\n <h3 className=\"font-medium text-text-primary\">{item.itemName}</h3>\n <p className=\"text-xs text-text-secondary\">\n {item.itemType.charAt(0) + item.itemType.slice(1).toLowerCase()}\n {item.day && ` · Day ${item.day}`}\n </p>\n <p className=\"mt-1 text-sm font-semibold text-status-success-text\">\n {item.currency} {item.price.toFixed(2)}\n </p>\n <p className=\"mt-1 text-xs text-text-secondary\">\n {tripPlan.status === 'BOOKED' || tripPlan.status === 'COMPLETED'\n ? t('ggnomad.tripPlan.milestone.booked', 'Booked')\n : t('ggnomad.tripPlan.milestone.planned', 'Planned')}\n </p>\n </div>\n </div>\n ))\n )}\n\n {/* Final Status */}\n {tripPlan.items.length > 0 && (\n <>\n <div className=\"flex gap-4\">\n <div className=\"flex flex-col items-center\">\n <div\n className={`size-3 rounded-full ${\n tripPlan.status === 'COMPLETED'\n ? 'bg-status-success-bg'\n : 'bg-status-secondary-bg'\n }`}\n />\n </div>\n <div>\n <h3 className=\"font-medium text-text-primary\">\n {tripPlan.status === 'COMPLETED'\n ? t('ggnomad.tripPlan.milestone.completed', 'Trip completed')\n : t('ggnomad.tripPlan.milestone.confirming', 'Awaiting completion')}\n </h3>\n <p className=\"text-xs text-text-secondary\">\n {tripPlan.status === 'COMPLETED'\n ? t('ggnomad.tripPlan.milestone.completedDesc', 'Your trip is complete')\n : t(\n 'ggnomad.tripPlan.milestone.confirmingDesc',\n 'Update status as your trip progresses'\n )}\n </p>\n </div>\n </div>\n </>\n )}\n </div>\n </GlassCard>\n </TabsContent>\n </Tabs>\n\n {/* Add Item Dialog */}\n <AlertDialog open={addingItem !== null} onOpenChange={(open) => !open && setAddingItem(null)}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n {t('ggnomad.tripPlan.addItemDialog.title', 'Add to itinerary?')}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {addingItem && (\n <>\n {addingItem.itemName}\n {' · '}\n {addingItem.currency} {addingItem.price.toFixed(2)}\n </>\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={addingItemMutation}>\n {t('ggnomad.tripPlan.addItemDialog.cancel', 'Cancel')}\n </AlertDialogCancel>\n <AlertDialogAction\n disabled={addingItemMutation}\n onClick={(event) => {\n event.preventDefault();\n void handleAddItem();\n }}\n >\n {addingItemMutation\n ? t('ggnomad.tripPlan.addItemDialog.adding', 'Adding…')\n : t('ggnomad.tripPlan.addItemDialog.add', 'Add item')}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n\n {/* Remove Item Dialog */}\n <AlertDialog\n open={removingItemId !== null}\n onOpenChange={(open) => !open && setRemovingItemId(null)}\n >\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n {t('ggnomad.tripPlan.removeItemDialog.title', 'Remove item from trip?')}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {t(\n 'ggnomad.tripPlan.removeItemDialog.description',\n 'This item will be removed from your itinerary.'\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel disabled={removingItemMutation}>\n {t('ggnomad.tripPlan.removeItemDialog.cancel', 'Keep item')}\n </AlertDialogCancel>\n <AlertDialogAction\n className=\"bg-action-danger-bg text-action-danger-text hover:bg-action-danger-bgHover\"\n disabled={removingItemMutation}\n onClick={(event) => {\n event.preventDefault();\n void handleRemoveItem();\n }}\n >\n {removingItemMutation\n ? t('ggnomad.tripPlan.removeItemDialog.removing', 'Removing…')\n : t('ggnomad.tripPlan.removeItemDialog.remove', 'Remove item')}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n\n {/* Checkout Dialog */}\n <AlertDialog open={showCheckout} onOpenChange={setShowCheckout}>\n <AlertDialogContent className=\"max-w-2xl\">\n <AlertDialogHeader>\n <AlertDialogTitle>\n {t('ggnomad.tripPlan.checkoutDialog.title', 'Review and book')}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {t(\n 'ggnomad.tripPlan.checkoutDialog.description',\n 'Review your items and confirm to book everything at once.'\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n\n <div className=\"space-y-4 max-h-96 overflow-y-auto\">\n {tripPlan.items.map((item) => (\n <div\n key={item.id}\n className=\"flex items-center justify-between rounded-md border border-border-seam bg-bg-canvas p-3\"\n >\n <div>\n <p className=\"font-medium text-text-primary\">{item.itemName}</p>\n <p className=\"text-xs text-text-secondary\">\n {item.itemType.charAt(0) + item.itemType.slice(1).toLowerCase()}\n </p>\n </div>\n <p className=\"font-semibold text-text-primary\">\n {item.currency} {item.price.toFixed(2)}\n </p>\n </div>\n ))}\n\n <div className=\"space-y-2 border-t border-border-seam pt-4\">\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Subtotal</span>\n <span className=\"text-text-primary\">USD {tripPlan.total.toFixed(2)}</span>\n </div>\n <div className=\"flex justify-between text-sm\">\n <span className=\"text-text-secondary\">Taxes (10%)</span>\n <span className=\"text-text-primary\">USD {(tripPlan.total * 0.1).toFixed(2)}</span>\n </div>\n <div className=\"flex justify-between border-t border-border-seam pt-2 text-lg font-bold\">\n <span className=\"text-text-primary\">Total</span>\n <span className=\"text-status-success-text\">\n USD {(tripPlan.total * 1.1).toFixed(2)}\n </span>\n </div>\n </div>\n </div>\n\n <AlertDialogFooter>\n <AlertDialogCancel disabled={false}>\n {t('ggnomad.tripPlan.checkoutDialog.cancel', 'Cancel')}\n </AlertDialogCancel>\n <AlertDialogAction\n onClick={(event) => {\n event.preventDefault();\n void handleCheckout();\n }}\n >\n {t('ggnomad.tripPlan.checkoutDialog.confirm', 'Confirm & book all')}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </PageShell>\n );\n}\n"],"mappings":"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"}
|
|
@@ -19,8 +19,8 @@ var k = {
|
|
|
19
19
|
};
|
|
20
20
|
function A() {
|
|
21
21
|
let { t: A } = u(), j = d(), [M, N] = o(!1), [P, F] = o(k), { data: I, refetch: L } = p(t, { variables: {
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
limit: 50,
|
|
23
|
+
offset: 0
|
|
24
24
|
} }), [R, { loading: z }] = f(e), B = I?.ggnomadTripPlans ?? [], V = async () => {
|
|
25
25
|
if (!P.name.trim()) {
|
|
26
26
|
a.warning(A("ggnomad.trips.toast.validationTitle", "Required field missing"), A("ggnomad.trips.toast.nameRequired", "Please enter a trip name"));
|