Files
ember-market-frontend/app/dashboard/analytics/page.tsx
NotII 18e87721e2 fix
2025-07-01 01:49:49 +01:00

145 lines
4.8 KiB
TypeScript

import { Suspense } from 'react';
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';
import Dashboard from "@/components/dashboard/dashboard";
import AnalyticsDashboard from '@/components/analytics/AnalyticsDashboard';
import AnalyticsDashboardSkeleton from '@/components/analytics/AnalyticsDashboardSkeleton';
import StoreSelector from '@/components/analytics/StoreSelector';
import { getAnalyticsOverviewServer } from '@/lib/server-api';
import { fetchServer } from '@/lib/api';
import { performance } from 'perf_hooks';
import { Info, GitCommit, User, Zap, BarChart3 } from 'lucide-react';
import packageJson from '../../../package.json';
import { getGitInfo } from '@/lib/utils/git';
// Vendor type for consistency
interface Vendor {
_id: string;
username: string;
storeId: string;
pgpKey: string;
__v: number;
}
interface User {
vendor: Vendor;
}
export default async function AnalyticsPage({
searchParams,
}: {
searchParams: Promise<{ storeId?: string }>;
}) {
const startTime = performance.now();
// Await searchParams as required by Next.js 15+
const resolvedSearchParams = await searchParams;
// Check for storeId in query parameters (for staff users)
const storeId = resolvedSearchParams?.storeId;
// Check for storeId in cookies (alternative method for staff users)
const cookieStore = await cookies();
const cookieStoreId = cookieStore.get('storeId')?.value;
// Use query parameter first, then cookie, then undefined (for vendors)
const finalStoreId = storeId || cookieStoreId;
try {
// Fetch user data and analytics data in parallel
const [userResponse, initialData] = await Promise.all([
fetchServer<User>("/auth/me"),
getAnalyticsOverviewServer(finalStoreId)
]);
// Get git info using the utility
const gitInfo = getGitInfo();
const endTime = performance.now();
const generationTime = (endTime - startTime).toFixed(2);
const panelVersion = packageJson.version;
const commitHash = gitInfo.hash;
const vendor = userResponse.vendor;
return (
<Dashboard>
<div className="space-y-6">
{/* Analytics Content */}
<Suspense fallback={<AnalyticsDashboardSkeleton />}>
<AnalyticsDashboard initialData={initialData} />
</Suspense>
</div>
<div className="fixed bottom-2 right-2 text-xs text-muted-foreground bg-background/80 backdrop-blur-sm px-2 py-1 rounded border border-border/50 z-50 flex items-center space-x-2">
<div className="flex items-center gap-1">
<Info size={12} className="text-muted-foreground/80" />
<span>v{panelVersion}</span>
</div>
<div className="flex items-center gap-1">
<User size={12} className="text-muted-foreground/80" />
<span>{vendor.username}</span>
</div>
<div className="flex items-center gap-1">
<GitCommit size={12} className="text-muted-foreground/80" />
<span>{commitHash}</span>
</div>
<div className="flex items-center gap-1">
<Zap size={12} className="text-amber-500" />
<span>Generated in {generationTime}ms</span>
</div>
<span className="px-1.5 py-0.5 text-xs rounded-sm bg-emerald-500/20 text-emerald-300">
{process.env.NODE_ENV || 'development'}
</span>
</div>
</Dashboard>
);
} catch (error) {
console.error('Error fetching analytics data:', error);
// If it's a 401/403 error, redirect to login
if (error instanceof Error && error.message.includes('401')) {
redirect('/login');
}
// If it's a 400 error (missing storeId for staff), show store selector
if (error instanceof Error && error.message.includes('400')) {
return (
<Dashboard>
<div className="space-y-6">
<div className="text-center mb-8">
<h1 className="text-3xl font-bold text-foreground mb-4">Analytics Dashboard</h1>
<p className="text-muted-foreground">
Please select a store to view analytics data.
</p>
</div>
<StoreSelector />
</div>
</Dashboard>
);
}
// For other errors, show a fallback
return (
<Dashboard>
<div className="space-y-6">
<div className="text-center py-8">
<h1 className="text-3xl font-bold text-foreground mb-4">Analytics Dashboard</h1>
<p className="text-muted-foreground">
Unable to load analytics data. Please try refreshing the page.
</p>
{finalStoreId && (
<p className="text-sm text-muted-foreground mt-2">
Accessing store: {finalStoreId}
</p>
)}
</div>
</div>
</Dashboard>
);
}
}