@burdenoff/microfe-ggnomad 2026.608.1 → 2026.626.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/ggnomad/components/DetailRow.js +18 -0
- package/dist/ggnomad/components/DetailRow.js.map +1 -0
- package/dist/ggnomad/components/EntityCard.js +50 -0
- package/dist/ggnomad/components/EntityCard.js.map +1 -0
- package/dist/ggnomad/components/SectionCard.js +21 -0
- package/dist/ggnomad/components/SectionCard.js.map +1 -0
- package/dist/ggnomad/components/StatCard.js +27 -0
- package/dist/ggnomad/components/StatCard.js.map +1 -0
- package/dist/ggnomad/components/StatusBadge.js +65 -0
- package/dist/ggnomad/components/StatusBadge.js.map +1 -0
- package/dist/ggnomad/components/index.js +5 -0
- package/dist/ggnomad/pages/ActivityDetailsPage.js +84 -37
- package/dist/ggnomad/pages/ActivityDetailsPage.js.map +1 -1
- package/dist/ggnomad/pages/AnalyticsPage.js +64 -55
- package/dist/ggnomad/pages/AnalyticsPage.js.map +1 -1
- package/dist/ggnomad/pages/BookingsPage.js +108 -60
- package/dist/ggnomad/pages/BookingsPage.js.map +1 -1
- package/dist/ggnomad/pages/DashboardPage.js +135 -110
- package/dist/ggnomad/pages/DashboardPage.js.map +1 -1
- package/dist/ggnomad/pages/EntertainmentPage.js +40 -33
- package/dist/ggnomad/pages/EntertainmentPage.js.map +1 -1
- package/dist/ggnomad/pages/EventDetailsPage.js +86 -39
- package/dist/ggnomad/pages/EventDetailsPage.js.map +1 -1
- package/dist/ggnomad/pages/FavoritesPage.js +44 -27
- package/dist/ggnomad/pages/FavoritesPage.js.map +1 -1
- package/dist/ggnomad/pages/HospitalityPage.js +45 -42
- package/dist/ggnomad/pages/HospitalityPage.js.map +1 -1
- package/dist/ggnomad/pages/PageShell.js +33 -11
- package/dist/ggnomad/pages/PageShell.js.map +1 -1
- package/dist/ggnomad/pages/PropertyDetailsPage.js +95 -45
- package/dist/ggnomad/pages/PropertyDetailsPage.js.map +1 -1
- package/dist/ggnomad/pages/ProviderPage.js +65 -29
- package/dist/ggnomad/pages/ProviderPage.js.map +1 -1
- package/dist/ggnomad/pages/SearchPage.js +57 -48
- package/dist/ggnomad/pages/SearchPage.js.map +1 -1
- package/dist/ggnomad/pages/TourDetailsPage.js +86 -39
- package/dist/ggnomad/pages/TourDetailsPage.js.map +1 -1
- package/dist/ggnomad/pages/TourismPage.js +64 -63
- package/dist/ggnomad/pages/TourismPage.js.map +1 -1
- package/dist/ggnomad/pages/TravelPage.js +43 -27
- package/dist/ggnomad/pages/TravelPage.js.map +1 -1
- package/dist/ggnomad/utils/cn.js +10 -0
- package/dist/ggnomad/utils/cn.js.map +1 -0
- package/package.json +2 -2
|
@@ -1,71 +1,119 @@
|
|
|
1
1
|
import { CANCEL_GGNOMAD_BOOKING_MUTATION as e, CREATE_GGNOMAD_BOOKING_MUTATION as t, GGNOMAD_BOOKINGS_QUERY as n } from "../graphql.js";
|
|
2
2
|
import { PageShell as r } from "./PageShell.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
3
|
+
import { StatusBadge as i } from "../components/StatusBadge.js";
|
|
4
|
+
import { EntityCard as a } from "../components/EntityCard.js";
|
|
5
|
+
import "../components/index.js";
|
|
6
|
+
import { CalendarCheck as o, Compass as s, Hotel as c, Plus as l, Ticket as u, XCircle as d } from "lucide-react";
|
|
7
|
+
import { useI18n as f } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
8
|
+
import { useNavigate as p } from "react-router-dom";
|
|
9
|
+
import { useMutation as m, useQuery as h } from "@apollo/client/react";
|
|
10
|
+
import { CTAOverflowMenu as g, GlassCard as _, IllustratedEmptyState as v, NextSteps as y, PagePurpose as b } from "@burdenoff/fe-libs/ui";
|
|
11
|
+
import { jsx as x, jsxs as S } from "react/jsx-runtime";
|
|
6
12
|
//#region src/ggnomad/pages/BookingsPage.tsx
|
|
7
|
-
function
|
|
8
|
-
let { t:
|
|
13
|
+
function C() {
|
|
14
|
+
let { t: C } = f(), w = p(), { data: T, refetch: E } = h(n, { variables: {
|
|
9
15
|
first: 20,
|
|
10
16
|
skip: 0
|
|
11
|
-
} }), [
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
17
|
+
} }), [D, { loading: O }] = m(t, { onCompleted: () => void E() }), [k] = m(e, { onCompleted: () => void E() }), A = T?.ggnomadBookings ?? [], j = () => {
|
|
18
|
+
D({ variables: { input: {
|
|
19
|
+
bookingType: "PROPERTY",
|
|
20
|
+
itemId: "demo-property",
|
|
21
|
+
itemName: "Demo Property",
|
|
22
|
+
guestName: "Demo Guest",
|
|
23
|
+
guestEmail: "demo@burdenoff.com",
|
|
24
|
+
guestPhone: "+910000000000",
|
|
25
|
+
guests: 2,
|
|
26
|
+
totalPrice: 299,
|
|
27
|
+
currency: "USD",
|
|
28
|
+
paymentMethod: "card"
|
|
29
|
+
} } });
|
|
30
|
+
}, M = (e) => {
|
|
31
|
+
window.confirm(C("ggnomad.bookings.actions.cancelConfirm", "Cancel this booking? This cannot be undone.")) && k({ variables: {
|
|
32
|
+
id: e,
|
|
33
|
+
reason: C("ggnomad.bookings.actions.cancelReason", "Cancelled via UI")
|
|
34
|
+
} });
|
|
35
|
+
};
|
|
36
|
+
return /* @__PURE__ */ S(r, {
|
|
37
|
+
title: C("ggnomad.bookings.title", "Bookings"),
|
|
38
|
+
titleAccent: C("ggnomad.bookings.title.accent", "Bookings"),
|
|
39
|
+
subtitle: C("ggnomad.bookings.subtitle", "End-to-end booking operations with real API mutations"),
|
|
40
|
+
actions: /* @__PURE__ */ x(g, {
|
|
41
|
+
primary: {
|
|
42
|
+
label: C("ggnomad.bookings.actions.createDemoBooking", "Create demo booking"),
|
|
43
|
+
onSelect: j,
|
|
44
|
+
disabled: O,
|
|
45
|
+
icon: /* @__PURE__ */ x(l, {})
|
|
46
|
+
},
|
|
47
|
+
actions: []
|
|
48
|
+
}),
|
|
49
|
+
children: [
|
|
50
|
+
/* @__PURE__ */ x(b, {
|
|
51
|
+
icon: /* @__PURE__ */ x(o, { className: "size-4" }),
|
|
52
|
+
children: C("ggnomad.bookings.purpose", "Your single place to manage every reservation across travel, stays, tours and events. Track each booking’s status and reference code in real time, and cancel a reservation when plans change — all backed by live API mutations.")
|
|
53
|
+
}),
|
|
54
|
+
/* @__PURE__ */ x(y, {
|
|
55
|
+
storageKey: "ggnomad-bookings",
|
|
56
|
+
steps: [
|
|
57
|
+
{
|
|
58
|
+
id: "book-stay",
|
|
59
|
+
label: C("ggnomad.bookings.next.stay", "Book a place to stay"),
|
|
60
|
+
description: C("ggnomad.bookings.next.stayDesc", "Browse hospitality listings and reserve a property."),
|
|
61
|
+
icon: /* @__PURE__ */ x(c, { className: "size-4" }),
|
|
62
|
+
onClick: () => w("../hospitality")
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
id: "book-tour",
|
|
66
|
+
label: C("ggnomad.bookings.next.tour", "Add a tour or activity"),
|
|
67
|
+
description: C("ggnomad.bookings.next.tourDesc", "Pick a curated experience from Tourism."),
|
|
68
|
+
icon: /* @__PURE__ */ x(s, { className: "size-4" }),
|
|
69
|
+
onClick: () => w("../tourism")
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: "book-event",
|
|
73
|
+
label: C("ggnomad.bookings.next.event", "Grab event tickets"),
|
|
74
|
+
description: C("ggnomad.bookings.next.eventDesc", "Find live events to round out the itinerary."),
|
|
75
|
+
icon: /* @__PURE__ */ x(u, { className: "size-4" }),
|
|
76
|
+
onClick: () => w("../entertainment")
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}),
|
|
80
|
+
A.length === 0 ? /* @__PURE__ */ x(v, {
|
|
81
|
+
illustration: "empty-data",
|
|
82
|
+
title: C("ggnomad.bookings.emptyTitle", "No bookings yet"),
|
|
83
|
+
description: C("ggnomad.bookings.emptyDescription", "Create your first booking to see it tracked here in real time.")
|
|
84
|
+
}) : /* @__PURE__ */ S(_, {
|
|
85
|
+
treatment: "glass",
|
|
86
|
+
glow: !0,
|
|
87
|
+
className: "border-border-seam p-5",
|
|
88
|
+
children: [/* @__PURE__ */ x("h2", {
|
|
89
|
+
className: "mb-4 text-lg font-medium tracking-tight text-text-primary",
|
|
90
|
+
children: C("ggnomad.bookings.activeBookings", "Your bookings")
|
|
91
|
+
}), /* @__PURE__ */ x("div", {
|
|
92
|
+
className: "grid gap-3 sm:grid-cols-2",
|
|
93
|
+
children: A.map((e) => /* @__PURE__ */ x(a, {
|
|
94
|
+
title: e.referenceCode,
|
|
95
|
+
meta: e.itemName,
|
|
96
|
+
price: `${e.currency} ${Number(e.totalPrice).toFixed(2)}`,
|
|
97
|
+
badge: /* @__PURE__ */ x(i, {
|
|
98
|
+
status: e.status,
|
|
99
|
+
live: e.status !== "CANCELLED"
|
|
100
|
+
}),
|
|
101
|
+
footer: e.status === "CANCELLED" ? null : /* @__PURE__ */ x(g, {
|
|
102
|
+
align: "end",
|
|
103
|
+
actions: [{
|
|
104
|
+
label: C("ggnomad.bookings.actions.cancel", "Cancel booking"),
|
|
105
|
+
onSelect: () => M(e.id),
|
|
106
|
+
intent: "destructive",
|
|
107
|
+
icon: /* @__PURE__ */ x(d, {})
|
|
108
|
+
}]
|
|
109
|
+
})
|
|
110
|
+
}, e.id))
|
|
63
111
|
})]
|
|
64
|
-
}
|
|
65
|
-
|
|
112
|
+
})
|
|
113
|
+
]
|
|
66
114
|
});
|
|
67
115
|
}
|
|
68
116
|
//#endregion
|
|
69
|
-
export {
|
|
117
|
+
export { C as BookingsPage };
|
|
70
118
|
|
|
71
119
|
//# sourceMappingURL=BookingsPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BookingsPage.js","names":[],"sources":["../../../src/ggnomad/pages/BookingsPage.tsx"],"sourcesContent":["import { useMutation, useQuery } from '@apollo/client/react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nimport {\n CANCEL_GGNOMAD_BOOKING_MUTATION,\n CREATE_GGNOMAD_BOOKING_MUTATION,\n GGNOMAD_BOOKINGS_QUERY,\n} from '../graphql';\nimport { PageShell } from './PageShell';\n\nexport function BookingsPage() {\n const { t } = useI18n();\n const { data, refetch } = useQuery
|
|
1
|
+
{"version":3,"file":"BookingsPage.js","names":[],"sources":["../../../src/ggnomad/pages/BookingsPage.tsx"],"sourcesContent":["import { useMutation, useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { CalendarCheck, Compass, Hotel, Plus, Ticket, XCircle } from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport {\n CTAOverflowMenu,\n GlassCard,\n IllustratedEmptyState,\n NextSteps,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\n\nimport {\n CANCEL_GGNOMAD_BOOKING_MUTATION,\n CREATE_GGNOMAD_BOOKING_MUTATION,\n GGNOMAD_BOOKINGS_QUERY,\n} from '../graphql';\nimport { PageShell } from './PageShell';\nimport { EntityCard, StatusBadge } from '../components';\n\nexport function BookingsPage() {\n const { t } = useI18n();\n const navigate = useNavigate();\n const { data, refetch } = useQuery(\n GGNOMAD_BOOKINGS_QUERY as TypedDocumentNode<\n {\n ggnomadBookings: Array<{\n id: string;\n referenceCode: string;\n itemName: string;\n status: string;\n totalPrice: number;\n currency: string;\n }>;\n },\n { first: number; skip: number }\n >,\n { variables: { first: 20, skip: 0 } }\n );\n const [createBooking, { loading: creating }] = useMutation(CREATE_GGNOMAD_BOOKING_MUTATION, {\n onCompleted: () => void refetch(),\n });\n const [cancelBooking] = useMutation(CANCEL_GGNOMAD_BOOKING_MUTATION, {\n onCompleted: () => void refetch(),\n });\n\n const bookings = data?.ggnomadBookings ?? [];\n\n const handleCreateDemoBooking = () => {\n void createBooking({\n variables: {\n input: {\n bookingType: 'PROPERTY',\n itemId: 'demo-property',\n itemName: 'Demo Property',\n guestName: 'Demo Guest',\n guestEmail: 'demo@burdenoff.com',\n guestPhone: '+910000000000',\n guests: 2,\n totalPrice: 299,\n currency: 'USD',\n paymentMethod: 'card',\n },\n },\n });\n };\n\n const handleCancel = (id: string) => {\n if (\n !window.confirm(\n t('ggnomad.bookings.actions.cancelConfirm', 'Cancel this booking? This cannot be undone.')\n )\n ) {\n return;\n }\n void cancelBooking({\n variables: {\n id,\n reason: t('ggnomad.bookings.actions.cancelReason', 'Cancelled via UI'),\n },\n });\n };\n\n return (\n <PageShell\n title={t('ggnomad.bookings.title', 'Bookings')}\n titleAccent={t('ggnomad.bookings.title.accent', 'Bookings')}\n subtitle={t(\n 'ggnomad.bookings.subtitle',\n 'End-to-end booking operations with real API mutations'\n )}\n actions={\n <CTAOverflowMenu\n primary={{\n label: t('ggnomad.bookings.actions.createDemoBooking', 'Create demo booking'),\n onSelect: handleCreateDemoBooking,\n disabled: creating,\n icon: <Plus />,\n }}\n actions={[]}\n />\n }\n >\n <PagePurpose icon={<CalendarCheck className=\"size-4\" />}>\n {t(\n 'ggnomad.bookings.purpose',\n 'Your single place to manage every reservation across travel, stays, tours and events. Track each booking’s status and reference code in real time, and cancel a reservation when plans change — all backed by live API mutations.'\n )}\n </PagePurpose>\n\n <NextSteps\n storageKey=\"ggnomad-bookings\"\n steps={[\n {\n id: 'book-stay',\n label: t('ggnomad.bookings.next.stay', 'Book a place to stay'),\n description: t(\n 'ggnomad.bookings.next.stayDesc',\n 'Browse hospitality listings and reserve a property.'\n ),\n icon: <Hotel className=\"size-4\" />,\n onClick: () => navigate('../hospitality'),\n },\n {\n id: 'book-tour',\n label: t('ggnomad.bookings.next.tour', 'Add a tour or activity'),\n description: t(\n 'ggnomad.bookings.next.tourDesc',\n 'Pick a curated experience from Tourism.'\n ),\n icon: <Compass className=\"size-4\" />,\n onClick: () => navigate('../tourism'),\n },\n {\n id: 'book-event',\n label: t('ggnomad.bookings.next.event', 'Grab event tickets'),\n description: t(\n 'ggnomad.bookings.next.eventDesc',\n 'Find live events to round out the itinerary.'\n ),\n icon: <Ticket className=\"size-4\" />,\n onClick: () => navigate('../entertainment'),\n },\n ]}\n />\n\n {bookings.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('ggnomad.bookings.emptyTitle', 'No bookings yet')}\n description={t(\n 'ggnomad.bookings.emptyDescription',\n 'Create your first booking to see it tracked here in real time.'\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.bookings.activeBookings', 'Your bookings')}\n </h2>\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {bookings.map((booking) => (\n <EntityCard\n key={booking.id}\n title={booking.referenceCode}\n meta={booking.itemName}\n price={`${booking.currency} ${Number(booking.totalPrice).toFixed(2)}`}\n badge={\n <StatusBadge status={booking.status} live={booking.status !== 'CANCELLED'} />\n }\n footer={\n booking.status !== 'CANCELLED' ? (\n <CTAOverflowMenu\n align=\"end\"\n actions={[\n {\n label: t('ggnomad.bookings.actions.cancel', 'Cancel booking'),\n onSelect: () => handleCancel(booking.id),\n intent: 'destructive',\n icon: <XCircle />,\n },\n ]}\n />\n ) : null\n }\n />\n ))}\n </div>\n </GlassCard>\n )}\n </PageShell>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,128 +1,153 @@
|
|
|
1
1
|
import { GGNOMAD_BOOKINGS_QUERY as e, GGNOMAD_EVENTS_QUERY as t, GGNOMAD_OVERVIEW_QUERY as n, GGNOMAD_PROPERTIES_QUERY as r, GGNOMAD_TOURS_QUERY as i } from "../graphql.js";
|
|
2
2
|
import { PageShell as a } from "./PageShell.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { StatCard as o } from "../components/StatCard.js";
|
|
4
|
+
import { StatusBadge as s } from "../components/StatusBadge.js";
|
|
5
|
+
import { SectionCard as c } from "../components/SectionCard.js";
|
|
6
|
+
import "../components/index.js";
|
|
7
|
+
import { Building as l, CalendarCheck as u, Compass as d, DollarSign as f, Hotel as p, Search as m, Users as h } from "lucide-react";
|
|
8
|
+
import { useI18n as g } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
9
|
+
import { useNavigate as _ } from "react-router-dom";
|
|
10
|
+
import { useQuery as v } from "@apollo/client/react";
|
|
11
|
+
import { EmphasisPanel as y, IllustratedEmptyState as b, NextSteps as x, PagePurpose as S } from "@burdenoff/fe-libs/ui";
|
|
12
|
+
import { jsx as C, jsxs as w } from "react/jsx-runtime";
|
|
6
13
|
//#region src/ggnomad/pages/DashboardPage.tsx
|
|
7
|
-
function
|
|
8
|
-
let { t:
|
|
14
|
+
function T() {
|
|
15
|
+
let { t: T } = g(), E = _(), D = v(n), O = v(e, { variables: {
|
|
9
16
|
first: 5,
|
|
10
17
|
skip: 0
|
|
11
|
-
} }),
|
|
18
|
+
} }), k = v(r, { variables: {
|
|
12
19
|
first: 4,
|
|
13
20
|
skip: 0
|
|
14
|
-
} }),
|
|
21
|
+
} }), A = v(i, { variables: {
|
|
15
22
|
first: 4,
|
|
16
23
|
skip: 0
|
|
17
|
-
} }),
|
|
24
|
+
} }), j = v(t, { variables: {
|
|
18
25
|
first: 4,
|
|
19
26
|
skip: 0
|
|
20
|
-
} }),
|
|
21
|
-
return /* @__PURE__ */
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
27
|
+
} }), M = D.data?.ggnomadOverviewStats, N = O.data?.ggnomadBookings ?? [];
|
|
28
|
+
return /* @__PURE__ */ w(a, {
|
|
29
|
+
hero: !0,
|
|
30
|
+
title: T("ggnomad.dashboard.title", "GGNomad Dashboard"),
|
|
31
|
+
titleAccent: T("ggnomad.dashboard.title.accent", "GGNomad"),
|
|
32
|
+
subtitle: T("ggnomad.dashboard.subtitle", "Unified travel, hospitality, tourism and entertainment operations"),
|
|
33
|
+
children: [
|
|
34
|
+
/* @__PURE__ */ C(S, {
|
|
35
|
+
icon: /* @__PURE__ */ C(d, { className: "size-4" }),
|
|
36
|
+
children: T("ggnomad.dashboard.purpose", "Your command centre for the whole GGNomad marketplace — see live revenue, users, listings and bookings across travel, hospitality, tourism and entertainment in one place, and jump straight into the area you want to work on.")
|
|
37
|
+
}),
|
|
38
|
+
/* @__PURE__ */ C(x, {
|
|
39
|
+
storageKey: "ggnomad-dashboard",
|
|
40
|
+
steps: [
|
|
41
|
+
{
|
|
42
|
+
id: "search",
|
|
43
|
+
label: T("ggnomad.dashboard.next.search", "Search the catalogue"),
|
|
44
|
+
description: T("ggnomad.dashboard.next.searchDesc", "Find inventory across every domain at once."),
|
|
45
|
+
icon: /* @__PURE__ */ C(m, { className: "size-4" }),
|
|
46
|
+
onClick: () => E("search")
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: "stays",
|
|
50
|
+
label: T("ggnomad.dashboard.next.stays", "Browse places to stay"),
|
|
51
|
+
description: T("ggnomad.dashboard.next.staysDesc", "Explore hospitality listings and open a property."),
|
|
52
|
+
icon: /* @__PURE__ */ C(p, { className: "size-4" }),
|
|
53
|
+
onClick: () => E("hospitality")
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: "tourism",
|
|
57
|
+
label: T("ggnomad.dashboard.next.tourism", "Discover tours & activities"),
|
|
58
|
+
description: T("ggnomad.dashboard.next.tourismDesc", "Plan what to do at each destination."),
|
|
59
|
+
icon: /* @__PURE__ */ C(d, { className: "size-4" }),
|
|
60
|
+
onClick: () => E("tourism")
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: "bookings",
|
|
64
|
+
label: T("ggnomad.dashboard.next.bookings", "Manage bookings"),
|
|
65
|
+
description: T("ggnomad.dashboard.next.bookingsDesc", "Track and cancel reservations in real time."),
|
|
66
|
+
icon: /* @__PURE__ */ C(u, { className: "size-4" }),
|
|
67
|
+
onClick: () => E("bookings")
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}),
|
|
71
|
+
/* @__PURE__ */ w("section", {
|
|
72
|
+
className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-4",
|
|
73
|
+
children: [
|
|
74
|
+
/* @__PURE__ */ C(o, {
|
|
75
|
+
hero: !0,
|
|
76
|
+
label: T("ggnomad.dashboard.stats.monthlyRevenue", "Monthly Revenue"),
|
|
77
|
+
value: `$${Number(M?.monthlyRevenue ?? 0).toLocaleString()}`,
|
|
78
|
+
icon: /* @__PURE__ */ C(f, {})
|
|
79
|
+
}),
|
|
80
|
+
/* @__PURE__ */ C(o, {
|
|
81
|
+
label: T("ggnomad.dashboard.stats.users", "Users"),
|
|
82
|
+
value: Number(M?.users ?? 0).toLocaleString(),
|
|
83
|
+
icon: /* @__PURE__ */ C(h, {})
|
|
84
|
+
}),
|
|
85
|
+
/* @__PURE__ */ C(o, {
|
|
86
|
+
label: T("ggnomad.dashboard.stats.listings", "Listings"),
|
|
87
|
+
value: Number(M?.listings ?? 0).toLocaleString(),
|
|
88
|
+
icon: /* @__PURE__ */ C(l, {})
|
|
89
|
+
}),
|
|
90
|
+
/* @__PURE__ */ C(o, {
|
|
91
|
+
label: T("ggnomad.dashboard.stats.bookings", "Bookings"),
|
|
92
|
+
value: Number(M?.bookings ?? 0).toLocaleString(),
|
|
93
|
+
icon: /* @__PURE__ */ C(u, {})
|
|
94
|
+
})
|
|
95
|
+
]
|
|
96
|
+
}),
|
|
97
|
+
/* @__PURE__ */ w(y, { children: [/* @__PURE__ */ w("div", {
|
|
98
|
+
className: "grid gap-4 sm:grid-cols-3",
|
|
99
|
+
children: [
|
|
100
|
+
/* @__PURE__ */ w("div", { children: [/* @__PURE__ */ C("p", {
|
|
101
|
+
className: "text-sm text-text-secondary",
|
|
102
|
+
children: T("ggnomad.dashboard.inventory.properties", "Properties")
|
|
103
|
+
}), /* @__PURE__ */ C("p", {
|
|
104
|
+
className: "mt-1 text-2xl font-semibold tabular-nums text-text-primary",
|
|
105
|
+
children: k.data?.ggnomadProperties?.length ?? 0
|
|
106
|
+
})] }),
|
|
107
|
+
/* @__PURE__ */ w("div", { children: [/* @__PURE__ */ C("p", {
|
|
108
|
+
className: "text-sm text-text-secondary",
|
|
109
|
+
children: T("ggnomad.dashboard.inventory.tours", "Tours")
|
|
110
|
+
}), /* @__PURE__ */ C("p", {
|
|
111
|
+
className: "mt-1 text-2xl font-semibold tabular-nums text-text-primary",
|
|
112
|
+
children: A.data?.ggnomadTours?.length ?? 0
|
|
113
|
+
})] }),
|
|
114
|
+
/* @__PURE__ */ w("div", { children: [/* @__PURE__ */ C("p", {
|
|
115
|
+
className: "text-sm text-text-secondary",
|
|
116
|
+
children: T("ggnomad.dashboard.inventory.events", "Events")
|
|
117
|
+
}), /* @__PURE__ */ C("p", {
|
|
118
|
+
className: "mt-1 text-2xl font-semibold tabular-nums text-text-primary",
|
|
119
|
+
children: j.data?.ggnomadEvents?.length ?? 0
|
|
120
|
+
})] })
|
|
121
|
+
]
|
|
122
|
+
}), /* @__PURE__ */ C("p", {
|
|
123
|
+
className: "mt-4 text-sm text-text-secondary",
|
|
124
|
+
children: T("ggnomad.dashboard.inventory.liveDataNotice", "Data is live from `wspace-ggnomad-svc` GraphQL APIs.")
|
|
125
|
+
})] }),
|
|
126
|
+
/* @__PURE__ */ C(c, {
|
|
127
|
+
title: T("ggnomad.dashboard.sections.recentBookings", "Recent bookings"),
|
|
128
|
+
children: N.length === 0 ? /* @__PURE__ */ C(b, {
|
|
129
|
+
illustration: "empty-data",
|
|
130
|
+
title: T("ggnomad.dashboard.recentBookings.emptyTitle", "No recent bookings"),
|
|
131
|
+
description: T("ggnomad.dashboard.recentBookings.emptyDescription", "New bookings across travel, hospitality and tourism will appear here.")
|
|
132
|
+
}) : /* @__PURE__ */ C("ul", {
|
|
76
133
|
className: "space-y-2 text-sm",
|
|
77
|
-
children:
|
|
78
|
-
className: "flex items-center justify-between rounded border p-
|
|
79
|
-
children: [/* @__PURE__ */
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
})]
|
|
134
|
+
children: N.map((e) => /* @__PURE__ */ w("li", {
|
|
135
|
+
className: "flex items-center justify-between gap-3 rounded-lg border border-border-seam bg-bg-surface/40 p-3",
|
|
136
|
+
children: [/* @__PURE__ */ w("span", {
|
|
137
|
+
className: "min-w-0 truncate text-text-primary",
|
|
138
|
+
children: [
|
|
139
|
+
e.referenceCode,
|
|
140
|
+
" — ",
|
|
141
|
+
e.itemName
|
|
142
|
+
]
|
|
143
|
+
}), /* @__PURE__ */ C(s, { status: e.status })]
|
|
87
144
|
}, e.id))
|
|
88
|
-
})
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
children: [/* @__PURE__ */ c("h2", {
|
|
92
|
-
className: "mb-3 text-lg font-medium",
|
|
93
|
-
children: u("ggnomad.dashboard.sections.featuredInventory", "Featured inventory")
|
|
94
|
-
}), /* @__PURE__ */ l("div", {
|
|
95
|
-
className: "grid gap-2 text-sm",
|
|
96
|
-
children: [
|
|
97
|
-
/* @__PURE__ */ l("p", { children: [
|
|
98
|
-
u("ggnomad.dashboard.inventory.properties", "Properties"),
|
|
99
|
-
":",
|
|
100
|
-
" ",
|
|
101
|
-
p.data?.ggnomadProperties?.length ?? 0
|
|
102
|
-
] }),
|
|
103
|
-
/* @__PURE__ */ l("p", { children: [
|
|
104
|
-
u("ggnomad.dashboard.inventory.tours", "Tours"),
|
|
105
|
-
":",
|
|
106
|
-
" ",
|
|
107
|
-
m.data?.ggnomadTours?.length ?? 0
|
|
108
|
-
] }),
|
|
109
|
-
/* @__PURE__ */ l("p", { children: [
|
|
110
|
-
u("ggnomad.dashboard.inventory.events", "Events"),
|
|
111
|
-
":",
|
|
112
|
-
" ",
|
|
113
|
-
h.data?.ggnomadEvents?.length ?? 0
|
|
114
|
-
] }),
|
|
115
|
-
/* @__PURE__ */ c("p", {
|
|
116
|
-
className: "text-muted-foreground",
|
|
117
|
-
children: u("ggnomad.dashboard.inventory.liveDataNotice", "Data is live from `wspace-ggnomad-svc` GraphQL APIs.")
|
|
118
|
-
})
|
|
119
|
-
]
|
|
120
|
-
})]
|
|
121
|
-
})]
|
|
122
|
-
})]
|
|
145
|
+
})
|
|
146
|
+
})
|
|
147
|
+
]
|
|
123
148
|
});
|
|
124
149
|
}
|
|
125
150
|
//#endregion
|
|
126
|
-
export {
|
|
151
|
+
export { T as DashboardPage };
|
|
127
152
|
|
|
128
153
|
//# sourceMappingURL=DashboardPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardPage.js","names":[],"sources":["../../../src/ggnomad/pages/DashboardPage.tsx"],"sourcesContent":["import { useQuery } from '@apollo/client/react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nimport {\n GGNOMAD_OVERVIEW_QUERY,\n GGNOMAD_BOOKINGS_QUERY,\n GGNOMAD_PROPERTIES_QUERY,\n GGNOMAD_TOURS_QUERY,\n GGNOMAD_EVENTS_QUERY,\n} from '../graphql';\nimport { PageShell } from './PageShell';\n\nexport function DashboardPage() {\n const { t } = useI18n();\n const overview = useQuery<{\n ggnomadOverviewStats: {\n users: number;\n listings: number;\n bookings: number;\n monthlyRevenue: number;\n };\n }>(GGNOMAD_OVERVIEW_QUERY);\n const bookings = useQuery<{\n ggnomadBookings: Array<{ id: string; referenceCode: string; itemName: string; status: string }>;\n }>(GGNOMAD_BOOKINGS_QUERY, {\n variables: { first: 5, skip: 0 },\n });\n const properties = useQuery<{ ggnomadProperties: Array<{ id: string }> }>(\n GGNOMAD_PROPERTIES_QUERY,\n { variables: { first: 4, skip: 0 } }\n );\n const tours = useQuery<{ ggnomadTours: Array<{ id: string }> }>(GGNOMAD_TOURS_QUERY, {\n variables: { first: 4, skip: 0 },\n });\n const events = useQuery<{ ggnomadEvents: Array<{ id: string }> }>(GGNOMAD_EVENTS_QUERY, {\n variables: { first: 4, skip: 0 },\n });\n\n const stats = overview.data?.ggnomadOverviewStats;\n\n return (\n <PageShell\n title={t('ggnomad.dashboard.title', 'GGNomad Dashboard')}\n subtitle={t(\n 'ggnomad.dashboard.subtitle',\n 'Unified travel, hospitality, tourism and entertainment operations'\n )}\n >\n <section className=\"grid gap-4 md:grid-cols-4\">\n <div className=\"rounded-lg border p-4\">\n <p className=\"text-sm text-muted-foreground\">\n {t('ggnomad.dashboard.stats.users', 'Users')}\n </p>\n <p className=\"text-2xl font-semibold\">{stats?.users ?? 0}</p>\n </div>\n <div className=\"rounded-lg border p-4\">\n <p className=\"text-sm text-muted-foreground\">\n {t('ggnomad.dashboard.stats.listings', 'Listings')}\n </p>\n <p className=\"text-2xl font-semibold\">{stats?.listings ?? 0}</p>\n </div>\n <div className=\"rounded-lg border p-4\">\n <p className=\"text-sm text-muted-foreground\">\n {t('ggnomad.dashboard.stats.bookings', 'Bookings')}\n </p>\n <p className=\"text-2xl font-semibold\">{stats?.bookings ?? 0}</p>\n </div>\n <div className=\"rounded-lg border p-4\">\n <p className=\"text-sm text-muted-foreground\">\n {t('ggnomad.dashboard.stats.monthlyRevenue', 'Monthly Revenue')}\n </p>\n <p className=\"text-2xl font-semibold\">\n ${Number(stats?.monthlyRevenue ?? 0).toLocaleString()}\n </p>\n </div>\n </section>\n\n <section className=\"grid gap-4 lg:grid-cols-2\">\n <div className=\"rounded-lg border p-4\">\n <h2 className=\"mb-3 text-lg font-medium\">\n {t('ggnomad.dashboard.sections.recentBookings', 'Recent bookings')}\n </h2>\n <ul className=\"space-y-2 text-sm\">\n {(bookings.data?.ggnomadBookings ?? []).map(\n (booking: {\n id: string;\n referenceCode: string;\n itemName: string;\n status: string;\n }) => (\n <li\n key={booking.id}\n className=\"flex items-center justify-between rounded border p-2\"\n >\n <span>\n {booking.referenceCode} - {booking.itemName}\n </span>\n <span className=\"text-muted-foreground\">{booking.status}</span>\n </li>\n )\n )}\n </ul>\n </div>\n <div className=\"rounded-lg border p-4\">\n <h2 className=\"mb-3 text-lg font-medium\">\n {t('ggnomad.dashboard.sections.featuredInventory', 'Featured inventory')}\n </h2>\n <div className=\"grid gap-2 text-sm\">\n <p>\n {t('ggnomad.dashboard.inventory.properties', 'Properties')}:{' '}\n {properties.data?.ggnomadProperties?.length ?? 0}\n </p>\n <p>\n {t('ggnomad.dashboard.inventory.tours', 'Tours')}:{' '}\n {tours.data?.ggnomadTours?.length ?? 0}\n </p>\n <p>\n {t('ggnomad.dashboard.inventory.events', 'Events')}:{' '}\n {events.data?.ggnomadEvents?.length ?? 0}\n </p>\n <p className=\"text-muted-foreground\">\n {t(\n 'ggnomad.dashboard.inventory.liveDataNotice',\n 'Data is live from `wspace-ggnomad-svc` GraphQL APIs.'\n )}\n </p>\n </div>\n </div>\n </section>\n </PageShell>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DashboardPage.js","names":[],"sources":["../../../src/ggnomad/pages/DashboardPage.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 { Building, CalendarCheck, Compass, DollarSign, Hotel, Search, Users } from 'lucide-react';\nimport { useNavigate } from 'react-router-dom';\nimport {\n EmphasisPanel,\n IllustratedEmptyState,\n NextSteps,\n PagePurpose,\n} from '@burdenoff/fe-libs/ui';\n\nimport {\n GGNOMAD_OVERVIEW_QUERY,\n GGNOMAD_BOOKINGS_QUERY,\n GGNOMAD_PROPERTIES_QUERY,\n GGNOMAD_TOURS_QUERY,\n GGNOMAD_EVENTS_QUERY,\n} from '../graphql';\nimport { PageShell } from './PageShell';\nimport { SectionCard, StatCard, StatusBadge } from '../components';\n\nexport function DashboardPage() {\n const { t } = useI18n();\n const navigate = useNavigate();\n const overview = useQuery(\n GGNOMAD_OVERVIEW_QUERY as TypedDocumentNode<\n {\n ggnomadOverviewStats: {\n users: number;\n listings: number;\n bookings: number;\n monthlyRevenue: number;\n };\n },\n Record<string, never>\n >\n );\n const bookings = useQuery(\n GGNOMAD_BOOKINGS_QUERY as TypedDocumentNode<\n {\n ggnomadBookings: Array<{\n id: string;\n referenceCode: string;\n itemName: string;\n status: string;\n }>;\n },\n { first: number; skip: number }\n >,\n {\n variables: { first: 5, skip: 0 },\n }\n );\n const properties = useQuery(\n GGNOMAD_PROPERTIES_QUERY as TypedDocumentNode<\n { ggnomadProperties: Array<{ id: string }> },\n { first: number; skip: number }\n >,\n { variables: { first: 4, skip: 0 } }\n );\n const tours = useQuery(\n GGNOMAD_TOURS_QUERY as TypedDocumentNode<\n { ggnomadTours: Array<{ id: string }> },\n { first: number; skip: number }\n >,\n {\n variables: { first: 4, skip: 0 },\n }\n );\n const events = useQuery(\n GGNOMAD_EVENTS_QUERY as TypedDocumentNode<\n { ggnomadEvents: Array<{ id: string }> },\n { first: number; skip: number }\n >,\n {\n variables: { first: 4, skip: 0 },\n }\n );\n\n const stats = overview.data?.ggnomadOverviewStats;\n const recentBookings = bookings.data?.ggnomadBookings ?? [];\n\n return (\n <PageShell\n hero\n title={t('ggnomad.dashboard.title', 'GGNomad Dashboard')}\n titleAccent={t('ggnomad.dashboard.title.accent', 'GGNomad')}\n subtitle={t(\n 'ggnomad.dashboard.subtitle',\n 'Unified travel, hospitality, tourism and entertainment operations'\n )}\n >\n <PagePurpose icon={<Compass className=\"size-4\" />}>\n {t(\n 'ggnomad.dashboard.purpose',\n 'Your command centre for the whole GGNomad marketplace — see live revenue, users, listings and bookings across travel, hospitality, tourism and entertainment in one place, and jump straight into the area you want to work on.'\n )}\n </PagePurpose>\n\n <NextSteps\n storageKey=\"ggnomad-dashboard\"\n steps={[\n {\n id: 'search',\n label: t('ggnomad.dashboard.next.search', 'Search the catalogue'),\n description: t(\n 'ggnomad.dashboard.next.searchDesc',\n 'Find inventory across every domain at once.'\n ),\n icon: <Search className=\"size-4\" />,\n onClick: () => navigate('search'),\n },\n {\n id: 'stays',\n label: t('ggnomad.dashboard.next.stays', 'Browse places to stay'),\n description: t(\n 'ggnomad.dashboard.next.staysDesc',\n 'Explore hospitality listings and open a property.'\n ),\n icon: <Hotel className=\"size-4\" />,\n onClick: () => navigate('hospitality'),\n },\n {\n id: 'tourism',\n label: t('ggnomad.dashboard.next.tourism', 'Discover tours & activities'),\n description: t(\n 'ggnomad.dashboard.next.tourismDesc',\n 'Plan what to do at each destination.'\n ),\n icon: <Compass className=\"size-4\" />,\n onClick: () => navigate('tourism'),\n },\n {\n id: 'bookings',\n label: t('ggnomad.dashboard.next.bookings', 'Manage bookings'),\n description: t(\n 'ggnomad.dashboard.next.bookingsDesc',\n 'Track and cancel reservations in real time.'\n ),\n icon: <CalendarCheck className=\"size-4\" />,\n onClick: () => navigate('bookings'),\n },\n ]}\n />\n\n <section className=\"grid gap-4 sm:grid-cols-2 xl:grid-cols-4\">\n <StatCard\n hero\n label={t('ggnomad.dashboard.stats.monthlyRevenue', 'Monthly Revenue')}\n value={`$${Number(stats?.monthlyRevenue ?? 0).toLocaleString()}`}\n icon={<DollarSign />}\n />\n <StatCard\n label={t('ggnomad.dashboard.stats.users', 'Users')}\n value={Number(stats?.users ?? 0).toLocaleString()}\n icon={<Users />}\n />\n <StatCard\n label={t('ggnomad.dashboard.stats.listings', 'Listings')}\n value={Number(stats?.listings ?? 0).toLocaleString()}\n icon={<Building />}\n />\n <StatCard\n label={t('ggnomad.dashboard.stats.bookings', 'Bookings')}\n value={Number(stats?.bookings ?? 0).toLocaleString()}\n icon={<CalendarCheck />}\n />\n </section>\n\n <EmphasisPanel>\n <div className=\"grid gap-4 sm:grid-cols-3\">\n <div>\n <p className=\"text-sm text-text-secondary\">\n {t('ggnomad.dashboard.inventory.properties', 'Properties')}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums text-text-primary\">\n {properties.data?.ggnomadProperties?.length ?? 0}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {t('ggnomad.dashboard.inventory.tours', 'Tours')}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums text-text-primary\">\n {tours.data?.ggnomadTours?.length ?? 0}\n </p>\n </div>\n <div>\n <p className=\"text-sm text-text-secondary\">\n {t('ggnomad.dashboard.inventory.events', 'Events')}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums text-text-primary\">\n {events.data?.ggnomadEvents?.length ?? 0}\n </p>\n </div>\n </div>\n <p className=\"mt-4 text-sm text-text-secondary\">\n {t(\n 'ggnomad.dashboard.inventory.liveDataNotice',\n 'Data is live from `wspace-ggnomad-svc` GraphQL APIs.'\n )}\n </p>\n </EmphasisPanel>\n\n <SectionCard title={t('ggnomad.dashboard.sections.recentBookings', 'Recent bookings')}>\n {recentBookings.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={t('ggnomad.dashboard.recentBookings.emptyTitle', 'No recent bookings')}\n description={t(\n 'ggnomad.dashboard.recentBookings.emptyDescription',\n 'New bookings across travel, hospitality and tourism will appear here.'\n )}\n />\n ) : (\n <ul className=\"space-y-2 text-sm\">\n {recentBookings.map((booking) => (\n <li\n key={booking.id}\n className=\"flex items-center justify-between gap-3 rounded-lg border border-border-seam bg-bg-surface/40 p-3\"\n >\n <span className=\"min-w-0 truncate text-text-primary\">\n {booking.referenceCode} — {booking.itemName}\n </span>\n <StatusBadge status={booking.status} />\n </li>\n ))}\n </ul>\n )}\n </SectionCard>\n </PageShell>\n );\n}\n"],"mappings":"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"}
|