Files
ERitors-Scribe-Desktop/components/book/settings/characters/editor/CharacterEditorDetail.tsx
natreex 64ed90d993 Remove unused components and models for improved maintainability
- 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.
2026-03-22 22:37:31 -04:00

96 lines
4.2 KiB
TypeScript

'use client';
import React, {useContext, useEffect} from 'react';
import {Attribute, CharacterAttribute, CharacterProps} from '@/lib/types/character';
import {characterCategories} from '@/lib/constants/character';
import {SelectBoxProps} from '@/components/form/SelectBox';
import {SeriesCharacterProps} from '@/lib/types/series';
import {useTranslations} from '@/lib/i18n';
import DetailField from '@/components/ui/DetailField';
import AvatarIcon from '@/components/ui/AvatarIcon';
import {SessionContext, SessionContextProps} from '@/context/SessionContext';
import {AlertContext, AlertContextProps} from '@/context/AlertContext';
import {LangContext, LangContextProps} from '@/context/LangContext';
import {apiGet} from '@/lib/api/client';
type AttributeResponse = { type: string; values: Attribute[] }[];
interface CharacterEditorDetailProps {
character: CharacterProps;
seriesCharacter?: SeriesCharacterProps | null;
onLoadAttributes?: (attributes: CharacterAttribute) => void;
}
/**
* CharacterEditorDetail - Version sidebar lecture seule
* Layout linéaire simple, juste les infos essentielles empilées
* PAS de CollapsableArea, PAS de grids
*/
export default function CharacterEditorDetail({
character,
seriesCharacter,
onLoadAttributes,
}: CharacterEditorDetailProps): React.JSX.Element {
const t = useTranslations();
const {lang}: LangContextProps = useContext<LangContextProps>(LangContext);
const {session}: SessionContextProps = useContext<SessionContextProps>(SessionContext);
const {errorMessage}: AlertContextProps = useContext<AlertContextProps>(AlertContext);
useEffect(function (): void {
if (character?.id !== null) {
getAttributes().then();
}
}, [character?.id]);
async function getAttributes(): Promise<void> {
try {
const response: AttributeResponse = await apiGet<AttributeResponse>(
'character/attribute',
session.accessToken,
lang,
{characterId: character?.id}
);
if (response && onLoadAttributes) {
const attributes: CharacterAttribute = {};
response.forEach(function (item: { type: string; values: Attribute[] }): void {
attributes[item.type] = item.values;
});
onLoadAttributes(attributes);
}
} catch (e: unknown) {
if (e instanceof Error) {
errorMessage(e.message);
}
}
}
function getCategoryLabel(category: string | null | undefined): string {
if (!category) return '';
const found: SelectBoxProps | undefined = characterCategories.find(function (c: SelectBoxProps): boolean {
return c.value === category;
});
return found ? t(found.label) : category;
}
return (
<div>
{character.image && (
<div className="flex justify-center mb-4">
<AvatarIcon size="xl" image={character.image} alt={character.name}/>
</div>
)}
<h3 className="text-text-primary font-semibold text-base mb-4">
{character.name} {character.lastName}
</h3>
<DetailField variant="compact" label={t('characterDetail.role')}
value={getCategoryLabel(character.category)}/>
<DetailField variant="compact" label={t('characterDetail.title')} value={character.title}/>
<DetailField variant="compact" label={t('characterDetail.gender')} value={character.gender}/>
<DetailField variant="compact" label={t('characterDetail.age')} value={character.age}/>
<DetailField variant="compact" label={t('characterDetail.biography')} value={character.biography}/>
<DetailField variant="compact" label={t('characterDetail.roleFull')} value={character.role}/>
</div>
);
}