import { useEffect, useState, useCallback } from "react"; import { useParams, useNavigate } from "react-router-dom"; import { getMemoryApi, updateMemoryApi, deleteMemoryApi, getFeedbackApi, submitFeedbackApi, } from "../api/client.ts"; import type { GetMemoryResult, Feedback } from "@fixonce/shared"; export function MemoryDetail() { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); const [result, setResult] = useState(null); const [feedback, setFeedback] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [editing, setEditing] = useState(false); const [editTitle, setEditTitle] = useState(""); const [editContent, setEditContent] = useState(""); const [editSummary, setEditSummary] = useState(""); const [saving, setSaving] = useState(false); // Feedback form const [feedbackText, setFeedbackText] = useState(""); const [feedbackTag, setFeedbackTag] = useState(""); const [feedbackAction, setFeedbackAction] = useState(""); const [submittingFeedback, setSubmittingFeedback] = useState(false); const loadMemory = useCallback(async () => { if (!id) return; setLoading(true); setError(null); try { const [memResult, fb] = await Promise.all([ getMemoryApi(id, "large"), getFeedbackApi(id), ]); setResult(memResult); setFeedback(fb); const m = memResult.memory; setEditTitle(m.title); setEditContent(m.content); setEditSummary(m.summary); } catch (err) { setError(err instanceof Error ? err.message : "Failed to load memory"); } finally { setLoading(false); } }, [id]); useEffect(() => { void loadMemory(); }, [loadMemory]); async function handleSave() { if (!id) return; setSaving(true); setError(null); try { await updateMemoryApi(id, { title: editTitle, content: editContent, summary: editSummary, }); setEditing(false); void loadMemory(); } catch (err) { setError(err instanceof Error ? err.message : "Failed to save changes"); } finally { setSaving(false); } } async function handleDelete() { if (!id) return; if (!window.confirm("Permanently delete this memory? This cannot be undone.")) { return; } try { await deleteMemoryApi(id); navigate("/"); } catch (err) { setError(err instanceof Error ? err.message : "Failed to delete memory"); } } async function handleSubmitFeedback(e: React.FormEvent) { e.preventDefault(); if (!id) return; setSubmittingFeedback(true); try { await submitFeedbackApi({ memory_id: id, text: feedbackText || undefined, tags: feedbackTag ? [feedbackTag as Feedback["tags"][number]] : undefined, suggested_action: feedbackAction ? (feedbackAction as "keep" | "remove" | "fix") : undefined, }); setFeedbackText(""); setFeedbackTag(""); setFeedbackAction(""); const fb = await getFeedbackApi(id); setFeedback(fb); } catch (err) { setError(err instanceof Error ? err.message : "Failed to submit feedback"); } finally { setSubmittingFeedback(false); } } if (loading) return

Loading memory...

; if (!result) return

Memory not found.

; const memory = result.memory; return (

{editing ? "Edit Memory" : memory.title}

{!editing && ( )}
{error &&

{error}

} {editing ? (
setEditTitle(e.target.value)} style={inputStyle} />