Files
catalogue_frontend/src/pages/AdminPage.jsx
2026-08-18 12:17:57 +05:30

106 lines
5.3 KiB
JavaScript

import React, { useEffect, useState } from 'react';
import { Wrench, Database } from 'lucide-react';
import { api } from '../api/client';
import { NavigationHeader } from '../components/NavigationHeader';
/*
* The admin panel is the project overview and nothing else.
*
* It used to carry three more sub-tabs behind a local `activeTab` switch -
* train/test dataset upload, a stock-remaining discount allocator, and a
* trigger for the vector ingestion pipeline. They were retired from the UI;
* with one view left there is nothing to switch between, so the tab bar and
* its state went too.
*
* Only the UI was removed. The endpoints behind those panels are still
* registered and still work - ingestion in particular is reachable from
* `python cli/ingest_brand.py "<brand>"` and from POST /api/catalog/generate.
*/
export function AdminPage() {
const [projectDetails, setProjectDetails] = useState(null);
const [loadingProject, setLoadingProject] = useState(true);
const fetchProjectDetails = async () => {
try {
setProjectDetails(await api.getProjectDetails());
} catch (e) {
console.warn('Could not fetch project details', e);
} finally {
setLoadingProject(false);
}
};
// This effect also drove a 3-second poll of ingestion job status; that went
// with the ingest panel, leaving a single fetch on mount.
useEffect(() => {
fetchProjectDetails();
}, []);
return (
<div className="flex h-screen w-full flex-col overflow-y-auto bg-paper-100 text-ink-950 font-sans">
<NavigationHeader
title="Admin Intelligence Panel"
subtitle="Brand catalogs, vector database tables & S3 storage overview"
icon={Wrench}
/>
<div className="mx-auto w-full max-w-6xl px-6 py-8 space-y-6">
<div className="space-y-6">
<div className="rounded-2xl border border-ink-900/10 bg-paper-50 p-6 shadow-xs">
<h2 className="font-display text-lg font-bold text-ink-950 flex items-center gap-2 mb-2">
<Database className="h-5 w-5 text-amber-500" /> Existing Project Details & System Architecture
</h2>
<p className="text-xs text-slate-500 leading-relaxed max-w-3xl">
High-level overview of active brand catalogs, PostgreSQL vector database tables, S3 image storage pipeline, and store intelligence ML models.
</p>
{loadingProject ? (
<div className="py-8 text-center text-xs text-slate-400">Loading project details...</div>
) : projectDetails ? (
<div className="mt-6 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
<div className="rounded-xl border border-amber-500/20 bg-amber-500/5 p-4">
<p className="text-[11px] font-semibold uppercase text-amber-700">Total Brands</p>
<p className="font-mono text-3xl font-extrabold text-ink-950 mt-1">{projectDetails.total_brands}</p>
<p className="text-[10px] text-slate-400 mt-1">Ingested brand tables in pgvector</p>
</div>
<div className="rounded-xl border border-emerald-500/20 bg-emerald-500/5 p-4">
<p className="text-[11px] font-semibold uppercase text-emerald-700">Total Products</p>
<p className="font-mono text-3xl font-extrabold text-ink-950 mt-1">{projectDetails.total_products}</p>
<p className="text-[10px] text-slate-400 mt-1">Unique products with vector embeddings</p>
</div>
<div className="rounded-xl border border-blue-500/20 bg-blue-500/5 p-4">
<p className="text-[11px] font-semibold uppercase text-blue-700">S3 Storage Status</p>
<p className="font-mono text-xl font-bold text-ink-950 mt-2 uppercase">{projectDetails.s3_image_status}</p>
<p className="text-[10px] text-slate-400 mt-1">Bucket: {projectDetails.storage_bucket}</p>
</div>
<div className="rounded-xl border border-purple-500/20 bg-purple-500/5 p-4">
<p className="text-[11px] font-semibold uppercase text-purple-700">System Version</p>
<p className="font-mono text-xl font-bold text-ink-950 mt-2">{projectDetails.version}</p>
<p className="text-[10px] text-slate-400 mt-1">Multi-Store & RAG Engine</p>
</div>
</div>
) : null}
</div>
{projectDetails?.brand_product_counts && (
<div className="rounded-2xl border border-ink-900/10 bg-paper-50 p-6 shadow-xs">
<h3 className="font-display text-sm font-bold text-ink-950 mb-4">Ingested Brand Database Breakdown</h3>
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-3">
{Object.entries(projectDetails.brand_product_counts).map(([bName, count]) => (
<div key={bName} className="flex items-center justify-between p-3 rounded-xl border border-ink-900/10 bg-white">
<span className="text-xs font-bold text-ink-950">{bName}</span>
<span className="font-mono text-xs font-bold bg-amber-100 text-amber-800 px-2 py-0.5 rounded-full">{count} items</span>
</div>
))}
</div>
</div>
)}
</div>
</div>
</div>
);
}