@burdenoff/microfe-ggnomad 2026.801.1 → 2026.827.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ggnomad/components/AvailabilityPanel.d.ts +15 -0
- package/dist/ggnomad/components/AvailabilityPanel.d.ts.map +1 -0
- package/dist/ggnomad/components/AvailabilityPanel.js +91 -0
- package/dist/ggnomad/components/AvailabilityPanel.js.map +1 -0
- package/dist/ggnomad/components/BookingPanel.d.ts +1 -3
- package/dist/ggnomad/components/BookingPanel.d.ts.map +1 -1
- package/dist/ggnomad/components/BookingPanel.js +91 -82
- package/dist/ggnomad/components/BookingPanel.js.map +1 -1
- package/dist/ggnomad/components/EcoAccessPanel.d.ts +17 -0
- package/dist/ggnomad/components/EcoAccessPanel.d.ts.map +1 -0
- package/dist/ggnomad/components/EcoAccessPanel.js +68 -0
- package/dist/ggnomad/components/EcoAccessPanel.js.map +1 -0
- package/dist/ggnomad/components/FactGrid.d.ts +18 -0
- package/dist/ggnomad/components/FactGrid.d.ts.map +1 -0
- package/dist/ggnomad/components/FactGrid.js +29 -0
- package/dist/ggnomad/components/FactGrid.js.map +1 -0
- package/dist/ggnomad/components/GroupTripPanel.d.ts +22 -0
- package/dist/ggnomad/components/GroupTripPanel.d.ts.map +1 -0
- package/dist/ggnomad/components/GroupTripPanel.js +350 -0
- package/dist/ggnomad/components/GroupTripPanel.js.map +1 -0
- package/dist/ggnomad/components/ListingFilters.d.ts +29 -0
- package/dist/ggnomad/components/ListingFilters.d.ts.map +1 -0
- package/dist/ggnomad/components/ListingFilters.js +164 -0
- package/dist/ggnomad/components/ListingFilters.js.map +1 -0
- package/dist/ggnomad/components/PhotoGallery.d.ts +15 -0
- package/dist/ggnomad/components/PhotoGallery.d.ts.map +1 -0
- package/dist/ggnomad/components/PhotoGallery.js +54 -0
- package/dist/ggnomad/components/PhotoGallery.js.map +1 -0
- package/dist/ggnomad/components/ProviderCard.d.ts +19 -0
- package/dist/ggnomad/components/ProviderCard.d.ts.map +1 -0
- package/dist/ggnomad/components/ProviderCard.js +66 -0
- package/dist/ggnomad/components/ProviderCard.js.map +1 -0
- package/dist/ggnomad/components/RatingSummary.d.ts +14 -0
- package/dist/ggnomad/components/RatingSummary.d.ts.map +1 -0
- package/dist/ggnomad/components/RatingSummary.js +32 -0
- package/dist/ggnomad/components/RatingSummary.js.map +1 -0
- package/dist/ggnomad/components/TagChips.d.ts +16 -0
- package/dist/ggnomad/components/TagChips.d.ts.map +1 -0
- package/dist/ggnomad/components/TagChips.js +20 -0
- package/dist/ggnomad/components/TagChips.js.map +1 -0
- package/dist/ggnomad/components/index.d.ts +13 -0
- package/dist/ggnomad/components/index.d.ts.map +1 -1
- package/dist/ggnomad/components/index.js +9 -0
- package/dist/ggnomad/graphql.d.ts +10 -0
- package/dist/ggnomad/graphql.d.ts.map +1 -1
- package/dist/ggnomad/graphql.js +308 -20
- package/dist/ggnomad/graphql.js.map +1 -1
- package/dist/ggnomad/pages/ActivityDetailsPage.d.ts.map +1 -1
- package/dist/ggnomad/pages/ActivityDetailsPage.js +174 -86
- package/dist/ggnomad/pages/ActivityDetailsPage.js.map +1 -1
- package/dist/ggnomad/pages/AnalyticsPage.d.ts.map +1 -1
- package/dist/ggnomad/pages/AnalyticsPage.js +109 -77
- package/dist/ggnomad/pages/AnalyticsPage.js.map +1 -1
- package/dist/ggnomad/pages/BookingsPage.d.ts.map +1 -1
- package/dist/ggnomad/pages/BookingsPage.js +188 -137
- package/dist/ggnomad/pages/BookingsPage.js.map +1 -1
- package/dist/ggnomad/pages/DashboardPage.d.ts.map +1 -1
- package/dist/ggnomad/pages/DashboardPage.js +245 -128
- package/dist/ggnomad/pages/DashboardPage.js.map +1 -1
- package/dist/ggnomad/pages/EntertainmentPage.d.ts.map +1 -1
- package/dist/ggnomad/pages/EntertainmentPage.js +115 -53
- package/dist/ggnomad/pages/EntertainmentPage.js.map +1 -1
- package/dist/ggnomad/pages/EventDetailsPage.d.ts.map +1 -1
- package/dist/ggnomad/pages/EventDetailsPage.js +170 -87
- package/dist/ggnomad/pages/EventDetailsPage.js.map +1 -1
- package/dist/ggnomad/pages/FavoritesPage.d.ts.map +1 -1
- package/dist/ggnomad/pages/FavoritesPage.js +201 -84
- package/dist/ggnomad/pages/FavoritesPage.js.map +1 -1
- package/dist/ggnomad/pages/HospitalityPage.d.ts.map +1 -1
- package/dist/ggnomad/pages/HospitalityPage.js +99 -56
- package/dist/ggnomad/pages/HospitalityPage.js.map +1 -1
- package/dist/ggnomad/pages/PropertyDetailsPage.d.ts.map +1 -1
- package/dist/ggnomad/pages/PropertyDetailsPage.js +177 -93
- package/dist/ggnomad/pages/PropertyDetailsPage.js.map +1 -1
- package/dist/ggnomad/pages/ProviderPage.d.ts.map +1 -1
- package/dist/ggnomad/pages/ProviderPage.js +112 -63
- package/dist/ggnomad/pages/ProviderPage.js.map +1 -1
- package/dist/ggnomad/pages/SearchPage.d.ts.map +1 -1
- package/dist/ggnomad/pages/SearchPage.js +236 -65
- package/dist/ggnomad/pages/SearchPage.js.map +1 -1
- package/dist/ggnomad/pages/TourDetailsPage.d.ts.map +1 -1
- package/dist/ggnomad/pages/TourDetailsPage.js +171 -86
- package/dist/ggnomad/pages/TourDetailsPage.js.map +1 -1
- package/dist/ggnomad/pages/TourismPage.d.ts.map +1 -1
- package/dist/ggnomad/pages/TourismPage.js +108 -54
- package/dist/ggnomad/pages/TourismPage.js.map +1 -1
- package/dist/ggnomad/pages/TravelPage.d.ts.map +1 -1
- package/dist/ggnomad/pages/TravelPage.js +406 -43
- package/dist/ggnomad/pages/TravelPage.js.map +1 -1
- package/dist/ggnomad/pages/TripPlanDetailPage.d.ts.map +1 -1
- package/dist/ggnomad/pages/TripPlanDetailPage.js +93 -70
- package/dist/ggnomad/pages/TripPlanDetailPage.js.map +1 -1
- package/dist/ggnomad/utils/format.d.ts +47 -0
- package/dist/ggnomad/utils/format.d.ts.map +1 -0
- package/dist/ggnomad/utils/format.js +125 -0
- package/dist/ggnomad/utils/format.js.map +1 -0
- package/dist/stories/BookingPanel.stories.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1,201 +1,318 @@
|
|
|
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
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { formatDate as a } from "../utils/format.js";
|
|
3
|
+
import { PageShell as o } from "./PageShell.js";
|
|
4
|
+
import { StatCard as s } from "../components/StatCard.js";
|
|
5
|
+
import { StatusBadge as c } from "../components/StatusBadge.js";
|
|
6
|
+
import { SectionCard as l } from "../components/SectionCard.js";
|
|
6
7
|
import "../components/index.js";
|
|
7
|
-
import { useMemo as
|
|
8
|
-
import { Building as
|
|
9
|
-
import { useI18n as
|
|
10
|
-
import { useNavigate as
|
|
11
|
-
import { useQuery as
|
|
12
|
-
import {
|
|
13
|
-
import { jsx as
|
|
8
|
+
import { useMemo as u } from "react";
|
|
9
|
+
import { ArrowRight as d, Building as f, CalendarCheck as p, CalendarRange as m, Compass as h, DollarSign as g, Hotel as _, Search as v, Users as y } from "lucide-react";
|
|
10
|
+
import { useI18n as b } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
11
|
+
import { Link as x, useNavigate as S } from "react-router";
|
|
12
|
+
import { useQuery as C } from "@apollo/client/react";
|
|
13
|
+
import { IllustratedEmptyState as w, NextSteps as T, PagePurpose as E } from "@burdenoff/fe-libs/ui";
|
|
14
|
+
import { jsx as D, jsxs as O } from "react/jsx-runtime";
|
|
14
15
|
//#region src/ggnomad/pages/DashboardPage.tsx
|
|
15
|
-
var
|
|
16
|
+
var k = [
|
|
16
17
|
"var(--color-chart-1)",
|
|
17
18
|
"var(--color-chart-2)",
|
|
18
19
|
"var(--color-chart-3)",
|
|
19
20
|
"var(--color-chart-4)",
|
|
20
21
|
"var(--color-chart-5)"
|
|
21
|
-
],
|
|
22
|
-
function
|
|
23
|
-
let { t:
|
|
22
|
+
], A = (e) => e.replace(/[_-]+/g, " ").trim().replace(/\b\w/g, (e) => e.toUpperCase()) || e;
|
|
23
|
+
function j() {
|
|
24
|
+
let { t: j } = b(), M = S(), N = C(n), P = C(e, { variables: {
|
|
24
25
|
limit: 5,
|
|
25
26
|
offset: 0
|
|
26
|
-
} }),
|
|
27
|
+
} }), F = C(r, { variables: {
|
|
27
28
|
limit: 4,
|
|
28
29
|
offset: 0
|
|
29
|
-
} }),
|
|
30
|
+
} }), I = C(i, { variables: {
|
|
30
31
|
limit: 4,
|
|
31
32
|
offset: 0
|
|
32
|
-
} }),
|
|
33
|
+
} }), L = C(t, { variables: {
|
|
33
34
|
limit: 4,
|
|
34
35
|
offset: 0
|
|
35
|
-
} }),
|
|
36
|
-
let e =
|
|
36
|
+
} }), R = N.data?.ggnomadOverviewStats, z = N.data?.ggnomadAnalytics, B = P.data?.ggnomadBookings ?? [], V = u(() => {
|
|
37
|
+
let e = z?.revenueByCategory ?? {};
|
|
37
38
|
return Object.entries(e).map(([e, t]) => ({
|
|
38
|
-
label:
|
|
39
|
+
label: A(e),
|
|
39
40
|
value: Number(t)
|
|
40
41
|
})).filter((e) => Number.isFinite(e.value) && e.value > 0).sort((e, t) => t.value - e.value);
|
|
41
|
-
}, [
|
|
42
|
-
return /* @__PURE__ */
|
|
42
|
+
}, [z?.revenueByCategory]), H = V.length > 0 ? V[0].value : 0;
|
|
43
|
+
return /* @__PURE__ */ O(o, {
|
|
43
44
|
hero: !0,
|
|
44
|
-
title:
|
|
45
|
-
titleAccent:
|
|
46
|
-
subtitle:
|
|
45
|
+
title: j("ggnomad.dashboard.title", "GGNomad Dashboard"),
|
|
46
|
+
titleAccent: j("ggnomad.dashboard.title.accent", "GGNomad"),
|
|
47
|
+
subtitle: j("ggnomad.dashboard.subtitle", "Unified travel, hospitality, tourism and entertainment operations"),
|
|
47
48
|
children: [
|
|
48
|
-
/* @__PURE__ */
|
|
49
|
-
icon: /* @__PURE__ */
|
|
50
|
-
children:
|
|
49
|
+
/* @__PURE__ */ D(E, {
|
|
50
|
+
icon: /* @__PURE__ */ D(h, { className: "size-4" }),
|
|
51
|
+
children: j("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.")
|
|
51
52
|
}),
|
|
52
|
-
/* @__PURE__ */
|
|
53
|
+
/* @__PURE__ */ D(T, {
|
|
53
54
|
storageKey: "ggnomad-dashboard",
|
|
54
55
|
steps: [
|
|
55
56
|
{
|
|
56
57
|
id: "search",
|
|
57
|
-
label:
|
|
58
|
-
description:
|
|
59
|
-
icon: /* @__PURE__ */
|
|
60
|
-
onClick: () =>
|
|
58
|
+
label: j("ggnomad.dashboard.next.search", "Search the catalogue"),
|
|
59
|
+
description: j("ggnomad.dashboard.next.searchDesc", "Find inventory across every domain at once."),
|
|
60
|
+
icon: /* @__PURE__ */ D(v, { className: "size-4" }),
|
|
61
|
+
onClick: () => M("search")
|
|
61
62
|
},
|
|
62
63
|
{
|
|
63
64
|
id: "stays",
|
|
64
|
-
label:
|
|
65
|
-
description:
|
|
66
|
-
icon: /* @__PURE__ */
|
|
67
|
-
onClick: () =>
|
|
65
|
+
label: j("ggnomad.dashboard.next.stays", "Browse places to stay"),
|
|
66
|
+
description: j("ggnomad.dashboard.next.staysDesc", "Explore hospitality listings and open a property."),
|
|
67
|
+
icon: /* @__PURE__ */ D(_, { className: "size-4" }),
|
|
68
|
+
onClick: () => M("hospitality")
|
|
68
69
|
},
|
|
69
70
|
{
|
|
70
71
|
id: "tourism",
|
|
71
|
-
label:
|
|
72
|
-
description:
|
|
73
|
-
icon: /* @__PURE__ */
|
|
74
|
-
onClick: () =>
|
|
72
|
+
label: j("ggnomad.dashboard.next.tourism", "Discover tours & activities"),
|
|
73
|
+
description: j("ggnomad.dashboard.next.tourismDesc", "Plan what to do at each destination."),
|
|
74
|
+
icon: /* @__PURE__ */ D(h, { className: "size-4" }),
|
|
75
|
+
onClick: () => M("tourism")
|
|
75
76
|
},
|
|
76
77
|
{
|
|
77
78
|
id: "bookings",
|
|
78
|
-
label:
|
|
79
|
-
description:
|
|
80
|
-
icon: /* @__PURE__ */
|
|
81
|
-
onClick: () =>
|
|
79
|
+
label: j("ggnomad.dashboard.next.bookings", "Manage bookings"),
|
|
80
|
+
description: j("ggnomad.dashboard.next.bookingsDesc", "Track and cancel reservations in real time."),
|
|
81
|
+
icon: /* @__PURE__ */ D(p, { className: "size-4" }),
|
|
82
|
+
onClick: () => M("bookings")
|
|
82
83
|
}
|
|
83
84
|
]
|
|
84
85
|
}),
|
|
85
|
-
/* @__PURE__ */
|
|
86
|
+
/* @__PURE__ */ O("section", {
|
|
86
87
|
className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-4",
|
|
87
88
|
children: [
|
|
88
|
-
/* @__PURE__ */
|
|
89
|
+
/* @__PURE__ */ D(s, {
|
|
89
90
|
hero: !0,
|
|
90
|
-
label:
|
|
91
|
-
value: `$${Number(
|
|
92
|
-
icon: /* @__PURE__ */
|
|
91
|
+
label: j("ggnomad.dashboard.stats.monthlyRevenue", "Monthly Revenue"),
|
|
92
|
+
value: `$${Number(R?.monthlyRevenue ?? 0).toLocaleString()}`,
|
|
93
|
+
icon: /* @__PURE__ */ D(g, {})
|
|
93
94
|
}),
|
|
94
|
-
/* @__PURE__ */
|
|
95
|
-
label:
|
|
96
|
-
value: Number(
|
|
97
|
-
icon: /* @__PURE__ */
|
|
95
|
+
/* @__PURE__ */ D(s, {
|
|
96
|
+
label: j("ggnomad.dashboard.stats.users", "Users"),
|
|
97
|
+
value: Number(R?.users ?? 0).toLocaleString(),
|
|
98
|
+
icon: /* @__PURE__ */ D(y, {})
|
|
98
99
|
}),
|
|
99
|
-
/* @__PURE__ */
|
|
100
|
-
label:
|
|
101
|
-
value: Number(
|
|
102
|
-
icon: /* @__PURE__ */
|
|
100
|
+
/* @__PURE__ */ D(s, {
|
|
101
|
+
label: j("ggnomad.dashboard.stats.listings", "Listings"),
|
|
102
|
+
value: Number(R?.listings ?? 0).toLocaleString(),
|
|
103
|
+
icon: /* @__PURE__ */ D(f, {})
|
|
103
104
|
}),
|
|
104
|
-
/* @__PURE__ */
|
|
105
|
-
label:
|
|
106
|
-
value: Number(
|
|
107
|
-
icon: /* @__PURE__ */
|
|
105
|
+
/* @__PURE__ */ D(s, {
|
|
106
|
+
label: j("ggnomad.dashboard.stats.bookings", "Bookings"),
|
|
107
|
+
value: Number(R?.bookings ?? 0).toLocaleString(),
|
|
108
|
+
icon: /* @__PURE__ */ D(p, {})
|
|
108
109
|
})
|
|
109
110
|
]
|
|
110
111
|
}),
|
|
111
|
-
/* @__PURE__ */
|
|
112
|
-
|
|
113
|
-
children:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
children: O("
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
112
|
+
/* @__PURE__ */ D(l, {
|
|
113
|
+
title: j("ggnomad.dashboard.inventory.title", "Latest inventory"),
|
|
114
|
+
children: /* @__PURE__ */ O("div", {
|
|
115
|
+
className: "grid gap-6 sm:grid-cols-3",
|
|
116
|
+
children: [
|
|
117
|
+
/* @__PURE__ */ O("div", { children: [/* @__PURE__ */ O("div", {
|
|
118
|
+
className: "mb-2 flex items-center justify-between gap-2",
|
|
119
|
+
children: [/* @__PURE__ */ D("p", {
|
|
120
|
+
className: "text-sm font-medium text-text-primary",
|
|
121
|
+
children: j("ggnomad.dashboard.inventory.properties", "Newest properties")
|
|
122
|
+
}), /* @__PURE__ */ O(x, {
|
|
123
|
+
to: "hospitality",
|
|
124
|
+
className: "inline-flex items-center gap-1 text-xs font-medium text-action-primary-bg hover:underline",
|
|
125
|
+
children: [j("ggnomad.dashboard.viewAll", "View all"), /* @__PURE__ */ D(d, {
|
|
126
|
+
className: "size-3",
|
|
127
|
+
"aria-hidden": "true"
|
|
128
|
+
})]
|
|
129
|
+
})]
|
|
130
|
+
}), /* @__PURE__ */ O("ul", {
|
|
131
|
+
className: "space-y-1 text-sm",
|
|
132
|
+
children: [(F.data?.ggnomadProperties ?? []).map((e) => /* @__PURE__ */ D("li", { children: /* @__PURE__ */ O(x, {
|
|
133
|
+
to: `hospitality/${e.id}`,
|
|
134
|
+
className: "flex items-baseline justify-between gap-2 rounded px-1 py-0.5 hover:bg-bg-sunken",
|
|
135
|
+
children: [/* @__PURE__ */ D("span", {
|
|
136
|
+
className: "truncate text-text-primary",
|
|
137
|
+
children: e.name
|
|
138
|
+
}), /* @__PURE__ */ O("span", {
|
|
139
|
+
className: "flex-shrink-0 tabular-nums text-text-secondary",
|
|
140
|
+
children: [
|
|
141
|
+
e.currency,
|
|
142
|
+
" ",
|
|
143
|
+
Number(e.pricePerNight).toFixed(0)
|
|
144
|
+
]
|
|
145
|
+
})]
|
|
146
|
+
}) }, e.id)), (F.data?.ggnomadProperties?.length ?? 0) === 0 ? /* @__PURE__ */ D("li", {
|
|
147
|
+
className: "text-text-secondary",
|
|
148
|
+
children: j("ggnomad.dashboard.inventory.none", "Nothing published yet")
|
|
149
|
+
}) : null]
|
|
150
|
+
})] }),
|
|
151
|
+
/* @__PURE__ */ O("div", { children: [/* @__PURE__ */ O("div", {
|
|
152
|
+
className: "mb-2 flex items-center justify-between gap-2",
|
|
153
|
+
children: [/* @__PURE__ */ D("p", {
|
|
154
|
+
className: "text-sm font-medium text-text-primary",
|
|
155
|
+
children: j("ggnomad.dashboard.inventory.tours", "Newest tours")
|
|
156
|
+
}), /* @__PURE__ */ O(x, {
|
|
157
|
+
to: "tourism",
|
|
158
|
+
className: "inline-flex items-center gap-1 text-xs font-medium text-action-primary-bg hover:underline",
|
|
159
|
+
children: [j("ggnomad.dashboard.viewAll", "View all"), /* @__PURE__ */ D(d, {
|
|
160
|
+
className: "size-3",
|
|
161
|
+
"aria-hidden": "true"
|
|
162
|
+
})]
|
|
163
|
+
})]
|
|
164
|
+
}), /* @__PURE__ */ O("ul", {
|
|
165
|
+
className: "space-y-1 text-sm",
|
|
166
|
+
children: [(I.data?.ggnomadTours ?? []).map((e) => /* @__PURE__ */ D("li", { children: /* @__PURE__ */ O(x, {
|
|
167
|
+
to: `tourism/tours/${e.id}`,
|
|
168
|
+
className: "flex items-baseline justify-between gap-2 rounded px-1 py-0.5 hover:bg-bg-sunken",
|
|
169
|
+
children: [/* @__PURE__ */ D("span", {
|
|
170
|
+
className: "truncate text-text-primary",
|
|
171
|
+
children: e.name
|
|
172
|
+
}), /* @__PURE__ */ O("span", {
|
|
173
|
+
className: "flex-shrink-0 tabular-nums text-text-secondary",
|
|
174
|
+
children: [
|
|
175
|
+
e.currency,
|
|
176
|
+
" ",
|
|
177
|
+
Number(e.price).toFixed(0)
|
|
178
|
+
]
|
|
179
|
+
})]
|
|
180
|
+
}) }, e.id)), (I.data?.ggnomadTours?.length ?? 0) === 0 ? /* @__PURE__ */ D("li", {
|
|
181
|
+
className: "text-text-secondary",
|
|
182
|
+
children: j("ggnomad.dashboard.inventory.none", "Nothing published yet")
|
|
183
|
+
}) : null]
|
|
184
|
+
})] }),
|
|
185
|
+
/* @__PURE__ */ O("div", { children: [/* @__PURE__ */ O("div", {
|
|
186
|
+
className: "mb-2 flex items-center justify-between gap-2",
|
|
187
|
+
children: [/* @__PURE__ */ D("p", {
|
|
188
|
+
className: "text-sm font-medium text-text-primary",
|
|
189
|
+
children: j("ggnomad.dashboard.inventory.events", "Upcoming events")
|
|
190
|
+
}), /* @__PURE__ */ O(x, {
|
|
191
|
+
to: "entertainment",
|
|
192
|
+
className: "inline-flex items-center gap-1 text-xs font-medium text-action-primary-bg hover:underline",
|
|
193
|
+
children: [j("ggnomad.dashboard.viewAll", "View all"), /* @__PURE__ */ D(d, {
|
|
194
|
+
className: "size-3",
|
|
195
|
+
"aria-hidden": "true"
|
|
196
|
+
})]
|
|
197
|
+
})]
|
|
198
|
+
}), /* @__PURE__ */ O("ul", {
|
|
199
|
+
className: "space-y-1 text-sm",
|
|
200
|
+
children: [(L.data?.ggnomadEvents ?? []).map((e) => /* @__PURE__ */ D("li", { children: /* @__PURE__ */ O(x, {
|
|
201
|
+
to: `entertainment/${e.id}`,
|
|
202
|
+
className: "flex items-baseline justify-between gap-2 rounded px-1 py-0.5 hover:bg-bg-sunken",
|
|
203
|
+
children: [/* @__PURE__ */ D("span", {
|
|
204
|
+
className: "truncate text-text-primary",
|
|
205
|
+
children: e.name
|
|
206
|
+
}), /* @__PURE__ */ D("span", {
|
|
207
|
+
className: "flex-shrink-0 tabular-nums text-text-secondary",
|
|
208
|
+
children: a(e.startsAt) ?? ""
|
|
209
|
+
})]
|
|
210
|
+
}) }, e.id)), (L.data?.ggnomadEvents?.length ?? 0) === 0 ? /* @__PURE__ */ D("li", {
|
|
211
|
+
className: "text-text-secondary",
|
|
212
|
+
children: j("ggnomad.dashboard.inventory.none", "Nothing published yet")
|
|
213
|
+
}) : null]
|
|
214
|
+
})] })
|
|
215
|
+
]
|
|
216
|
+
})
|
|
217
|
+
}),
|
|
218
|
+
/* @__PURE__ */ D(l, {
|
|
219
|
+
title: j("ggnomad.dashboard.sections.recentBookings", "Recent bookings"),
|
|
220
|
+
action: /* @__PURE__ */ O(x, {
|
|
221
|
+
to: "bookings",
|
|
222
|
+
className: "inline-flex items-center gap-1 text-sm font-medium text-action-primary-bg hover:underline",
|
|
223
|
+
children: [j("ggnomad.dashboard.viewAllBookings", "View all bookings"), /* @__PURE__ */ D(d, {
|
|
224
|
+
className: "size-3.5",
|
|
225
|
+
"aria-hidden": "true"
|
|
226
|
+
})]
|
|
227
|
+
}),
|
|
228
|
+
children: B.length === 0 ? /* @__PURE__ */ D(w, {
|
|
143
229
|
illustration: "empty-data",
|
|
144
|
-
title:
|
|
145
|
-
description:
|
|
146
|
-
}) : /* @__PURE__ */
|
|
230
|
+
title: j("ggnomad.dashboard.recentBookings.emptyTitle", "No recent bookings"),
|
|
231
|
+
description: j("ggnomad.dashboard.recentBookings.emptyDescription", "New bookings across travel, hospitality and tourism will appear here.")
|
|
232
|
+
}) : /* @__PURE__ */ D("ul", {
|
|
147
233
|
className: "space-y-2 text-sm",
|
|
148
|
-
children:
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
className: "
|
|
152
|
-
children: [
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
234
|
+
children: B.map((e) => {
|
|
235
|
+
let t = a(e.checkIn), n = a(e.checkOut), r = a(e.eventDate), i = t ? n ? `${t} – ${n}` : t : r;
|
|
236
|
+
return /* @__PURE__ */ O("li", {
|
|
237
|
+
className: "flex flex-wrap items-center justify-between gap-3 rounded-lg border border-border-seam bg-bg-surface/40 p-3",
|
|
238
|
+
children: [/* @__PURE__ */ O("div", {
|
|
239
|
+
className: "min-w-0",
|
|
240
|
+
children: [/* @__PURE__ */ O("p", {
|
|
241
|
+
className: "truncate text-text-primary",
|
|
242
|
+
children: [
|
|
243
|
+
e.referenceCode,
|
|
244
|
+
" — ",
|
|
245
|
+
e.itemName
|
|
246
|
+
]
|
|
247
|
+
}), /* @__PURE__ */ O("p", {
|
|
248
|
+
className: "mt-0.5 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-text-secondary",
|
|
249
|
+
children: [i ? /* @__PURE__ */ O("span", {
|
|
250
|
+
className: "inline-flex items-center gap-1",
|
|
251
|
+
children: [/* @__PURE__ */ D(m, {
|
|
252
|
+
className: "size-3",
|
|
253
|
+
"aria-hidden": "true"
|
|
254
|
+
}), i]
|
|
255
|
+
}) : null, /* @__PURE__ */ O("span", {
|
|
256
|
+
className: "inline-flex items-center gap-1 tabular-nums",
|
|
257
|
+
children: [/* @__PURE__ */ D(y, {
|
|
258
|
+
className: "size-3",
|
|
259
|
+
"aria-hidden": "true"
|
|
260
|
+
}), e.guests]
|
|
261
|
+
})]
|
|
262
|
+
})]
|
|
263
|
+
}), /* @__PURE__ */ O("div", {
|
|
264
|
+
className: "flex flex-shrink-0 items-center gap-3",
|
|
265
|
+
children: [/* @__PURE__ */ O("span", {
|
|
266
|
+
className: "tabular-nums text-text-primary",
|
|
267
|
+
children: [
|
|
268
|
+
e.currency,
|
|
269
|
+
" ",
|
|
270
|
+
Number(e.totalPrice).toFixed(2)
|
|
271
|
+
]
|
|
272
|
+
}), /* @__PURE__ */ D(c, { status: e.status })]
|
|
273
|
+
})]
|
|
274
|
+
}, e.id);
|
|
275
|
+
})
|
|
159
276
|
})
|
|
160
277
|
}),
|
|
161
|
-
/* @__PURE__ */
|
|
162
|
-
title:
|
|
163
|
-
children:
|
|
278
|
+
/* @__PURE__ */ D(l, {
|
|
279
|
+
title: j("ggnomad.dashboard.sections.revenueByCategory", "Revenue by category"),
|
|
280
|
+
children: V.length === 0 ? /* @__PURE__ */ O("div", {
|
|
164
281
|
className: "flex flex-col items-center gap-2 py-8 text-center",
|
|
165
282
|
children: [
|
|
166
|
-
/* @__PURE__ */
|
|
283
|
+
/* @__PURE__ */ D("span", {
|
|
167
284
|
className: "flex size-10 items-center justify-center rounded-full bg-[var(--color-accent-soft)] text-text-secondary",
|
|
168
|
-
children: /* @__PURE__ */
|
|
285
|
+
children: /* @__PURE__ */ D(g, { className: "size-5" })
|
|
169
286
|
}),
|
|
170
|
-
/* @__PURE__ */
|
|
287
|
+
/* @__PURE__ */ D("p", {
|
|
171
288
|
className: "text-sm font-medium text-text-primary",
|
|
172
|
-
children:
|
|
289
|
+
children: j("ggnomad.dashboard.empty.title", "Revenue data coming soon")
|
|
173
290
|
}),
|
|
174
|
-
/* @__PURE__ */
|
|
291
|
+
/* @__PURE__ */ D("p", {
|
|
175
292
|
className: "max-w-sm text-sm text-text-secondary",
|
|
176
|
-
children:
|
|
293
|
+
children: j("ggnomad.dashboard.empty.description", "Revenue by category appears here as bookings come in across stays, tours and events.")
|
|
177
294
|
})
|
|
178
295
|
]
|
|
179
|
-
}) : /* @__PURE__ */
|
|
296
|
+
}) : /* @__PURE__ */ D("ul", {
|
|
180
297
|
className: "flex flex-col gap-4",
|
|
181
|
-
children:
|
|
182
|
-
let n =
|
|
183
|
-
return /* @__PURE__ */
|
|
298
|
+
children: V.map((e, t) => {
|
|
299
|
+
let n = H > 0 ? Math.max(e.value / H * 100, 2) : 0;
|
|
300
|
+
return /* @__PURE__ */ O("li", { children: [/* @__PURE__ */ O("div", {
|
|
184
301
|
className: "flex items-baseline justify-between gap-3",
|
|
185
|
-
children: [/* @__PURE__ */
|
|
302
|
+
children: [/* @__PURE__ */ D("span", {
|
|
186
303
|
className: "truncate text-sm font-medium text-text-primary",
|
|
187
304
|
children: e.label
|
|
188
|
-
}), /* @__PURE__ */
|
|
305
|
+
}), /* @__PURE__ */ O("span", {
|
|
189
306
|
className: "flex-shrink-0 text-sm tabular-nums text-text-secondary",
|
|
190
307
|
children: ["$", e.value.toLocaleString()]
|
|
191
308
|
})]
|
|
192
|
-
}), /* @__PURE__ */
|
|
309
|
+
}), /* @__PURE__ */ D("div", {
|
|
193
310
|
className: "mt-1.5 h-2.5 w-full overflow-hidden rounded-full bg-bg-sunken",
|
|
194
|
-
children: /* @__PURE__ */
|
|
311
|
+
children: /* @__PURE__ */ D("div", {
|
|
195
312
|
className: "h-full rounded-full transition-[width] duration-500 ease-out",
|
|
196
313
|
style: {
|
|
197
314
|
width: `${n}%`,
|
|
198
|
-
backgroundColor:
|
|
315
|
+
backgroundColor: k[t % k.length]
|
|
199
316
|
}
|
|
200
317
|
})
|
|
201
318
|
})] }, e.label);
|
|
@@ -206,6 +323,6 @@ function O() {
|
|
|
206
323
|
});
|
|
207
324
|
}
|
|
208
325
|
//#endregion
|
|
209
|
-
export {
|
|
326
|
+
export { j as DashboardPage };
|
|
210
327
|
|
|
211
328
|
//# sourceMappingURL=DashboardPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardPage.js","names":[],"sources":["../../../src/ggnomad/pages/DashboardPage.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { Building, CalendarCheck, Compass, DollarSign, Hotel, Search, Users } from 'lucide-react';\nimport { useNavigate } from 'react-router';\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\nconst CHART_COLORS = [\n 'var(--color-chart-1)',\n 'var(--color-chart-2)',\n 'var(--color-chart-3)',\n 'var(--color-chart-4)',\n 'var(--color-chart-5)',\n];\n\nconst humanizeCategory = (key: string): string =>\n key\n .replace(/[_-]+/g, ' ')\n .trim()\n .replace(/\\b\\w/g, (char) => char.toUpperCase()) || key;\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 ggnomadAnalytics: {\n totalRevenue: number;\n totalBookings: number;\n totalUsers: number;\n conversionRate: number;\n revenueByCategory: Record<string, unknown>;\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 { limit: number; offset: number }\n >,\n {\n variables: { limit: 5, offset: 0 },\n }\n );\n const properties = useQuery(\n GGNOMAD_PROPERTIES_QUERY as TypedDocumentNode<\n { ggnomadProperties: Array<{ id: string }> },\n { limit: number; offset: number }\n >,\n { variables: { limit: 4, offset: 0 } }\n );\n const tours = useQuery(\n GGNOMAD_TOURS_QUERY as TypedDocumentNode<\n { ggnomadTours: Array<{ id: string }> },\n { limit: number; offset: number }\n >,\n {\n variables: { limit: 4, offset: 0 },\n }\n );\n const events = useQuery(\n GGNOMAD_EVENTS_QUERY as TypedDocumentNode<\n { ggnomadEvents: Array<{ id: string }> },\n { limit: number; offset: number }\n >,\n {\n variables: { limit: 4, offset: 0 },\n }\n );\n\n const stats = overview.data?.ggnomadOverviewStats;\n const analytics = overview.data?.ggnomadAnalytics;\n const recentBookings = bookings.data?.ggnomadBookings ?? [];\n\n const categories = useMemo(() => {\n const raw = analytics?.revenueByCategory ?? {};\n return Object.entries(raw)\n .map(([key, value]) => ({ label: humanizeCategory(key), value: Number(value) }))\n .filter((entry) => Number.isFinite(entry.value) && entry.value > 0)\n .sort((a, b) => b.value - a.value);\n }, [analytics?.revenueByCategory]);\n\n const maxCategory = categories.length > 0 ? categories[0].value : 0;\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('ggnomad.dashboard.inventory.liveDataNotice', 'Data is live from the GraphQL API.')}\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\n <SectionCard title={t('ggnomad.dashboard.sections.revenueByCategory', 'Revenue by category')}>\n {categories.length === 0 ? (\n <div className=\"flex flex-col items-center gap-2 py-8 text-center\">\n <span className=\"flex size-10 items-center justify-center rounded-full bg-[var(--color-accent-soft)] text-text-secondary\">\n <DollarSign className=\"size-5\" />\n </span>\n <p className=\"text-sm font-medium text-text-primary\">\n {t('ggnomad.dashboard.empty.title', 'Revenue data coming soon')}\n </p>\n <p className=\"max-w-sm text-sm text-text-secondary\">\n {t(\n 'ggnomad.dashboard.empty.description',\n 'Revenue by category appears here as bookings come in across stays, tours and events.'\n )}\n </p>\n </div>\n ) : (\n <ul className=\"flex flex-col gap-4\">\n {categories.map((category, index) => {\n const pct = maxCategory > 0 ? Math.max((category.value / maxCategory) * 100, 2) : 0;\n return (\n <li key={category.label}>\n <div className=\"flex items-baseline justify-between gap-3\">\n <span className=\"truncate text-sm font-medium text-text-primary\">\n {category.label}\n </span>\n <span className=\"flex-shrink-0 text-sm tabular-nums text-text-secondary\">\n ${category.value.toLocaleString()}\n </span>\n </div>\n <div className=\"mt-1.5 h-2.5 w-full overflow-hidden rounded-full bg-bg-sunken\">\n <div\n className=\"h-full rounded-full transition-[width] duration-500 ease-out\"\n style={{\n width: `${pct}%`,\n backgroundColor: CHART_COLORS[index % CHART_COLORS.length],\n }}\n />\n </div>\n </li>\n );\n })}\n </ul>\n )}\n </SectionCard>\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 { useMemo } from 'react';\nimport { useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n ArrowRight,\n Building,\n CalendarCheck,\n CalendarRange,\n Compass,\n DollarSign,\n Hotel,\n Search,\n Users,\n} from 'lucide-react';\nimport { Link, useNavigate } from 'react-router';\nimport { IllustratedEmptyState, NextSteps, PagePurpose } 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 { formatDate } from '../utils/format';\nimport { PageShell } from './PageShell';\nimport { SectionCard, StatCard, StatusBadge } from '../components';\n\ntype RecentListing = { id: string; name: string; currency: string; images?: string[] };\n\nconst CHART_COLORS = [\n 'var(--color-chart-1)',\n 'var(--color-chart-2)',\n 'var(--color-chart-3)',\n 'var(--color-chart-4)',\n 'var(--color-chart-5)',\n];\n\nconst humanizeCategory = (key: string): string =>\n key\n .replace(/[_-]+/g, ' ')\n .trim()\n .replace(/\\b\\w/g, (char) => char.toUpperCase()) || key;\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 ggnomadAnalytics: {\n totalRevenue: number;\n totalBookings: number;\n totalUsers: number;\n conversionRate: number;\n revenueByCategory: Record<string, unknown>;\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 bookingType: string;\n status: string;\n guests: number;\n checkIn?: string | null;\n checkOut?: string | null;\n eventDate?: string | null;\n totalPrice: number;\n currency: string;\n }>;\n },\n { limit: number; offset: number }\n >,\n {\n variables: { limit: 5, offset: 0 },\n }\n );\n const properties = useQuery(\n GGNOMAD_PROPERTIES_QUERY as TypedDocumentNode<\n { ggnomadProperties: Array<RecentListing & { pricePerNight: number }> },\n { limit: number; offset: number }\n >,\n { variables: { limit: 4, offset: 0 } }\n );\n const tours = useQuery(\n GGNOMAD_TOURS_QUERY as TypedDocumentNode<\n { ggnomadTours: Array<RecentListing & { price: number }> },\n { limit: number; offset: number }\n >,\n {\n variables: { limit: 4, offset: 0 },\n }\n );\n const events = useQuery(\n GGNOMAD_EVENTS_QUERY as TypedDocumentNode<\n { ggnomadEvents: Array<RecentListing & { price: number; startsAt: string }> },\n { limit: number; offset: number }\n >,\n {\n variables: { limit: 4, offset: 0 },\n }\n );\n\n const stats = overview.data?.ggnomadOverviewStats;\n const analytics = overview.data?.ggnomadAnalytics;\n const recentBookings = bookings.data?.ggnomadBookings ?? [];\n\n const categories = useMemo(() => {\n const raw = analytics?.revenueByCategory ?? {};\n return Object.entries(raw)\n .map(([key, value]) => ({ label: humanizeCategory(key), value: Number(value) }))\n .filter((entry) => Number.isFinite(entry.value) && entry.value > 0)\n .sort((a, b) => b.value - a.value);\n }, [analytics?.revenueByCategory]);\n\n const maxCategory = categories.length > 0 ? categories[0].value : 0;\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 <SectionCard title={t('ggnomad.dashboard.inventory.title', 'Latest inventory')}>\n <div className=\"grid gap-6 sm:grid-cols-3\">\n <div>\n <div className=\"mb-2 flex items-center justify-between gap-2\">\n <p className=\"text-sm font-medium text-text-primary\">\n {t('ggnomad.dashboard.inventory.properties', 'Newest properties')}\n </p>\n <Link\n to=\"hospitality\"\n className=\"inline-flex items-center gap-1 text-xs font-medium text-action-primary-bg hover:underline\"\n >\n {t('ggnomad.dashboard.viewAll', 'View all')}\n <ArrowRight className=\"size-3\" aria-hidden=\"true\" />\n </Link>\n </div>\n <ul className=\"space-y-1 text-sm\">\n {(properties.data?.ggnomadProperties ?? []).map((property) => (\n <li key={property.id}>\n <Link\n to={`hospitality/${property.id}`}\n className=\"flex items-baseline justify-between gap-2 rounded px-1 py-0.5 hover:bg-bg-sunken\"\n >\n <span className=\"truncate text-text-primary\">{property.name}</span>\n <span className=\"flex-shrink-0 tabular-nums text-text-secondary\">\n {property.currency} {Number(property.pricePerNight).toFixed(0)}\n </span>\n </Link>\n </li>\n ))}\n {(properties.data?.ggnomadProperties?.length ?? 0) === 0 ? (\n <li className=\"text-text-secondary\">\n {t('ggnomad.dashboard.inventory.none', 'Nothing published yet')}\n </li>\n ) : null}\n </ul>\n </div>\n <div>\n <div className=\"mb-2 flex items-center justify-between gap-2\">\n <p className=\"text-sm font-medium text-text-primary\">\n {t('ggnomad.dashboard.inventory.tours', 'Newest tours')}\n </p>\n <Link\n to=\"tourism\"\n className=\"inline-flex items-center gap-1 text-xs font-medium text-action-primary-bg hover:underline\"\n >\n {t('ggnomad.dashboard.viewAll', 'View all')}\n <ArrowRight className=\"size-3\" aria-hidden=\"true\" />\n </Link>\n </div>\n <ul className=\"space-y-1 text-sm\">\n {(tours.data?.ggnomadTours ?? []).map((tour) => (\n <li key={tour.id}>\n <Link\n to={`tourism/tours/${tour.id}`}\n className=\"flex items-baseline justify-between gap-2 rounded px-1 py-0.5 hover:bg-bg-sunken\"\n >\n <span className=\"truncate text-text-primary\">{tour.name}</span>\n <span className=\"flex-shrink-0 tabular-nums text-text-secondary\">\n {tour.currency} {Number(tour.price).toFixed(0)}\n </span>\n </Link>\n </li>\n ))}\n {(tours.data?.ggnomadTours?.length ?? 0) === 0 ? (\n <li className=\"text-text-secondary\">\n {t('ggnomad.dashboard.inventory.none', 'Nothing published yet')}\n </li>\n ) : null}\n </ul>\n </div>\n <div>\n <div className=\"mb-2 flex items-center justify-between gap-2\">\n <p className=\"text-sm font-medium text-text-primary\">\n {t('ggnomad.dashboard.inventory.events', 'Upcoming events')}\n </p>\n <Link\n to=\"entertainment\"\n className=\"inline-flex items-center gap-1 text-xs font-medium text-action-primary-bg hover:underline\"\n >\n {t('ggnomad.dashboard.viewAll', 'View all')}\n <ArrowRight className=\"size-3\" aria-hidden=\"true\" />\n </Link>\n </div>\n <ul className=\"space-y-1 text-sm\">\n {(events.data?.ggnomadEvents ?? []).map((event) => (\n <li key={event.id}>\n <Link\n to={`entertainment/${event.id}`}\n className=\"flex items-baseline justify-between gap-2 rounded px-1 py-0.5 hover:bg-bg-sunken\"\n >\n <span className=\"truncate text-text-primary\">{event.name}</span>\n <span className=\"flex-shrink-0 tabular-nums text-text-secondary\">\n {formatDate(event.startsAt) ?? ''}\n </span>\n </Link>\n </li>\n ))}\n {(events.data?.ggnomadEvents?.length ?? 0) === 0 ? (\n <li className=\"text-text-secondary\">\n {t('ggnomad.dashboard.inventory.none', 'Nothing published yet')}\n </li>\n ) : null}\n </ul>\n </div>\n </div>\n </SectionCard>\n\n <SectionCard\n title={t('ggnomad.dashboard.sections.recentBookings', 'Recent bookings')}\n action={\n <Link\n to=\"bookings\"\n className=\"inline-flex items-center gap-1 text-sm font-medium text-action-primary-bg hover:underline\"\n >\n {t('ggnomad.dashboard.viewAllBookings', 'View all bookings')}\n <ArrowRight className=\"size-3.5\" aria-hidden=\"true\" />\n </Link>\n }\n >\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 const checkIn = formatDate(booking.checkIn);\n const checkOut = formatDate(booking.checkOut);\n const eventDate = formatDate(booking.eventDate);\n const dateLabel = checkIn\n ? checkOut\n ? `${checkIn} – ${checkOut}`\n : checkIn\n : eventDate;\n return (\n <li\n key={booking.id}\n className=\"flex flex-wrap items-center justify-between gap-3 rounded-lg border border-border-seam bg-bg-surface/40 p-3\"\n >\n <div className=\"min-w-0\">\n <p className=\"truncate text-text-primary\">\n {booking.referenceCode} — {booking.itemName}\n </p>\n <p className=\"mt-0.5 flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-text-secondary\">\n {dateLabel ? (\n <span className=\"inline-flex items-center gap-1\">\n <CalendarRange className=\"size-3\" aria-hidden=\"true\" />\n {dateLabel}\n </span>\n ) : null}\n <span className=\"inline-flex items-center gap-1 tabular-nums\">\n <Users className=\"size-3\" aria-hidden=\"true\" />\n {booking.guests}\n </span>\n </p>\n </div>\n <div className=\"flex flex-shrink-0 items-center gap-3\">\n <span className=\"tabular-nums text-text-primary\">\n {booking.currency} {Number(booking.totalPrice).toFixed(2)}\n </span>\n <StatusBadge status={booking.status} />\n </div>\n </li>\n );\n })}\n </ul>\n )}\n </SectionCard>\n\n <SectionCard title={t('ggnomad.dashboard.sections.revenueByCategory', 'Revenue by category')}>\n {categories.length === 0 ? (\n <div className=\"flex flex-col items-center gap-2 py-8 text-center\">\n <span className=\"flex size-10 items-center justify-center rounded-full bg-[var(--color-accent-soft)] text-text-secondary\">\n <DollarSign className=\"size-5\" />\n </span>\n <p className=\"text-sm font-medium text-text-primary\">\n {t('ggnomad.dashboard.empty.title', 'Revenue data coming soon')}\n </p>\n <p className=\"max-w-sm text-sm text-text-secondary\">\n {t(\n 'ggnomad.dashboard.empty.description',\n 'Revenue by category appears here as bookings come in across stays, tours and events.'\n )}\n </p>\n </div>\n ) : (\n <ul className=\"flex flex-col gap-4\">\n {categories.map((category, index) => {\n const pct = maxCategory > 0 ? Math.max((category.value / maxCategory) * 100, 2) : 0;\n return (\n <li key={category.label}>\n <div className=\"flex items-baseline justify-between gap-3\">\n <span className=\"truncate text-sm font-medium text-text-primary\">\n {category.label}\n </span>\n <span className=\"flex-shrink-0 text-sm tabular-nums text-text-secondary\">\n ${category.value.toLocaleString()}\n </span>\n </div>\n <div className=\"mt-1.5 h-2.5 w-full overflow-hidden rounded-full bg-bg-sunken\">\n <div\n className=\"h-full rounded-full transition-[width] duration-500 ease-out\"\n style={{\n width: `${pct}%`,\n backgroundColor: CHART_COLORS[index % CHART_COLORS.length],\n }}\n />\n </div>\n </li>\n );\n })}\n </ul>\n )}\n </SectionCard>\n </PageShell>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntertainmentPage.d.ts","sourceRoot":"","sources":["../../../src/ggnomad/pages/EntertainmentPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"EntertainmentPage.d.ts","sourceRoot":"","sources":["../../../src/ggnomad/pages/EntertainmentPage.tsx"],"names":[],"mappings":"AAmCA,wBAAgB,iBAAiB,gCA+IhC"}
|