- Added offline detection logic with `OfflineContext` to improve app functionality in offline scenarios. - Integrated Tauri IPC functions to handle local tool settings and character attributes when offline. - Refined indentation logic in `TextEditor` for better compatibility with WebKit engines. - Removed unused `indent` property and related settings in editor components to simplify configuration. - Updated locale files with improved translation consistency and parameterized placeholders.
105 lines
4.8 KiB
TypeScript
105 lines
4.8 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 {BookContext, BookContextProps} from '@/context/BookContext';
|
|
import OfflineContext, {OfflineContextType} from '@/context/OfflineContext';
|
|
import {isDesktop} from '@/lib/configs';
|
|
import {apiGet} from '@/lib/api/client';
|
|
import {getCharacterAttributes} from '@/lib/tauri';
|
|
|
|
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);
|
|
const {book}: BookContextProps = useContext<BookContextProps>(BookContext);
|
|
const {isCurrentlyOffline} = useContext(OfflineContext);
|
|
|
|
useEffect(function (): void {
|
|
if (character?.id !== null) {
|
|
getAttributes().then();
|
|
}
|
|
}, [character?.id]);
|
|
|
|
async function getAttributes(): Promise<void> {
|
|
try {
|
|
const useLocal: boolean = isDesktop && (isCurrentlyOffline() || !!book?.localBook);
|
|
const response: AttributeResponse = useLocal
|
|
? await getCharacterAttributes(character.id!) as 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>
|
|
);
|
|
}
|