- Deleted `CharacterComponent` and `CharacterDetail` files from the project. - Refactored related logic to improve code maintainability and reduce redundancy.
122 lines
4.8 KiB
TypeScript
122 lines
4.8 KiB
TypeScript
'use client';
|
|
import React, {useContext, useEffect} from 'react';
|
|
import {
|
|
Attribute,
|
|
CharacterAttribute,
|
|
characterCategories,
|
|
CharacterProps
|
|
} from '@/lib/models/Character';
|
|
import {SeriesCharacterProps} from '@/lib/models/Series';
|
|
import {useTranslations} from 'next-intl';
|
|
import {SessionContext} from '@/context/SessionContext';
|
|
import {AlertContext} from '@/context/AlertContext';
|
|
import {LangContext} from '@/context/LangContext';
|
|
import OfflineContext, {OfflineContextType} from '@/context/OfflineContext';
|
|
import {BookContext} from '@/context/BookContext';
|
|
import System from '@/lib/models/System';
|
|
|
|
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} = useContext(LangContext);
|
|
const {session} = useContext(SessionContext);
|
|
const {errorMessage} = useContext(AlertContext);
|
|
const {isCurrentlyOffline} = useContext<OfflineContextType>(OfflineContext);
|
|
const {book} = useContext(BookContext);
|
|
|
|
useEffect(function (): void {
|
|
if (character?.id !== null) {
|
|
getAttributes().then();
|
|
}
|
|
}, [character?.id]);
|
|
|
|
async function getAttributes(): Promise<void> {
|
|
try {
|
|
let response: AttributeResponse;
|
|
if (isCurrentlyOffline()) {
|
|
response = await window.electron.invoke<AttributeResponse>('db:character:attributes', {characterId: character?.id});
|
|
} else if (book?.localBook) {
|
|
response = await window.electron.invoke<AttributeResponse>('db:character:attributes', {characterId: character?.id});
|
|
} else {
|
|
response = await System.authGetQueryToServer<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 renderField(label: string, value: string | number | null | undefined): React.JSX.Element | null {
|
|
if (!value) return null;
|
|
return (
|
|
<div className="mb-3">
|
|
<span className="text-text-secondary text-xs block mb-1">{label}</span>
|
|
<p className="text-text-primary text-sm">{value}</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function getCategoryLabel(category: string | null | undefined): string {
|
|
if (!category) return '';
|
|
const found = characterCategories.find(function (c): boolean { return c.value === category; });
|
|
return found ? t(found.label) : category;
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
{/* Image du personnage - version compacte */}
|
|
{character.image && (
|
|
<div className="flex justify-center mb-4">
|
|
<div className="w-16 h-16 rounded-full border-2 border-primary overflow-hidden">
|
|
<img
|
|
src={character.image}
|
|
alt={character.name}
|
|
className="w-full h-full object-cover"
|
|
/>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<h3 className="text-text-primary font-semibold text-base mb-4">
|
|
{character.name} {character.lastName}
|
|
</h3>
|
|
|
|
{renderField(t('characterDetail.role'), getCategoryLabel(character.category))}
|
|
{renderField(t('characterDetail.title'), character.title)}
|
|
{renderField(t('characterDetail.gender'), character.gender)}
|
|
{renderField(t('characterDetail.age'), character.age)}
|
|
{renderField(t('characterDetail.biography'), character.biography)}
|
|
{renderField(t('characterDetail.roleFull'), character.role)}
|
|
</div>
|
|
);
|
|
}
|