"use client"; import { useEffect, useState } from "react"; import { CheckCircle2, Download, CreditCard, RefreshCw, Tag } from "lucide-react"; import { api, apiBase } from "@/lib/api"; import { inr } from "@/lib/utils"; import { purchasePlan } from "@/lib/razorpay"; export default function Billing() { const [sub, setSub] = useState(null); const [plans, setPlans] = useState([]); const [invoices, setInvoices] = useState([]); const [coupon, setCoupon] = useState(""); const [couponMsg, setCouponMsg] = useState(""); const [busy, setBusy] = useState(""); const [toast, setToast] = useState(""); async function load() { api("/billing/subscription").then(setSub).catch(() => {}); api("/billing/plans").then(setPlans).catch(() => setPlans([])); api("/billing/invoices").then(setInvoices).catch(() => {}); } useEffect(() => { load(); }, []); async function applyCoupon() { setCouponMsg(""); try { const r = await api("/billing/coupon/apply", { method: "POST", body: JSON.stringify({ code: coupon }) }); setCouponMsg(`✓ ${r.code}: ${r.percent_off}% off applied`); } catch (e: any) { setCouponMsg(typeof e.detail === "string" ? e.detail : "Invalid coupon"); } } async function choose(planId: string, planName: string) { setBusy(planId); try { await purchasePlan(planId, coupon, (inv) => { setToast(`${planName} activated${inv ? ` · Invoice ${inv}` : ""}`); }); await load(); } catch (e: any) { setToast(e?.message || "Payment failed"); } finally { setBusy(""); } } async function toggleAutoRenew() { const next = !sub?.auto_renew; await api("/billing/subscription/auto-renewal", { method: "PUT", body: JSON.stringify({ auto_renew: next }) }); load(); } const u = sub?.usage; return (
{toast && (
{toast}
)}

Billing & Subscription

{/* KPIs */}
Auto-renewal
{/* Usage bars */} {u && (

Usage

)} {/* Coupon */}

Have a coupon?

setCoupon(e.target.value)} placeholder="WELCOME10" className="flex-1 px-3 py-2 rounded-lg border border-slate-200 text-sm" />
{couponMsg &&

{couponMsg}

}
{/* Available plans */}

Available Plans

{plans.map((p) => { const current = sub?.plan?.id === p.id; return (

{p.name}

{p.price ? inr(p.price) : "Free"} {p.price > 0 && /mo}
  • Products: {p.product_limit ?? "∞"}
  • Users: {p.user_limit ?? "∞"}
  • Storage: {p.storage_gb} GB
); })} {plans.length === 0 &&

Plans load for billing admins.

}
{/* Payment history */}

Payment History

{invoices.map((i) => ( ))} {invoices.length === 0 && ( )}
Invoice Plan Subtotal GST Total Status
{i.invoice_number} {i.plan_name} {inr(i.subtotal)} {inr(i.gst_amount)} {inr(i.total)} {i.status} PDF
No invoices yet.
); } function Kpi({ label, value, className }: any) { return (
{label}
{value}
); } function Usage({ label, used, limit }: { label: string; used: number; limit: number | null }) { const pct = limit == null ? 8 : Math.min(100, Math.round((used / limit) * 100)); return (
{label} {used} / {limit ?? "∞"}
); }