Files
shadow-gunbuilder-ai-proto/app/admin/import-status/page.tsx
T
2025-12-07 09:57:46 -05:00

112 lines
3.7 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
type ImportStatus = "RAW" | "PENDING_MAPPING" | "MAPPED";
type SummaryRow = {
status: ImportStatus;
count: number;
};
type ByMerchantRow = {
merchantName: string;
platform: string;
status: ImportStatus;
count: number;
};
const API_BASE_URL =
process.env.NEXT_PUBLIC_API_BASE_URL ?? "http://localhost:8080";
export default function ImportStatusPage() {
const [summary, setSummary] = useState<SummaryRow[]>([]);
const [byMerchant, setByMerchant] = useState<ByMerchantRow[]>([]);
useEffect(() => {
async function load() {
const [summaryRes, byMerchantRes] = await Promise.all([
fetch(`${API_BASE_URL}/api/admin/import-status/summary`),
fetch(`${API_BASE_URL}/api/admin/import-status/by-merchant`),
]);
setSummary(await summaryRes.json());
setByMerchant(await byMerchantRes.json());
}
load();
}, []);
const total = summary.reduce((sum, row) => sum + row.count, 0);
return (
<main className="min-h-screen bg-black text-zinc-50">
<div className="mx-auto max-w-5xl px-4 py-6">
<h1 className="text-xl font-semibold tracking-tight">
Import Status Dashboard
</h1>
<p className="mt-1 text-sm text-zinc-400">
Quick sanity check on how clean (or not) your catalog is.
</p>
{/* Status cards */}
<div className="mt-4 grid grid-cols-1 gap-3 sm:grid-cols-3">
{summary.map((row) => (
<div
key={row.status}
className="rounded-lg border border-zinc-800 bg-zinc-950/80 p-3"
>
<div className="text-xs font-semibold uppercase tracking-[0.14em] text-zinc-500">
{row.status}
</div>
<div className="mt-1 text-2xl font-semibold text-amber-300">
{row.count}
</div>
<div className="mt-1 text-[0.7rem] text-zinc-500">
{total > 0
? `${((row.count / total) * 100).toFixed(1)}% of catalog`
: "—"}
</div>
</div>
))}
</div>
{/* Merchant breakdown */}
<section className="mt-6 rounded-lg border border-zinc-800 bg-zinc-950/80 p-3">
<h2 className="text-xs font-semibold uppercase tracking-[0.14em] text-zinc-500">
By Merchant & Platform
</h2>
<div className="mt-2 overflow-x-auto">
<table className="min-w-full text-xs">
<thead>
<tr className="border-b border-zinc-800 bg-zinc-900/60">
<th className="px-2 py-1 text-left text-zinc-400">Merchant</th>
<th className="px-2 py-1 text-left text-zinc-400">Platform</th>
<th className="px-2 py-1 text-left text-zinc-400">Status</th>
<th className="px-2 py-1 text-right text-zinc-400">Count</th>
</tr>
</thead>
<tbody>
{byMerchant.map((row, i) => (
<tr
key={`${row.merchantName}-${row.platform}-${row.status}-${i}`}
className="border-b border-zinc-900"
>
<td className="px-2 py-1 text-zinc-100">
{row.merchantName}
</td>
<td className="px-2 py-1 text-zinc-300">{row.platform}</td>
<td className="px-2 py-1 text-zinc-400">{row.status}</td>
<td className="px-2 py-1 text-right text-zinc-100">
{row.count}
</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
</div>
</main>
);
}