+
+ { setTitle(e.target.value); updateNote(note.id, { title: e.target.value }); }}
+ onBlur={handleSave}
+ placeholder="Untitled"
+ className="flex-1 text-lg font-semibold bg-transparent focus:outline-none"
+ />
+
+ {saving ? 'Saving...' : 'Saved'}
+
+
+
+
+ updateNote(note.id, { content })}
+ />
+
+
+ );
+}
diff --git a/apps/web/src/notes/NoteList.tsx b/apps/web/src/notes/NoteList.tsx
new file mode 100644
index 0000000..b3ce65a
--- /dev/null
+++ b/apps/web/src/notes/NoteList.tsx
@@ -0,0 +1,87 @@
+import { Trash2, Search } from 'lucide-react';
+import { useNotesStore } from '../stores/notes';
+import { cn } from '@yetanother/utils';
+
+function formatDate(dateStr: string) {
+ const d = new Date(dateStr);
+ const now = new Date();
+ const diff = now.getTime() - d.getTime();
+ if (diff < 86400000) return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
+ if (diff < 604800000) return d.toLocaleDateString([], { weekday: 'short' });
+ return d.toLocaleDateString([], { month: 'short', day: 'numeric' });
+}
+
+export function NoteList() {
+ const notes = useNotesStore((s) => s.notes);
+ const selectedNoteId = useNotesStore((s) => s.selectedNoteId);
+ const setSelectedNoteId = useNotesStore((s) => s.setSelectedNoteId);
+ const searchQuery = useNotesStore((s) => s.searchQuery);
+ const setSearchQuery = useNotesStore((s) => s.setSearchQuery);
+
+ const filtered = notes.filter((n) => {
+ if (n.status === 'deleted') return false;
+ if (!searchQuery) return true;
+ return n.title.toLowerCase().includes(searchQuery.toLowerCase());
+ });
+
+ return (
+
+
+
+
+ setSearchQuery(e.target.value)}
+ className="w-full pl-8 pr-3 py-1.5 text-sm rounded-md border bg-background focus:outline-none focus:ring-2 focus:ring-ring"
+ />
+
+
+
+
+ {filtered.length === 0 && (
+
+ {searchQuery ? 'No notes found' : 'No notes yet. Create one!'}
+
+ )}
+
+ {filtered.map((note) => (
+
+ ))}
+
+
+
+
+
+
+ );
+}
diff --git a/apps/web/src/notes/NotesPage.tsx b/apps/web/src/notes/NotesPage.tsx
new file mode 100644
index 0000000..723aa5a
--- /dev/null
+++ b/apps/web/src/notes/NotesPage.tsx
@@ -0,0 +1,47 @@
+import { Plus } from 'lucide-react';
+import { useNotesStore } from '../stores/notes';
+import { NoteList } from './NoteList';
+import { NoteEditor } from './NoteEditor';
+import { Button } from '@yetanother/ui';
+
+export function NotesPage() {
+ const addNote = useNotesStore((s) => s.addNote);
+ const setSelectedNoteId = useNotesStore((s) => s.setSelectedNoteId);
+
+ const handleCreate = () => {
+ const now = new Date().toISOString();
+ const newNote = {
+ id: crypto.randomUUID(),
+ title: '',
+ type: 'note' as const,
+ content: { type: 'doc', content: [{ type: 'paragraph' }] },
+ plainText: '',
+ status: 'active' as const,
+ workspaceId: crypto.randomUUID(),
+ tags: [],
+ folderId: null,
+ createdAt: now,
+ updatedAt: now,
+ };
+ addNote(newNote);
+ setSelectedNoteId(newNote.id);
+ };
+
+ return (
+