74 lines
3.4 KiB
TypeScript
74 lines
3.4 KiB
TypeScript
"use client";
|
|
import { useEffect, useState } from "react";
|
|
import { Download } from "lucide-react";
|
|
import { api, apiBase } from "@/lib/api";
|
|
|
|
export default function Utilization() {
|
|
const [orgs, setOrgs] = useState<any[]>([]);
|
|
useEffect(() => { api("/admin/organizations").then(setOrgs).catch(() => {}); }, []);
|
|
|
|
const totals = orgs.reduce((a, o) => ({
|
|
products: a.products + o.products_used,
|
|
qrs: a.qrs + o.qr_codes,
|
|
scans: a.scans + o.total_scans,
|
|
revenue: a.revenue + (o.plan_price || 0),
|
|
}), { products: 0, qrs: 0, scans: 0, revenue: 0 });
|
|
|
|
return (
|
|
<div className="space-y-5">
|
|
<div className="flex items-center justify-between">
|
|
<h2 className="text-xl font-bold">Utilization Report</h2>
|
|
<div className="flex gap-2">
|
|
<a href={`${apiBase}/admin/utilization-report?format=csv`} className="flex items-center gap-2 border border-slate-200 px-3 py-1.5 rounded-lg text-sm font-medium"><Download className="h-4 w-4" /> CSV</a>
|
|
<a href={`${apiBase}/admin/utilization-report?format=pdf`} className="flex items-center gap-2 border border-slate-200 px-3 py-1.5 rounded-lg text-sm font-medium"><Download className="h-4 w-4" /> PDF</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="card overflow-x-auto">
|
|
<table className="w-full text-sm">
|
|
<thead className="bg-slate-50 text-slate-500 text-left">
|
|
<tr>
|
|
<th className="px-4 py-3 font-medium">Organization</th>
|
|
<th className="px-4 py-3 font-medium">Plan</th>
|
|
<th className="px-4 py-3 font-medium">Products</th>
|
|
<th className="px-4 py-3 font-medium">Users</th>
|
|
<th className="px-4 py-3 font-medium">Storage</th>
|
|
<th className="px-4 py-3 font-medium">QRs</th>
|
|
<th className="px-4 py-3 font-medium">Scans</th>
|
|
<th className="px-4 py-3 font-medium">Revenue</th>
|
|
<th className="px-4 py-3 font-medium">Status</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-slate-100">
|
|
{orgs.map((o) => (
|
|
<tr key={o.org_id} className="hover:bg-slate-50">
|
|
<td className="px-4 py-3 font-medium">{o.name}</td>
|
|
<td className="px-4 py-3">{o.plan ?? "—"}</td>
|
|
<td className="px-4 py-3">{o.products_used} / {o.product_limit ?? "∞"}</td>
|
|
<td className="px-4 py-3">{o.users_used} / {o.user_limit ?? "∞"}</td>
|
|
<td className="px-4 py-3">{o.storage_used_gb} GB</td>
|
|
<td className="px-4 py-3">{o.qr_codes}</td>
|
|
<td className="px-4 py-3">{o.total_scans}</td>
|
|
<td className="px-4 py-3">₹{o.plan_price}</td>
|
|
<td className="px-4 py-3 capitalize">{o.subscription_status}</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
<tfoot>
|
|
<tr className="bg-slate-50 font-semibold">
|
|
<td className="px-4 py-3" colSpan={2}>Totals ({orgs.length} orgs)</td>
|
|
<td className="px-4 py-3">{totals.products}</td>
|
|
<td className="px-4 py-3"></td>
|
|
<td className="px-4 py-3"></td>
|
|
<td className="px-4 py-3">{totals.qrs}</td>
|
|
<td className="px-4 py-3">{totals.scans}</td>
|
|
<td className="px-4 py-3">₹{totals.revenue}</td>
|
|
<td className="px-4 py-3"></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|