Spaces:
Running
Running
| "use client"; | |
| import { useEffect, useState } from "react"; | |
| import { supabaseClient } from "@/lib/supabase-client"; | |
| import { Button } from "@/components/ui/button"; | |
| import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; | |
| import { Loader2, CreditCard, Zap, CheckCircle, AlertCircle } from "lucide-react"; | |
| import { useRouter } from "next/navigation"; | |
| import Link from "next/link"; | |
| export default function BillingPage() { | |
| const [user, setUser] = useState<any>(null); | |
| const [credits, setCredits] = useState(0); | |
| const [loading, setLoading] = useState(true); | |
| const router = useRouter(); | |
| const supabase = supabaseClient; | |
| useEffect(() => { | |
| const getData = async () => { | |
| const { data: { user } } = await supabase.auth.getUser(); | |
| if (!user) { | |
| router.push("/auth/signin"); | |
| return; | |
| } | |
| setUser(user); | |
| // Fetch user credits only | |
| const { data: userData } = await supabase | |
| .from("users") | |
| .select("credits") | |
| .eq("id", user.id) | |
| .single(); | |
| setCredits(userData?.credits ?? 0); | |
| setLoading(false); | |
| }; | |
| getData(); | |
| }, [supabase, router]); | |
| if (loading) { | |
| return ( | |
| <div className="flex h-screen items-center justify-center bg-slate-950"> | |
| <Loader2 className="h-8 w-8 animate-spin text-blue-500" /> | |
| </div> | |
| ); | |
| } | |
| // Static plan info for now | |
| const plan = { | |
| name: "Free", | |
| price: "$0", | |
| features: [ | |
| "5 video credits per month", | |
| "720p video quality", | |
| "Standard generation speed" | |
| ] | |
| }; | |
| return ( | |
| <div className="min-h-screen bg-slate-950 text-slate-200 py-12 px-4 sm:px-6 lg:px-8"> | |
| <div className="max-w-4xl mx-auto space-y-8"> | |
| <div> | |
| <h1 className="text-3xl font-bold text-white">Billing & Usage</h1> | |
| <p className="text-slate-400 mt-2">Manage your subscription and view credit usage.</p> | |
| </div> | |
| <div className="grid gap-6 md:grid-cols-2"> | |
| {/* Current Plan */} | |
| <Card className="bg-slate-900 border-slate-800"> | |
| <CardHeader> | |
| <CardTitle className="text-white flex items-center gap-2"> | |
| <CreditCard className="h-5 w-5 text-blue-500" /> | |
| Current Plan | |
| </CardTitle> | |
| <CardDescription className="text-slate-400"> | |
| You are currently on the <span className="text-white font-medium">{plan.name} Tier</span>. | |
| </CardDescription> | |
| </CardHeader> | |
| <CardContent className="space-y-6"> | |
| <div className="flex items-center justify-between p-4 bg-slate-950/50 rounded-lg border border-slate-800"> | |
| <div> | |
| <p className="text-sm font-medium text-slate-300">{plan.name} Plan</p> | |
| <p className="text-2xl font-bold text-white">{plan.price}<span className="text-sm text-slate-500 font-normal">/month</span></p> | |
| </div> | |
| <div className="h-2 w-2 rounded-full bg-green-500 animate-pulse" /> | |
| </div> | |
| <div className="space-y-2"> | |
| {plan.features.map((feature: string) => ( | |
| <div key={feature} className="flex items-center gap-2 text-sm text-slate-300"> | |
| <CheckCircle className="h-4 w-4 text-green-500" /> | |
| <span>{feature}</span> | |
| </div> | |
| ))} | |
| </div> | |
| <Button asChild className="w-full bg-gradient-to-r from-blue-600 to-violet-600 hover:from-blue-500 hover:to-violet-500 text-white border-0"> | |
| <Link href="/pricing">Upgrade Plan</Link> | |
| </Button> | |
| </CardContent> | |
| </Card> | |
| {/* Credit Usage */} | |
| <Card className="bg-slate-900 border-slate-800"> | |
| <CardHeader> | |
| <CardTitle className="text-white flex items-center gap-2"> | |
| <Zap className="h-5 w-5 text-yellow-500" /> | |
| Credit Usage | |
| </CardTitle> | |
| <CardDescription className="text-slate-400"> | |
| Your monthly generation credits. | |
| </CardDescription> | |
| </CardHeader> | |
| <CardContent className="space-y-6"> | |
| <div className="space-y-2"> | |
| <div className="flex justify-between text-sm"> | |
| <span className="text-slate-300">Credits Remaining</span> | |
| <span className="text-white font-mono">{credits} / 5</span> | |
| </div> | |
| <div className="h-3 bg-slate-950 rounded-full overflow-hidden border border-slate-800"> | |
| <div | |
| className="h-full bg-gradient-to-r from-blue-500 to-violet-500 transition-all duration-500" | |
| style={{ width: `${Math.min((credits / 5) * 100, 100)}%` }} | |
| /> | |
| </div> | |
| <p className="text-xs text-slate-500 pt-1"> | |
| Credits reset on the 1st of every month. | |
| </p> | |
| </div> | |
| {credits === 0 && ( | |
| <div className="p-3 bg-red-500/10 border border-red-500/20 rounded-lg flex gap-3"> | |
| <AlertCircle className="h-5 w-5 text-red-400 shrink-0" /> | |
| <p className="text-sm text-red-300"> | |
| You have run out of credits. Upgrade your plan to continue generating videos. | |
| </p> | |
| </div> | |
| )} | |
| </CardContent> | |
| </Card> | |
| </div> | |
| {/* Invoice History Placeholder */} | |
| <Card className="bg-slate-900 border-slate-800"> | |
| <CardHeader> | |
| <CardTitle className="text-white">Billing History</CardTitle> | |
| </CardHeader> | |
| <CardContent> | |
| <div className="text-center py-8 text-slate-500 text-sm"> | |
| No invoices found. | |
| </div> | |
| </CardContent> | |
| </Card> | |
| </div> | |
| </div> | |
| ); | |
| } | |