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:
2025-12-18 15:16:44 +01:00
parent f83243fd90
commit 42b4b2b2e1
5 changed files with 773 additions and 0 deletions

View File

@@ -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"

View 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>
);
}