"use client"; import Link from "next/link"; import { useEffect, useState } from "react"; import { getBackendErrorMessage } from "@/lib/error-message"; interface AdminQueueItem { id: string; name: string; seller: string; date: string; note: string; market: string; totalStock: number; minPrice: number; maxPrice: number; } interface AdminDashboardPayload { metrics: { totalPending: number; inReview: number; categoriesTotal: number; newsTotal: number; placesTotal: number; }; reviewQueue: AdminQueueItem[]; updateQueue: AdminQueueItem[]; } function getToken() { if (typeof window === "undefined") return ""; return sessionStorage.getItem("token") || localStorage.getItem("token") || ""; } function formatPrice(min: number, max: number) { const formatter = new Intl.NumberFormat("id-ID"); if (!min && !max) return "—"; if (min === max || !max) return `Rp ${formatter.format(min || max)}`; return `Rp ${formatter.format(min)} - Rp ${formatter.format(max)}`; } export default function AdminDashboardPage() { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); useEffect(() => { async function load() { setLoading(true); setError(""); try { const res = await fetch("/api/dashboard/admin", { headers: { "x-auth-token": getToken() }, }); const result = await res.json(); if (!res.ok) { throw new Error(getBackendErrorMessage(result, "Failed to load admin dashboard")); } setData(result); } catch (err) { setError(err instanceof Error ? err.message : "Failed to load admin dashboard"); } finally { setLoading(false); } } load(); }, []); return ( <>

Curator Intelligence

Central oversight for global inventory. Reviewing market listings and vendor updates for the Ina Trading ecosystem.

bolt {loading ? "Loading..." : `${data?.metrics.categoriesTotal ?? 0} Categories Active`}
{[ { label: "Total Pending", value: String(data?.metrics.totalPending ?? 0), sub: `${data?.metrics.newsTotal ?? 0} news`, subColor: "text-primary" }, { label: "In Review", value: String(data?.metrics.inReview ?? 0), sub: `${data?.metrics.placesTotal ?? 0} places`, subColor: "text-tertiary" }, { label: "Categories", value: String(data?.metrics.categoriesTotal ?? 0), sub: "taxonomy live", subColor: "text-slate-400", valueColor: "text-tertiary" }, ].map((metric) => (

{metric.label}

{loading ? "—" : metric.value}

{metric.sub}
))}

New Product Review Queue

Initial Listing Requests

View All
{["Product Name", "Vendor", "Request Date", "Action"].map((h) => ( ))} {(data?.reviewQueue || []).map((item) => ( ))} {!loading && !error && (data?.reviewQueue || []).length === 0 ? ( ) : null}
{h}
inventory_2
{item.name}
{item.seller} {item.date} Take Review
No pending review items.

Update Queue

Metadata & Pricing Refinement

{(data?.updateQueue || []).map((item) => (
{item.market || "Update"}
{item.name}

Vendor: {item.seller}

{item.date}

{item.note || formatPrice(item.minPrice, item.maxPrice)}

Review Changes →
))} {!loading && !error && (data?.updateQueue || []).length === 0 ? (
No update queue items available.
) : null}
Recent Curator Actions
{[ { color: "bg-tertiary-fixed", dot: "bg-tertiary", text: `${data?.metrics.newsTotal ?? 0} news articles currently published`, by: "Editorial data", }, { color: "bg-primary-fixed", dot: "bg-primary", text: `${data?.metrics.placesTotal ?? 0} places indexed for admin`, by: "Location registry", }, ].map((action) => (

{action.text}

{action.by}

))}
{error ? (
{error}
) : null}

Market Saturation Report

Current pending review load is{" "} {data?.metrics.totalPending ?? 0} items across products, places, and content workflows.

Open Review Queue
); }