'use client' import {ChangeEvent, forwardRef, useContext, useEffect, useImperativeHandle, useState} from 'react'; import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"; import {faPlus, IconDefinition} from "@fortawesome/free-solid-svg-icons"; import {WorldContext} from '@/context/WorldContext'; import {BookContext} from "@/context/BookContext"; import {AlertContext} from "@/context/AlertContext"; import {SelectBoxProps} from "@/shared/interface"; import System from "@/lib/models/System"; import {elementSections, WorldProps} from "@/lib/models/World"; import {SessionContext} from "@/context/SessionContext"; import InputField from "@/components/form/InputField"; import TextInput from '@/components/form/TextInput'; import TexteAreaInput from "@/components/form/TexteAreaInput"; import WorldElementComponent from './WorldElement'; import SelectBox from "@/components/form/SelectBox"; import {useTranslations} from "next-intl"; import {LangContext, LangContextProps} from "@/context/LangContext"; import OfflineContext, {OfflineContextType} from "@/context/OfflineContext"; import {LocalSyncQueueContext, LocalSyncQueueContextProps} from "@/context/SyncQueueContext"; import {BooksSyncContext, BooksSyncContextProps} from "@/context/BooksSyncContext"; import {SyncedBook} from "@/lib/models/SyncedBook"; export interface ElementSection { title: string; section: keyof WorldProps; icon: IconDefinition; } export function WorldSetting(props: any, ref: any) { const t = useTranslations(); const {lang} = useContext(LangContext); const {isCurrentlyOffline} = useContext(OfflineContext); const {addToQueue} = useContext(LocalSyncQueueContext); const {localSyncedBooks} = useContext(BooksSyncContext); const {errorMessage, successMessage} = useContext(AlertContext); const {session} = useContext(SessionContext); const {book} = useContext(BookContext); const bookId: string = book?.bookId ? book.bookId.toString() : ''; const [worlds, setWorlds] = useState([]); const [newWorldName, setNewWorldName] = useState(''); const [selectedWorldIndex, setSelectedWorldIndex] = useState(0); const [worldsSelector, setWorldsSelector] = useState([]); const [showAddNewWorld, setShowAddNewWorld] = useState(false); useImperativeHandle(ref, function () { return { handleSave: handleUpdateWorld, }; }); useEffect((): void => { getWorlds().then(); }, []); async function getWorlds() { try { let response: WorldProps[]; if (isCurrentlyOffline()) { response = await window.electron.invoke('db:book:worlds:get', {bookid: bookId}); } else { if (book?.localBook) { response = await window.electron.invoke('db:book:worlds:get', {bookid: bookId}); } else { response = await System.authGetQueryToServer(`book/worlds`, session.accessToken, lang, { bookid: bookId, }); } } if (response) { setWorlds(response); const formattedWorlds: SelectBoxProps[] = response.map( (world: WorldProps): SelectBoxProps => ({ label: world.name, value: world.id.toString(), }), ); setWorldsSelector(formattedWorlds); } } catch (e: unknown) { if (e instanceof Error) { errorMessage(e.message); } else { errorMessage(t("worldSetting.unknownError")) } } } async function handleAddNewWorld(): Promise { if (newWorldName.trim() === '') { errorMessage(t("worldSetting.newWorldNameError")); return; } try { let worldId: string; if (isCurrentlyOffline() || book?.localBook) { worldId = await window.electron.invoke('db:book:world:add', { worldName: newWorldName, bookId: bookId, }); } else { worldId = await System.authPostToServer('book/world/add', { worldName: newWorldName, bookId: bookId, }, session.accessToken, lang); if (localSyncedBooks.find((syncedBook: SyncedBook): boolean => syncedBook.id === bookId)) { addToQueue('db:book:world:add', { worldName: newWorldName, worldId, bookId: bookId, }); } } if (!worldId) { errorMessage(t("worldSetting.addWorldError")); return; } const newWorldId: string = worldId; const newWorld: WorldProps = { id: newWorldId, name: newWorldName, history: '', politics: '', economy: '', religion: '', languages: '', laws: [], biomes: [], issues: [], customs: [], kingdoms: [], climate: [], resources: [], wildlife: [], arts: [], ethnicGroups: [], socialClasses: [], importantCharacters: [], }; setWorlds([...worlds, newWorld]); setWorldsSelector([ ...worldsSelector, {label: newWorldName, value: newWorldId.toString()}, ]); setNewWorldName(''); setShowAddNewWorld(false); } catch (e: unknown) { if (e instanceof Error) { errorMessage(e.message); } else { errorMessage(t("worldSetting.unknownError")) } } } async function handleUpdateWorld(): Promise { try { let response: boolean; const worldData = { world: worlds[selectedWorldIndex], bookId: bookId, }; if (isCurrentlyOffline() || book?.localBook) { response = await window.electron.invoke('db:book:world:update', worldData); } else { response = await System.authPatchToServer('book/world/update', worldData, session.accessToken, lang); if (localSyncedBooks.find((syncedBook: SyncedBook): boolean => syncedBook.id === bookId)) { addToQueue('db:book:world:update', worldData); } } if (!response) { errorMessage(t("worldSetting.updateWorldError")); return; } successMessage(t("worldSetting.updateWorldSuccess")); } catch (e: unknown) { if (e instanceof Error) { errorMessage(e.message); } else { errorMessage(t("worldSetting.unknownError")) } } } function handleInputChange(value: string, field: keyof WorldProps) { const updatedWorlds = [...worlds] as WorldProps[]; (updatedWorlds[selectedWorldIndex][field] as string) = value; setWorlds(updatedWorlds); } return (
{ const worldId = e.target.value; const index = worlds.findIndex(world => world.id.toString() === worldId); if (index !== -1) { setSelectedWorldIndex(index); } }} data={worldsSelector.length > 0 ? worldsSelector : [{ label: t("worldSetting.noWorldAvailable"), value: '0' }]} defaultValue={worlds[selectedWorldIndex]?.id.toString() || '0'} placeholder={t("worldSetting.selectWorldPlaceholder")} /> } actionIcon={faPlus} actionLabel={t("worldSetting.addWorldLabel")} action={async () => setShowAddNewWorld(!showAddNewWorld)} /> {showAddNewWorld && ( ) => setNewWorldName(e.target.value)} placeholder={t("worldSetting.newWorldPlaceholder")} /> } actionIcon={faPlus} actionLabel={t("worldSetting.createWorldLabel")} addButtonCallBack={handleAddNewWorld} /> )}
{worlds.length > 0 && worlds[selectedWorldIndex] ? (
) => { const updatedWorlds: WorldProps[] = [...worlds]; updatedWorlds[selectedWorldIndex].name = e.target.value setWorlds(updatedWorlds); }} placeholder={t("worldSetting.worldNamePlaceholder")} /> } />
handleInputChange(e.target.value, 'history')} placeholder={t("worldSetting.worldHistoryPlaceholder")} /> } />
handleInputChange(e.target.value, 'politics')} placeholder={t("worldSetting.politicsPlaceholder")} /> } /> handleInputChange(e.target.value, 'economy')} placeholder={t("worldSetting.economyPlaceholder")} /> } />
handleInputChange(e.target.value, 'religion')} placeholder={t("worldSetting.religionPlaceholder")} /> } /> handleInputChange(e.target.value, 'languages')} placeholder={t("worldSetting.languagesPlaceholder")} /> } />
{elementSections.map((section, index) => (

{section.title} {worlds[selectedWorldIndex][section.section]?.length || 0}

))}
) : (

{t("worldSetting.noWorldAvailable")}

)}
); } export default forwardRef(WorldSetting);