@burdenoff/microfe-ggnomad 2026.728.2 → 2026.728.3

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.
@@ -1 +1 @@
1
- {"version":3,"file":"ProviderAnalyticsPage.d.ts","sourceRoot":"","sources":["../../../src/ggnomad/pages/ProviderAnalyticsPage.tsx"],"names":[],"mappings":"AAwDA;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,gCAkSpC"}
1
+ {"version":3,"file":"ProviderAnalyticsPage.d.ts","sourceRoot":"","sources":["../../../src/ggnomad/pages/ProviderAnalyticsPage.tsx"],"names":[],"mappings":"AAwDA;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,gCA6SpC"}
@@ -27,8 +27,8 @@ function T() {
27
27
  let { t: T } = p(), { data: E, loading: D } = m(e), O = E?.myGgnomadProviders ?? [], [k, A] = o(""), [j, M] = o(() => C(w(30))), [N, P] = o(() => C(/* @__PURE__ */ new Date())), [F, I] = o("day"), L = k || O[0]?.id || "", { data: R, loading: z } = m(t, {
28
28
  variables: {
29
29
  providerId: L,
30
- dateFrom: j,
31
- dateTo: N,
30
+ dateFrom: `${j}T00:00:00.000Z`,
31
+ dateTo: `${N}T23:59:59.999Z`,
32
32
  granularity: F
33
33
  },
34
34
  skip: !L
@@ -1 +1 @@
1
- {"version":3,"file":"ProviderAnalyticsPage.js","names":[],"sources":["../../../src/ggnomad/pages/ProviderAnalyticsPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { BarChart3, CalendarCheck, DollarSign, Gauge, TrendingUp, XCircle } from 'lucide-react';\nimport { IllustratedEmptyState, PagePurpose, Spinner } from '@burdenoff/fe-libs/ui';\n\nimport { GGNOMAD_MY_PROVIDERS_QUERY, GGNOMAD_MY_PROVIDER_ANALYTICS_QUERY } from '../graphql';\nimport { PageShell } from './PageShell';\nimport { SectionCard, StatCard } 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 INPUT_CLASSES =\n 'mt-1 w-full rounded-md border border-border-seam bg-bg-canvas px-3 py-2 text-sm text-text-primary focus:border-action-primary-bg focus:outline-none focus:ring-1 focus:ring-action-primary-bg';\n\ntype MyProvider = { id: string; name: string; type: string; status: string };\n\ntype AnalyticsPoint = { period: string; bookings: number; revenue: number };\n\ntype ListingAnalytics = {\n listingId: string;\n listingType: string;\n listingName: string;\n bookings: number;\n revenue: number;\n cancellationRate: number;\n capacityUtilizationRate: number;\n};\n\ntype ProviderAnalytics = {\n providerId: string;\n providerName: string;\n totalBookings: number;\n totalRevenue: number;\n cancelledBookings: number;\n cancellationRate: number;\n capacityUtilizationRate: number;\n bookingsOverTime: AnalyticsPoint[];\n topListings: ListingAnalytics[];\n};\n\nfunction toISODate(date: Date): string {\n return date.toISOString().slice(0, 10);\n}\n\nfunction daysAgo(days: number): Date {\n return new Date(Date.now() - days * 24 * 60 * 60 * 1000);\n}\n\n/**\n * BOFF-4390 — provider-facing analytics dashboard: bookings-over-time,\n * revenue, cancellation rate and capacity utilization, plus a per-listing\n * drill-down table. Self-scoped: only providers the calling actor created\n * are listed, and the analytics call is owner-verified server-side — a\n * provider can never see another provider's numbers. Forecasting and\n * custom-report building are explicitly out of scope for this core; see the\n * `myGgnomadProviderAnalytics` schema doc comment.\n */\nexport function ProviderAnalyticsPage() {\n const { t } = useI18n();\n\n const { data: providersData, loading: providersLoading } = useQuery(\n GGNOMAD_MY_PROVIDERS_QUERY as TypedDocumentNode<\n { myGgnomadProviders: MyProvider[] },\n Record<string, never>\n >\n );\n const providers = providersData?.myGgnomadProviders ?? [];\n\n const [selectedProviderId, setSelectedProviderId] = useState('');\n const [dateFrom, setDateFrom] = useState(() => toISODate(daysAgo(30)));\n const [dateTo, setDateTo] = useState(() => toISODate(new Date()));\n const [granularity, setGranularity] = useState<'day' | 'week' | 'month'>('day');\n\n const activeProviderId = selectedProviderId || providers[0]?.id || '';\n\n const { data: analyticsData, loading: analyticsLoading } = useQuery(\n GGNOMAD_MY_PROVIDER_ANALYTICS_QUERY as TypedDocumentNode<\n { myGgnomadProviderAnalytics: ProviderAnalytics },\n { providerId: string; dateFrom?: string; dateTo?: string; granularity?: string }\n >,\n {\n variables: { providerId: activeProviderId, dateFrom, dateTo, granularity },\n skip: !activeProviderId,\n }\n );\n const analytics = analyticsData?.myGgnomadProviderAnalytics;\n\n const maxTrend = useMemo(() => {\n const points = analytics?.bookingsOverTime ?? [];\n return points.length > 0 ? Math.max(...points.map((p) => p.bookings)) : 0;\n }, [analytics?.bookingsOverTime]);\n\n return (\n <PageShell\n title={t('ggnomad.providerAnalytics.title', 'Provider Analytics')}\n titleAccent={t('ggnomad.providerAnalytics.title.accent', 'Analytics')}\n subtitle={t(\n 'ggnomad.providerAnalytics.subtitle',\n 'Your bookings, revenue and listing performance'\n )}\n >\n <PagePurpose icon={<TrendingUp className=\"size-4\" />}>\n {t(\n 'ggnomad.providerAnalytics.purpose',\n 'A self-service dashboard for providers: bookings and revenue over time, cancellation rate, capacity utilization, and a per-listing breakdown — scoped to only the listings you own. Pick a date range and a listing granularity to drill in.'\n )}\n </PagePurpose>\n\n {!providersLoading && providers.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-people\"\n title={t('ggnomad.providerAnalytics.emptyTitle', 'No provider profile yet')}\n description={t(\n 'ggnomad.providerAnalytics.emptyDescription',\n 'Once you create a GGNomad provider profile, your bookings and revenue analytics will appear here.'\n )}\n />\n ) : (\n <>\n <SectionCard title={t('ggnomad.providerAnalytics.filters', 'Filters')}>\n <div className=\"grid gap-3 sm:grid-cols-4\">\n <div>\n <label\n htmlFor=\"provider-analytics-provider\"\n className=\"block text-sm font-medium text-text-primary\"\n >\n {t('ggnomad.providerAnalytics.provider', 'Provider')}\n </label>\n <select\n id=\"provider-analytics-provider\"\n value={activeProviderId}\n onChange={(e) => setSelectedProviderId(e.target.value)}\n className={INPUT_CLASSES}\n >\n {providers.map((provider) => (\n <option key={provider.id} value={provider.id}>\n {provider.name}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label\n htmlFor=\"provider-analytics-from\"\n className=\"block text-sm font-medium text-text-primary\"\n >\n {t('ggnomad.providerAnalytics.from', 'From')}\n </label>\n <input\n id=\"provider-analytics-from\"\n type=\"date\"\n value={dateFrom}\n max={dateTo}\n onChange={(e) => setDateFrom(e.target.value)}\n className={INPUT_CLASSES}\n />\n </div>\n <div>\n <label\n htmlFor=\"provider-analytics-to\"\n className=\"block text-sm font-medium text-text-primary\"\n >\n {t('ggnomad.providerAnalytics.to', 'To')}\n </label>\n <input\n id=\"provider-analytics-to\"\n type=\"date\"\n value={dateTo}\n min={dateFrom}\n max={toISODate(new Date())}\n onChange={(e) => setDateTo(e.target.value)}\n className={INPUT_CLASSES}\n />\n </div>\n <div>\n <label\n htmlFor=\"provider-analytics-granularity\"\n className=\"block text-sm font-medium text-text-primary\"\n >\n {t('ggnomad.providerAnalytics.granularity', 'Granularity')}\n </label>\n <select\n id=\"provider-analytics-granularity\"\n value={granularity}\n onChange={(e) => setGranularity(e.target.value as 'day' | 'week' | 'month')}\n className={INPUT_CLASSES}\n >\n <option value=\"day\">{t('ggnomad.providerAnalytics.day', 'Day')}</option>\n <option value=\"week\">{t('ggnomad.providerAnalytics.week', 'Week')}</option>\n <option value=\"month\">{t('ggnomad.providerAnalytics.month', 'Month')}</option>\n </select>\n </div>\n </div>\n </SectionCard>\n\n {analyticsLoading ? (\n <div className=\"flex justify-center py-12\">\n <Spinner size=\"lg\" />\n </div>\n ) : !analytics ? (\n <IllustratedEmptyState\n illustration=\"empty-people\"\n title={t('ggnomad.providerAnalytics.noDataTitle', 'No bookings in this range')}\n description={t(\n 'ggnomad.providerAnalytics.noDataDescription',\n 'Try widening the date range — analytics appear here once bookings come in for your listings.'\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.providerAnalytics.totalBookings', 'Bookings')}\n value={analytics.totalBookings.toLocaleString()}\n icon={<CalendarCheck />}\n />\n <StatCard\n label={t('ggnomad.providerAnalytics.totalRevenue', 'Revenue')}\n value={`$${Number(analytics.totalRevenue).toLocaleString()}`}\n icon={<DollarSign />}\n />\n <StatCard\n label={t('ggnomad.providerAnalytics.cancellationRate', 'Cancellation rate')}\n value={`${(analytics.cancellationRate * 100).toFixed(1)}%`}\n icon={<XCircle />}\n />\n <StatCard\n label={t('ggnomad.providerAnalytics.capacityUtilization', 'Capacity utilization')}\n value={`${(analytics.capacityUtilizationRate * 100).toFixed(1)}%`}\n icon={<Gauge />}\n />\n </section>\n\n <SectionCard\n title={t('ggnomad.providerAnalytics.bookingsOverTime', 'Bookings over time')}\n >\n {analytics.bookingsOverTime.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 <BarChart3 className=\"size-5\" />\n </span>\n <p className=\"text-sm font-medium text-text-primary\">\n {t('ggnomad.providerAnalytics.trendEmpty', 'No bookings in this window yet')}\n </p>\n </div>\n ) : (\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-end gap-2 overflow-x-auto pb-2\">\n {analytics.bookingsOverTime.map((point, index) => {\n const pct =\n maxTrend > 0 ? Math.max((point.bookings / maxTrend) * 100, 5) : 5;\n return (\n <div key={point.period} className=\"flex flex-col items-center gap-1\">\n <div className=\"flex h-24 items-end\">\n <div\n className=\"w-8 rounded-t transition-all duration-500 ease-out\"\n style={{\n height: `${pct}%`,\n backgroundColor: CHART_COLORS[index % CHART_COLORS.length],\n }}\n title={`${point.period}: ${point.bookings} bookings, $${point.revenue.toLocaleString()} revenue`}\n />\n </div>\n <p className=\"truncate text-xs text-text-secondary\">{point.period}</p>\n </div>\n );\n })}\n </div>\n <p className=\"text-xs text-text-secondary\">\n {t(\n 'ggnomad.providerAnalytics.trendNote',\n 'Bar height is booking volume per period; hover a bar for its exact bookings and revenue.'\n )}\n </p>\n </div>\n )}\n </SectionCard>\n\n <SectionCard title={t('ggnomad.providerAnalytics.topListings', 'Top listings')}>\n {analytics.topListings.length === 0 ? (\n <p className=\"py-6 text-center text-sm text-text-secondary\">\n {t(\n 'ggnomad.providerAnalytics.topListingsEmpty',\n 'No listing bookings in this range yet.'\n )}\n </p>\n ) : (\n <div className=\"overflow-x-auto\">\n <table className=\"w-full min-w-[560px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam text-left text-text-secondary\">\n <th className=\"py-2 pr-3 font-medium\">\n {t('ggnomad.providerAnalytics.listing', 'Listing')}\n </th>\n <th className=\"py-2 pr-3 font-medium\">\n {t('ggnomad.providerAnalytics.type', 'Type')}\n </th>\n <th className=\"py-2 pr-3 text-right font-medium\">\n {t('ggnomad.providerAnalytics.bookings', 'Bookings')}\n </th>\n <th className=\"py-2 pr-3 text-right font-medium\">\n {t('ggnomad.providerAnalytics.revenue', 'Revenue')}\n </th>\n <th className=\"py-2 pr-3 text-right font-medium\">\n {t('ggnomad.providerAnalytics.cancellation', 'Cancellation')}\n </th>\n <th className=\"py-2 text-right font-medium\">\n {t('ggnomad.providerAnalytics.utilization', 'Utilization')}\n </th>\n </tr>\n </thead>\n <tbody>\n {analytics.topListings.map((listing) => (\n <tr\n key={listing.listingId}\n className=\"border-b border-border-seam/50 last:border-0\"\n >\n <td className=\"py-2 pr-3 font-medium text-text-primary\">\n {listing.listingName}\n </td>\n <td className=\"py-2 pr-3 text-text-secondary\">{listing.listingType}</td>\n <td className=\"py-2 pr-3 text-right tabular-nums text-text-primary\">\n {listing.bookings}\n </td>\n <td className=\"py-2 pr-3 text-right tabular-nums text-text-primary\">\n ${listing.revenue.toLocaleString()}\n </td>\n <td className=\"py-2 pr-3 text-right tabular-nums text-text-primary\">\n {(listing.cancellationRate * 100).toFixed(0)}%\n </td>\n <td className=\"py-2 text-right tabular-nums text-text-primary\">\n {(listing.capacityUtilizationRate * 100).toFixed(0)}%\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </SectionCard>\n </>\n )}\n </>\n )}\n </PageShell>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ProviderAnalyticsPage.js","names":[],"sources":["../../../src/ggnomad/pages/ProviderAnalyticsPage.tsx"],"sourcesContent":["import { useMemo, useState } from 'react';\nimport { useQuery } from '@apollo/client/react';\nimport type { TypedDocumentNode } from '@apollo/client';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { BarChart3, CalendarCheck, DollarSign, Gauge, TrendingUp, XCircle } from 'lucide-react';\nimport { IllustratedEmptyState, PagePurpose, Spinner } from '@burdenoff/fe-libs/ui';\n\nimport { GGNOMAD_MY_PROVIDERS_QUERY, GGNOMAD_MY_PROVIDER_ANALYTICS_QUERY } from '../graphql';\nimport { PageShell } from './PageShell';\nimport { SectionCard, StatCard } 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 INPUT_CLASSES =\n 'mt-1 w-full rounded-md border border-border-seam bg-bg-canvas px-3 py-2 text-sm text-text-primary focus:border-action-primary-bg focus:outline-none focus:ring-1 focus:ring-action-primary-bg';\n\ntype MyProvider = { id: string; name: string; type: string; status: string };\n\ntype AnalyticsPoint = { period: string; bookings: number; revenue: number };\n\ntype ListingAnalytics = {\n listingId: string;\n listingType: string;\n listingName: string;\n bookings: number;\n revenue: number;\n cancellationRate: number;\n capacityUtilizationRate: number;\n};\n\ntype ProviderAnalytics = {\n providerId: string;\n providerName: string;\n totalBookings: number;\n totalRevenue: number;\n cancelledBookings: number;\n cancellationRate: number;\n capacityUtilizationRate: number;\n bookingsOverTime: AnalyticsPoint[];\n topListings: ListingAnalytics[];\n};\n\nfunction toISODate(date: Date): string {\n return date.toISOString().slice(0, 10);\n}\n\nfunction daysAgo(days: number): Date {\n return new Date(Date.now() - days * 24 * 60 * 60 * 1000);\n}\n\n/**\n * BOFF-4390 — provider-facing analytics dashboard: bookings-over-time,\n * revenue, cancellation rate and capacity utilization, plus a per-listing\n * drill-down table. Self-scoped: only providers the calling actor created\n * are listed, and the analytics call is owner-verified server-side — a\n * provider can never see another provider's numbers. Forecasting and\n * custom-report building are explicitly out of scope for this core; see the\n * `myGgnomadProviderAnalytics` schema doc comment.\n */\nexport function ProviderAnalyticsPage() {\n const { t } = useI18n();\n\n const { data: providersData, loading: providersLoading } = useQuery(\n GGNOMAD_MY_PROVIDERS_QUERY as TypedDocumentNode<\n { myGgnomadProviders: MyProvider[] },\n Record<string, never>\n >\n );\n const providers = providersData?.myGgnomadProviders ?? [];\n\n const [selectedProviderId, setSelectedProviderId] = useState('');\n // `dateFrom`/`dateTo` are the plain YYYY-MM-DD strings bound to the <input\n // type=\"date\"> controls. They are NOT sent to GraphQL as-is: a bare date\n // string parses to UTC midnight, so using \"today\" as dateTo would exclude\n // every booking made later that same day. The query variables below\n // convert dateFrom to the start of that UTC day and dateTo to the end of\n // it, so \"today\" always includes today's activity.\n const [dateFrom, setDateFrom] = useState(() => toISODate(daysAgo(30)));\n const [dateTo, setDateTo] = useState(() => toISODate(new Date()));\n const [granularity, setGranularity] = useState<'day' | 'week' | 'month'>('day');\n\n const activeProviderId = selectedProviderId || providers[0]?.id || '';\n\n const { data: analyticsData, loading: analyticsLoading } = useQuery(\n GGNOMAD_MY_PROVIDER_ANALYTICS_QUERY as TypedDocumentNode<\n { myGgnomadProviderAnalytics: ProviderAnalytics },\n { providerId: string; dateFrom?: string; dateTo?: string; granularity?: string }\n >,\n {\n variables: {\n providerId: activeProviderId,\n dateFrom: `${dateFrom}T00:00:00.000Z`,\n dateTo: `${dateTo}T23:59:59.999Z`,\n granularity,\n },\n skip: !activeProviderId,\n }\n );\n const analytics = analyticsData?.myGgnomadProviderAnalytics;\n\n const maxTrend = useMemo(() => {\n const points = analytics?.bookingsOverTime ?? [];\n return points.length > 0 ? Math.max(...points.map((p) => p.bookings)) : 0;\n }, [analytics?.bookingsOverTime]);\n\n return (\n <PageShell\n title={t('ggnomad.providerAnalytics.title', 'Provider Analytics')}\n titleAccent={t('ggnomad.providerAnalytics.title.accent', 'Analytics')}\n subtitle={t(\n 'ggnomad.providerAnalytics.subtitle',\n 'Your bookings, revenue and listing performance'\n )}\n >\n <PagePurpose icon={<TrendingUp className=\"size-4\" />}>\n {t(\n 'ggnomad.providerAnalytics.purpose',\n 'A self-service dashboard for providers: bookings and revenue over time, cancellation rate, capacity utilization, and a per-listing breakdown — scoped to only the listings you own. Pick a date range and a listing granularity to drill in.'\n )}\n </PagePurpose>\n\n {!providersLoading && providers.length === 0 ? (\n <IllustratedEmptyState\n illustration=\"empty-people\"\n title={t('ggnomad.providerAnalytics.emptyTitle', 'No provider profile yet')}\n description={t(\n 'ggnomad.providerAnalytics.emptyDescription',\n 'Once you create a GGNomad provider profile, your bookings and revenue analytics will appear here.'\n )}\n />\n ) : (\n <>\n <SectionCard title={t('ggnomad.providerAnalytics.filters', 'Filters')}>\n <div className=\"grid gap-3 sm:grid-cols-4\">\n <div>\n <label\n htmlFor=\"provider-analytics-provider\"\n className=\"block text-sm font-medium text-text-primary\"\n >\n {t('ggnomad.providerAnalytics.provider', 'Provider')}\n </label>\n <select\n id=\"provider-analytics-provider\"\n value={activeProviderId}\n onChange={(e) => setSelectedProviderId(e.target.value)}\n className={INPUT_CLASSES}\n >\n {providers.map((provider) => (\n <option key={provider.id} value={provider.id}>\n {provider.name}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label\n htmlFor=\"provider-analytics-from\"\n className=\"block text-sm font-medium text-text-primary\"\n >\n {t('ggnomad.providerAnalytics.from', 'From')}\n </label>\n <input\n id=\"provider-analytics-from\"\n type=\"date\"\n value={dateFrom}\n max={dateTo}\n onChange={(e) => setDateFrom(e.target.value)}\n className={INPUT_CLASSES}\n />\n </div>\n <div>\n <label\n htmlFor=\"provider-analytics-to\"\n className=\"block text-sm font-medium text-text-primary\"\n >\n {t('ggnomad.providerAnalytics.to', 'To')}\n </label>\n <input\n id=\"provider-analytics-to\"\n type=\"date\"\n value={dateTo}\n min={dateFrom}\n max={toISODate(new Date())}\n onChange={(e) => setDateTo(e.target.value)}\n className={INPUT_CLASSES}\n />\n </div>\n <div>\n <label\n htmlFor=\"provider-analytics-granularity\"\n className=\"block text-sm font-medium text-text-primary\"\n >\n {t('ggnomad.providerAnalytics.granularity', 'Granularity')}\n </label>\n <select\n id=\"provider-analytics-granularity\"\n value={granularity}\n onChange={(e) => setGranularity(e.target.value as 'day' | 'week' | 'month')}\n className={INPUT_CLASSES}\n >\n <option value=\"day\">{t('ggnomad.providerAnalytics.day', 'Day')}</option>\n <option value=\"week\">{t('ggnomad.providerAnalytics.week', 'Week')}</option>\n <option value=\"month\">{t('ggnomad.providerAnalytics.month', 'Month')}</option>\n </select>\n </div>\n </div>\n </SectionCard>\n\n {analyticsLoading ? (\n <div className=\"flex justify-center py-12\">\n <Spinner size=\"lg\" />\n </div>\n ) : !analytics ? (\n <IllustratedEmptyState\n illustration=\"empty-people\"\n title={t('ggnomad.providerAnalytics.noDataTitle', 'No bookings in this range')}\n description={t(\n 'ggnomad.providerAnalytics.noDataDescription',\n 'Try widening the date range — analytics appear here once bookings come in for your listings.'\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.providerAnalytics.totalBookings', 'Bookings')}\n value={analytics.totalBookings.toLocaleString()}\n icon={<CalendarCheck />}\n />\n <StatCard\n label={t('ggnomad.providerAnalytics.totalRevenue', 'Revenue')}\n value={`$${Number(analytics.totalRevenue).toLocaleString()}`}\n icon={<DollarSign />}\n />\n <StatCard\n label={t('ggnomad.providerAnalytics.cancellationRate', 'Cancellation rate')}\n value={`${(analytics.cancellationRate * 100).toFixed(1)}%`}\n icon={<XCircle />}\n />\n <StatCard\n label={t('ggnomad.providerAnalytics.capacityUtilization', 'Capacity utilization')}\n value={`${(analytics.capacityUtilizationRate * 100).toFixed(1)}%`}\n icon={<Gauge />}\n />\n </section>\n\n <SectionCard\n title={t('ggnomad.providerAnalytics.bookingsOverTime', 'Bookings over time')}\n >\n {analytics.bookingsOverTime.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 <BarChart3 className=\"size-5\" />\n </span>\n <p className=\"text-sm font-medium text-text-primary\">\n {t('ggnomad.providerAnalytics.trendEmpty', 'No bookings in this window yet')}\n </p>\n </div>\n ) : (\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-end gap-2 overflow-x-auto pb-2\">\n {analytics.bookingsOverTime.map((point, index) => {\n const pct =\n maxTrend > 0 ? Math.max((point.bookings / maxTrend) * 100, 5) : 5;\n return (\n <div key={point.period} className=\"flex flex-col items-center gap-1\">\n <div className=\"flex h-24 items-end\">\n <div\n className=\"w-8 rounded-t transition-all duration-500 ease-out\"\n style={{\n height: `${pct}%`,\n backgroundColor: CHART_COLORS[index % CHART_COLORS.length],\n }}\n title={`${point.period}: ${point.bookings} bookings, $${point.revenue.toLocaleString()} revenue`}\n />\n </div>\n <p className=\"truncate text-xs text-text-secondary\">{point.period}</p>\n </div>\n );\n })}\n </div>\n <p className=\"text-xs text-text-secondary\">\n {t(\n 'ggnomad.providerAnalytics.trendNote',\n 'Bar height is booking volume per period; hover a bar for its exact bookings and revenue.'\n )}\n </p>\n </div>\n )}\n </SectionCard>\n\n <SectionCard title={t('ggnomad.providerAnalytics.topListings', 'Top listings')}>\n {analytics.topListings.length === 0 ? (\n <p className=\"py-6 text-center text-sm text-text-secondary\">\n {t(\n 'ggnomad.providerAnalytics.topListingsEmpty',\n 'No listing bookings in this range yet.'\n )}\n </p>\n ) : (\n <div className=\"overflow-x-auto\">\n <table className=\"w-full min-w-[560px] text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam text-left text-text-secondary\">\n <th className=\"py-2 pr-3 font-medium\">\n {t('ggnomad.providerAnalytics.listing', 'Listing')}\n </th>\n <th className=\"py-2 pr-3 font-medium\">\n {t('ggnomad.providerAnalytics.type', 'Type')}\n </th>\n <th className=\"py-2 pr-3 text-right font-medium\">\n {t('ggnomad.providerAnalytics.bookings', 'Bookings')}\n </th>\n <th className=\"py-2 pr-3 text-right font-medium\">\n {t('ggnomad.providerAnalytics.revenue', 'Revenue')}\n </th>\n <th className=\"py-2 pr-3 text-right font-medium\">\n {t('ggnomad.providerAnalytics.cancellation', 'Cancellation')}\n </th>\n <th className=\"py-2 text-right font-medium\">\n {t('ggnomad.providerAnalytics.utilization', 'Utilization')}\n </th>\n </tr>\n </thead>\n <tbody>\n {analytics.topListings.map((listing) => (\n <tr\n key={listing.listingId}\n className=\"border-b border-border-seam/50 last:border-0\"\n >\n <td className=\"py-2 pr-3 font-medium text-text-primary\">\n {listing.listingName}\n </td>\n <td className=\"py-2 pr-3 text-text-secondary\">{listing.listingType}</td>\n <td className=\"py-2 pr-3 text-right tabular-nums text-text-primary\">\n {listing.bookings}\n </td>\n <td className=\"py-2 pr-3 text-right tabular-nums text-text-primary\">\n ${listing.revenue.toLocaleString()}\n </td>\n <td className=\"py-2 pr-3 text-right tabular-nums text-text-primary\">\n {(listing.cancellationRate * 100).toFixed(0)}%\n </td>\n <td className=\"py-2 text-right tabular-nums text-text-primary\">\n {(listing.capacityUtilizationRate * 100).toFixed(0)}%\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </SectionCard>\n </>\n )}\n </>\n )}\n </PageShell>\n );\n}\n"],"mappings":";;;;;;;;;;;;AAWA,IAAM,IAAe;CACnB;CACA;CACA;CACA;CACA;AACF,GAEM,IACJ;AA4BF,SAAS,EAAU,GAAoB;CACrC,OAAO,EAAK,YAAY,EAAE,MAAM,GAAG,EAAE;AACvC;AAEA,SAAS,EAAQ,GAAoB;CACnC,uBAAO,IAAI,KAAK,KAAK,IAAI,IAAI,IAAO,KAAK,KAAK,KAAK,GAAI;AACzD;AAWA,SAAgB,IAAwB;CACtC,IAAM,EAAE,SAAM,EAAQ,GAEhB,EAAE,MAAM,GAAe,SAAS,MAAqB,EACzD,CAIF,GACM,IAAY,GAAe,sBAAsB,CAAC,GAElD,CAAC,GAAoB,KAAyB,EAAS,EAAE,GAOzD,CAAC,GAAU,KAAe,QAAe,EAAU,EAAQ,EAAE,CAAC,CAAC,GAC/D,CAAC,GAAQ,KAAa,QAAe,kBAAU,IAAI,KAAK,CAAC,CAAC,GAC1D,CAAC,GAAa,KAAkB,EAAmC,KAAK,GAExE,IAAmB,KAAsB,EAAU,IAAI,MAAM,IAE7D,EAAE,MAAM,GAAe,SAAS,MAAqB,EACzD,GAIA;EACE,WAAW;GACT,YAAY;GACZ,UAAU,GAAG,EAAS;GACtB,QAAQ,GAAG,EAAO;GAClB;EACF;EACA,MAAM,CAAC;CACT,CACF,GACM,IAAY,GAAe,4BAE3B,IAAW,QAAc;EAC7B,IAAM,IAAS,GAAW,oBAAoB,CAAC;EAC/C,OAAO,EAAO,SAAS,IAAI,KAAK,IAAI,GAAG,EAAO,KAAK,MAAM,EAAE,QAAQ,CAAC,IAAI;CAC1E,GAAG,CAAC,GAAW,gBAAgB,CAAC;CAEhC,OACE,kBAAC,GAAD;EACE,OAAO,EAAE,mCAAmC,oBAAoB;EAChE,aAAa,EAAE,0CAA0C,WAAW;EACpE,UAAU,EACR,sCACA,gDACF;YANF,CAQE,kBAAC,GAAD;GAAa,MAAM,kBAAC,GAAD,EAAY,WAAU,SAAU,CAAA;aAChD,EACC,qCACA,8OACF;EACW,CAAA,GAEZ,CAAC,KAAoB,EAAU,WAAW,IACzC,kBAAC,GAAD;GACE,cAAa;GACb,OAAO,EAAE,wCAAwC,yBAAyB;GAC1E,aAAa,EACX,8CACA,mGACF;EACD,CAAA,IAED,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;GAAa,OAAO,EAAE,qCAAqC,SAAS;aAClE,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;MACE,SAAQ;MACR,WAAU;gBAET,EAAE,sCAAsC,UAAU;KAC9C,CAAA,GACP,kBAAC,UAAD;MACE,IAAG;MACH,OAAO;MACP,WAAW,MAAM,EAAsB,EAAE,OAAO,KAAK;MACrD,WAAW;gBAEV,EAAU,KAAK,MACd,kBAAC,UAAD;OAA0B,OAAO,EAAS;iBACvC,EAAS;MACJ,GAFK,EAAS,EAEd,CACT;KACK,CAAA,CACL,EAAA,CAAA;KACL,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;MACE,SAAQ;MACR,WAAU;gBAET,EAAE,kCAAkC,MAAM;KACtC,CAAA,GACP,kBAAC,SAAD;MACE,IAAG;MACH,MAAK;MACL,OAAO;MACP,KAAK;MACL,WAAW,MAAM,EAAY,EAAE,OAAO,KAAK;MAC3C,WAAW;KACZ,CAAA,CACE,EAAA,CAAA;KACL,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;MACE,SAAQ;MACR,WAAU;gBAET,EAAE,gCAAgC,IAAI;KAClC,CAAA,GACP,kBAAC,SAAD;MACE,IAAG;MACH,MAAK;MACL,OAAO;MACP,KAAK;MACL,KAAK,kBAAU,IAAI,KAAK,CAAC;MACzB,WAAW,MAAM,EAAU,EAAE,OAAO,KAAK;MACzC,WAAW;KACZ,CAAA,CACE,EAAA,CAAA;KACL,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;MACE,SAAQ;MACR,WAAU;gBAET,EAAE,yCAAyC,aAAa;KACpD,CAAA,GACP,kBAAC,UAAD;MACE,IAAG;MACH,OAAO;MACP,WAAW,MAAM,EAAe,EAAE,OAAO,KAAiC;MAC1E,WAAW;gBAJb;OAME,kBAAC,UAAD;QAAQ,OAAM;kBAAO,EAAE,iCAAiC,KAAK;OAAU,CAAA;OACvE,kBAAC,UAAD;QAAQ,OAAM;kBAAQ,EAAE,kCAAkC,MAAM;OAAU,CAAA;OAC1E,kBAAC,UAAD;QAAQ,OAAM;kBAAS,EAAE,mCAAmC,OAAO;OAAU,CAAA;MACvE;OACL,EAAA,CAAA;IACF;;EACM,CAAA,GAEZ,IACC,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,GAAD,EAAS,MAAK,KAAM,CAAA;EACjB,CAAA,IACF,IAUH,kBAAA,GAAA,EAAA,UAAA;GACE,kBAAC,WAAD;IAAS,WAAU;cAAnB;KACE,kBAAC,GAAD;MACE,MAAA;MACA,OAAO,EAAE,2CAA2C,UAAU;MAC9D,OAAO,EAAU,cAAc,eAAe;MAC9C,MAAM,kBAAC,GAAD,CAAgB,CAAA;KACvB,CAAA;KACD,kBAAC,GAAD;MACE,OAAO,EAAE,0CAA0C,SAAS;MAC5D,OAAO,IAAI,OAAO,EAAU,YAAY,EAAE,eAAe;MACzD,MAAM,kBAAC,GAAD,CAAa,CAAA;KACpB,CAAA;KACD,kBAAC,GAAD;MACE,OAAO,EAAE,8CAA8C,mBAAmB;MAC1E,OAAO,IAAI,EAAU,mBAAmB,KAAK,QAAQ,CAAC,EAAE;MACxD,MAAM,kBAAC,GAAD,CAAU,CAAA;KACjB,CAAA;KACD,kBAAC,GAAD;MACE,OAAO,EAAE,iDAAiD,sBAAsB;MAChF,OAAO,IAAI,EAAU,0BAA0B,KAAK,QAAQ,CAAC,EAAE;MAC/D,MAAM,kBAAC,GAAD,CAAQ,CAAA;KACf,CAAA;IACM;;GAET,kBAAC,GAAD;IACE,OAAO,EAAE,8CAA8C,oBAAoB;cAE1E,EAAU,iBAAiB,WAAW,IACrC,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,QAAD;MAAM,WAAU;gBACd,kBAAC,GAAD,EAAW,WAAU,SAAU,CAAA;KAC3B,CAAA,GACN,kBAAC,KAAD;MAAG,WAAU;gBACV,EAAE,wCAAwC,gCAAgC;KAC1E,CAAA,CACA;SAEL,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBACZ,EAAU,iBAAiB,KAAK,GAAO,MAIpC,kBAAC,OAAD;OAAwB,WAAU;iBAAlC,CACE,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,OAAD;SACE,WAAU;SACV,OAAO;UACL,QAAQ,GAPhB,IAAW,IAAI,KAAK,IAAK,EAAM,WAAW,IAAY,KAAK,CAAC,IAAI,EAOzC;UACf,iBAAiB,EAAa,IAAQ,EAAa;SACrD;SACA,OAAO,GAAG,EAAM,OAAO,IAAI,EAAM,SAAS,cAAc,EAAM,QAAQ,eAAe,EAAE;QACxF,CAAA;OACE,CAAA,GACL,kBAAC,KAAD;QAAG,WAAU;kBAAwC,EAAM;OAAU,CAAA,CAClE;SAZK,EAAM,MAYX,CAER;KACE,CAAA,GACL,kBAAC,KAAD;MAAG,WAAU;gBACV,EACC,uCACA,0FACF;KACC,CAAA,CACA;;GAEI,CAAA;GAEb,kBAAC,GAAD;IAAa,OAAO,EAAE,yCAAyC,cAAc;cAC1E,EAAU,YAAY,WAAW,IAChC,kBAAC,KAAD;KAAG,WAAU;eACV,EACC,8CACA,wCACF;IACC,CAAA,IAEH,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,SAAD;MAAO,WAAU;gBAAjB,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD;OAAI,WAAU;iBAAd;QACE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAE,qCAAqC,SAAS;QAC/C,CAAA;QACJ,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAE,kCAAkC,MAAM;QACzC,CAAA;QACJ,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAE,sCAAsC,UAAU;QACjD,CAAA;QACJ,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAE,qCAAqC,SAAS;QAC/C,CAAA;QACJ,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAE,0CAA0C,cAAc;QACzD,CAAA;QACJ,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAE,yCAAyC,aAAa;QACvD,CAAA;OACF;SACC,CAAA,GACP,kBAAC,SAAD,EAAA,UACG,EAAU,YAAY,KAAK,MAC1B,kBAAC,MAAD;OAEE,WAAU;iBAFZ;QAIE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAQ;QACP,CAAA;QACJ,kBAAC,MAAD;SAAI,WAAU;mBAAiC,EAAQ;QAAgB,CAAA;QACvE,kBAAC,MAAD;SAAI,WAAU;mBACX,EAAQ;QACP,CAAA;QACJ,kBAAC,MAAD;SAAI,WAAU;mBAAd,CAAoE,KAChE,EAAQ,QAAQ,eAAe,CAC/B;;QACJ,kBAAC,MAAD;SAAI,WAAU;mBAAd,EACI,EAAQ,mBAAmB,KAAK,QAAQ,CAAC,GAAE,GAC3C;;QACJ,kBAAC,MAAD;SAAI,WAAU;mBAAd,EACI,EAAQ,0BAA0B,KAAK,QAAQ,CAAC,GAAE,GAClD;;OACF;SAnBG,EAAQ,SAmBX,CACL,EACI,CAAA,CACF;;IACJ,CAAA;GAEI,CAAA;EACb,EAAA,CAAA,IA7IF,kBAAC,GAAD;GACE,cAAa;GACb,OAAO,EAAE,yCAAyC,2BAA2B;GAC7E,aAAa,EACX,+CACA,8FACF;EACD,CAAA,CAwIH,EAAA,CAAA,CAEK;;AAEf"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-ggnomad",
3
- "version": "2026.728.2",
3
+ "version": "2026.728.3",
4
4
  "description": "Burdenoff GGNomad Microfrontend",
5
5
  "type": "module",
6
6
  "files": [