From a6404847d157fbf20c1fdf97dbcf7b36f7c0c292 Mon Sep 17 00:00:00 2001 From: PJ Date: Sat, 20 Jun 2026 15:09:13 -0400 Subject: [PATCH] refactor(store): nullable open book with open/close for library nav --- src/store/useBook.ts | 83 +++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 47 deletions(-) diff --git a/src/store/useBook.ts b/src/store/useBook.ts index 01a004e..695d3e2 100644 --- a/src/store/useBook.ts +++ b/src/store/useBook.ts @@ -1,61 +1,50 @@ import { create } from "zustand"; import type { JSONContent } from "@tiptap/core"; -import { type Book, type BookMetadata, type BookSettings, createChapter, starterBook } from "../model/book"; +import { type Book, type BookMetadata, type BookSettings, createChapter } from "../model/book"; interface BookState { - book: Book; + book: Book | null; activeChapterId: string; - path: string | null; dirty: boolean; + openBook: (book: Book) => void; + closeBook: () => void; setActiveChapter: (id: string) => void; setChapterContent: (id: string, content: JSONContent) => void; setChapterTitle: (id: string, title: string) => void; addChapter: () => void; setMetadata: (patch: Partial) => void; setSettings: (patch: Partial) => void; - replaceBook: (book: Book, path: string) => void; - markSaved: (path: string) => void; + markSaved: () => void; } -export const useBook = create((set) => { - const book = starterBook(); - return { - book, - activeChapterId: book.chapters[0].id, - path: null, - dirty: false, - setActiveChapter: (id) => set({ activeChapterId: id }), - setChapterContent: (id, content) => - set((s) => ({ - dirty: true, - book: { - ...s.book, - chapters: s.book.chapters.map((c) => (c.id === id ? { ...c, content } : c)), - }, - })), - setChapterTitle: (id, title) => - set((s) => ({ - dirty: true, - book: { - ...s.book, - chapters: s.book.chapters.map((c) => (c.id === id ? { ...c, title } : c)), - }, - })), - addChapter: () => - set((s) => { - const chapter = createChapter(); - return { - activeChapterId: chapter.id, - dirty: true, - book: { ...s.book, chapters: [...s.book.chapters, chapter] }, - }; - }), - setMetadata: (patch) => - set((s) => ({ dirty: true, book: { ...s.book, metadata: { ...s.book.metadata, ...patch } } })), - setSettings: (patch) => - set((s) => ({ dirty: true, book: { ...s.book, settings: { ...s.book.settings, ...patch } } })), - replaceBook: (book, path) => - set({ book, activeChapterId: book.chapters[0]?.id ?? "", path, dirty: false }), - markSaved: (path) => set({ path, dirty: false }), - }; -}); +export const useBook = create((set) => ({ + book: null, + activeChapterId: "", + dirty: false, + openBook: (book) => set({ book, activeChapterId: book.chapters[0]?.id ?? "", dirty: false }), + closeBook: () => set({ book: null, activeChapterId: "", dirty: false }), + setActiveChapter: (id) => set({ activeChapterId: id }), + setChapterContent: (id, content) => + set((s) => + s.book + ? { dirty: true, book: { ...s.book, chapters: s.book.chapters.map((c) => (c.id === id ? { ...c, content } : c)) } } + : {} + ), + setChapterTitle: (id, title) => + set((s) => + s.book + ? { dirty: true, book: { ...s.book, chapters: s.book.chapters.map((c) => (c.id === id ? { ...c, title } : c)) } } + : {} + ), + addChapter: () => + set((s) => { + if (!s.book) return {}; + const chapter = createChapter(); + return { activeChapterId: chapter.id, dirty: true, book: { ...s.book, chapters: [...s.book.chapters, chapter] } }; + }), + setMetadata: (patch) => + set((s) => (s.book ? { dirty: true, book: { ...s.book, metadata: { ...s.book.metadata, ...patch } } } : {})), + setSettings: (patch) => + set((s) => (s.book ? { dirty: true, book: { ...s.book, settings: { ...s.book.settings, ...patch } } } : {})), + markSaved: () => set({ dirty: false }), +}));