'use client'; import {ChangeEvent, useContext, useState} from "react"; import {WorldContext} from "@/context/WorldContext"; import TextInput from "@/components/form/TextInput"; import TexteAreaInput from "@/components/form/TexteAreaInput"; import {WorldElement, WorldProps} from "@/lib/models/World"; import {AlertContext} from "@/context/AlertContext"; import {SessionContext} from "@/context/SessionContext"; import System from "@/lib/models/System"; import InputField from "@/components/form/InputField"; import {useTranslations} from "next-intl"; import {LangContext, LangContextProps} from "@/context/LangContext"; import OfflineContext, {OfflineContextType} from "@/context/OfflineContext"; import {BookContext} from "@/context/BookContext"; import {LocalSyncQueueContext, LocalSyncQueueContextProps} from "@/context/SyncQueueContext"; import {BooksSyncContext, BooksSyncContextProps} from "@/context/BooksSyncContext"; import {SyncedBook} from "@/lib/models/SyncedBook"; import {SeriesContext, SeriesContextProps} from "@/context/SeriesContext"; import {SeriesSyncContext, SeriesSyncContextProps} from "@/context/SeriesSyncContext"; import {SyncedSeries} from "@/lib/models/SyncedSeries"; import * as tauri from '@/lib/tauri'; interface WorldElementInputProps { sectionLabel: string; sectionType: string; } function getElementTypeNumber(sectionType: string): number { const typeMap: { [key: string]: number } = { 'laws': 0, 'biomes': 1, 'issues': 2, 'customs': 3, 'kingdoms': 4, 'climate': 5, 'resources': 6, 'wildlife': 7, 'arts': 8, 'ethnicGroups': 9, 'socialClasses': 10, 'importantCharacters': 11, }; return typeMap[sectionType] ?? 0; } export default function WorldElementComponent({sectionLabel, sectionType}: WorldElementInputProps) { const t = useTranslations(); const {lang} = useContext(LangContext); const {isCurrentlyOffline} = useContext(OfflineContext); const {addToQueue} = useContext(LocalSyncQueueContext); const {localSyncedBooks} = useContext(BooksSyncContext); const {book} = useContext(BookContext); const {worlds, setWorlds, selectedWorldIndex, isSeriesMode} = useContext(WorldContext); const {errorMessage} = useContext(AlertContext); const {session} = useContext(SessionContext); const {seriesId, localSeries} = useContext(SeriesContext); const {localSyncedSeries} = useContext(SeriesSyncContext); const [newElementName, setNewElementName] = useState(''); async function handleRemoveElement( section: keyof WorldProps, index: number, ): Promise { try { let response: boolean; const elementId = (worlds[selectedWorldIndex][section] as WorldElement[])[index].id; const deletedAt: number = System.timeStampInSeconds(); if (isSeriesMode) { const deleteData = {elementId, deletedAt}; if (isCurrentlyOffline() || localSeries) { response = await tauri.deleteSeriesWorldElement(elementId, deletedAt); } else { response = await System.authDeleteToServer('series/world/element/delete', deleteData, session.accessToken, lang); if (localSyncedSeries.find((s: SyncedSeries): boolean => s.id === seriesId)) { addToQueue('delete_series_world_element', {data: deleteData}); } } } else if (isCurrentlyOffline() || book?.localBook) { response = await tauri.removeWorldElement(elementId, book?.bookId || '', deletedAt); } else { response = await System.authDeleteToServer('book/world/element/delete', { elementId, bookId: book?.bookId, deletedAt, }, session.accessToken, lang); if (localSyncedBooks.find((syncedBook: SyncedBook): boolean => syncedBook.id === book?.bookId)) { addToQueue('remove_world_element', {data: { elementId: elementId, bookId: book?.bookId, deletedAt, }}); } } if (!response) { errorMessage(t("worldSetting.unknownError")) } const updatedWorlds: WorldProps[] = [...worlds]; (updatedWorlds[selectedWorldIndex][section] as WorldElement[]).splice( index, 1, ); setWorlds(updatedWorlds); } catch (e: unknown) { if (e instanceof Error) { errorMessage(e.toString()); } else { errorMessage(t("worldElementComponent.errorUnknown")); } } } async function handleAddElement(section: keyof WorldProps): Promise { if (newElementName.trim() === '') { errorMessage(t("worldElementComponent.emptyField", {section: sectionLabel})); return; } try { let elementId: string; if (isSeriesMode) { const addData = { worldId: worlds[selectedWorldIndex].id, elementType: getElementTypeNumber(section as string), name: newElementName, }; if (isCurrentlyOffline() || localSeries) { elementId = await tauri.addSeriesWorldElement(addData); } else { elementId = await System.authPostToServer( 'series/world/element/add', addData, session.accessToken, lang ); if (localSyncedSeries.find((s: SyncedSeries): boolean => s.id === seriesId)) { addToQueue('add_series_world_element', {data: addData}); } } if (!elementId) { errorMessage(t("worldSetting.unknownError")) return; } } else if (isCurrentlyOffline() || book?.localBook) { elementId = await tauri.addWorldElement(worlds[selectedWorldIndex].id, newElementName, section as string); } else { elementId = await System.authPostToServer('book/world/element/add', { elementType: section, worldId: worlds[selectedWorldIndex].id, elementName: newElementName, }, session.accessToken, lang); if (localSyncedBooks.find((syncedBook: SyncedBook): boolean => syncedBook.id === book?.bookId)) { addToQueue('add_world_element', {data: { elementType: section, worldId: worlds[selectedWorldIndex].id, elementId, elementName: newElementName, }}); } } if (!elementId) { errorMessage(t("worldSetting.unknownError")) return; } const updatedWorlds: WorldProps[] = [...worlds]; (updatedWorlds[selectedWorldIndex][section] as WorldElement[]).push({ id: elementId, name: newElementName, description: '', }); setWorlds(updatedWorlds); setNewElementName(''); } catch (e: unknown) { if (e instanceof Error) { errorMessage(e.message); } else { errorMessage(t("worldElementComponent.errorUnknown")); } } } function handleElementChange( section: keyof WorldProps, index: number, field: keyof WorldElement, value: string, ): void { const updatedWorlds: WorldProps[] = [...worlds]; const sectionElements = updatedWorlds[selectedWorldIndex][ section ] as WorldElement[]; sectionElements[index] = {...sectionElements[index], [field]: value}; setWorlds(updatedWorlds); } return (
{Array.isArray(worlds[selectedWorldIndex][sectionType as keyof WorldProps]) && (worlds[selectedWorldIndex][sectionType as keyof WorldProps] as WorldElement[]).map( (element: WorldElement, index: number) => (
) => handleElementChange(sectionType as keyof WorldProps, index, 'name', e.target.value)} placeholder={t("worldElementComponent.namePlaceholder", {section: sectionLabel.toLowerCase()})} />} removeButtonCallBack={(): Promise => handleRemoveElement(sectionType as keyof WorldProps, index)}/>
handleElementChange(sectionType as keyof WorldProps, index, 'description', e.target.value)} placeholder={t("worldElementComponent.descriptionPlaceholder", {section: sectionLabel.toLowerCase()})} />
) ) } ): void => setNewElementName(e.target.value)} placeholder={t("worldElementComponent.newPlaceholder", {section: sectionLabel.toLowerCase()})} />} addButtonCallBack={(): Promise => handleAddElement(sectionType as keyof WorldProps)}/>
); }