From d47d1a014a71ae65cbbf1b384eed87c6fe078b07 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 2 May 2026 11:58:13 +0900 Subject: feat(note-types): make note type CRUD work fully offline-first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CreateNoteTypeModal, DeleteNoteTypeModal, and the NoteTypeEditor (which covers field add/edit/delete/reorder) now write through the local IndexedDB repositories and fire-and-forget syncActionAtom, mirroring the deck-CRUD pattern. The dead EditNoteTypeModal — never imported — is removed. The local hasNotes / hasNoteFieldValues guards mirror the server's delete-time checks so a note type with attached notes, or a field with saved values, can't be silently soft-deleted offline. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/client/db/repositories.ts | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'src/client/db') diff --git a/src/client/db/repositories.ts b/src/client/db/repositories.ts index 9f1d27c..085a23c 100644 --- a/src/client/db/repositories.ts +++ b/src/client/db/repositories.ts @@ -461,6 +461,19 @@ export const localNoteTypeRepository = { return true; }, + /** + * Returns true if any non-deleted note still uses this note type. Used to + * block deletion (mirrors the server's hasNotes check). + */ + async hasNotes(id: string): Promise { + const note = await db.notes + .where("noteTypeId") + .equals(id) + .filter((n) => n.deletedAt === null) + .first(); + return note !== undefined; + }, + /** * Get all unsynced note types */ @@ -572,6 +585,48 @@ export const localNoteFieldTypeRepository = { return true; }, + /** + * Returns true if any noteFieldValue references this field type. Used to + * block deletion (mirrors the server's hasNoteFieldValues check). + */ + async hasNoteFieldValues(id: string): Promise { + const value = await db.noteFieldValues + .where("noteFieldTypeId") + .equals(id) + .first(); + return value !== undefined; + }, + + /** + * Reorder field types in a note type. The given fieldIds become the new + * ordering 0..n-1. Returns the reordered field types in the new order. + */ + async reorder( + noteTypeId: string, + fieldIds: string[], + ): Promise { + const now = new Date(); + const result = await db.transaction("rw", db.noteFieldTypes, async () => { + const updated: LocalNoteFieldType[] = []; + for (let i = 0; i < fieldIds.length; i++) { + const fieldId = fieldIds[i]; + if (!fieldId) continue; + const field = await db.noteFieldTypes.get(fieldId); + if (!field || field.noteTypeId !== noteTypeId) continue; + const next: LocalNoteFieldType = { + ...field, + order: i, + updatedAt: now, + _synced: false, + }; + await db.noteFieldTypes.put(next); + updated.push(next); + } + return updated; + }); + return result.sort((a, b) => a.order - b.order); + }, + /** * Get all unsynced field types */ -- cgit v1.3.1