@burdenoff/microfe-ggnomad 2026.705.6 → 2026.710.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.
- package/dist/dev/main.d.ts +2 -0
- package/dist/dev/main.d.ts.map +1 -0
- package/dist/generated/global-operations.d.ts +2 -0
- package/dist/generated/global-operations.d.ts.map +1 -0
- package/dist/generated/global-types.d.ts +23527 -0
- package/dist/generated/global-types.d.ts.map +1 -0
- package/dist/generated/wspace-operations.d.ts +2 -0
- package/dist/generated/wspace-operations.d.ts.map +1 -0
- package/dist/generated/wspace-types.d.ts +57851 -0
- package/dist/generated/wspace-types.d.ts.map +1 -0
- package/dist/ggnomad/GGNomadRoot.d.ts +5 -0
- package/dist/ggnomad/GGNomadRoot.d.ts.map +1 -0
- package/dist/ggnomad/GGNomadRoutes.d.ts +2 -0
- package/dist/ggnomad/GGNomadRoutes.d.ts.map +1 -0
- package/dist/ggnomad/GGNomadRoutes.js.map +1 -1
- package/dist/ggnomad/components/BookingPanel.d.ts +16 -0
- package/dist/ggnomad/components/BookingPanel.d.ts.map +1 -0
- package/dist/ggnomad/components/DetailHero.d.ts +13 -0
- package/dist/ggnomad/components/DetailHero.d.ts.map +1 -0
- package/dist/ggnomad/components/DetailRow.d.ts +8 -0
- package/dist/ggnomad/components/DetailRow.d.ts.map +1 -0
- package/dist/ggnomad/components/EntityCard.d.ts +27 -0
- package/dist/ggnomad/components/EntityCard.d.ts.map +1 -0
- package/dist/ggnomad/components/ListingEditDialog.d.ts +20 -0
- package/dist/ggnomad/components/ListingEditDialog.d.ts.map +1 -0
- package/dist/ggnomad/components/ListingEditDialog.js +151 -0
- package/dist/ggnomad/components/ListingEditDialog.js.map +1 -0
- package/dist/ggnomad/components/LoadMoreButton.d.ts +13 -0
- package/dist/ggnomad/components/LoadMoreButton.d.ts.map +1 -0
- package/dist/ggnomad/components/ReviewsSection.d.ts +12 -0
- package/dist/ggnomad/components/ReviewsSection.d.ts.map +1 -0
- package/dist/ggnomad/components/SectionCard.d.ts +12 -0
- package/dist/ggnomad/components/SectionCard.d.ts.map +1 -0
- package/dist/ggnomad/components/StatCard.d.ts +17 -0
- package/dist/ggnomad/components/StatCard.d.ts.map +1 -0
- package/dist/ggnomad/components/StatusBadge.d.ts +12 -0
- package/dist/ggnomad/components/StatusBadge.d.ts.map +1 -0
- package/dist/ggnomad/components/index.d.ts +11 -0
- package/dist/ggnomad/components/index.d.ts.map +1 -0
- package/dist/ggnomad/components/index.js +1 -0
- package/dist/ggnomad/graphql.d.ts +47 -0
- package/dist/ggnomad/graphql.d.ts.map +1 -0
- package/dist/ggnomad/graphql.js +46 -1
- package/dist/ggnomad/graphql.js.map +1 -1
- package/dist/ggnomad/index.d.ts +4 -0
- package/dist/ggnomad/index.d.ts.map +1 -0
- package/dist/ggnomad/pages/ActivityDetailsPage.d.ts +2 -0
- package/dist/ggnomad/pages/ActivityDetailsPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/ActivityDetailsPage.js +86 -61
- package/dist/ggnomad/pages/ActivityDetailsPage.js.map +1 -1
- package/dist/ggnomad/pages/AnalyticsPage.d.ts +2 -0
- package/dist/ggnomad/pages/AnalyticsPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/BookingsPage.d.ts +2 -0
- package/dist/ggnomad/pages/BookingsPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/DashboardPage.d.ts +2 -0
- package/dist/ggnomad/pages/DashboardPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/EntertainmentPage.d.ts +2 -0
- package/dist/ggnomad/pages/EntertainmentPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/EventDetailsPage.d.ts +2 -0
- package/dist/ggnomad/pages/EventDetailsPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/EventDetailsPage.js +87 -62
- package/dist/ggnomad/pages/EventDetailsPage.js.map +1 -1
- package/dist/ggnomad/pages/FavoritesPage.d.ts +2 -0
- package/dist/ggnomad/pages/FavoritesPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/HospitalityPage.d.ts +2 -0
- package/dist/ggnomad/pages/HospitalityPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/PageShell.d.ts +23 -0
- package/dist/ggnomad/pages/PageShell.d.ts.map +1 -0
- package/dist/ggnomad/pages/PropertyDetailsPage.d.ts +2 -0
- package/dist/ggnomad/pages/PropertyDetailsPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/PropertyDetailsPage.js +91 -66
- package/dist/ggnomad/pages/PropertyDetailsPage.js.map +1 -1
- package/dist/ggnomad/pages/ProviderPage.d.ts +2 -0
- package/dist/ggnomad/pages/ProviderPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/SearchPage.d.ts +2 -0
- package/dist/ggnomad/pages/SearchPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/TourDetailsPage.d.ts +2 -0
- package/dist/ggnomad/pages/TourDetailsPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/TourDetailsPage.js +86 -61
- package/dist/ggnomad/pages/TourDetailsPage.js.map +1 -1
- package/dist/ggnomad/pages/TourismPage.d.ts +2 -0
- package/dist/ggnomad/pages/TourismPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/TravelPage.d.ts +2 -0
- package/dist/ggnomad/pages/TravelPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/TripPlanDetailPage.d.ts +2 -0
- package/dist/ggnomad/pages/TripPlanDetailPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/TripPlanDetailPage.js +23 -3
- package/dist/ggnomad/pages/TripPlanDetailPage.js.map +1 -1
- package/dist/ggnomad/pages/TripsPage.d.ts +2 -0
- package/dist/ggnomad/pages/TripsPage.d.ts.map +1 -0
- package/dist/ggnomad/pages/TripsPage.js.map +1 -1
- package/dist/ggnomad/providers/GGNomadProvider.d.ts +6 -0
- package/dist/ggnomad/providers/GGNomadProvider.d.ts.map +1 -0
- package/dist/ggnomad/types/index.d.ts +58 -0
- package/dist/ggnomad/types/index.d.ts.map +1 -0
- package/dist/ggnomad/utils/cn.d.ts +4 -0
- package/dist/ggnomad/utils/cn.d.ts.map +1 -0
- package/dist/ggnomad/utils/navigation.d.ts +2 -0
- package/dist/ggnomad/utils/navigation.d.ts.map +1 -0
- package/dist/ggnomad/utils/notify.d.ts +22 -0
- package/dist/ggnomad/utils/notify.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -1
- package/dist/services/createSandboxAssistantTransport.d.ts +44 -0
- package/dist/services/createSandboxAssistantTransport.d.ts.map +1 -0
- package/dist/services/createSandboxAssistantTransport.js +338 -0
- package/dist/services/createSandboxAssistantTransport.js.map +1 -0
- package/dist/utils/pageContext.d.ts +28 -0
- package/dist/utils/pageContext.d.ts.map +1 -0
- package/dist/utils/pageContext.js +50 -0
- package/dist/utils/pageContext.js.map +1 -0
- package/package.json +5 -1
|
@@ -352,12 +352,32 @@ function j() {
|
|
|
352
352
|
})]
|
|
353
353
|
})]
|
|
354
354
|
}),
|
|
355
|
-
/* @__PURE__ */
|
|
355
|
+
/* @__PURE__ */ A("div", {
|
|
356
356
|
className: "my-4",
|
|
357
|
-
children: /* @__PURE__ */ A("div", {
|
|
357
|
+
children: [/* @__PURE__ */ A("div", {
|
|
358
358
|
className: "text-2xl font-bold text-text-primary",
|
|
359
359
|
children: ["USD ", G.total.toFixed(2)]
|
|
360
|
-
})
|
|
360
|
+
}), G.travelers > 0 && /* @__PURE__ */ A("div", {
|
|
361
|
+
className: "mt-3 rounded-md border border-border-seam bg-bg-canvas/50 p-3",
|
|
362
|
+
children: [
|
|
363
|
+
/* @__PURE__ */ k("p", {
|
|
364
|
+
className: "text-xs font-medium text-text-secondary",
|
|
365
|
+
children: j("ggnomad.tripPlan.costSplit", "Split {{count}} ways").replace("{{count}}", String(G.travelers))
|
|
366
|
+
}),
|
|
367
|
+
/* @__PURE__ */ A("p", {
|
|
368
|
+
className: "mt-1 text-lg font-semibold text-action-primary-text",
|
|
369
|
+
children: [
|
|
370
|
+
"USD ",
|
|
371
|
+
(G.total / G.travelers).toFixed(2),
|
|
372
|
+
" each"
|
|
373
|
+
]
|
|
374
|
+
}),
|
|
375
|
+
/* @__PURE__ */ k("p", {
|
|
376
|
+
className: "mt-2 text-xs text-text-secondary",
|
|
377
|
+
children: j("ggnomad.tripPlan.costSplitNote", "This trip plan is shared with everyone in your workspace.")
|
|
378
|
+
})
|
|
379
|
+
]
|
|
380
|
+
})]
|
|
361
381
|
}),
|
|
362
382
|
/* @__PURE__ */ A("div", {
|
|
363
383
|
className: "space-y-2",
|
|
@@ -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 {\n ChevronDown,\n Plus,\n Users,\n X,\n} 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(\n t('ggnomad.tripPlan.toast.removeItemSuccessTitle', 'Item removed'),\n ''\n );\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('{{day}}', String(day))}\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(\n 'ggnomad.tripPlan.removeItem',\n 'Remove item'\n )}\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\n treatment=\"glass\"\n glow\n className=\"sticky top-6 border-border-seam p-5\"\n >\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 </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(\n 'ggnomad.tripPlan.milestone.completedDesc',\n 'Your trip is complete'\n )\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\">\n USD {(tripPlan.total * 0.1).toFixed(2)}\n </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 { 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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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TripsPage.d.ts","sourceRoot":"","sources":["../../../src/ggnomad/pages/TripsPage.tsx"],"names":[],"mappings":"AAuCA,wBAAgB,SAAS,gCA8RxB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TripsPage.js","names":[],"sources":["../../../src/ggnomad/pages/TripsPage.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 { Calendar, Map, Plus } from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n CTAOverflowMenu,\n GlassCard,\n IllustratedEmptyState,\n NextSteps,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\n\nimport {\n CREATE_GGNOMAD_TRIP_PLAN_MUTATION,\n GGNOMAD_TRIP_PLANS_QUERY,\n} from '../graphql';\nimport { PageShell } from './PageShell';\nimport { EntityCard, StatusBadge } from '../components';\nimport { notify } from '../utils/notify';\n\ninterface NewTripFormState {\n name: string;\n startDate: string;\n endDate: string;\n}\n\nconst defaultFormState: NewTripFormState = {\n name: '',\n startDate: '',\n endDate: '',\n};\n\nexport function TripsPage() {\n const { t } = useI18n();\n const navigate = useNavigate();\n const [showNewTripDialog, setShowNewTripDialog] = useState(false);\n const [formState, setFormState] = useState<NewTripFormState>(defaultFormState);\n\n const { data, refetch } = useQuery(\n GGNOMAD_TRIP_PLANS_QUERY as TypedDocumentNode<\n {\n ggnomadTripPlans: Array<{\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 createdAt: string;\n }>;\n },\n { first: number; skip: number }\n >,\n { variables: { first: 50, skip: 0 } }\n );\n\n const [createTripPlan, { loading: creating }] = useMutation(\n CREATE_GGNOMAD_TRIP_PLAN_MUTATION as TypedDocumentNode<\n {\n createGgnomadTripPlan: {\n id: string;\n name: string;\n startDate?: string;\n endDate?: string;\n };\n },\n {\n input: {\n name: string;\n description?: string;\n startDate?: string;\n endDate?: string;\n travelers?: number;\n };\n }\n >\n );\n\n const trips = data?.ggnomadTripPlans ?? [];\n\n const handleCreateTrip = async () => {\n if (!formState.name.trim()) {\n notify.warning(\n t('ggnomad.trips.toast.validationTitle', 'Required field missing'),\n t('ggnomad.trips.toast.nameRequired', 'Please enter a trip name')\n );\n return;\n }\n\n try {\n const result = await createTripPlan({\n variables: {\n input: {\n name: formState.name.trim(),\n startDate: formState.startDate ? new Date(formState.startDate).toISOString() : undefined,\n endDate: formState.endDate ? new Date(formState.endDate).toISOString() : undefined,\n travelers: 1,\n },\n },\n });\n\n if (result.error) {\n notify.error(\n t('ggnomad.trips.toast.createErrorTitle', 'Could not create trip'),\n result.error.message\n );\n return;\n }\n\n const created = result.data?.createGgnomadTripPlan;\n if (!created) return;\n\n notify.success(\n t('ggnomad.trips.toast.createSuccessTitle', 'Trip created'),\n created.name\n );\n\n setShowNewTripDialog(false);\n setFormState(defaultFormState);\n await refetch();\n navigate(`trips/${created.id}`);\n } catch (err) {\n notify.error(\n t('ggnomad.trips.toast.createErrorTitle', 'Could not create trip'),\n err instanceof Error ? err.message : String(err)\n );\n }\n };\n\n const formatDate = (dateStr?: string) => {\n if (!dateStr) return '';\n const date = new Date(dateStr);\n return date.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n });\n };\n\n return (\n <PageShell\n title={t('ggnomad.trips.title', 'Trips')}\n titleAccent={t('ggnomad.trips.title.accent', 'Trips')}\n subtitle={t(\n 'ggnomad.trips.subtitle',\n 'Plan complete itineraries with real trip planning API mutations'\n )}\n actions={\n <CTAOverflowMenu\n primary={{\n label: t('ggnomad.trips.actions.newTrip', 'New trip'),\n onSelect: () => setShowNewTripDialog(true),\n disabled: creating,\n icon: <Plus />,\n }}\n actions={[]}\n />\n }\n >\n <PagePurpose icon={<Map className=\"size-4\" />}>\n {t(\n 'ggnomad.trips.purpose',\n 'Organize every aspect of your journey — build itineraries day by day, add activities and accommodations, manage your trip status, and book everything at once. All your trips in one place.'\n )}\n </PagePurpose>\n\n <NextSteps\n storageKey=\"ggnomad-trips\"\n steps={[\n {\n id: 'add-stays',\n label: t('ggnomad.trips.next.stays', 'Add places to stay'),\n description: t(\n 'ggnomad.trips.next.staysDesc',\n 'Browse accommodations and add them to your itinerary.'\n ),\n icon: <Calendar className=\"size-4\" />,\n onClick: () => navigate('../hospitality'),\n },\n {\n id: 'build-activities',\n label: t('ggnomad.trips.next.activities', 'Plan activities'),\n description: t(\n 'ggnomad.trips.next.activitiesDesc',\n 'Mix in tours, events, and activities by day.'\n ),\n icon: <Map className=\"size-4\" />,\n onClick: () => navigate('../tourism'),\n },\n ]}\n />\n\n {trips.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('ggnomad.trips.emptyTitle', 'No trips yet')}\n description={t(\n 'ggnomad.trips.emptyDescription',\n 'Create your first trip to start building an itinerary.'\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.trips.yourTrips', 'Your trips')}\n </h2>\n <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-3\">\n {trips.map((trip) => (\n <EntityCard\n key={trip.id}\n to={`trips/${trip.id}`}\n title={trip.name}\n meta={`${trip.travelers} ${\n trip.travelers === 1\n ? t('ggnomad.trips.card.traveler', 'traveler')\n : t('ggnomad.trips.card.travelers', 'travelers')\n } · ${trip.itemCount} ${t('ggnomad.trips.card.items', 'items')}`}\n price={trip.total > 0 ? `USD ${trip.total.toFixed(2)}` : ''}\n badge={<StatusBadge status={trip.status} live={trip.status !== 'CANCELLED'} />}\n footer={\n trip.startDate && trip.endDate\n ? `${formatDate(trip.startDate)} – ${formatDate(trip.endDate)}`\n : t('ggnomad.trips.card.noDates', 'No dates set')\n }\n />\n ))}\n </div>\n </GlassCard>\n )}\n\n <AlertDialog open={showNewTripDialog} onOpenChange={setShowNewTripDialog}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n {t('ggnomad.trips.newDialog.title', 'Create a new trip')}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {t(\n 'ggnomad.trips.newDialog.description',\n 'Name your trip and set the dates to get started building your itinerary.'\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n\n <div className=\"space-y-4\">\n <div>\n <label htmlFor=\"trip-name\" className=\"block text-sm font-medium text-text-primary\">\n {t('ggnomad.trips.newDialog.tripName', 'Trip name')}\n </label>\n <input\n id=\"trip-name\"\n type=\"text\"\n className=\"mt-1 w-full rounded-md border border-border-seam bg-bg-canvas px-3 py-2 text-sm text-text-primary placeholder-text-secondary focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary\"\n placeholder={t(\n 'ggnomad.trips.newDialog.tripNamePlaceholder',\n 'e.g. Summer Europe Adventure'\n )}\n value={formState.name}\n onChange={(e) =>\n setFormState((prev) => ({ ...prev, name: e.target.value }))\n }\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label\n htmlFor=\"trip-start-date\"\n className=\"block text-sm font-medium text-text-primary\"\n >\n {t('ggnomad.trips.newDialog.startDate', 'Start date')}\n </label>\n <input\n id=\"trip-start-date\"\n type=\"date\"\n className=\"mt-1 w-full rounded-md border border-border-seam bg-bg-canvas px-3 py-2 text-sm text-text-primary focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary\"\n value={formState.startDate}\n onChange={(e) =>\n setFormState((prev) => ({ ...prev, startDate: e.target.value }))\n }\n />\n </div>\n <div>\n <label\n htmlFor=\"trip-end-date\"\n className=\"block text-sm font-medium text-text-primary\"\n >\n {t('ggnomad.trips.newDialog.endDate', 'End date')}\n </label>\n <input\n id=\"trip-end-date\"\n type=\"date\"\n className=\"mt-1 w-full rounded-md border border-border-seam bg-bg-canvas px-3 py-2 text-sm text-text-primary focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary\"\n value={formState.endDate}\n onChange={(e) =>\n setFormState((prev) => ({ ...prev, endDate: e.target.value }))\n }\n />\n </div>\n </div>\n </div>\n\n <AlertDialogFooter>\n <AlertDialogCancel disabled={creating}>\n {t('ggnomad.trips.newDialog.cancel', 'Cancel')}\n </AlertDialogCancel>\n <AlertDialogAction\n disabled={creating || !formState.name.trim()}\n onClick={(event) => {\n event.preventDefault();\n void handleCreateTrip();\n }}\n >\n {creating\n ? t('ggnomad.trips.newDialog.creating', 'Creating…')\n : t('ggnomad.trips.newDialog.create', 'Create trip')}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </PageShell>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TripsPage.js","names":[],"sources":["../../../src/ggnomad/pages/TripsPage.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 { Calendar, Map, Plus } from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n CTAOverflowMenu,\n GlassCard,\n IllustratedEmptyState,\n NextSteps,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\n\nimport { CREATE_GGNOMAD_TRIP_PLAN_MUTATION, GGNOMAD_TRIP_PLANS_QUERY } from '../graphql';\nimport { PageShell } from './PageShell';\nimport { EntityCard, StatusBadge } from '../components';\nimport { notify } from '../utils/notify';\n\ninterface NewTripFormState {\n name: string;\n startDate: string;\n endDate: string;\n}\n\nconst defaultFormState: NewTripFormState = {\n name: '',\n startDate: '',\n endDate: '',\n};\n\nexport function TripsPage() {\n const { t } = useI18n();\n const navigate = useNavigate();\n const [showNewTripDialog, setShowNewTripDialog] = useState(false);\n const [formState, setFormState] = useState<NewTripFormState>(defaultFormState);\n\n const { data, refetch } = useQuery(\n GGNOMAD_TRIP_PLANS_QUERY as TypedDocumentNode<\n {\n ggnomadTripPlans: Array<{\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 createdAt: string;\n }>;\n },\n { first: number; skip: number }\n >,\n { variables: { first: 50, skip: 0 } }\n );\n\n const [createTripPlan, { loading: creating }] = useMutation(\n CREATE_GGNOMAD_TRIP_PLAN_MUTATION as TypedDocumentNode<\n {\n createGgnomadTripPlan: {\n id: string;\n name: string;\n startDate?: string;\n endDate?: string;\n };\n },\n {\n input: {\n name: string;\n description?: string;\n startDate?: string;\n endDate?: string;\n travelers?: number;\n };\n }\n >\n );\n\n const trips = data?.ggnomadTripPlans ?? [];\n\n const handleCreateTrip = async () => {\n if (!formState.name.trim()) {\n notify.warning(\n t('ggnomad.trips.toast.validationTitle', 'Required field missing'),\n t('ggnomad.trips.toast.nameRequired', 'Please enter a trip name')\n );\n return;\n }\n\n try {\n const result = await createTripPlan({\n variables: {\n input: {\n name: formState.name.trim(),\n startDate: formState.startDate\n ? new Date(formState.startDate).toISOString()\n : undefined,\n endDate: formState.endDate ? new Date(formState.endDate).toISOString() : undefined,\n travelers: 1,\n },\n },\n });\n\n if (result.error) {\n notify.error(\n t('ggnomad.trips.toast.createErrorTitle', 'Could not create trip'),\n result.error.message\n );\n return;\n }\n\n const created = result.data?.createGgnomadTripPlan;\n if (!created) return;\n\n notify.success(t('ggnomad.trips.toast.createSuccessTitle', 'Trip created'), created.name);\n\n setShowNewTripDialog(false);\n setFormState(defaultFormState);\n await refetch();\n navigate(`trips/${created.id}`);\n } catch (err) {\n notify.error(\n t('ggnomad.trips.toast.createErrorTitle', 'Could not create trip'),\n err instanceof Error ? err.message : String(err)\n );\n }\n };\n\n const formatDate = (dateStr?: string) => {\n if (!dateStr) return '';\n const date = new Date(dateStr);\n return date.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n });\n };\n\n return (\n <PageShell\n title={t('ggnomad.trips.title', 'Trips')}\n titleAccent={t('ggnomad.trips.title.accent', 'Trips')}\n subtitle={t(\n 'ggnomad.trips.subtitle',\n 'Plan complete itineraries with real trip planning API mutations'\n )}\n actions={\n <CTAOverflowMenu\n primary={{\n label: t('ggnomad.trips.actions.newTrip', 'New trip'),\n onSelect: () => setShowNewTripDialog(true),\n disabled: creating,\n icon: <Plus />,\n }}\n actions={[]}\n />\n }\n >\n <PagePurpose icon={<Map className=\"size-4\" />}>\n {t(\n 'ggnomad.trips.purpose',\n 'Organize every aspect of your journey — build itineraries day by day, add activities and accommodations, manage your trip status, and book everything at once. All your trips in one place.'\n )}\n </PagePurpose>\n\n <NextSteps\n storageKey=\"ggnomad-trips\"\n steps={[\n {\n id: 'add-stays',\n label: t('ggnomad.trips.next.stays', 'Add places to stay'),\n description: t(\n 'ggnomad.trips.next.staysDesc',\n 'Browse accommodations and add them to your itinerary.'\n ),\n icon: <Calendar className=\"size-4\" />,\n onClick: () => navigate('../hospitality'),\n },\n {\n id: 'build-activities',\n label: t('ggnomad.trips.next.activities', 'Plan activities'),\n description: t(\n 'ggnomad.trips.next.activitiesDesc',\n 'Mix in tours, events, and activities by day.'\n ),\n icon: <Map className=\"size-4\" />,\n onClick: () => navigate('../tourism'),\n },\n ]}\n />\n\n {trips.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('ggnomad.trips.emptyTitle', 'No trips yet')}\n description={t(\n 'ggnomad.trips.emptyDescription',\n 'Create your first trip to start building an itinerary.'\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.trips.yourTrips', 'Your trips')}\n </h2>\n <div className=\"grid gap-3 sm:grid-cols-2 lg:grid-cols-3\">\n {trips.map((trip) => (\n <EntityCard\n key={trip.id}\n to={`trips/${trip.id}`}\n title={trip.name}\n meta={`${trip.travelers} ${\n trip.travelers === 1\n ? t('ggnomad.trips.card.traveler', 'traveler')\n : t('ggnomad.trips.card.travelers', 'travelers')\n } · ${trip.itemCount} ${t('ggnomad.trips.card.items', 'items')}`}\n price={trip.total > 0 ? `USD ${trip.total.toFixed(2)}` : ''}\n badge={<StatusBadge status={trip.status} live={trip.status !== 'CANCELLED'} />}\n footer={\n trip.startDate && trip.endDate\n ? `${formatDate(trip.startDate)} – ${formatDate(trip.endDate)}`\n : t('ggnomad.trips.card.noDates', 'No dates set')\n }\n />\n ))}\n </div>\n </GlassCard>\n )}\n\n <AlertDialog open={showNewTripDialog} onOpenChange={setShowNewTripDialog}>\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>\n {t('ggnomad.trips.newDialog.title', 'Create a new trip')}\n </AlertDialogTitle>\n <AlertDialogDescription>\n {t(\n 'ggnomad.trips.newDialog.description',\n 'Name your trip and set the dates to get started building your itinerary.'\n )}\n </AlertDialogDescription>\n </AlertDialogHeader>\n\n <div className=\"space-y-4\">\n <div>\n <label htmlFor=\"trip-name\" className=\"block text-sm font-medium text-text-primary\">\n {t('ggnomad.trips.newDialog.tripName', 'Trip name')}\n </label>\n <input\n id=\"trip-name\"\n type=\"text\"\n className=\"mt-1 w-full rounded-md border border-border-seam bg-bg-canvas px-3 py-2 text-sm text-text-primary placeholder-text-secondary focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary\"\n placeholder={t(\n 'ggnomad.trips.newDialog.tripNamePlaceholder',\n 'e.g. Summer Europe Adventure'\n )}\n value={formState.name}\n onChange={(e) => setFormState((prev) => ({ ...prev, name: e.target.value }))}\n />\n </div>\n\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label\n htmlFor=\"trip-start-date\"\n className=\"block text-sm font-medium text-text-primary\"\n >\n {t('ggnomad.trips.newDialog.startDate', 'Start date')}\n </label>\n <input\n id=\"trip-start-date\"\n type=\"date\"\n className=\"mt-1 w-full rounded-md border border-border-seam bg-bg-canvas px-3 py-2 text-sm text-text-primary focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary\"\n value={formState.startDate}\n onChange={(e) => setFormState((prev) => ({ ...prev, startDate: e.target.value }))}\n />\n </div>\n <div>\n <label\n htmlFor=\"trip-end-date\"\n className=\"block text-sm font-medium text-text-primary\"\n >\n {t('ggnomad.trips.newDialog.endDate', 'End date')}\n </label>\n <input\n id=\"trip-end-date\"\n type=\"date\"\n className=\"mt-1 w-full rounded-md border border-border-seam bg-bg-canvas px-3 py-2 text-sm text-text-primary focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary\"\n value={formState.endDate}\n onChange={(e) => setFormState((prev) => ({ ...prev, endDate: e.target.value }))}\n />\n </div>\n </div>\n </div>\n\n <AlertDialogFooter>\n <AlertDialogCancel disabled={creating}>\n {t('ggnomad.trips.newDialog.cancel', 'Cancel')}\n </AlertDialogCancel>\n <AlertDialogAction\n disabled={creating || !formState.name.trim()}\n onClick={(event) => {\n event.preventDefault();\n void handleCreateTrip();\n }}\n >\n {creating\n ? t('ggnomad.trips.newDialog.creating', 'Creating…')\n : t('ggnomad.trips.newDialog.create', 'Create trip')}\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </PageShell>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { FC, PropsWithChildren } from 'react';
|
|
2
|
+
import { GGNomadRootProps } from '../types';
|
|
3
|
+
|
|
4
|
+
export declare const useGGNomad: () => GGNomadRootProps;
|
|
5
|
+
export declare const GGNomadProvider: FC<PropsWithChildren<GGNomadRootProps>>;
|
|
6
|
+
//# sourceMappingURL=GGNomadProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GGNomadProvider.d.ts","sourceRoot":"","sources":["../../../src/ggnomad/providers/GGNomadProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAQnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAMjD,eAAO,MAAM,UAAU,QAAO,gBAM7B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAsEnE,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface NavItem {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
path: string;
|
|
7
|
+
icon?: React.ReactNode;
|
|
8
|
+
order?: number;
|
|
9
|
+
group?: string;
|
|
10
|
+
children?: NavItem[];
|
|
11
|
+
}
|
|
12
|
+
export interface FooterItem {
|
|
13
|
+
id: string;
|
|
14
|
+
label: string;
|
|
15
|
+
type: 'status' | 'action';
|
|
16
|
+
order?: number;
|
|
17
|
+
section: 'left' | 'center' | 'right';
|
|
18
|
+
}
|
|
19
|
+
export interface GGNomadRootProps {
|
|
20
|
+
basePath?: string;
|
|
21
|
+
workspaceId?: string;
|
|
22
|
+
tenantId?: string;
|
|
23
|
+
apiGatewayUrl?: string;
|
|
24
|
+
authToken?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Workspace-scoped JWT token. The gateway requires both authToken
|
|
27
|
+
* (Authorization) and workspaceToken (X-Workspace-Authorization)
|
|
28
|
+
* for workspace-scoped operations.
|
|
29
|
+
*/
|
|
30
|
+
workspaceToken?: string;
|
|
31
|
+
navigate?: (path: string) => void;
|
|
32
|
+
currentUser?: {
|
|
33
|
+
id: string;
|
|
34
|
+
email: string;
|
|
35
|
+
firstName?: string;
|
|
36
|
+
lastName?: string;
|
|
37
|
+
avatar?: string;
|
|
38
|
+
username?: string;
|
|
39
|
+
name?: string;
|
|
40
|
+
role?: string;
|
|
41
|
+
} | null;
|
|
42
|
+
registerNavItems?: (items: NavItem | NavItem[]) => () => void;
|
|
43
|
+
registerFooterItems?: (items: FooterItem | FooterItem[]) => () => void;
|
|
44
|
+
onAuthError?: () => void;
|
|
45
|
+
}
|
|
46
|
+
export interface OverviewMetric {
|
|
47
|
+
label: string;
|
|
48
|
+
value: string;
|
|
49
|
+
trend: string;
|
|
50
|
+
}
|
|
51
|
+
export interface WorkItem {
|
|
52
|
+
id: string;
|
|
53
|
+
title: string;
|
|
54
|
+
status: 'active' | 'planned' | 'at_risk' | 'completed';
|
|
55
|
+
owner: string;
|
|
56
|
+
updatedAt: string;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ggnomad/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,CAAC,EAAE;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,IAAI,CAAC;IACT,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,EAAE,KAAK,MAAM,IAAI,CAAC;IAC9D,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,EAAE,KAAK,MAAM,IAAI,CAAC;IACvE,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;IACvD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cn.d.ts","sourceRoot":"","sources":["../../../src/ggnomad/utils/cn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAC;AAG7C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../../src/ggnomad/utils/navigation.ts"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAIvE"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { toast } from 'sonner';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Module-wide toast API. sonner is a global singleton; the matching <Toaster>
|
|
5
|
+
* is owned by the HOST — the production app shell mounts a single one via
|
|
6
|
+
* AppShellProvider, and the standalone dev harness mounts its own (see
|
|
7
|
+
* GGNomadRoot's `renderToaster`). Every page/component must emit feedback
|
|
8
|
+
* through these helpers instead of hand-rolling fixed-position toast markup.
|
|
9
|
+
*
|
|
10
|
+
* Durations follow the notification spec: success/info auto-dismiss, errors
|
|
11
|
+
* stay until the user dismisses them (sonner renders a close button and
|
|
12
|
+
* announces via aria-live).
|
|
13
|
+
*/
|
|
14
|
+
export declare const notify: {
|
|
15
|
+
success(message: string, description?: string): void;
|
|
16
|
+
info(message: string, description?: string): void;
|
|
17
|
+
warning(message: string, description?: string): void;
|
|
18
|
+
error(message: string, description?: string): void;
|
|
19
|
+
dismiss(id?: string | number): void;
|
|
20
|
+
};
|
|
21
|
+
export { toast };
|
|
22
|
+
//# sourceMappingURL=notify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../../src/ggnomad/utils/notify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAE/B;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM;qBACA,MAAM,gBAAgB,MAAM,GAAG,IAAI;kBAGtC,MAAM,gBAAgB,MAAM,GAAG,IAAI;qBAGhC,MAAM,gBAAgB,MAAM,GAAG,IAAI;mBAGrC,MAAM,gBAAgB,MAAM,GAAG,IAAI;iBAGrC,MAAM,GAAG,MAAM,GAAG,IAAI;CAGpC,CAAC;AAEF,OAAO,EAAE,KAAK,EAAE,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,4BAA4B,EAAE,MAAM,4CAA4C,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useGGNomad as e } from "./ggnomad/providers/GGNomadProvider.js";
|
|
2
2
|
import { GGNomadRoot as t } from "./ggnomad/GGNomadRoot.js";
|
|
3
3
|
import "./ggnomad/index.js";
|
|
4
|
-
|
|
4
|
+
import { useSandboxAssistantTransport as n } from "./services/createSandboxAssistantTransport.js";
|
|
5
|
+
export { t as GGNomadRoot, e as useGGNomad, n as useSandboxAssistantTransport };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GGNomad adapter for the shared fe-libs AssistantWidget.
|
|
3
|
+
*
|
|
4
|
+
* The floating widget (fe-libs, Layer 1) is backend-agnostic — it calls an
|
|
5
|
+
* injected `AssistantTransport`. This hook builds a transport that reuses the
|
|
6
|
+
* sandbox `api-calls` agent: it provisions/reuses a sandbox, opens a session,
|
|
7
|
+
* dispatches the prompt async, then polls for the streamed answer. The agent
|
|
8
|
+
* introspects the GraphQL schema and performs API calls on the user's behalf
|
|
9
|
+
* using their workspace token, contextual to the current screen (via
|
|
10
|
+
* `gatherPageContext`).
|
|
11
|
+
*
|
|
12
|
+
* This file is intentionally self-contained so the MFE can ship its transport
|
|
13
|
+
* without depending on generated GraphQL operation files. All GraphQL
|
|
14
|
+
* documents are declared inline with `gql` and executed through the workspace
|
|
15
|
+
* Apollo client returned by `useGatewayClient('workspace')`.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Locally-defined mirror of the fe-libs `AssistantTransport` contract.
|
|
19
|
+
*
|
|
20
|
+
* We intentionally do NOT import the type from `@burdenoff/fe-libs` here:
|
|
21
|
+
* microfe's tsconfig maps `@burdenoff/fe-libs/*` to fe-libs *source*, so
|
|
22
|
+
* vite-plugin-dts would rewrite a cross-package type used in this hook's
|
|
23
|
+
* public signature to a broken source-relative path in the emitted `.d.ts`.
|
|
24
|
+
* Structural typing makes this shape assignable to fe-libs' `AssistantTransport`
|
|
25
|
+
* at the call site (ggnomad-app's AppShell), which is where compatibility
|
|
26
|
+
* is enforced — drift there fails the app type-check.
|
|
27
|
+
*/
|
|
28
|
+
export interface AssistantSendArgs {
|
|
29
|
+
prompt: string;
|
|
30
|
+
onProgress: (partialText: string) => void;
|
|
31
|
+
signal: AbortSignal;
|
|
32
|
+
}
|
|
33
|
+
export interface AssistantTransport {
|
|
34
|
+
sendPrompt: (args: AssistantSendArgs) => Promise<{
|
|
35
|
+
text: string;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Returns a memoized `AssistantTransport` wired to the GGNomad sandbox
|
|
40
|
+
* `api-calls` agent. The sandbox + session are cached in refs so follow-up
|
|
41
|
+
* turns reuse the warm environment for the lifetime of the host shell.
|
|
42
|
+
*/
|
|
43
|
+
export declare function useSandboxAssistantTransport(): AssistantTransport;
|
|
44
|
+
//# sourceMappingURL=createSandboxAssistantTransport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createSandboxAssistantTransport.d.ts","sourceRoot":"","sources":["../../src/services/createSandboxAssistantTransport.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAQH;;;;;;;;;;GAUG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpE;AAqjBD;;;;GAIG;AACH,wBAAgB,4BAA4B,IAAI,kBAAkB,CA6GjE"}
|