aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/client/components/CreateNoteTypeModal.tsx
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-02 11:58:13 +0900
committernsfisis <nsfisis@gmail.com>2026-05-02 11:58:13 +0900
commitd47d1a014a71ae65cbbf1b384eed87c6fe078b07 (patch)
tree76c3af22e10f963104f84f3d680c5dddfc8b2be6 /src/client/components/CreateNoteTypeModal.tsx
parent023d0fcfce575030ee503c5f60df8c28dba7ab07 (diff)
downloadkioku-d47d1a014a71ae65cbbf1b384eed87c6fe078b07.tar.gz
kioku-d47d1a014a71ae65cbbf1b384eed87c6fe078b07.tar.zst
kioku-d47d1a014a71ae65cbbf1b384eed87c6fe078b07.zip
feat(note-types): make note type CRUD work fully offline-firstHEADmain
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) <noreply@anthropic.com>
Diffstat (limited to 'src/client/components/CreateNoteTypeModal.tsx')
-rw-r--r--src/client/components/CreateNoteTypeModal.tsx39
1 files changed, 19 insertions, 20 deletions
diff --git a/src/client/components/CreateNoteTypeModal.tsx b/src/client/components/CreateNoteTypeModal.tsx
index bbd43a1..382935f 100644
--- a/src/client/components/CreateNoteTypeModal.tsx
+++ b/src/client/components/CreateNoteTypeModal.tsx
@@ -1,7 +1,7 @@
-import { useAtomValue } from "jotai";
+import { useAtomValue, useSetAtom } from "jotai";
import { type FormEvent, useState } from "react";
-import { ApiClientError, apiClient } from "../api";
-import { isOnlineAtom } from "../atoms";
+import { syncActionAtom, userAtom } from "../atoms";
+import { localNoteTypeRepository } from "../db/repositories";
interface CreateNoteTypeModalProps {
isOpen: boolean;
@@ -20,7 +20,8 @@ export function CreateNoteTypeModal({
const [isReversible, setIsReversible] = useState(false);
const [error, setError] = useState<string | null>(null);
const [isSubmitting, setIsSubmitting] = useState(false);
- const isOnline = useAtomValue(isOnlineAtom);
+ const user = useAtomValue(userAtom);
+ const triggerSync = useSetAtom(syncActionAtom);
const resetForm = () => {
setName("");
@@ -37,29 +38,28 @@ export function CreateNoteTypeModal({
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
+ if (!user) {
+ setError("You must be signed in to create a note type.");
+ return;
+ }
setError(null);
setIsSubmitting(true);
try {
- const res = await apiClient.rpc.api["note-types"].$post({
- json: {
- name: name.trim(),
- frontTemplate: frontTemplate.trim(),
- backTemplate: backTemplate.trim(),
- isReversible,
- },
+ await localNoteTypeRepository.create({
+ userId: user.id,
+ name: name.trim(),
+ frontTemplate: frontTemplate.trim(),
+ backTemplate: backTemplate.trim(),
+ isReversible,
});
- await apiClient.handleResponse(res);
resetForm();
onNoteTypeCreated();
onClose();
- } catch (err) {
- if (err instanceof ApiClientError) {
- setError(err.message);
- } else {
- setError("Failed to create note type. Please try again.");
- }
+ void triggerSync().catch(() => {});
+ } catch {
+ setError("Failed to create note type. Please try again.");
} finally {
setIsSubmitting(false);
}
@@ -200,8 +200,7 @@ export function CreateNoteTypeModal({
</button>
<button
type="submit"
- disabled={isSubmitting || !name.trim() || !isOnline}
- title={!isOnline ? "Reconnect to create" : undefined}
+ disabled={isSubmitting || !name.trim()}
className="px-4 py-2 bg-primary hover:bg-primary-dark text-white font-medium rounded-lg transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed"
>
{isSubmitting ? "Creating..." : "Create"}