"use client"; import { useEffect, useState } from "react"; import Link from "next/link"; const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL ?? ""; const formatCount = (value: number | null | undefined) => (typeof value === "number" ? value : 0).toLocaleString(); type ImportSummary = { totalProducts: number; mappedProducts: number; pendingProducts: number; }; type RawByMerchantRow = { merchantId: number; merchantName: string; platform: string; status: string; count: number; }; type MerchantImportRow = { merchantId: number; merchantName: string; totalProducts: number; mappedProducts: number; pendingProducts: number; lastImportAt?: string | null; }; export default function ImportStatusPage() { const [summary, setSummary] = useState(null); const [rows, setRows] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [importingId, setImportingId] = useState(null); useEffect(() => { async function load() { try { setLoading(true); setError(null); 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`), ]); if (!summaryRes.ok || !byMerchantRes.ok) { throw new Error("Failed to load import status"); } const summaryJson: ImportSummary = await summaryRes.json(); const byMerchantRaw: RawByMerchantRow[] = await byMerchantRes.json(); // Aggregate per merchant using merchantId as the key const merchantMap = new Map(); for (const row of byMerchantRaw) { const id = row.merchantId; const name = row.merchantName; const status = row.status; const count = row.count ?? 0; if (!merchantMap.has(id)) { merchantMap.set(id, { merchantId: id, merchantName: name, totalProducts: 0, mappedProducts: 0, pendingProducts: 0, lastImportAt: null, // not provided by API yet }); } const agg = merchantMap.get(id)!; agg.totalProducts += count; if (status === "MAPPED") { agg.mappedProducts += count; } else if (status === "PENDING_MAPPING") { agg.pendingProducts += count; } } const byMerchantJson: MerchantImportRow[] = Array.from( merchantMap.values() ); setSummary(summaryJson); setRows(byMerchantJson); } catch (e: any) { console.error(e); setError(e.message ?? "Failed to load import status"); } finally { setLoading(false); } } load(); }, []); async function handleReimport(merchantId: number) { try { setImportingId(merchantId); const res = await fetch( `${API_BASE_URL}/api/admin/merchants/${merchantId}/import`, { method: "POST", } ); if (!res.ok) { throw new Error(`Re-import failed (${res.status})`); } // Optionally re-load data here if you want the table to refresh automatically } catch (e: any) { console.error(e); alert(e.message ?? "Failed to trigger import"); } finally { setImportingId(null); } } return (

Import Status

Per-merchant feed health and mapping coverage.

← Back to Admin Home
{loading && (

Loading import status…

)} {error &&

Error: {error}

} {summary && !loading && !error && ( <> {/* Summary cards */}

Total Products

{formatCount(summary.totalProducts)}

Mapped

{formatCount(summary.mappedProducts)}

Pending Mapping

{formatCount(summary.pendingProducts)}

By Merchant

{rows.map((row) => ( ))}
Merchant Total Mapped Pending Last Import Actions
{row.merchantName} {formatCount(row.totalProducts)} {formatCount(row.mappedProducts)} {formatCount(row.pendingProducts)} {row.lastImportAt ? new Date(row.lastImportAt).toLocaleString() : "—"}
Mapping
)}
); }