import { useState, useEffect, Fragment } from "react"; import type { CorpusStats } from "./types"; import { api, checkConnection } from "./api"; import TrainingPanel from "./components/TrainingPanel"; import EngineSetup from "./components/EngineSetup"; import SemanticSearch from "./components/SemanticSearch"; import TextCompare from "./components/TextCompare"; import KeywordAnalysis from "./components/KeywordAnalysis"; import KeywordMatcher from "./components/KeywordMatcher"; import BatchAnalysis from "./components/BatchAnalysis"; import SimilarWords from "./components/SimilarWords"; import ContextAnalysis from "./components/ContextAnalysis"; import Word2VecPanel from "./components/Word2VecPanel"; import Word2VecTools from "./components/Word2VecTools"; import DatasetPanel from "./components/DatasetPanel"; import MetricCard from "./components/MetricCard"; import "./styles.css"; type NavGroup = "data" | "training" | "analysis"; type TrainingTab = "model" | "w2v"; type AnalysisTab = "context" | "words" | "search" | "compare" | "keyword" | "match" | "batch"; const STEPS: { id: NavGroup; label: string; needsIndex?: boolean }[] = [ { id: "data", label: "Data & Setup" }, { id: "training", label: "Training" }, { id: "analysis", label: "Analysis", needsIndex: true }, ]; const TRAINING_TABS: { id: TrainingTab; label: string }[] = [ { id: "model", label: "Fine-tune Model" }, { id: "w2v", label: "Word2Vec Baseline" }, ]; const ANALYSIS_TABS: { id: AnalysisTab; label: string }[] = [ { id: "context", label: "Context" }, { id: "words", label: "Similar Words" }, { id: "search", label: "Search" }, { id: "compare", label: "Compare" }, { id: "keyword", label: "Keywords" }, { id: "match", label: "Matcher" }, { id: "batch", label: "Batch" }, ]; export default function App() { const [group, setGroup] = useState("data"); const [trainingTab, setTrainingTab] = useState("model"); const [analysisTab, setAnalysisTab] = useState("context"); const [stats, setStats] = useState(null); const [showManualSetup, setShowManualSetup] = useState(false); const [serverError, setServerError] = useState(null); const [w2vReady, setW2vReady] = useState(false); const [w2vInfo, setW2vInfo] = useState<{ vocab_size: number; sentences: number; vector_size: number } | null>(null); const [resetLoading, setResetLoading] = useState(false); const ready = stats !== null && stats.index_built; useEffect(() => { checkConnection().then((err) => { setServerError(err); if (!err) { api.getStats().then(setStats).catch(() => {}); api.w2vStatus().then(res => { if (res.ready) { setW2vReady(true); setW2vInfo({ vocab_size: res.vocab_size!, sentences: res.sentences!, vector_size: res.vector_size! }); } }).catch(() => {}); } }); const interval = setInterval(() => { checkConnection().then(setServerError); }, 15000); return () => clearInterval(interval); }, []); function handleW2vReady(ready: boolean, info?: { vocab_size: number; sentences: number; vector_size: number }) { setW2vReady(ready); setW2vInfo(ready && info ? info : null); } async function handleReset() { setResetLoading(true); try { await api.w2vReset(); setW2vReady(false); setW2vInfo(null); } catch { // ignore } finally { setResetLoading(false); } } function handleStepClick(id: NavGroup, needsIndex?: boolean) { if (needsIndex && !ready) return; setGroup(id); } // ── W2V trained: stats bar + analysis tabs, no stepper ── if (w2vReady && w2vInfo) { return (

Contextual Similarity Engine

{stats && (
{stats.model_name} {stats.total_documents} docs {stats.total_chunks} chunks
)}
{serverError && (
Server unavailable: {serverError}
)} {/* W2V stats bar */}

Word2Vec Baseline

{/* W2V-specific tools: Similar Words, Compare, Semantic Search */}
{/* Transformer Analysis sub-tabs */} {/* Analysis content */}
{analysisTab === "context" && } {analysisTab === "words" && } {analysisTab === "search" && } {analysisTab === "compare" && } {analysisTab === "keyword" && } {analysisTab === "match" && } {analysisTab === "batch" && }
); } // ── Normal stepper flow ── return (

Contextual Similarity Engine

{stats && (
{stats.model_name} {stats.total_documents} docs {stats.total_chunks} chunks {stats.index_built ? "Index ready" : "Index not built"}
)}
{serverError && (
Server unavailable: {serverError}
)} {/* Progress Stepper */} {/* Sub-tabs */} {group === "training" && ( )} {group === "analysis" && ( )} {/* Content */}
{group === "data" && ( <> {showManualSetup && } )} {group === "training" && trainingTab === "model" && } {group === "training" && trainingTab === "w2v" && } {group === "analysis" && analysisTab === "context" && } {group === "analysis" && analysisTab === "words" && } {group === "analysis" && analysisTab === "search" && } {group === "analysis" && analysisTab === "compare" && } {group === "analysis" && analysisTab === "keyword" && } {group === "analysis" && analysisTab === "match" && } {group === "analysis" && analysisTab === "batch" && }
); }