import { useAtomValue, useSetAtom } from "jotai"; import { type FormEvent, useState } from "react"; import { syncActionAtom, userAtom } from "../atoms"; import { localDeckRepository } from "../db/repositories"; interface CreateDeckModalProps { isOpen: boolean; onClose: () => void; onDeckCreated: () => void; } export function CreateDeckModal({ isOpen, onClose, onDeckCreated, }: CreateDeckModalProps) { const [name, setName] = useState(""); const [description, setDescription] = useState(""); const [error, setError] = useState(null); const [isSubmitting, setIsSubmitting] = useState(false); const user = useAtomValue(userAtom); const triggerSync = useSetAtom(syncActionAtom); const resetForm = () => { setName(""); setDescription(""); setError(null); }; const handleClose = () => { resetForm(); onClose(); }; const handleSubmit = async (e: FormEvent) => { e.preventDefault(); if (!user) { setError("You must be signed in to create a deck."); return; } setError(null); setIsSubmitting(true); try { await localDeckRepository.create({ userId: user.id, name: name.trim(), description: description.trim() || null, defaultNoteTypeId: null, }); resetForm(); onDeckCreated(); onClose(); // Fire-and-forget: server push will be retried by the sync engine if it // fails (e.g. offline), so we deliberately do not await or surface errors. void triggerSync().catch(() => {}); } catch { setError("Failed to create deck. Please try again."); } finally { setIsSubmitting(false); } }; if (!isOpen) { return null; } return (
{ if (e.target === e.currentTarget) { handleClose(); } }} onKeyDown={(e) => { if (e.key === "Escape") { handleClose(); } }} >

Create New Deck

{error && (
{error}
)}
setName(e.target.value)} required maxLength={255} disabled={isSubmitting} className="w-full px-4 py-2.5 bg-ivory border border-border rounded-lg text-slate placeholder-muted transition-all duration-200 hover:border-muted focus:border-primary focus:ring-2 focus:ring-primary/10 disabled:opacity-50 disabled:cursor-not-allowed" placeholder="My New Deck" />