- Deleted redundant components (`AddActionButton`, `AlertBox`, `AlertStack`, `BackButton`, `CancelButton`, and `CollapsableArea`) and related files. - Removed unused models (`Book`, `BookSerie`, `BookTables`, `Character`, and `Chapter`) to reduce codebase clutter. - Updated project structure and references to reflect these removals.
173 lines
6.8 KiB
TypeScript
173 lines
6.8 KiB
TypeScript
'use client';
|
|
import React, {useCallback, useContext, useMemo, useState} from 'react';
|
|
import {useWorlds, UseWorldsConfig} from '@/hooks/settings/useWorlds';
|
|
import {useTranslations} from '@/lib/i18n';
|
|
import PulseLoader from '@/components/ui/PulseLoader';
|
|
import {BookContext, BookContextProps} from '@/context/BookContext';
|
|
import {WorldProps, WorldTextField} from '@/lib/types/world';
|
|
import {SeriesWorldProps} from '@/lib/types/series';
|
|
import SeriesImportSelector from '@/components/form/SeriesImportSelector';
|
|
import ToolDetailHeader from '@/components/book/settings/ToolDetailHeader';
|
|
|
|
import WorldSettingsList from './WorldSettingsList';
|
|
import WorldSettingsDetail from './WorldSettingsDetail';
|
|
import WorldSettingsEdit from './WorldSettingsEdit';
|
|
|
|
interface WorldSettingsProps {
|
|
entityType?: 'book' | 'series';
|
|
entityId?: string;
|
|
toolEnabled?: boolean;
|
|
}
|
|
|
|
/**
|
|
* WorldSettings - Orchestrateur pour BookSetting/SerieSetting
|
|
* Gère le viewMode (list/detail/edit) et coordonne les sous-composants
|
|
* Inclut: toggle tool, import from series, export to series
|
|
*/
|
|
export default function WorldSettings({
|
|
entityType = 'book',
|
|
entityId,
|
|
toolEnabled: parentToolEnabled,
|
|
}: WorldSettingsProps): React.JSX.Element {
|
|
const t = useTranslations();
|
|
const {book}: BookContextProps = useContext<BookContextProps>(BookContext);
|
|
const [showDeleteConfirm, setShowDeleteConfirm] = useState<boolean>(false);
|
|
|
|
const resolvedEntityId: string = entityId || book?.bookId || '';
|
|
|
|
const config: UseWorldsConfig = useMemo(function (): UseWorldsConfig {
|
|
return {
|
|
entityType,
|
|
entityId: resolvedEntityId,
|
|
};
|
|
}, [entityType, resolvedEntityId]);
|
|
|
|
const {
|
|
worlds,
|
|
seriesWorlds,
|
|
selectedWorldIndex,
|
|
toolEnabled,
|
|
isLoading,
|
|
isSeriesMode,
|
|
bookSeriesId,
|
|
newWorldName,
|
|
viewMode,
|
|
addNewWorld,
|
|
saveWorld,
|
|
updateWorldField,
|
|
toggleTool,
|
|
importFromSeries,
|
|
exportToSeries,
|
|
refreshSeriesWorlds,
|
|
setNewWorldName,
|
|
setWorlds,
|
|
getSeriesWorldForCurrentWorld,
|
|
enterDetailMode,
|
|
enterEditMode,
|
|
exitEditMode,
|
|
backToList,
|
|
} = useWorlds(config);
|
|
|
|
const availableSeriesWorlds = useMemo(function (): SeriesWorldProps[] {
|
|
return seriesWorlds.filter(function (sw: SeriesWorldProps): boolean {
|
|
return !worlds.some(function (w: WorldProps): boolean {
|
|
return w.seriesWorldId === sw.id;
|
|
});
|
|
});
|
|
}, [seriesWorlds, worlds]);
|
|
|
|
const handleWorldFieldChange = useCallback(function (field: WorldTextField, value: string): void {
|
|
updateWorldField(field, value);
|
|
}, [updateWorldField]);
|
|
|
|
async function handleSave(): Promise<void> {
|
|
await exitEditMode(true);
|
|
}
|
|
|
|
function handleCancel(): void {
|
|
exitEditMode(false);
|
|
}
|
|
|
|
if (isLoading) {
|
|
return <PulseLoader/>;
|
|
}
|
|
|
|
const selectedWorld: WorldProps | undefined = worlds[selectedWorldIndex];
|
|
const canExport: boolean = Boolean(bookSeriesId && selectedWorld && !selectedWorld.seriesWorldId);
|
|
|
|
return (
|
|
<div className="flex flex-col h-full">
|
|
{/* Header - uniquement pour detail/edit */}
|
|
<ToolDetailHeader
|
|
title={selectedWorld?.name || ''}
|
|
defaultTitle={t('worldSetting.newWorld')}
|
|
viewMode={viewMode}
|
|
isNew={false}
|
|
onBack={backToList}
|
|
onEdit={enterEditMode}
|
|
onSave={handleSave}
|
|
onCancel={handleCancel}
|
|
onExport={canExport ? exportToSeries : undefined}
|
|
showExport={canExport}
|
|
showDelete={false}
|
|
/>
|
|
|
|
{/* Contenu principal */}
|
|
<div className="flex-1 overflow-y-auto">
|
|
{viewMode === 'list' && (
|
|
<div className="space-y-5 p-4">
|
|
{((parentToolEnabled !== undefined ? parentToolEnabled : toolEnabled) || isSeriesMode) && (
|
|
<>
|
|
{/* Import from series */}
|
|
{!isSeriesMode && bookSeriesId && availableSeriesWorlds.length > 0 && (
|
|
<SeriesImportSelector
|
|
availableItems={availableSeriesWorlds.map(function (sw: SeriesWorldProps) {
|
|
return {id: sw.id, name: sw.name};
|
|
})}
|
|
onImport={importFromSeries}
|
|
placeholder={t("seriesImport.selectElement")}
|
|
label={t("seriesImport.importFromSeries")}
|
|
/>
|
|
)}
|
|
|
|
{/* Liste des mondes */}
|
|
<WorldSettingsList
|
|
worlds={worlds}
|
|
onWorldClick={enterDetailMode}
|
|
onAddWorld={addNewWorld}
|
|
newWorldName={newWorldName}
|
|
onNewWorldNameChange={setNewWorldName}
|
|
/>
|
|
</>
|
|
)}
|
|
</div>
|
|
)}
|
|
|
|
{viewMode === 'detail' && selectedWorld && (
|
|
<div className="p-4">
|
|
<WorldSettingsDetail
|
|
world={selectedWorld}
|
|
seriesWorld={getSeriesWorldForCurrentWorld()}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{viewMode === 'edit' && selectedWorld && (
|
|
<div className="p-4">
|
|
<WorldSettingsEdit
|
|
world={selectedWorld}
|
|
worlds={worlds}
|
|
selectedWorldIndex={selectedWorldIndex}
|
|
setWorlds={setWorlds}
|
|
onWorldFieldChange={handleWorldFieldChange}
|
|
seriesWorld={getSeriesWorldForCurrentWorld()}
|
|
isSeriesMode={isSeriesMode}
|
|
onSyncComplete={refreshSeriesWorlds}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|