editable fact triggers in the UI

master
Avraham Sakal 2 months ago
parent df1e263ef7
commit d44215841e

@ -53,6 +53,10 @@ export default function ChatPage() {
const [editingFactId, setEditingFactId] = useState<string | null>(null); const [editingFactId, setEditingFactId] = useState<string | null>(null);
const [editingFactContent, setEditingFactContent] = useState(""); const [editingFactContent, setEditingFactContent] = useState("");
// State for editing fact triggers
const [editingFactTriggerId, setEditingFactTriggerId] = useState<string | null>(null);
const [editingFactTriggerContent, setEditingFactTriggerContent] = useState("");
// Handle clicking outside to cancel editing // Handle clicking outside to cancel editing
useEffect(() => { useEffect(() => {
function handleClickOutside(event: MouseEvent) { function handleClickOutside(event: MouseEvent) {
@ -62,13 +66,20 @@ export default function ChatPage() {
setEditingFactId(null); setEditingFactId(null);
} }
} }
if (editingFactTriggerId && event.target instanceof Element) {
const editingElement = event.target.closest('.editing-fact-trigger');
if (!editingElement) {
setEditingFactTriggerId(null);
}
}
} }
document.addEventListener('mousedown', handleClickOutside); document.addEventListener('mousedown', handleClickOutside);
return () => { return () => {
document.removeEventListener('mousedown', handleClickOutside); document.removeEventListener('mousedown', handleClickOutside);
}; };
}, [editingFactId]); }, [editingFactId, editingFactTriggerId]);
const { const {
conversation, conversation,
@ -125,6 +136,16 @@ export default function ChatPage() {
await trpc.chat.factTriggers.deleteOne.mutate({ factTriggerId }); await trpc.chat.factTriggers.deleteOne.mutate({ factTriggerId });
} }
async function handleUpdateFactTrigger(factTriggerId: string, content: string) {
// Update the local state first
setFactTriggers(factTriggers.map(factTrigger =>
factTrigger.id === factTriggerId ? { ...factTrigger, content } : factTrigger
));
// Then update the database
await trpc.chat.factTriggers.update.mutate({ factTriggerId, content });
}
return ( return (
<> <>
<div> <div>
@ -285,16 +306,59 @@ export default function ChatPage() {
<List> <List>
{factTriggers.map((factTrigger) => ( {factTriggers.map((factTrigger) => (
<List.Item key={factTrigger.id}> <List.Item key={factTrigger.id}>
{factTrigger.content}{" "} {editingFactTriggerId === factTrigger.id ? (
<IconTrash <Group wrap="nowrap" className="editing-fact-trigger">
size={16} <Textarea
stroke={1.5} value={editingFactTriggerContent}
onClick={(e) => { onChange={(e) => setEditingFactTriggerContent(e.target.value)}
e.stopPropagation(); onKeyDown={(e) => {
e.preventDefault(); if (e.key === "Enter") {
handleDeleteFactTrigger(factTrigger.id); e.preventDefault();
}} handleUpdateFactTrigger(factTrigger.id, editingFactTriggerContent);
/> setEditingFactTriggerId(null);
} else if (e.key === "Escape") {
setEditingFactTriggerId(null);
}
}}
autoFocus
style={{ flex: 1 }}
/>
<ActionIcon
onClick={() => {
handleUpdateFactTrigger(factTrigger.id, editingFactTriggerContent);
setEditingFactTriggerId(null);
}}
>
<IconCheck size={16} />
</ActionIcon>
<ActionIcon
onClick={() => setEditingFactTriggerId(null)}
>
<IconX size={16} />
</ActionIcon>
</Group>
) : (
<Group wrap="nowrap">
<span style={{ flex: 1 }}>{factTrigger.content}</span>
<ActionIcon
onClick={() => {
setEditingFactTriggerId(factTrigger.id);
setEditingFactTriggerContent(factTrigger.content);
}}
>
<IconEdit size={16} />
</ActionIcon>
<IconTrash
size={16}
stroke={1.5}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
handleDeleteFactTrigger(factTrigger.id);
}}
/>
</Group>
)}
</List.Item> </List.Item>
))} ))}
</List> </List>

@ -78,6 +78,23 @@ export const factTriggers = router({
await db.write(); await db.write();
return { ok: true }; return { ok: true };
}), }),
update: publicProcedure
.input(
(x) =>
x as {
factTriggerId: string;
content: string;
},
)
.mutation(async ({ input: { factTriggerId, content } }) => {
const factTriggerIndex = db.data.factTriggers.findIndex(
(factTrigger) => factTrigger.id === factTriggerId,
);
if (factTriggerIndex === -1) throw new Error("Fact trigger not found");
db.data.factTriggers[factTriggerIndex].content = content;
await db.write();
return { ok: true };
}),
generateFromFact: publicProcedure generateFromFact: publicProcedure
.input( .input(
(x) => (x) =>

Loading…
Cancel
Save