Files
CreaBook/client/src/stores/bookStore.ts
T
2026-04-05 03:08:53 +02:00

186 lines
4.3 KiB
TypeScript

import { create } from 'zustand';
export interface Chapter {
number: number;
title: string;
summary: string;
content: string;
isGenerated: boolean;
}
export interface BookOutline {
title: string;
genre: string;
logline: string;
chapters: Chapter[];
}
export interface Character {
name: string;
role: string;
traits: string[];
motivation: string;
backstory: string;
}
export interface Book {
id: string;
title: string;
genre: string;
idea: string;
outline: BookOutline | null;
characters: Character[];
currentChapter: number;
coverId?: string;
createdAt: Date;
updatedAt: Date;
}
interface BookState {
books: Book[];
activeBook: Book | null;
isGenerating: boolean;
generationProgress: number;
// Actions
addBook: (book: Book) => void;
updateBook: (id: string, updates: Partial<Book>) => void;
deleteBook: (id: string) => void;
setActiveBook: (book: Book | null) => void;
setOutline: (outline: BookOutline) => void;
addCharacter: (character: Character) => void;
updateChapterContent: (chapterNumber: number, content: string) => void;
setCurrentChapter: (chapterNumber: number) => void;
setCoverForBook: (coverId: string) => void;
setIsGenerating: (isGenerating: boolean) => void;
setGenerationProgress: (progress: number) => void;
}
export const useBookStore = create<BookState>((set) => ({
books: [],
activeBook: null,
isGenerating: false,
generationProgress: 0,
addBook: (book) =>
set((state) => ({
books: [book, ...state.books],
activeBook: book,
})),
updateBook: (id, updates) =>
set((state) => ({
books: state.books.map((b) =>
b.id === id ? { ...b, ...updates, updatedAt: new Date() } : b
),
activeBook: state.activeBook?.id === id
? { ...state.activeBook, ...updates, updatedAt: new Date() }
: state.activeBook,
})),
deleteBook: (id) =>
set((state) => ({
books: state.books.filter((b) => b.id !== id),
activeBook: state.activeBook?.id === id ? null : state.activeBook,
})),
setActiveBook: (book) => set({ activeBook: book }),
setOutline: (outline) =>
set((state) => {
if (!state.activeBook) return state;
const updatedBook = {
...state.activeBook,
outline,
updatedAt: new Date(),
};
return {
activeBook: updatedBook,
books: state.books.map((b) =>
b.id === state.activeBook!.id ? updatedBook : b
),
};
}),
addCharacter: (character) =>
set((state) => {
if (!state.activeBook) return state;
const updatedBook = {
...state.activeBook,
characters: [...state.activeBook.characters, character],
updatedAt: new Date(),
};
return {
activeBook: updatedBook,
books: state.books.map((b) =>
b.id === state.activeBook!.id ? updatedBook : b
),
};
}),
updateChapterContent: (chapterNumber, content) =>
set((state) => {
if (!state.activeBook || !state.activeBook.outline) return state;
const updatedOutline = {
...state.activeBook.outline,
chapters: state.activeBook.outline.chapters.map((chapter) =>
chapter.number === chapterNumber
? { ...chapter, content, isGenerated: true }
: chapter
),
};
const updatedBook = {
...state.activeBook,
outline: updatedOutline,
updatedAt: new Date(),
};
return {
activeBook: updatedBook,
books: state.books.map((b) =>
b.id === state.activeBook!.id ? updatedBook : b
),
};
}),
setCurrentChapter: (chapterNumber) =>
set((state) => {
if (!state.activeBook) return state;
return {
activeBook: {
...state.activeBook,
currentChapter: chapterNumber,
},
};
}),
setCoverForBook: (coverId) =>
set((state) => {
if (!state.activeBook) return state;
const updatedBook = {
...state.activeBook,
coverId,
updatedAt: new Date(),
};
return {
activeBook: updatedBook,
books: state.books.map((b) =>
b.id === state.activeBook!.id ? updatedBook : b
),
};
}),
setIsGenerating: (isGenerating) => set({ isGenerating }),
setGenerationProgress: (progress) => set({ generationProgress: progress }),
}));