diff --git a/web/src/app/(app)/notes/[noteId]/page.tsx b/web/src/app/(app)/notes/[noteId]/page.tsx index ace9b28..9aee76f 100644 --- a/web/src/app/(app)/notes/[noteId]/page.tsx +++ b/web/src/app/(app)/notes/[noteId]/page.tsx @@ -9,7 +9,7 @@ import { LinkedNotesPanel } from "@/components/LinkedNotesPanel"; import { TaskReviewPanel } from "@/components/TaskReviewPanel"; import { ArtifactPanel } from "@/components/ArtifactPanel"; import { AgentTimeline } from "@/components/AgentTimeline"; -import { createNoteArtifact, getNoteDetail, updateNoteDetail } from "@/lib/notes-client"; +import { createNoteArtifact, createNoteTask, getNoteDetail, updateNoteDetail } from "@/lib/notes-client"; import type { NoteDetail } from "@/lib/types"; export default function NoteDetailPage() { @@ -17,6 +17,7 @@ export default function NoteDetailPage() { const noteId = params.noteId; const [note, setNote] = useState(null); const [isSaving, setIsSaving] = useState(false); + const [isCreatingTask, setIsCreatingTask] = useState(false); const [isCreatingArtifact, setIsCreatingArtifact] = useState(false); const [error, setError] = useState(null); @@ -81,6 +82,32 @@ export default function NoteDetailPage() { } } + async function handleCreateTask(input: { title: string; description?: string }) { + if (!note) { + return; + } + + setIsCreatingTask(true); + + try { + await createNoteTask({ + id: crypto.randomUUID(), + workspaceId: note.workspaceId, + noteId: note.id, + title: input.title, + description: input.description, + source: "manual", + }); + const refreshed = await getNoteDetail(note.id); + setNote(refreshed); + setError(null); + } catch (err) { + setError(err instanceof Error ? err.message : "Unable to create task"); + } finally { + setIsCreatingTask(false); + } + } + if (!note) { return ( {error} : null} - + diff --git a/web/src/components/TaskReviewPanel.tsx b/web/src/components/TaskReviewPanel.tsx index e3a1400..2a06e50 100644 --- a/web/src/components/TaskReviewPanel.tsx +++ b/web/src/components/TaskReviewPanel.tsx @@ -1,11 +1,77 @@ +import { useState } from "react"; import type { NoteTask } from "@/lib/types"; -export function TaskReviewPanel({ tasks }: { tasks: NoteTask[] }) { +export function TaskReviewPanel({ + tasks, + onCreate, + isCreating = false, +}: { + tasks: NoteTask[]; + onCreate: (input: { title: string; description?: string }) => Promise; + isCreating?: boolean; +}) { + const [title, setTitle] = useState(""); + const [description, setDescription] = useState(""); + + async function handleCreateTask() { + if (!title.trim()) { + return; + } + + await onCreate({ + title: title.trim(), + description: description.trim() || undefined, + }); + + setTitle(""); + setDescription(""); + } + return (
Task extraction review
- mock extraction + backend-backed review +
+
+
+ + setTitle(event.target.value)} + placeholder="Task title" + /> +
+