"use client"; import { TryTab } from "./Sidebar"; import { useState, useRef, useCallback, useEffect } from "react"; import { saveLatestUpload, getLatestUpload, deleteLatestUpload } from "../../lib/idb"; interface CenterPanelProps { tab: TryTab; } interface UploadedFileMeta { name: string; size: number; type: string; contentPreview: string; } export function CenterPanel({ tab }: CenterPanelProps) { const [fileMeta, setFileMeta] = useState(null); const [isDragging, setIsDragging] = useState(false); const [progress, setProgress] = useState(0); const inputRef = useRef(null); const [loadedFromCache, setLoadedFromCache] = useState(false); const reset = () => { setFileMeta(null); setProgress(0); }; const processFile = useCallback((f: File) => { if (!f) return; setProgress(0); if (f.size > 1024 * 1024) { setFileMeta({ name: f.name, size: f.size, type: f.type, contentPreview: "File too large for preview (limit 1MB).", }); return; } const reader = new FileReader(); reader.onprogress = (evt) => { if (evt.lengthComputable) { const pct = Math.min(100, Math.round((evt.loaded / evt.total) * 100)); setProgress(pct); } else { setProgress((p) => (p < 90 ? p + 5 : p)); } }; reader.onload = async () => { try { const buf = reader.result as ArrayBuffer; const decoder = new TextDecoder(); const text = decoder.decode(buf); const metaObj: UploadedFileMeta = { name: f.name, size: f.size, type: f.type || "unknown", contentPreview: text.slice(0, 4000), }; setFileMeta(metaObj); // Save file blob and meta to browser cache (IndexedDB) try { await saveLatestUpload(f, metaObj); } catch {} setProgress(100); } catch (e) { const metaObj: UploadedFileMeta = { name: f.name, size: f.size, type: f.type || "unknown", contentPreview: "Unable to decode preview.", }; setFileMeta(metaObj); try { await saveLatestUpload(f, metaObj); } catch {} setProgress(100); } }; reader.onerror = () => { setProgress(0); }; reader.readAsArrayBuffer(f); }, []); function handleFileChange(e: React.ChangeEvent) { const f = e.target.files?.[0]; processFile(f as File); } const onDragOver = (e: React.DragEvent) => { e.preventDefault(); setIsDragging(true); }; const onDragLeave = () => setIsDragging(false); const onDrop = (e: React.DragEvent) => { e.preventDefault(); setIsDragging(false); const f = e.dataTransfer.files?.[0]; processFile(f as File); }; // Load last cached upload on mount (processing tab only) useEffect(() => { let ignore = false; if (tab !== "processing") return; (async () => { try { const { meta } = await getLatestUpload(); if (!ignore && meta) { setFileMeta(meta as UploadedFileMeta); setLoadedFromCache(true); } } catch {} })(); return () => { ignore = true; }; }, [tab]); function renderTabContent() { switch (tab) { case "processing": return (

Upload & Process Data

Upload a CSV / JSON / text file. We will later parse, detect PII, and queue analyses.

Drag & drop a CSV / JSON / TXT here, or click to browse.

{progress > 0 && (
Processing {progress}%
)} {fileMeta && (
{fileMeta.name}
{Math.round(fileMeta.size / 1024)} KB
{loadedFromCache && (
Loaded from browser cache
)}
{fileMeta.type || "Unknown type"}
										{fileMeta.contentPreview || "(no preview)"}
									
)}
); case "bias-analysis": return (

Bias Analysis (Placeholder)

Once processing completes, bias metrics will appear here (distribution, representation, fairness indicators).

); case "risk-analysis": return (

Risk Analysis (Placeholder)

Potential privacy exposure, sensitive attribute concentration, consent gaps will be displayed.

); case "bias-risk-mitigation": return (

Mitigation Suggestions (Placeholder)

Recommended transformations, anonymization strategies, sampling adjustments, consent workflows.

); case "results": return (

Results Summary (Placeholder)

Aggregated findings and downloadable compliance report will appear here.

); default: return null; } } return (
{renderTabContent()}
); }