MVP: Pulse, Memory, History modules
- Mobile-first PWA with dark glassmorphic theme - Pulse: status card, recent sessions, memory snapshot - Memory: view/edit agent + user memory with usage bars - History: session list, platform filter, search, session replay - TanStack Query hooks for all Hermes WebAPI endpoints - Bottom tab navigation, safe-area support
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Pencil, Trash2, Check, X } from "lucide-react";
|
||||
|
||||
interface Props {
|
||||
content: string;
|
||||
onPatch: (newContent: string) => void;
|
||||
onDelete: () => void;
|
||||
}
|
||||
|
||||
export function MemoryEntry({ content, onPatch, onDelete }: Props) {
|
||||
const [editing, setEditing] = useState(false);
|
||||
const [editText, setEditText] = useState(content);
|
||||
const [confirmDelete, setConfirmDelete] = useState(false);
|
||||
|
||||
const handleSave = () => {
|
||||
if (editText.trim() && editText !== content) {
|
||||
onPatch(editText.trim());
|
||||
}
|
||||
setEditing(false);
|
||||
};
|
||||
|
||||
if (editing) {
|
||||
return (
|
||||
<div className="glass p-3 space-y-2">
|
||||
<textarea
|
||||
value={editText}
|
||||
onChange={(e) => setEditText(e.target.value)}
|
||||
className="w-full bg-transparent text-sm text-zinc-200 resize-none outline-none min-h-[80px]"
|
||||
autoFocus
|
||||
/>
|
||||
<div className="flex gap-2 justify-end">
|
||||
<button
|
||||
onClick={() => { setEditing(false); setEditText(content); }}
|
||||
className="p-1.5 rounded-lg text-zinc-500"
|
||||
>
|
||||
<X size={16} />
|
||||
</button>
|
||||
<button
|
||||
onClick={handleSave}
|
||||
className="p-1.5 rounded-lg"
|
||||
style={{ color: "#22c55e" }}
|
||||
>
|
||||
<Check size={16} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="glass p-4 group">
|
||||
<p className="text-sm text-zinc-300 whitespace-pre-wrap leading-relaxed">
|
||||
{content}
|
||||
</p>
|
||||
<div className="flex gap-2 justify-end mt-2 opacity-0 group-active:opacity-100 transition-opacity">
|
||||
<button
|
||||
onClick={() => setEditing(true)}
|
||||
className="p-1.5 rounded-lg text-zinc-500 active:text-zinc-300"
|
||||
>
|
||||
<Pencil size={14} />
|
||||
</button>
|
||||
{confirmDelete ? (
|
||||
<button
|
||||
onClick={() => { onDelete(); setConfirmDelete(false); }}
|
||||
className="px-2 py-1 rounded-lg text-xs font-medium"
|
||||
style={{ background: "rgba(239,68,68,0.2)", color: "#ef4444" }}
|
||||
>
|
||||
Confirm
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
onClick={() => setConfirmDelete(true)}
|
||||
className="p-1.5 rounded-lg text-zinc-500 active:text-red-400"
|
||||
>
|
||||
<Trash2 size={14} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user