'use client'; import React, {ChangeEvent, useContext, useState} from "react"; import {WorldContext, WorldContextProps} from "@/context/WorldContext"; import TextInput from "@/components/form/TextInput"; import TextAreaInput from "@/components/form/TextAreaInput"; import {WorldElement, WorldElementSection, WorldProps} from "@/lib/types/world"; import {AlertContext, AlertContextProps} from "@/context/AlertContext"; import {SessionContext, SessionContextProps} from "@/context/SessionContext"; import {apiDelete, apiPost} from "@/lib/api/client"; import {isDesktop} from '@/lib/configs'; import * as tauri from '@/lib/tauri'; import OfflineContext, {OfflineContextType} from '@/context/OfflineContext'; import {BookContext, BookContextProps} from '@/context/BookContext'; import InputField from "@/components/form/InputField"; import {useTranslations} from '@/lib/i18n'; import {LangContext, LangContextProps} from "@/context/LangContext"; interface WorldElementInputProps { sectionLabel: string; sectionType: WorldElementSection; } function getElementTypeNumber(sectionType: WorldElementSection): number { const typeMap: Record = { '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): React.JSX.Element { const t = useTranslations(); const {lang}: LangContextProps = useContext(LangContext); const { worlds, setWorlds, selectedWorldIndex, isSeriesMode }: WorldContextProps = useContext(WorldContext); const {errorMessage}: AlertContextProps = useContext(AlertContext); const {session}: SessionContextProps = useContext(SessionContext); const {book}: BookContextProps = useContext(BookContext); const {isCurrentlyOffline}: OfflineContextType = useContext(OfflineContext); const [newElementName, setNewElementName] = useState(''); async function handleRemoveElement( section: WorldElementSection, index: number, ): Promise { try { const elements: WorldElement[] = worlds[selectedWorldIndex][section]; let response: boolean; if (!isSeriesMode && isDesktop && (isCurrentlyOffline() || book?.localBook)) { response = await tauri.removeWorldElement(elements[index].id, book?.bookId ?? '', Date.now()); } else { const endpoint: string = isSeriesMode ? 'series/world/element/delete' : 'book/world/element/delete'; response = await apiDelete(endpoint, { elementId: elements[index].id, }, session.accessToken, lang); } if (!response) { errorMessage(t("worldSetting.unknownError")) } const updatedWorlds: WorldProps[] = [...worlds]; updatedWorlds[selectedWorldIndex][section].splice(index, 1); setWorlds(updatedWorlds); } catch (e: unknown) { if (e instanceof Error) { errorMessage(e.message); } else { errorMessage(t("worldElementComponent.errorUnknown")); } } } async function handleAddElement(section: WorldElementSection): Promise { if (newElementName.trim() === '') { errorMessage(t("worldElementComponent.emptyField", {section: sectionLabel})); return; } try { let elementId: string; if (isSeriesMode) { elementId = await apiPost( 'series/world/element/add', { worldId: worlds[selectedWorldIndex].id, elementType: getElementTypeNumber(section), name: newElementName, }, session.accessToken, lang ); if (!elementId) { errorMessage(t("worldSetting.unknownError")) return; } } else if (isDesktop && (isCurrentlyOffline() || book?.localBook)) { elementId = await tauri.addWorldElement(worlds[selectedWorldIndex].id, newElementName, section); if (!elementId) { errorMessage(t("worldSetting.unknownError")) return; } } else { elementId = await apiPost('book/world/element/add', { elementType: section, worldId: worlds[selectedWorldIndex].id, elementName: newElementName, }, session.accessToken, lang); if (!elementId) { errorMessage(t("worldSetting.unknownError")) return; } } const updatedWorlds: WorldProps[] = [...worlds]; updatedWorlds[selectedWorldIndex][section].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: WorldElementSection, index: number, field: keyof WorldElement, value: string, ): void { const updatedWorlds: WorldProps[] = [...worlds]; const sectionElements: WorldElement[] = updatedWorlds[selectedWorldIndex][section]; sectionElements[index] = {...sectionElements[index], [field]: value}; setWorlds(updatedWorlds); } return (
{worlds[selectedWorldIndex][sectionType].map( (element: WorldElement, index: number): React.JSX.Element => (
): void => handleElementChange(sectionType, index, 'name', e.target.value)} placeholder={t("worldElementComponent.namePlaceholder", {section: sectionLabel.toLowerCase()})} />} removeButtonCallBack={(): Promise => handleRemoveElement(sectionType, index)}/>
): void => handleElementChange(sectionType, 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)}/>
); }