- Add Skeletons.tsx with TastingListSkeleton, ChartSkeleton, etc. - Add useOptimistic.ts hooks for React 19 optimistic updates - Update stats page to use skeleton loading instead of spinner - Remove force-dynamic exports (12 files) for SSG compatibility - Note: PPR (cacheComponents) tested but reverted - requires RSC-first refactor
49 lines
1.8 KiB
TypeScript
49 lines
1.8 KiB
TypeScript
import { createClient } from '@/lib/supabase/server';
|
|
import { redirect } from 'next/navigation';
|
|
import { checkIsAdmin } from '@/services/track-api-usage';
|
|
import { getAllPlans } from '@/services/subscription-service';
|
|
import Link from 'next/link';
|
|
import { ChevronLeft, Package } from 'lucide-react';
|
|
import PlanManagementClient from '@/components/PlanManagementClient';
|
|
|
|
export default async function AdminPlansPage() {
|
|
const supabase = await createClient();
|
|
const { data: { user } } = await supabase.auth.getUser();
|
|
|
|
if (!user) {
|
|
redirect('/');
|
|
}
|
|
|
|
const isAdmin = await checkIsAdmin(user.id);
|
|
if (!isAdmin) {
|
|
redirect('/');
|
|
}
|
|
|
|
// Fetch all plans
|
|
const plans = await getAllPlans();
|
|
|
|
return (
|
|
<main className="min-h-screen bg-zinc-50 dark:bg-black p-4 md:p-12">
|
|
<div className="max-w-7xl mx-auto space-y-8">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between">
|
|
<div>
|
|
<Link
|
|
href="/admin"
|
|
className="inline-flex items-center gap-2 text-zinc-500 hover:text-amber-600 transition-colors font-medium mb-2"
|
|
>
|
|
<ChevronLeft size={20} />
|
|
Back to Dashboard
|
|
</Link>
|
|
<h1 className="text-3xl font-black text-zinc-900 dark:text-white tracking-tight">Subscription Plans</h1>
|
|
<p className="text-zinc-500 mt-1">Manage subscription tiers and monthly credits</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Plan Management */}
|
|
<PlanManagementClient initialPlans={plans} />
|
|
</div>
|
|
</main>
|
|
);
|
|
}
|