umami/src/app/share/ShareProvider.tsx
Mike Cao 4e8be724ac Handle domain name in share URL path
Skip domain-like segments (containing dots) when parsing the share path.
e.g., /share/slug/aol.com is treated as /share/slug
      /share/slug/aol.com/events is treated as /share/slug/events

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 23:38:07 -08:00

77 lines
1.9 KiB
TypeScript

'use client';
import { Loading } from '@umami/react-zen';
import { usePathname, useRouter } from 'next/navigation';
import { createContext, type ReactNode, useEffect } from 'react';
import { useShareTokenQuery } from '@/components/hooks';
import type { WhiteLabel } from '@/lib/types';
export interface ShareData {
shareId: string;
slug: string;
websiteId: string;
parameters: any;
token: string;
whiteLabel?: WhiteLabel;
}
export const ShareContext = createContext<ShareData>(null);
const ALL_SECTION_IDS = [
'overview',
'events',
'sessions',
'realtime',
'compare',
'breakdown',
'goals',
'funnels',
'journeys',
'retention',
'utm',
'revenue',
'attribution',
];
function getSharePath(pathname: string) {
const segments = pathname.split('/');
const firstSegment = segments[3];
// If first segment looks like a domain name, skip it
if (firstSegment?.includes('.')) {
return segments[4];
}
return firstSegment;
}
export function ShareProvider({ slug, children }: { slug: string; children: ReactNode }) {
const { share, isLoading, isFetching } = useShareTokenQuery(slug);
const router = useRouter();
const pathname = usePathname();
const path = getSharePath(pathname);
const allowedSections = share?.parameters
? ALL_SECTION_IDS.filter(id => share.parameters[id] !== false)
: [];
const shouldRedirect =
allowedSections.length === 1 &&
allowedSections[0] !== 'overview' &&
(path === undefined || path === '' || path === 'overview');
useEffect(() => {
if (shouldRedirect) {
router.replace(`/share/${slug}/${allowedSections[0]}`);
}
}, [shouldRedirect, slug, allowedSections, router]);
if (isFetching && isLoading) {
return <Loading placement="absolute" />;
}
if (!share || shouldRedirect) {
return null;
}
return <ShareContext.Provider value={{ ...share, slug }}>{children}</ShareContext.Provider>;
}