'use client' import { useState, useEffect } from 'react' import { NetworkGraph } from '@/components/network-graph' import { useRouter } from 'next/navigation' import { motion } from 'motion/react' import { Sparkles, RefreshCw, Layers, Trophy, Zap, Lightbulb } from 'lucide-react' interface Note { id: string title: string | null content: string clusterId?: number } interface Cluster { id: string clusterId: number name?: string noteIds: string[] color?: string } interface BridgeNote { noteId: string bridgeScore: number clustersConnected: number[] clusterNames?: string[] note?: { id: string title: string | null content: string } } interface BridgeSuggestion { clusterAId: number clusterBId: number clusterAName: string clusterBName: string suggestedTitle: string suggestedContent: string justification: string } const COLOR_PALETTE = ['#F87171', '#60A5FA', '#34D399', '#FBBF24', '#A78BFA', '#F472B6', '#2DD4BF'] export default function InsightsPage() { const router = useRouter() const [notes, setNotes] = useState([]) const [clusters, setClusters] = useState([]) const [bridgeNotes, setBridgeNotes] = useState([]) const [suggestions, setSuggestions] = useState([]) const [loading, setLoading] = useState(true) const [isCalculating, setIsCalculating] = useState(false) useEffect(() => { loadInitialData() }, []) const loadInitialData = async () => { setLoading(true) try { // First, try to get cached clusters const res = await fetch('/api/clusters') if (res.ok) { const data = await res.json() // Check if we have clusters if (data.clusters && data.clusters.length > 0) { const clustersWithColors = data.clusters.map((c: Cluster, i: number) => ({ ...c, id: c.clusterId.toString(), color: COLOR_PALETTE[i % COLOR_PALETTE.length] })) setNotes(data.notes || []) setClusters(clustersWithColors) // Load bridge notes const bridgeRes = await fetch('/api/bridge-notes?details=true') if (bridgeRes.ok) { const bridgeData = await bridgeRes.json() setBridgeNotes(bridgeData.bridgeNotes || []) } // Load suggestions const suggestionsRes = await fetch('/api/bridge-notes/suggestions') if (suggestionsRes.ok) { const suggestionsData = await suggestionsRes.json() setSuggestions(suggestionsData.suggestions || []) } } else { // No clusters - trigger calculation if we have enough notes if (data.totalNotes >= 10) { await performAnalysis() } else { // Not enough notes - show empty state } } } } catch (error) { console.error('Error loading data:', error) } finally { setLoading(false) } } const performAnalysis = async () => { setIsCalculating(true) try { const res = await fetch('/api/clusters', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ force: true }) }) if (res.ok) { const data = await res.json() const clustersWithColors = (data.clusters || []).map((c: Cluster, i: number) => ({ ...c, id: c.clusterId.toString(), color: COLOR_PALETTE[i % COLOR_PALETTE.length] })) setNotes(data.notes || []) setClusters(clustersWithColors) setBridgeNotes(data.bridgeNotes || []) // Load suggestions (they were generated during POST) const suggestionsRes = await fetch('/api/bridge-notes/suggestions') if (suggestionsRes.ok) { const suggestionsData = await suggestionsRes.json() setSuggestions(suggestionsData.suggestions || []) } } } catch (error) { console.error('Error running analysis:', error) } finally { setIsCalculating(false) } } const handleNoteClick = (noteId: string) => { router.push(`/home?note=${noteId}`) } const bridgeList = bridgeNotes.map(b => ({ ...b, title: b.note?.title || 'Unknown Note' })) return (
{/* Header */}

Semantic Insights

Discovering the hidden architecture of your knowledge

{/* Loading State */} {loading && (

Analyzing your notes...

)} {/* Empty State - only if truly no notes */} {!loading && clusters.length === 0 && !isCalculating && (

Discover your knowledge clusters

Click "Re-sync Network" to analyze your notes and find hidden connections

)} {/* Main Content */} {!loading && clusters.length > 0 && (
{/* Left: Graph View */}
{/* Right: Insight Dashboard */}
{/* Stats Summary */}
Clusters
{clusters.length}
Bridge Notes
{bridgeNotes.length}
{/* Bridge Notes Section */}

Powerful Bridge Notes

{bridgeList.map((bridge) => ( handleNoteClick(bridge.noteId)} className="p-4 rounded-xl bg-white dark:bg-white/5 border border-border hover:border-ochre/40 transition-all cursor-pointer group" >

{bridge.title}

Score: {(bridge.bridgeScore * 100).toFixed(0)}%
{bridge.clusterNames?.map((name, i) => { const cluster = clusters.find(c => c.name === name) return (
{name}
) })}
))} {bridgeList.length === 0 && !isCalculating && (
No significant bridge notes found yet. Deepen your research to find new connections.
)}
{/* Connection Suggestions */}

Missing Links (AI Generated)

{suggestions.map((s, idx) => (
A
B
Bridging {s.clusterAName} & {s.clusterBName}

{s.suggestedTitle}

{s.suggestedContent}

{s.justification}
))} {suggestions.length === 0 && !isCalculating && (

No connection suggestions yet

All your clusters may already be connected!

)} {isCalculating && (
{[1, 2].map(i => (
))}
)}
)}
) }