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 [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
useEffect(() => {
function handleClickOutside(event: MouseEvent) {
@ -62,13 +66,20 @@ export default function ChatPage() {
setEditingFactId(null);
}
}
if (editingFactTriggerId && event.target instanceof Element) {
const editingElement = event.target.closest('.editing-fact-trigger');
if (!editingElement) {
setEditingFactTriggerId(null);
}
}
}
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [editingFactId]);
}, [editingFactId, editingFactTriggerId]);
const {
conversation,
@ -125,6 +136,16 @@ export default function ChatPage() {
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 (
<>
<div>
@ -285,16 +306,59 @@ export default function ChatPage() {
<List>
{factTriggers.map((factTrigger) => (
<List.Item key={factTrigger.id}>
{factTrigger.content}{" "}
<IconTrash
size={16}
stroke={1.5}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();
handleDeleteFactTrigger(factTrigger.id);
}}
/>
{editingFactTriggerId === factTrigger.id ? (
<Group wrap="nowrap" className="editing-fact-trigger">
<Textarea
value={editingFactTriggerContent}
onChange={(e) => setEditingFactTriggerContent(e.target.value)}
onKeyDown={(e) => {
if (e.key === "Enter") {
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>

@ -78,6 +78,23 @@ export const factTriggers = router({
await db.write();
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
.input(
(x) =>

Loading…
Cancel
Save