@@ -165,6 +165,7 @@ export default function SettingsPage() {
165165 const [ loading , setLoading ] = useState ( true )
166166 const [ saving , setSaving ] = useState ( false )
167167 const [ exporting , setExporting ] = useState ( false )
168+ const [ rebuildingGraph , setRebuildingGraph ] = useState ( false )
168169 const [ deleteConfirm , setDeleteConfirm ] = useState ( false )
169170 const [ deleting , setDeleting ] = useState ( false )
170171
@@ -260,6 +261,21 @@ export default function SettingsPage() {
260261 }
261262 }
262263
264+ async function handleRebuildGraph ( ) {
265+ if ( rebuildingGraph ) return
266+ setRebuildingGraph ( true )
267+ try {
268+ const res = await fetch ( "/api/graph" , { method : "POST" } )
269+ if ( ! res . ok ) throw new Error ( "Rebuild failed" )
270+ const { count } = await res . json ( )
271+ toast . success ( `Knowledge graph rebuilt — ${ count } connection${ count !== 1 ? "s" : "" } found.` )
272+ } catch {
273+ toast . error ( "Graph rebuild failed. Make sure the API is running." )
274+ } finally {
275+ setRebuildingGraph ( false )
276+ }
277+ }
278+
263279 async function handleDelete ( ) {
264280 if ( deleting || ! user ) return
265281 setDeleting ( true )
@@ -458,6 +474,53 @@ export default function SettingsPage() {
458474 ) }
459475 </ button >
460476 </ div >
477+
478+ < div className = "mt-4 flex items-center justify-between gap-4 border-t border-border pt-4" >
479+ < div >
480+ < p className = "text-sm font-medium" > Knowledge graph</ p >
481+ < p className = "mt-0.5 text-[11px] text-muted-foreground" >
482+ Re-analyse all snippets to detect prerequisite relationships
483+ </ p >
484+ </ div >
485+ < button
486+ type = "button"
487+ onClick = { handleRebuildGraph }
488+ disabled = { rebuildingGraph }
489+ className = { cn (
490+ "flex shrink-0 items-center gap-1.5 rounded-xl border border-border px-3.5 py-2" ,
491+ "text-sm font-medium text-foreground" ,
492+ "hover:bg-accent transition-colors duration-150" ,
493+ "active:scale-[0.97]" ,
494+ "disabled:cursor-not-allowed disabled:opacity-50" ,
495+ ) }
496+ >
497+ { rebuildingGraph ? (
498+ < >
499+ < Spinner className = "size-3.5" />
500+ Building…
501+ </ >
502+ ) : (
503+ < >
504+ < svg width = "13" height = "13" viewBox = "0 0 13 13" fill = "none" aria-hidden >
505+ < path
506+ d = "M2 6.5a4.5 4.5 0 014.5-4.5A4.5 4.5 0 0111 6.5M11 6.5a4.5 4.5 0 01-4.5 4.5A4.5 4.5 0 012 6.5"
507+ stroke = "currentColor"
508+ strokeWidth = "1.4"
509+ strokeLinecap = "round"
510+ />
511+ < path
512+ d = "M9.5 4.5L11 6.5l2-1.5"
513+ stroke = "currentColor"
514+ strokeWidth = "1.4"
515+ strokeLinecap = "round"
516+ strokeLinejoin = "round"
517+ />
518+ </ svg >
519+ Rebuild
520+ </ >
521+ ) }
522+ </ button >
523+ </ div >
461524 </ Section >
462525
463526 { /* ── Danger zone ── */ }
0 commit comments