"use client" import { useState } from "react" import { BookOpen, InboxIcon, LoaderCircle, RefreshCw, Zap, Clock, Tag, FileText, Lightbulb, Repeat2, StickyNote, ArrowRightLeft, CalendarClock, ListTodo, } from "lucide-react" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import type { KnowledgeData, KnowledgeEntry, CapturesData, CaptureEntry, Classification, } from "@/lib/knowledge-captures-types" import { cn } from "@/lib/utils" import { useSFWorkspaceActions, useSFWorkspaceState, } from "@/lib/sf-workspace-store" // ═══════════════════════════════════════════════════════════════════════ // SHARED HELPERS // ═══════════════════════════════════════════════════════════════════════ function PanelHeader({ title, subtitle, status, onRefresh, refreshing, }: { title: string subtitle?: string | null status?: React.ReactNode onRefresh: () => void refreshing: boolean }) { return (

{title}

{status} {subtitle && {subtitle}}
) } function PanelError({ message }: { message: string }) { return (
{message}
) } function PanelLoading({ label }: { label: string }) { return (
{label}
) } function PanelEmpty({ message }: { message: string }) { return (
{message}
) } function StatPill({ label, value, variant }: { label: string; value: number | string; variant?: "default" | "error" | "warning" | "info" }) { return (
{label} {value}
) } // ═══════════════════════════════════════════════════════════════════════ // KNOWLEDGE TYPE STYLING // ═══════════════════════════════════════════════════════════════════════ function knowledgeTypeBadge(type: KnowledgeEntry["type"]) { switch (type) { case "rule": return { label: "Rule", className: "border-violet-500/30 bg-violet-500/10 text-violet-400" } case "pattern": return { label: "Pattern", className: "border-info/30 bg-info/10 text-info" } case "lesson": return { label: "Lesson", className: "border-warning/30 bg-warning/10 text-warning" } case "freeform": return { label: "Freeform", className: "border-success/30 bg-success/10 text-success" } } } function KnowledgeTypeIcon({ type, className }: { type: KnowledgeEntry["type"]; className?: string }) { const base = cn("h-3.5 w-3.5 shrink-0", className) switch (type) { case "rule": return case "pattern": return case "lesson": return case "freeform": return } } // ═══════════════════════════════════════════════════════════════════════ // CAPTURE STATUS STYLING // ═══════════════════════════════════════════════════════════════════════ function captureStatusStyle(status: CaptureEntry["status"]) { switch (status) { case "pending": return { label: "Pending", className: "border-warning/30 bg-warning/10 text-warning" } case "triaged": return { label: "Triaged", className: "border-info/30 bg-info/10 text-info" } case "resolved": return { label: "Resolved", className: "border-success/30 bg-success/10 text-success" } } } function classificationLabel(c: Classification): string { switch (c) { case "quick-task": return "Quick Task" case "inject": return "Inject" case "defer": return "Defer" case "replan": return "Replan" case "note": return "Note" } } function ClassificationIcon({ classification, className }: { classification: Classification; className?: string }) { const base = cn("h-3 w-3 shrink-0", className) switch (classification) { case "quick-task": return case "inject": return case "defer": return case "replan": return case "note": return } } const CLASSIFICATION_OPTIONS: Classification[] = ["quick-task", "inject", "defer", "replan", "note"] // ═══════════════════════════════════════════════════════════════════════ // KNOWLEDGE TAB CONTENT // ═══════════════════════════════════════════════════════════════════════ function KnowledgeEntryRow({ entry }: { entry: KnowledgeEntry }) { const badge = knowledgeTypeBadge(entry.type) return (
{entry.title} {badge.label}
{entry.content && (

{entry.content}

)}
) } function KnowledgeTabContent({ data, phase, error, onRefresh, }: { data: KnowledgeData | null phase: string error: string | null onRefresh: () => void }) { if (phase === "loading") return if (phase === "error" && error) return if (!data || data.entries.length === 0) return return (
{data.entries.map((entry) => ( ))}
{data.lastModified && (

Last modified: {new Date(data.lastModified).toLocaleString()}

)}
) } // ═══════════════════════════════════════════════════════════════════════ // CAPTURES TAB CONTENT // ═══════════════════════════════════════════════════════════════════════ function CaptureEntryRow({ entry, onResolve, resolvePending, }: { entry: CaptureEntry onResolve: (captureId: string, classification: Classification) => void resolvePending: boolean }) { const status = captureStatusStyle(entry.status) return (
{entry.text} {status.label} {entry.classification && ( {classificationLabel(entry.classification)} )}
{entry.timestamp && (
{entry.timestamp}
)} {entry.resolution && (

{entry.resolution}

)} {entry.status === "pending" && (
{CLASSIFICATION_OPTIONS.map((c) => ( ))}
)}
) } function CapturesTabContent({ data, phase, error, resolvePending, resolveError, onRefresh, onResolve, }: { data: CapturesData | null phase: string error: string | null resolvePending: boolean resolveError: string | null onRefresh: () => void onResolve: (captureId: string, classification: Classification) => void }) { if (phase === "loading") return if (phase === "error" && error) return if (!data || data.entries.length === 0) return return (
0 ? "warning" : "default"} /> 0 ? "info" : "default"} />
} onRefresh={onRefresh} refreshing={phase === "loading"} /> {resolveError && (
Resolve error: {resolveError}
)}
{data.entries.map((entry) => ( ))}
) } // ═══════════════════════════════════════════════════════════════════════ // MAIN PANEL COMPONENT // ═══════════════════════════════════════════════════════════════════════ interface KnowledgeCapturesPanelProps { initialTab: "knowledge" | "captures" } export function KnowledgeCapturesPanel({ initialTab }: KnowledgeCapturesPanelProps) { const [activeTab, setActiveTab] = useState<"knowledge" | "captures">(initialTab) const workspace = useSFWorkspaceState() const { loadKnowledgeData, loadCapturesData, resolveCaptureAction } = useSFWorkspaceActions() const knowledgeCaptures = workspace.commandSurface.knowledgeCaptures const knowledgeState = knowledgeCaptures.knowledge const capturesState = knowledgeCaptures.captures const resolveState = knowledgeCaptures.resolveRequest const capturesData = capturesState.data as CapturesData | null const pendingCount = capturesData?.pendingCount ?? 0 const handleResolve = (captureId: string, classification: Classification) => { void resolveCaptureAction({ captureId, classification, resolution: "Manual browser triage", rationale: "Triaged via web UI", }) } return (
{/* Tab bar */}
{/* Tab content */}
{activeTab === "knowledge" ? ( void loadKnowledgeData()} /> ) : ( void loadCapturesData()} onResolve={handleResolve} /> )}
) }