import { useState, useEffect, useCallback } from 'react' import { motion, AnimatePresence } from 'framer-motion' import { FileText, Shield, Copy, Check, ChevronLeft, Layers, Search, Database, Hash, Activity, Code, } from 'lucide-react' const API_BASE = '' export default function FileDetail({ fileId, onClear }) { const [files, setFiles] = useState([]) const [selectedId, setSelectedId] = useState(fileId) const [meta, setMeta] = useState(null) const [summary, setSummary] = useState(null) const [capabilities, setCapabilities] = useState(null) const [state, setState] = useState(null) const [loading, setLoading] = useState(false) const [copied, setCopied] = useState(false) const [activeTab, setActiveTab] = useState('meta') // Fetch file list useEffect(() => { const fetchFiles = async () => { try { const res = await fetch(`${API_BASE}/files`) const data = await res.json() setFiles(data.files || []) if (!selectedId && data.files?.length > 0) { setSelectedId(data.files[0].file_id) } } catch { setFiles([]) } } fetchFiles() }, []) // Update selectedId when fileId prop changes useEffect(() => { if (fileId) setSelectedId(fileId) }, [fileId]) // Fetch detail data for selected file const fetchDetail = useCallback(async (id) => { if (!id) return setLoading(true) setMeta(null) setSummary(null) setCapabilities(null) setState(null) try { const [mRes, sRes, cRes, stRes] = await Promise.all([ fetch(`${API_BASE}/meta/${id}`).then(r => r.json()).catch(() => null), fetch(`${API_BASE}/summary/${id}`).then(r => r.json()).catch(() => null), fetch(`${API_BASE}/capabilities/${id}`).then(r => r.json()).catch(() => null), fetch(`${API_BASE}/superpose/state/${id}`).then(r => r.json()).catch(() => null), ]) setMeta(mRes) setSummary(sRes) setCapabilities(cRes) setState(stRes) } finally { setLoading(false) } }, []) useEffect(() => { fetchDetail(selectedId) }, [selectedId, fetchDetail]) const copyUrl = () => { navigator.clipboard?.writeText(`${API_BASE}/meta/${selectedId}`) setCopied(true) setTimeout(() => setCopied(false), 2000) } const selectedFile = files.find(f => f.file_id === selectedId) const isLive = state?.session_status === 'live' return (
{/* File selector */}
{onClear && ( )} {files.map(f => ( ))}
{loading && (
Fetching file data...
)} {!loading && meta && ( <> {/* File header */}
{meta.meta?.filename || selectedFile?.filename}
{selectedId}
{isLive ? '● LIVE' : '● OFFLINE'}
{/* Real measured metadata grid */}
{[ ['Size', meta.meta?.size_human || '—'], ['Lines', meta.meta?.total_lines || '—'], ['Format', meta.meta?.format || '—'], ['Chunks', meta.meta?.total_chunks || '—'], ['Words', meta.meta?.total_words || '—'], ['Chars', meta.meta?.total_chars || '—'], ['Entropy', meta.meta?.entropy || '—'], ['Merkle Root', meta.meta?.merkle_root?.slice(0, 12) + '...' || '—'], ].map(([label, value]) => (
{label}
{value}
))}
{state && (
Index Size
{state.compression_ratio || '—'}
Queries
{state.total_queries || 0}
Last Access
{state.last_access ? new Date(state.last_access * 1000).toLocaleTimeString() : 'Never'}
)}
{/* Tabs */}
{[ { id: 'meta', label: 'Meta', icon: FileText }, { id: 'summary', label: 'Summary', icon: Activity }, { id: 'capabilities', label: 'Capabilities', icon: Shield }, { id: 'chunks', label: 'Chunks', icon: Layers }, ].map(tab => ( ))}
{/* Tab content */} {/* Meta tab */} {activeTab === 'meta' && meta && (
Metadata
                    {JSON.stringify(meta, null, 2)}
                  
)} {/* Summary tab */} {activeTab === 'summary' && summary && (
{/* Semantic chunks */} {summary.semantic_chunks && (
Semantic Chunks ({summary.semantic_chunks.length})
{summary.semantic_chunks.map(chunk => (
#{chunk.idx} {chunk.type} L{chunk.lines} {chunk.size}B
))}
)} {/* Functions */} {summary.functions && summary.functions.length > 0 && (
Functions ({summary.functions.length})
{summary.functions.map((fn, i) => (
L{fn.line} {fn.symbol}
))}
)} {/* Top words */} {summary.top_words && (
Top Words
{summary.top_words.map((w, i) => ( {w.word} ×{w.count} ))}
)} {/* Section headers */} {summary.section_headers && summary.section_headers.length > 0 && (
Sections ({summary.section_headers.length})
{summary.section_headers.map((s, i) => (
{s.header} ×{s.count}
))}
)}
)} {/* Capabilities tab */} {activeTab === 'capabilities' && capabilities && (
{capabilities.total} Capabilities
{capabilities.capabilities?.map(cap => (
{cap.name}
))}
)} {/* Chunks tab */} {activeTab === 'chunks' && summary?.semantic_chunks && ( )}
)} {!loading && !meta && (
{files.length === 0 ? 'No files indexed.' : 'Select a file to inspect.'}
)}
) } function ChunkViewer({ fileId, chunks }) { const [selectedChunk, setSelectedChunk] = useState(null) const [chunkData, setChunkData] = useState(null) const [loadingChunk, setLoadingChunk] = useState(false) const fetchChunk = async (idx) => { setSelectedChunk(idx) setLoadingChunk(true) setChunkData(null) try { const res = await fetch(`${API_BASE}/chunk/${fileId}/${idx}`) const data = await res.json() setChunkData(data) } catch { setChunkData({ error: 'Failed to fetch chunk' }) } finally { setLoadingChunk(false) } } return (
{/* Chunk list */}
Chunks ({chunks.length})
{chunks.map(chunk => ( ))}
{/* Chunk content */}
{loadingChunk && (
Fetching chunk...
)} {!loadingChunk && !selectedChunk && (
Select a chunk to view its content.
)} {!loadingChunk && chunkData && (
Chunk #{selectedChunk} {chunkData.error && {chunkData.error}}
                {chunkData.content || chunkData.chunk_content || chunkData.text || JSON.stringify(chunkData, null, 2)}
              
)}
) }