- DB: new note_folders table (per-user unique name) + nullable folder_id on
notes with ON DELETE SET NULL.
- API: full /note-folders CRUD with user scoping; /notes POST/PATCH validate
folder ownership; folder noteCount is tab-aware (active vs archived) via
?archived= query.
- Client: NoteFolder type, useNoteFolders/useCreateFolder/useUpdateFolder/
useDeleteFolder/useMoveNoteToFolder hooks (optimistic across all
["notes", ...] caches).
- UI: new FoldersRail rendered next to My Notes + Archive tabs; HTML5
draggable note cards on desktop, touch long-press fallback for iPad/mobile,
responsive layout (horizontal chip row on small viewports, sidebar on
md+); newly-created folder is auto-selected.
- Bilingual: notes.folders.* keys added to en.json and ar.json (RTL works
via existing dir prop wired from i18n.language).
- Test: tests/notes-folders.spec.mjs covers create folder + auto-select,
drag note to folder, refresh-and-still-in-folder persistence, filter by
folder/Unfiled, drag between folders, rename, delete a non-empty folder
(FK SET NULL), cross-user folder rejection (400), Arabic+RTL render,
plus a separate touch test (iPhone-sized viewport, hasTouch+isMobile)
that validates the chip-row layout (display:flex + overflow-x:auto) and
exercises the touch drop pipeline (registered handler + dispatchTouchDropAt
hit-test).
Drift from plan: none. Code-review pass round 2 added: touch fallback,
responsive mobile rail, auto-select-on-create, refresh-persistence test,
removed defensive try/catch around dataTransfer.
- DB: new note_folders table (per-user unique name) + nullable folder_id on
notes with ON DELETE SET NULL.
- API: full /note-folders CRUD with user scoping; /notes POST/PATCH validate
folder ownership; folder noteCount is tab-aware (active vs archived) via
?archived= query.
- Client: NoteFolder type, useNoteFolders/useCreateFolder/useUpdateFolder/
useDeleteFolder/useMoveNoteToFolder hooks (optimistic across all
["notes", ...] caches).
- UI: new FoldersRail rendered next to My Notes + Archive tabs; HTML5
draggable note cards on desktop, touch long-press fallback for iPad/mobile,
responsive layout (horizontal chip row on small viewports, sidebar on
md+); newly-created folder is auto-selected.
- Bilingual: notes.folders.* keys added to en.json and ar.json (RTL works
via existing dir prop wired from i18n.language).
- Test: tests/notes-folders.spec.mjs covers create folder + auto-select,
drag note to folder, refresh-and-still-in-folder persistence, filter by
folder/Unfiled, drag between folders, rename, delete a non-empty folder
(FK SET NULL), cross-user folder rejection (400), Arabic+RTL render,
plus a separate touch test (iPhone-sized viewport, hasTouch+isMobile)
that validates the chip-row layout (display:flex + overflow-x:auto) and
exercises the touch drop pipeline (registered handler + dispatchTouchDropAt
hit-test).
Drift from plan: none. Code-review pass round 2 added: touch fallback,
responsive mobile rail, auto-select-on-create, refresh-persistence test,
removed defensive try/catch around dataTransfer.
- DB: new note_folders table (per-user unique name) + nullable folder_id on
notes with ON DELETE SET NULL; pushed via @workspace/db.
- API: full /note-folders CRUD with user scoping; /notes POST/PATCH validate
folder ownership; folder noteCount is tab-aware (active vs archived) via
?archived= query param computed by GROUP BY (drizzle correlated subquery
was returning 0 — replaced with two queries merged in JS).
- Client: NoteFolder type, useNoteFolders/useCreateFolder/useUpdateFolder/
useDeleteFolder/useMoveNoteToFolder hooks (optimistic update for moves
across all ["notes", ...] caches).
- UI: new FoldersRail (artifacts/tx-os/src/components/notes/folders-rail.tsx)
rendered next to My Notes + Archive tabs; HTML5 draggable note cards with
module-scoped DRAGGING_NOTE_ID fallback; visible drop highlight; rename +
delete + create inline; folder-scoped + Unfiled filtering in notes.tsx.
- Bilingual: notes.folders.* keys added to en.json and ar.json (RTL works
via existing dir prop wired from i18n.language).
- Test: artifacts/tx-os/tests/notes-folders.spec.mjs covers create folder,
drag note to folder, filter by folder/Unfiled, drag between folders,
rename, delete a non-empty folder (verifies FK SET NULL + Unfiled count),
cross-user folder rejection (400), and Arabic+RTL rendering.
Drift from plan: none — all originally scoped work shipped. Strengthened
e2e + cross-user check + tab-aware counts added per code review feedback.