import type { PlayerCharacterStore } from "@initiative/application"; import { createPlayerCharacterUseCase, deletePlayerCharacterUseCase, editPlayerCharacterUseCase, } from "@initiative/application"; import type { PlayerCharacter, PlayerCharacterId } from "@initiative/domain"; import { isDomainError, playerCharacterId } from "@initiative/domain"; import { useCallback, useEffect, useRef, useState } from "react"; import { loadPlayerCharacters, savePlayerCharacters, } from "../persistence/player-character-storage.js"; function initializeCharacters(): PlayerCharacter[] { return loadPlayerCharacters(); } let nextPcId = 0; function generatePcId(): PlayerCharacterId { return playerCharacterId(`pc-${++nextPcId}`); } interface EditFields { readonly name?: string; readonly ac?: number; readonly maxHp?: number; readonly color?: string | null; readonly icon?: string | null; } export function usePlayerCharacters() { const [characters, setCharacters] = useState(initializeCharacters); const charactersRef = useRef(characters); charactersRef.current = characters; useEffect(() => { savePlayerCharacters(characters); }, [characters]); const makeStore = useCallback((): PlayerCharacterStore => { return { getAll: () => charactersRef.current, save: (updated) => { charactersRef.current = updated; setCharacters(updated); }, }; }, []); const createCharacter = useCallback( ( name: string, ac: number, maxHp: number, color: string | undefined, icon: string | undefined, ) => { const id = generatePcId(); const result = createPlayerCharacterUseCase( makeStore(), id, name, ac, maxHp, color, icon, ); if (isDomainError(result)) { return result; } return undefined; }, [makeStore], ); const editCharacter = useCallback( (id: PlayerCharacterId, fields: EditFields) => { const result = editPlayerCharacterUseCase(makeStore(), id, fields); if (isDomainError(result)) { return result; } return undefined; }, [makeStore], ); const deleteCharacter = useCallback( (id: PlayerCharacterId) => { const result = deletePlayerCharacterUseCase(makeStore(), id); if (isDomainError(result)) { return result; } return undefined; }, [makeStore], ); return { characters, createCharacter, editCharacter, deleteCharacter, makeStore, } as const; }