feat: implement subscription plan system with monthly credits
- Database schema: * subscription_plans table - stores plan tiers (Starter, Bronze, Silver, Gold) * user_subscriptions table - assigns users to plans * Default plans created (10, 50, 100, 250 credits/month) * All existing users assigned to Starter plan - Subscription service (subscription-service.ts): * getAllPlans() - fetch all plans * getActivePlans() - fetch active plans for users * createPlan() - admin creates new plan * updatePlan() - admin edits plan * deletePlan() - admin removes plan * getUserSubscription() - get user's current plan * setUserPlan() - admin assigns user to plan * grantMonthlyCredits() - distribute credits to all users - Plan management interface (/admin/plans): * Visual plan cards with credits, price, description * Create/Edit/Delete plans * Toggle active/inactive status * Sort order management * Grant monthly credits button (manual trigger) - Features: * Monthly credit allocation based on plan * Prevents duplicate credit grants (tracks last_credit_grant_at) * Admin can manually trigger monthly credit distribution * Plans can be activated/deactivated * Custom pricing and credit amounts per plan - UI: * Beautiful plan cards with color coding * Modal for create/edit with validation * Success/error messages * Manage Plans button in admin dashboard Ready for future automation (cron job for monthly credits) and payment integration (Stripe/PayPal).
This commit is contained in:
@@ -83,6 +83,12 @@ export default async function AdminPage() {
|
||||
<p className="text-zinc-500 mt-1">API Usage Monitoring & Statistics</p>
|
||||
</div>
|
||||
<div className="flex gap-3">
|
||||
<Link
|
||||
href="/admin/plans"
|
||||
className="px-4 py-2 bg-purple-600 hover:bg-purple-700 text-white rounded-xl font-bold transition-colors"
|
||||
>
|
||||
Manage Plans
|
||||
</Link>
|
||||
<Link
|
||||
href="/admin/users"
|
||||
className="px-4 py-2 bg-amber-600 hover:bg-amber-700 text-white rounded-xl font-bold transition-colors"
|
||||
|
||||
49
src/app/admin/plans/page.tsx
Normal file
49
src/app/admin/plans/page.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import { createServerComponentClient } from '@supabase/auth-helpers-nextjs';
|
||||
import { cookies } from 'next/headers';
|
||||
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 = createServerComponentClient({ cookies });
|
||||
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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user