Expand character model with additional attributes and advanced customization options
- Added fields such as `nickname`, `age`, `gender`, `species`, `nationality`, `status`, and others to enhance character customization. - Modified localization files to include new field labels and placeholders. - Updated `CharacterComponent` and `CharacterDetail` components with UI elements for the newly added attributes. - Introduced "Advanced Mode" toggle to manage visibility of extended customization options. - Refactored database models and repository methods (`addNewCharacter`, `updateCharacter`, and `fetchCharacters`) to handle the extended schema. - Improved data encryption and decryption workflows for secure storage of added attributes. - Enhanced user experience by reorganizing character customization layouts.
This commit is contained in:
@@ -35,12 +35,23 @@ const initialCharacterState: CharacterProps = {
|
|||||||
id: null,
|
id: null,
|
||||||
name: '',
|
name: '',
|
||||||
lastName: '',
|
lastName: '',
|
||||||
|
nickname: '',
|
||||||
|
age: '',
|
||||||
|
gender: '',
|
||||||
|
species: '',
|
||||||
|
nationality: '',
|
||||||
|
status: 'alive',
|
||||||
category: 'none',
|
category: 'none',
|
||||||
title: '',
|
title: '',
|
||||||
role: '',
|
role: '',
|
||||||
image: 'https://via.placeholder.com/150',
|
image: 'https://via.placeholder.com/150',
|
||||||
biography: '',
|
biography: '',
|
||||||
history: '',
|
history: '',
|
||||||
|
speechPattern: '',
|
||||||
|
catchphrase: '',
|
||||||
|
residence: '',
|
||||||
|
notes: '',
|
||||||
|
color: '',
|
||||||
physical: [],
|
physical: [],
|
||||||
psychological: [],
|
psychological: [],
|
||||||
relations: [],
|
relations: [],
|
||||||
@@ -49,6 +60,16 @@ const initialCharacterState: CharacterProps = {
|
|||||||
strengths: [],
|
strengths: [],
|
||||||
goals: [],
|
goals: [],
|
||||||
motivations: [],
|
motivations: [],
|
||||||
|
arc: [],
|
||||||
|
secrets: [],
|
||||||
|
fears: [],
|
||||||
|
flaws: [],
|
||||||
|
beliefs: [],
|
||||||
|
conflicts: [],
|
||||||
|
quotes: [],
|
||||||
|
distinguishingMarks: [],
|
||||||
|
items: [],
|
||||||
|
affiliations: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
export function CharacterComponent({showToggle = true}: {showToggle?: boolean}, ref: any) {
|
export function CharacterComponent({showToggle = true}: {showToggle?: boolean}, ref: any) {
|
||||||
@@ -102,7 +123,8 @@ export function CharacterComponent({showToggle = true}: {showToggle?: boolean},
|
|||||||
setBook({...book, tools: {
|
setBook({...book, tools: {
|
||||||
characters: enabled,
|
characters: enabled,
|
||||||
worlds: book.tools?.worlds ?? false,
|
worlds: book.tools?.worlds ?? false,
|
||||||
locations: book.tools?.locations ?? false
|
locations: book.tools?.locations ?? false,
|
||||||
|
spells: book.tools?.spells ?? false
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
@@ -133,7 +155,8 @@ export function CharacterComponent({showToggle = true}: {showToggle?: boolean},
|
|||||||
setBook({...book, tools: {
|
setBook({...book, tools: {
|
||||||
characters: response.enabled,
|
characters: response.enabled,
|
||||||
worlds: book.tools?.worlds ?? false,
|
worlds: book.tools?.worlds ?? false,
|
||||||
locations: book.tools?.locations ?? false
|
locations: book.tools?.locations ?? false,
|
||||||
|
spells: book.tools?.spells ?? false
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,23 +10,26 @@ import {
|
|||||||
CharacterAttribute,
|
CharacterAttribute,
|
||||||
characterCategories,
|
characterCategories,
|
||||||
CharacterElement,
|
CharacterElement,
|
||||||
characterElementCategory,
|
basicCharacterElements,
|
||||||
|
advancedCharacterElements,
|
||||||
CharacterProps,
|
CharacterProps,
|
||||||
characterTitle
|
characterStatus
|
||||||
} from "@/lib/models/Character";
|
} from "@/lib/models/Character";
|
||||||
import System from "@/lib/models/System";
|
import System from "@/lib/models/System";
|
||||||
import {
|
import {
|
||||||
faAddressCard,
|
|
||||||
faArrowLeft,
|
faArrowLeft,
|
||||||
faBook,
|
faBook,
|
||||||
faLayerGroup,
|
|
||||||
faPlus,
|
faPlus,
|
||||||
faSave,
|
faSave,
|
||||||
faScroll,
|
faScroll,
|
||||||
faUser
|
faUser,
|
||||||
|
faSliders,
|
||||||
|
faGlobe,
|
||||||
|
faCommentDots,
|
||||||
|
faStickyNote
|
||||||
} from "@fortawesome/free-solid-svg-icons";
|
} from "@fortawesome/free-solid-svg-icons";
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||||
import {Dispatch, SetStateAction, useContext, useEffect} from "react";
|
import {Dispatch, SetStateAction, useContext, useEffect, useState} from "react";
|
||||||
import CharacterSectionElement from "@/components/book/settings/characters/CharacterSectionElement";
|
import CharacterSectionElement from "@/components/book/settings/characters/CharacterSectionElement";
|
||||||
import DeleteButton from "@/components/form/DeleteButton";
|
import DeleteButton from "@/components/form/DeleteButton";
|
||||||
import {useTranslations} from "next-intl";
|
import {useTranslations} from "next-intl";
|
||||||
@@ -67,6 +70,7 @@ export default function CharacterDetail(
|
|||||||
const {book} = useContext(BookContext);
|
const {book} = useContext(BookContext);
|
||||||
const {session} = useContext(SessionContext);
|
const {session} = useContext(SessionContext);
|
||||||
const {errorMessage} = useContext(AlertContext);
|
const {errorMessage} = useContext(AlertContext);
|
||||||
|
const [showAdvanced, setShowAdvanced] = useState<boolean>(false);
|
||||||
|
|
||||||
useEffect((): void => {
|
useEffect((): void => {
|
||||||
if (selectedCharacter?.id !== null) {
|
if (selectedCharacter?.id !== null) {
|
||||||
@@ -104,13 +108,24 @@ export default function CharacterDetail(
|
|||||||
setSelectedCharacter({
|
setSelectedCharacter({
|
||||||
id: selectedCharacter?.id ?? '',
|
id: selectedCharacter?.id ?? '',
|
||||||
name: selectedCharacter?.name ?? '',
|
name: selectedCharacter?.name ?? '',
|
||||||
image: selectedCharacter?.image ?? '',
|
|
||||||
lastName: selectedCharacter?.lastName ?? '',
|
lastName: selectedCharacter?.lastName ?? '',
|
||||||
|
nickname: selectedCharacter?.nickname ?? '',
|
||||||
|
age: selectedCharacter?.age ?? '',
|
||||||
|
gender: selectedCharacter?.gender ?? '',
|
||||||
|
species: selectedCharacter?.species ?? '',
|
||||||
|
nationality: selectedCharacter?.nationality ?? '',
|
||||||
|
status: selectedCharacter?.status ?? 'alive',
|
||||||
category: selectedCharacter?.category ?? 'none',
|
category: selectedCharacter?.category ?? 'none',
|
||||||
title: selectedCharacter?.title ?? '',
|
title: selectedCharacter?.title ?? '',
|
||||||
|
image: selectedCharacter?.image ?? '',
|
||||||
|
role: selectedCharacter?.role ?? '',
|
||||||
biography: selectedCharacter?.biography,
|
biography: selectedCharacter?.biography,
|
||||||
history: selectedCharacter?.history,
|
history: selectedCharacter?.history,
|
||||||
role: selectedCharacter?.role ?? '',
|
speechPattern: selectedCharacter?.speechPattern,
|
||||||
|
catchphrase: selectedCharacter?.catchphrase,
|
||||||
|
residence: selectedCharacter?.residence,
|
||||||
|
notes: selectedCharacter?.notes,
|
||||||
|
color: selectedCharacter?.color,
|
||||||
physical: attributes.physical ?? [],
|
physical: attributes.physical ?? [],
|
||||||
psychological: attributes.psychological ?? [],
|
psychological: attributes.psychological ?? [],
|
||||||
relations: attributes.relations ?? [],
|
relations: attributes.relations ?? [],
|
||||||
@@ -119,6 +134,16 @@ export default function CharacterDetail(
|
|||||||
strengths: attributes.strengths ?? [],
|
strengths: attributes.strengths ?? [],
|
||||||
goals: attributes.goals ?? [],
|
goals: attributes.goals ?? [],
|
||||||
motivations: attributes.motivations ?? [],
|
motivations: attributes.motivations ?? [],
|
||||||
|
arc: attributes.arc ?? [],
|
||||||
|
secrets: attributes.secrets ?? [],
|
||||||
|
fears: attributes.fears ?? [],
|
||||||
|
flaws: attributes.flaws ?? [],
|
||||||
|
beliefs: attributes.beliefs ?? [],
|
||||||
|
conflicts: attributes.conflicts ?? [],
|
||||||
|
quotes: attributes.quotes ?? [],
|
||||||
|
distinguishingMarks: attributes.distinguishingMarks ?? [],
|
||||||
|
items: attributes.items ?? [],
|
||||||
|
affiliations: attributes.affiliations ?? [],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
@@ -185,6 +210,17 @@ export default function CharacterDetail(
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<InputField
|
||||||
|
fieldName={t("characterDetail.nickname")}
|
||||||
|
input={
|
||||||
|
<TextInput
|
||||||
|
value={selectedCharacter?.nickname || ''}
|
||||||
|
setValue={(e) => handleCharacterChange('nickname', e.target.value)}
|
||||||
|
placeholder={t("characterDetail.nicknamePlaceholder")}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<InputField
|
<InputField
|
||||||
fieldName={t("characterDetail.role")}
|
fieldName={t("characterDetail.role")}
|
||||||
input={
|
input={
|
||||||
@@ -196,19 +232,39 @@ export default function CharacterDetail(
|
|||||||
data={characterCategories}
|
data={characterCategories}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
icon={faLayerGroup}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<InputField
|
<InputField
|
||||||
fieldName={t("characterDetail.title")}
|
fieldName={t("characterDetail.title")}
|
||||||
input={
|
input={
|
||||||
<SelectBox
|
<TextInput
|
||||||
defaultValue={selectedCharacter?.title || 'none'}
|
value={selectedCharacter?.title || ''}
|
||||||
onChangeCallBack={(e) => handleCharacterChange('title', e.target.value)}
|
setValue={(e) => handleCharacterChange('title', e.target.value)}
|
||||||
data={characterTitle}
|
placeholder={t("characterDetail.titlePlaceholder")}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InputField
|
||||||
|
fieldName={t("characterDetail.gender")}
|
||||||
|
input={
|
||||||
|
<TextInput
|
||||||
|
value={selectedCharacter?.gender || ''}
|
||||||
|
setValue={(e) => handleCharacterChange('gender', e.target.value)}
|
||||||
|
placeholder={t("characterDetail.genderPlaceholder")}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InputField
|
||||||
|
fieldName={t("characterDetail.age")}
|
||||||
|
input={
|
||||||
|
<TextInput
|
||||||
|
value={selectedCharacter?.age || ''}
|
||||||
|
setValue={(e) => handleCharacterChange('age', e.target.value)}
|
||||||
|
placeholder={t("characterDetail.agePlaceholder")}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
icon={faAddressCard}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</CollapsableArea>
|
</CollapsableArea>
|
||||||
@@ -253,9 +309,10 @@ export default function CharacterDetail(
|
|||||||
</div>
|
</div>
|
||||||
</CollapsableArea>
|
</CollapsableArea>
|
||||||
|
|
||||||
{characterElementCategory.map((item: CharacterElement, index: number) => (
|
{/* Attributs de base - toujours visibles */}
|
||||||
|
{basicCharacterElements.map((item: CharacterElement, index: number) => (
|
||||||
<CharacterSectionElement
|
<CharacterSectionElement
|
||||||
key={index}
|
key={`basic-${index}`}
|
||||||
title={item.title}
|
title={item.title}
|
||||||
section={item.section}
|
section={item.section}
|
||||||
placeholder={item.placeholder}
|
placeholder={item.placeholder}
|
||||||
@@ -266,6 +323,149 @@ export default function CharacterDetail(
|
|||||||
handleRemoveElement={handleRemoveElement}
|
handleRemoveElement={handleRemoveElement}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
{/* Toggle Mode Avancé */}
|
||||||
|
<div className="flex items-center justify-between p-4 bg-secondary/30 rounded-xl border border-secondary/50">
|
||||||
|
<div className="flex items-center gap-3">
|
||||||
|
<FontAwesomeIcon icon={faSliders} className="text-primary w-5 h-5"/>
|
||||||
|
<span className="text-text-primary font-medium">{t("characterDetail.advancedMode")}</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={() => setShowAdvanced(!showAdvanced)}
|
||||||
|
className={`px-4 py-2 rounded-lg transition-all duration-200 ${
|
||||||
|
showAdvanced
|
||||||
|
? 'bg-primary text-white'
|
||||||
|
: 'bg-secondary/50 text-text-primary hover:bg-secondary'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{showAdvanced ? t("characterDetail.hideAdvanced") : t("characterDetail.showAdvanced")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Sections avancées - visibles uniquement si showAdvanced est true */}
|
||||||
|
{showAdvanced && (
|
||||||
|
<>
|
||||||
|
{/* Identité étendue */}
|
||||||
|
<CollapsableArea title={t("characterDetail.identitySection")} icon={faGlobe}>
|
||||||
|
<div className="space-y-4 p-4 bg-secondary/20 rounded-xl border border-secondary/30">
|
||||||
|
<InputField
|
||||||
|
fieldName={t("characterDetail.species")}
|
||||||
|
input={
|
||||||
|
<TextInput
|
||||||
|
value={selectedCharacter?.species || ''}
|
||||||
|
setValue={(e) => handleCharacterChange('species', e.target.value)}
|
||||||
|
placeholder={t("characterDetail.speciesPlaceholder")}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InputField
|
||||||
|
fieldName={t("characterDetail.nationality")}
|
||||||
|
input={
|
||||||
|
<TextInput
|
||||||
|
value={selectedCharacter?.nationality || ''}
|
||||||
|
setValue={(e) => handleCharacterChange('nationality', e.target.value)}
|
||||||
|
placeholder={t("characterDetail.nationalityPlaceholder")}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InputField
|
||||||
|
fieldName={t("characterDetail.status")}
|
||||||
|
input={
|
||||||
|
<SelectBox
|
||||||
|
defaultValue={selectedCharacter?.status || 'alive'}
|
||||||
|
onChangeCallBack={(e) => setSelectedCharacter(prev =>
|
||||||
|
prev ? {...prev, status: e.target.value as CharacterProps['status']} : prev
|
||||||
|
)}
|
||||||
|
data={characterStatus}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InputField
|
||||||
|
fieldName={t("characterDetail.residence")}
|
||||||
|
input={
|
||||||
|
<TextInput
|
||||||
|
value={selectedCharacter?.residence || ''}
|
||||||
|
setValue={(e) => handleCharacterChange('residence', e.target.value)}
|
||||||
|
placeholder={t("characterDetail.residencePlaceholder")}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</CollapsableArea>
|
||||||
|
|
||||||
|
{/* Voix du personnage */}
|
||||||
|
<CollapsableArea title={t("characterDetail.voiceSection")} icon={faCommentDots}>
|
||||||
|
<div className="space-y-4 p-4 bg-secondary/20 rounded-xl border border-secondary/30">
|
||||||
|
<InputField
|
||||||
|
fieldName={t("characterDetail.speechPattern")}
|
||||||
|
input={
|
||||||
|
<TexteAreaInput
|
||||||
|
value={selectedCharacter?.speechPattern || ''}
|
||||||
|
setValue={(e) => handleCharacterChange('speechPattern', e.target.value)}
|
||||||
|
placeholder={t("characterDetail.speechPatternPlaceholder")}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InputField
|
||||||
|
fieldName={t("characterDetail.catchphrase")}
|
||||||
|
input={
|
||||||
|
<TextInput
|
||||||
|
value={selectedCharacter?.catchphrase || ''}
|
||||||
|
setValue={(e) => handleCharacterChange('catchphrase', e.target.value)}
|
||||||
|
placeholder={t("characterDetail.catchphrasePlaceholder")}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</CollapsableArea>
|
||||||
|
|
||||||
|
{/* Notes de l'auteur */}
|
||||||
|
<CollapsableArea title={t("characterDetail.authorSection")} icon={faStickyNote}>
|
||||||
|
<div className="space-y-4 p-4 bg-secondary/20 rounded-xl border border-secondary/30">
|
||||||
|
<InputField
|
||||||
|
fieldName={t("characterDetail.notes")}
|
||||||
|
input={
|
||||||
|
<TexteAreaInput
|
||||||
|
value={selectedCharacter?.notes || ''}
|
||||||
|
setValue={(e) => handleCharacterChange('notes', e.target.value)}
|
||||||
|
placeholder={t("characterDetail.notesPlaceholder")}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<InputField
|
||||||
|
fieldName={t("characterDetail.colorLabel")}
|
||||||
|
input={
|
||||||
|
<TextInput
|
||||||
|
value={selectedCharacter?.color || ''}
|
||||||
|
setValue={(e) => handleCharacterChange('color', e.target.value)}
|
||||||
|
placeholder={t("characterDetail.colorPlaceholder")}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</CollapsableArea>
|
||||||
|
|
||||||
|
{/* Attributs avancés */}
|
||||||
|
{advancedCharacterElements.map((item: CharacterElement, index: number) => (
|
||||||
|
<CharacterSectionElement
|
||||||
|
key={`advanced-${index}`}
|
||||||
|
title={item.title}
|
||||||
|
section={item.section}
|
||||||
|
placeholder={item.placeholder}
|
||||||
|
icon={item.icon}
|
||||||
|
selectedCharacter={selectedCharacter as CharacterProps}
|
||||||
|
setSelectedCharacter={setSelectedCharacter}
|
||||||
|
handleAddElement={handleAddElement}
|
||||||
|
handleRemoveElement={handleRemoveElement}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,6 +13,12 @@ export interface CharacterPropsPost {
|
|||||||
id: string | null;
|
id: string | null;
|
||||||
name: string;
|
name: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
|
nickname: string;
|
||||||
|
age: string;
|
||||||
|
gender: string;
|
||||||
|
species: string;
|
||||||
|
nationality: string;
|
||||||
|
status: 'alive' | 'dead' | 'unknown';
|
||||||
category: CharacterCategory;
|
category: CharacterCategory;
|
||||||
title: string;
|
title: string;
|
||||||
image: string;
|
image: string;
|
||||||
@@ -24,9 +30,24 @@ export interface CharacterPropsPost {
|
|||||||
strengths: { name: string }[];
|
strengths: { name: string }[];
|
||||||
goals: { name: string }[];
|
goals: { name: string }[];
|
||||||
motivations: { name: string }[];
|
motivations: { name: string }[];
|
||||||
|
arc: { name: string }[];
|
||||||
|
secrets: { name: string }[];
|
||||||
|
fears: { name: string }[];
|
||||||
|
flaws: { name: string }[];
|
||||||
|
beliefs: { name: string }[];
|
||||||
|
conflicts: { name: string }[];
|
||||||
|
quotes: { name: string }[];
|
||||||
|
distinguishingMarks: { name: string }[];
|
||||||
|
items: { name: string }[];
|
||||||
|
affiliations: { name: string }[];
|
||||||
role: string;
|
role: string;
|
||||||
biography?: string;
|
biography?: string;
|
||||||
history?: string;
|
history?: string;
|
||||||
|
speechPattern?: string;
|
||||||
|
catchphrase?: string;
|
||||||
|
residence?: string;
|
||||||
|
notes?: string;
|
||||||
|
color?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -34,12 +55,23 @@ export interface CharacterProps {
|
|||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
|
nickname: string;
|
||||||
|
age: string;
|
||||||
|
gender: string;
|
||||||
|
species: string;
|
||||||
|
nationality: string;
|
||||||
|
status: string;
|
||||||
title: string;
|
title: string;
|
||||||
category: string;
|
category: string;
|
||||||
image: string;
|
image: string;
|
||||||
role: string;
|
role: string;
|
||||||
biography: string;
|
biography: string;
|
||||||
history: string;
|
history: string;
|
||||||
|
speechPattern: string;
|
||||||
|
catchphrase: string;
|
||||||
|
residence: string;
|
||||||
|
notes: string;
|
||||||
|
color: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CharacterListResponse {
|
export interface CharacterListResponse {
|
||||||
@@ -51,12 +83,23 @@ export interface CompleteCharacterProps {
|
|||||||
id?: string;
|
id?: string;
|
||||||
name: string;
|
name: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
|
nickname?: string;
|
||||||
|
age?: string;
|
||||||
|
gender?: string;
|
||||||
|
species?: string;
|
||||||
|
nationality?: string;
|
||||||
|
status?: string;
|
||||||
title: string;
|
title: string;
|
||||||
category: string;
|
category: string;
|
||||||
image?: string;
|
image?: string;
|
||||||
role: string;
|
role: string;
|
||||||
biography: string;
|
biography: string;
|
||||||
history: string;
|
history: string;
|
||||||
|
speechPattern?: string;
|
||||||
|
catchphrase?: string;
|
||||||
|
residence?: string;
|
||||||
|
notes?: string;
|
||||||
|
color?: string;
|
||||||
[key: string]: Attribute[] | string | undefined;
|
[key: string]: Attribute[] | string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,12 +151,23 @@ export default class Character {
|
|||||||
id: encryptedCharacter.character_id,
|
id: encryptedCharacter.character_id,
|
||||||
name: encryptedCharacter.first_name ? System.decryptDataWithUserKey(encryptedCharacter.first_name, userEncryptionKey) : '',
|
name: encryptedCharacter.first_name ? System.decryptDataWithUserKey(encryptedCharacter.first_name, userEncryptionKey) : '',
|
||||||
lastName: encryptedCharacter.last_name ? System.decryptDataWithUserKey(encryptedCharacter.last_name, userEncryptionKey) : '',
|
lastName: encryptedCharacter.last_name ? System.decryptDataWithUserKey(encryptedCharacter.last_name, userEncryptionKey) : '',
|
||||||
|
nickname: encryptedCharacter.nickname ? System.decryptDataWithUserKey(encryptedCharacter.nickname, userEncryptionKey) : '',
|
||||||
|
age: encryptedCharacter.age ? System.decryptDataWithUserKey(encryptedCharacter.age, userEncryptionKey) : '',
|
||||||
|
gender: encryptedCharacter.gender ? System.decryptDataWithUserKey(encryptedCharacter.gender, userEncryptionKey) : '',
|
||||||
|
species: encryptedCharacter.species ? System.decryptDataWithUserKey(encryptedCharacter.species, userEncryptionKey) : '',
|
||||||
|
nationality: encryptedCharacter.nationality ? System.decryptDataWithUserKey(encryptedCharacter.nationality, userEncryptionKey) : '',
|
||||||
|
status: encryptedCharacter.status ? System.decryptDataWithUserKey(encryptedCharacter.status, userEncryptionKey) : 'alive',
|
||||||
title: encryptedCharacter.title ? System.decryptDataWithUserKey(encryptedCharacter.title, userEncryptionKey) : '',
|
title: encryptedCharacter.title ? System.decryptDataWithUserKey(encryptedCharacter.title, userEncryptionKey) : '',
|
||||||
category: encryptedCharacter.category ? System.decryptDataWithUserKey(encryptedCharacter.category, userEncryptionKey) : '',
|
category: encryptedCharacter.category ? System.decryptDataWithUserKey(encryptedCharacter.category, userEncryptionKey) : '',
|
||||||
image: encryptedCharacter.image ? System.decryptDataWithUserKey(encryptedCharacter.image, userEncryptionKey) : '',
|
image: encryptedCharacter.image ? System.decryptDataWithUserKey(encryptedCharacter.image, userEncryptionKey) : '',
|
||||||
role: encryptedCharacter.role ? System.decryptDataWithUserKey(encryptedCharacter.role, userEncryptionKey) : '',
|
role: encryptedCharacter.role ? System.decryptDataWithUserKey(encryptedCharacter.role, userEncryptionKey) : '',
|
||||||
biography: encryptedCharacter.biography ? System.decryptDataWithUserKey(encryptedCharacter.biography, userEncryptionKey) : '',
|
biography: encryptedCharacter.biography ? System.decryptDataWithUserKey(encryptedCharacter.biography, userEncryptionKey) : '',
|
||||||
history: encryptedCharacter.history ? System.decryptDataWithUserKey(encryptedCharacter.history, userEncryptionKey) : '',
|
history: encryptedCharacter.history ? System.decryptDataWithUserKey(encryptedCharacter.history, userEncryptionKey) : '',
|
||||||
|
speechPattern: encryptedCharacter.speech_pattern ? System.decryptDataWithUserKey(encryptedCharacter.speech_pattern, userEncryptionKey) : '',
|
||||||
|
catchphrase: encryptedCharacter.catchphrase ? System.decryptDataWithUserKey(encryptedCharacter.catchphrase, userEncryptionKey) : '',
|
||||||
|
residence: encryptedCharacter.residence ? System.decryptDataWithUserKey(encryptedCharacter.residence, userEncryptionKey) : '',
|
||||||
|
notes: encryptedCharacter.notes ? System.decryptDataWithUserKey(encryptedCharacter.notes, userEncryptionKey) : '',
|
||||||
|
color: encryptedCharacter.color ? System.decryptDataWithUserKey(encryptedCharacter.color, userEncryptionKey) : '',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return { characters: decryptedCharacterList, enabled };
|
return { characters: decryptedCharacterList, enabled };
|
||||||
@@ -132,15 +186,30 @@ export default class Character {
|
|||||||
public static addNewCharacter(userId: string, character: CharacterPropsPost, bookId: string, lang: 'fr' | 'en' = 'fr', existingCharacterId?: string): string {
|
public static addNewCharacter(userId: string, character: CharacterPropsPost, bookId: string, lang: 'fr' | 'en' = 'fr', existingCharacterId?: string): string {
|
||||||
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
||||||
const characterId: string = existingCharacterId || System.createUniqueId();
|
const characterId: string = existingCharacterId || System.createUniqueId();
|
||||||
const encryptedName: string = System.encryptDataWithUserKey(character.name, userEncryptionKey);
|
|
||||||
const encryptedLastName: string = System.encryptDataWithUserKey(character.lastName, userEncryptionKey);
|
const characterData = {
|
||||||
const encryptedTitle: string = System.encryptDataWithUserKey(character.title, userEncryptionKey);
|
firstName: System.encryptDataWithUserKey(character.name, userEncryptionKey),
|
||||||
const encryptedCategory: string = System.encryptDataWithUserKey(character.category, userEncryptionKey);
|
lastName: System.encryptDataWithUserKey(character.lastName, userEncryptionKey),
|
||||||
const encryptedImage: string = System.encryptDataWithUserKey(character.image, userEncryptionKey);
|
nickname: System.encryptDataWithUserKey(character.nickname || '', userEncryptionKey),
|
||||||
const encryptedRole: string = System.encryptDataWithUserKey(character.role, userEncryptionKey);
|
age: System.encryptDataWithUserKey(character.age || '', userEncryptionKey),
|
||||||
const encryptedBiography: string = System.encryptDataWithUserKey(character.biography ? character.biography : '', userEncryptionKey);
|
gender: System.encryptDataWithUserKey(character.gender || '', userEncryptionKey),
|
||||||
const encryptedHistory: string = System.encryptDataWithUserKey(character.history ? character.history : '', userEncryptionKey);
|
species: System.encryptDataWithUserKey(character.species || '', userEncryptionKey),
|
||||||
CharacterRepo.addNewCharacter(userId, characterId, encryptedName, encryptedLastName, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, bookId, lang);
|
nationality: System.encryptDataWithUserKey(character.nationality || '', userEncryptionKey),
|
||||||
|
status: System.encryptDataWithUserKey(character.status || 'alive', userEncryptionKey),
|
||||||
|
title: System.encryptDataWithUserKey(character.title, userEncryptionKey),
|
||||||
|
category: System.encryptDataWithUserKey(character.category, userEncryptionKey),
|
||||||
|
image: System.encryptDataWithUserKey(character.image, userEncryptionKey),
|
||||||
|
role: System.encryptDataWithUserKey(character.role, userEncryptionKey),
|
||||||
|
biography: System.encryptDataWithUserKey(character.biography || '', userEncryptionKey),
|
||||||
|
history: System.encryptDataWithUserKey(character.history || '', userEncryptionKey),
|
||||||
|
speechPattern: System.encryptDataWithUserKey(character.speechPattern || '', userEncryptionKey),
|
||||||
|
catchphrase: System.encryptDataWithUserKey(character.catchphrase || '', userEncryptionKey),
|
||||||
|
residence: System.encryptDataWithUserKey(character.residence || '', userEncryptionKey),
|
||||||
|
notes: System.encryptDataWithUserKey(character.notes || '', userEncryptionKey),
|
||||||
|
color: System.encryptDataWithUserKey(character.color || '', userEncryptionKey),
|
||||||
|
};
|
||||||
|
|
||||||
|
CharacterRepo.addNewCharacter(userId, characterId, characterData, bookId, lang);
|
||||||
const characterPropertyKeys: string[] = Object.keys(character);
|
const characterPropertyKeys: string[] = Object.keys(character);
|
||||||
for (const propertyKey of characterPropertyKeys) {
|
for (const propertyKey of characterPropertyKeys) {
|
||||||
if (Array.isArray(character[propertyKey as keyof CharacterPropsPost])) {
|
if (Array.isArray(character[propertyKey as keyof CharacterPropsPost])) {
|
||||||
@@ -170,15 +239,30 @@ export default class Character {
|
|||||||
if (!character.id) {
|
if (!character.id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const encryptedName: string = System.encryptDataWithUserKey(character.name, userEncryptionKey);
|
|
||||||
const encryptedLastName: string = System.encryptDataWithUserKey(character.lastName, userEncryptionKey);
|
const characterData = {
|
||||||
const encryptedTitle: string = System.encryptDataWithUserKey(character.title, userEncryptionKey);
|
firstName: System.encryptDataWithUserKey(character.name, userEncryptionKey),
|
||||||
const encryptedCategory: string = System.encryptDataWithUserKey(character.category, userEncryptionKey);
|
lastName: System.encryptDataWithUserKey(character.lastName, userEncryptionKey),
|
||||||
const encryptedImage: string = System.encryptDataWithUserKey(character.image, userEncryptionKey);
|
nickname: System.encryptDataWithUserKey(character.nickname || '', userEncryptionKey),
|
||||||
const encryptedRole: string = System.encryptDataWithUserKey(character.role, userEncryptionKey);
|
age: System.encryptDataWithUserKey(character.age || '', userEncryptionKey),
|
||||||
const encryptedBiography: string = System.encryptDataWithUserKey(character.biography ? character.biography : '', userEncryptionKey);
|
gender: System.encryptDataWithUserKey(character.gender || '', userEncryptionKey),
|
||||||
const encryptedHistory: string = System.encryptDataWithUserKey(character.history ? character.history : '', userEncryptionKey);
|
species: System.encryptDataWithUserKey(character.species || '', userEncryptionKey),
|
||||||
return CharacterRepo.updateCharacter(userId, character.id, encryptedName, encryptedLastName, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, System.timeStampInSeconds(), lang);
|
nationality: System.encryptDataWithUserKey(character.nationality || '', userEncryptionKey),
|
||||||
|
status: System.encryptDataWithUserKey(character.status || 'alive', userEncryptionKey),
|
||||||
|
title: System.encryptDataWithUserKey(character.title, userEncryptionKey),
|
||||||
|
category: System.encryptDataWithUserKey(character.category, userEncryptionKey),
|
||||||
|
image: System.encryptDataWithUserKey(character.image, userEncryptionKey),
|
||||||
|
role: System.encryptDataWithUserKey(character.role, userEncryptionKey),
|
||||||
|
biography: System.encryptDataWithUserKey(character.biography || '', userEncryptionKey),
|
||||||
|
history: System.encryptDataWithUserKey(character.history || '', userEncryptionKey),
|
||||||
|
speechPattern: System.encryptDataWithUserKey(character.speechPattern || '', userEncryptionKey),
|
||||||
|
catchphrase: System.encryptDataWithUserKey(character.catchphrase || '', userEncryptionKey),
|
||||||
|
residence: System.encryptDataWithUserKey(character.residence || '', userEncryptionKey),
|
||||||
|
notes: System.encryptDataWithUserKey(character.notes || '', userEncryptionKey),
|
||||||
|
color: System.encryptDataWithUserKey(character.color || '', userEncryptionKey),
|
||||||
|
};
|
||||||
|
|
||||||
|
return CharacterRepo.updateCharacter(userId, character.id, characterData, System.timeStampInSeconds(), lang);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -285,11 +369,22 @@ export default class Character {
|
|||||||
id: '',
|
id: '',
|
||||||
name: encryptedCharacter.first_name ? System.decryptDataWithUserKey(encryptedCharacter.first_name, userEncryptionKey) : '',
|
name: encryptedCharacter.first_name ? System.decryptDataWithUserKey(encryptedCharacter.first_name, userEncryptionKey) : '',
|
||||||
lastName: encryptedCharacter.last_name ? System.decryptDataWithUserKey(encryptedCharacter.last_name, userEncryptionKey) : '',
|
lastName: encryptedCharacter.last_name ? System.decryptDataWithUserKey(encryptedCharacter.last_name, userEncryptionKey) : '',
|
||||||
title: encryptedCharacter.title ? System.decryptDataWithUserKey(encryptedCharacter.title, userEncryptionKey) : '',
|
nickname: encryptedCharacter.nickname ? System.decryptDataWithUserKey(encryptedCharacter.nickname as string, userEncryptionKey) : '',
|
||||||
category: encryptedCharacter.category ? System.decryptDataWithUserKey(encryptedCharacter.category, userEncryptionKey) : '',
|
age: encryptedCharacter.age ? System.decryptDataWithUserKey(encryptedCharacter.age as string, userEncryptionKey) : '',
|
||||||
role: encryptedCharacter.role ? System.decryptDataWithUserKey(encryptedCharacter.role, userEncryptionKey) : '',
|
gender: encryptedCharacter.gender ? System.decryptDataWithUserKey(encryptedCharacter.gender as string, userEncryptionKey) : '',
|
||||||
biography: encryptedCharacter.biography ? System.decryptDataWithUserKey(encryptedCharacter.biography, userEncryptionKey) : '',
|
species: encryptedCharacter.species ? System.decryptDataWithUserKey(encryptedCharacter.species as string, userEncryptionKey) : '',
|
||||||
history: encryptedCharacter.history ? System.decryptDataWithUserKey(encryptedCharacter.history, userEncryptionKey) : '',
|
nationality: encryptedCharacter.nationality ? System.decryptDataWithUserKey(encryptedCharacter.nationality as string, userEncryptionKey) : '',
|
||||||
|
status: encryptedCharacter.status ? System.decryptDataWithUserKey(encryptedCharacter.status as string, userEncryptionKey) : 'alive',
|
||||||
|
title: encryptedCharacter.title ? System.decryptDataWithUserKey(encryptedCharacter.title as string, userEncryptionKey) : '',
|
||||||
|
category: encryptedCharacter.category ? System.decryptDataWithUserKey(encryptedCharacter.category as string, userEncryptionKey) : '',
|
||||||
|
role: encryptedCharacter.role ? System.decryptDataWithUserKey(encryptedCharacter.role as string, userEncryptionKey) : '',
|
||||||
|
biography: encryptedCharacter.biography ? System.decryptDataWithUserKey(encryptedCharacter.biography as string, userEncryptionKey) : '',
|
||||||
|
history: encryptedCharacter.history ? System.decryptDataWithUserKey(encryptedCharacter.history as string, userEncryptionKey) : '',
|
||||||
|
speechPattern: encryptedCharacter.speech_pattern ? System.decryptDataWithUserKey(encryptedCharacter.speech_pattern as string, userEncryptionKey) : '',
|
||||||
|
catchphrase: encryptedCharacter.catchphrase ? System.decryptDataWithUserKey(encryptedCharacter.catchphrase as string, userEncryptionKey) : '',
|
||||||
|
residence: encryptedCharacter.residence ? System.decryptDataWithUserKey(encryptedCharacter.residence as string, userEncryptionKey) : '',
|
||||||
|
notes: encryptedCharacter.notes ? System.decryptDataWithUserKey(encryptedCharacter.notes as string, userEncryptionKey) : '',
|
||||||
|
color: encryptedCharacter.color ? System.decryptDataWithUserKey(encryptedCharacter.color as string, userEncryptionKey) : '',
|
||||||
physical: [],
|
physical: [],
|
||||||
psychological: [],
|
psychological: [],
|
||||||
relations: [],
|
relations: [],
|
||||||
@@ -297,7 +392,17 @@ export default class Character {
|
|||||||
weaknesses: [],
|
weaknesses: [],
|
||||||
strengths: [],
|
strengths: [],
|
||||||
goals: [],
|
goals: [],
|
||||||
motivations: []
|
motivations: [],
|
||||||
|
arc: [],
|
||||||
|
secrets: [],
|
||||||
|
fears: [],
|
||||||
|
flaws: [],
|
||||||
|
beliefs: [],
|
||||||
|
conflicts: [],
|
||||||
|
quotes: [],
|
||||||
|
distinguishingMarks: [],
|
||||||
|
items: [],
|
||||||
|
affiliations: []
|
||||||
};
|
};
|
||||||
completeCharactersMap.set(encryptedCharacter.character_id, decryptedCharacter);
|
completeCharactersMap.set(encryptedCharacter.character_id, decryptedCharacter);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,15 +106,28 @@ export default class Download {
|
|||||||
if (!chapterInfosInserted) return false;
|
if (!chapterInfosInserted) return false;
|
||||||
|
|
||||||
const charactersInserted: boolean = data.characters.every((character: BookCharactersTable): boolean => {
|
const charactersInserted: boolean = data.characters.every((character: BookCharactersTable): boolean => {
|
||||||
const encryptedCharacterFirstName: string = System.encryptDataWithUserKey(character.first_name, userEncryptionKey);
|
const characterData = {
|
||||||
const encryptedCharacterLastName: string | null = character.last_name ? System.encryptDataWithUserKey(character.last_name, userEncryptionKey) : null;
|
firstName: System.encryptDataWithUserKey(character.first_name, userEncryptionKey),
|
||||||
const encryptedCharacterCategory: string = System.encryptDataWithUserKey(character.category, userEncryptionKey);
|
lastName: character.last_name ? System.encryptDataWithUserKey(character.last_name, userEncryptionKey) : null,
|
||||||
const encryptedCharacterTitle: string | null = character.title ? System.encryptDataWithUserKey(character.title, userEncryptionKey) : null;
|
nickname: character.nickname ? System.encryptDataWithUserKey(character.nickname, userEncryptionKey) : null,
|
||||||
const encryptedCharacterImage: string | null = character.image ? System.encryptDataWithUserKey(character.image, userEncryptionKey) : null;
|
age: character.age ? System.encryptDataWithUserKey(character.age, userEncryptionKey) : null,
|
||||||
const encryptedCharacterRole: string | null = character.role ? System.encryptDataWithUserKey(character.role, userEncryptionKey) : null;
|
gender: character.gender ? System.encryptDataWithUserKey(character.gender, userEncryptionKey) : null,
|
||||||
const encryptedCharacterBiography: string | null = character.biography ? System.encryptDataWithUserKey(character.biography, userEncryptionKey) : null;
|
species: character.species ? System.encryptDataWithUserKey(character.species, userEncryptionKey) : null,
|
||||||
const encryptedCharacterHistory: string | null = character.history ? System.encryptDataWithUserKey(character.history, userEncryptionKey) : null;
|
nationality: character.nationality ? System.encryptDataWithUserKey(character.nationality, userEncryptionKey) : null,
|
||||||
return CharacterRepo.insertSyncCharacter(character.character_id, character.book_id, userId, encryptedCharacterFirstName, encryptedCharacterLastName, encryptedCharacterCategory, encryptedCharacterTitle, encryptedCharacterImage, encryptedCharacterRole, encryptedCharacterBiography, encryptedCharacterHistory, character.last_update, lang);
|
status: character.status ? System.encryptDataWithUserKey(character.status, userEncryptionKey) : null,
|
||||||
|
category: System.encryptDataWithUserKey(character.category, userEncryptionKey),
|
||||||
|
title: character.title ? System.encryptDataWithUserKey(character.title, userEncryptionKey) : null,
|
||||||
|
image: character.image ? System.encryptDataWithUserKey(character.image, userEncryptionKey) : null,
|
||||||
|
role: character.role ? System.encryptDataWithUserKey(character.role, userEncryptionKey) : null,
|
||||||
|
biography: character.biography ? System.encryptDataWithUserKey(character.biography, userEncryptionKey) : null,
|
||||||
|
history: character.history ? System.encryptDataWithUserKey(character.history, userEncryptionKey) : null,
|
||||||
|
speechPattern: character.speech_pattern ? System.encryptDataWithUserKey(character.speech_pattern, userEncryptionKey) : null,
|
||||||
|
catchphrase: character.catchphrase ? System.encryptDataWithUserKey(character.catchphrase, userEncryptionKey) : null,
|
||||||
|
residence: character.residence ? System.encryptDataWithUserKey(character.residence, userEncryptionKey) : null,
|
||||||
|
notes: character.notes ? System.encryptDataWithUserKey(character.notes, userEncryptionKey) : null,
|
||||||
|
color: character.color ? System.encryptDataWithUserKey(character.color, userEncryptionKey) : null
|
||||||
|
};
|
||||||
|
return CharacterRepo.insertSyncCharacter(character.character_id, character.book_id, userId, characterData, character.last_update, lang);
|
||||||
});
|
});
|
||||||
if (!charactersInserted) return false;
|
if (!charactersInserted) return false;
|
||||||
|
|
||||||
|
|||||||
@@ -200,11 +200,22 @@ export default class Sync {
|
|||||||
...characterRecord,
|
...characterRecord,
|
||||||
first_name: System.decryptDataWithUserKey(characterRecord.first_name, userEncryptionKey),
|
first_name: System.decryptDataWithUserKey(characterRecord.first_name, userEncryptionKey),
|
||||||
last_name: characterRecord.last_name ? System.decryptDataWithUserKey(characterRecord.last_name, userEncryptionKey) : null,
|
last_name: characterRecord.last_name ? System.decryptDataWithUserKey(characterRecord.last_name, userEncryptionKey) : null,
|
||||||
|
nickname: characterRecord.nickname ? System.decryptDataWithUserKey(characterRecord.nickname, userEncryptionKey) : null,
|
||||||
|
age: characterRecord.age ? System.decryptDataWithUserKey(characterRecord.age, userEncryptionKey) : null,
|
||||||
|
gender: characterRecord.gender ? System.decryptDataWithUserKey(characterRecord.gender, userEncryptionKey) : null,
|
||||||
|
species: characterRecord.species ? System.decryptDataWithUserKey(characterRecord.species, userEncryptionKey) : null,
|
||||||
|
nationality: characterRecord.nationality ? System.decryptDataWithUserKey(characterRecord.nationality, userEncryptionKey) : null,
|
||||||
|
status: characterRecord.status ? System.decryptDataWithUserKey(characterRecord.status, userEncryptionKey) : null,
|
||||||
category: System.decryptDataWithUserKey(characterRecord.category, userEncryptionKey),
|
category: System.decryptDataWithUserKey(characterRecord.category, userEncryptionKey),
|
||||||
title: characterRecord.title ? System.decryptDataWithUserKey(characterRecord.title, userEncryptionKey) : null,
|
title: characterRecord.title ? System.decryptDataWithUserKey(characterRecord.title, userEncryptionKey) : null,
|
||||||
role: characterRecord.role ? System.decryptDataWithUserKey(characterRecord.role, userEncryptionKey) : null,
|
role: characterRecord.role ? System.decryptDataWithUserKey(characterRecord.role, userEncryptionKey) : null,
|
||||||
biography: characterRecord.biography ? System.decryptDataWithUserKey(characterRecord.biography, userEncryptionKey) : null,
|
biography: characterRecord.biography ? System.decryptDataWithUserKey(characterRecord.biography, userEncryptionKey) : null,
|
||||||
history: characterRecord.history ? System.decryptDataWithUserKey(characterRecord.history, userEncryptionKey) : null
|
history: characterRecord.history ? System.decryptDataWithUserKey(characterRecord.history, userEncryptionKey) : null,
|
||||||
|
speech_pattern: characterRecord.speech_pattern ? System.decryptDataWithUserKey(characterRecord.speech_pattern, userEncryptionKey) : null,
|
||||||
|
catchphrase: characterRecord.catchphrase ? System.decryptDataWithUserKey(characterRecord.catchphrase, userEncryptionKey) : null,
|
||||||
|
residence: characterRecord.residence ? System.decryptDataWithUserKey(characterRecord.residence, userEncryptionKey) : null,
|
||||||
|
notes: characterRecord.notes ? System.decryptDataWithUserKey(characterRecord.notes, userEncryptionKey) : null,
|
||||||
|
color: characterRecord.color ? System.decryptDataWithUserKey(characterRecord.color, userEncryptionKey) : null
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -562,21 +573,34 @@ export default class Sync {
|
|||||||
if (serverCharacters && serverCharacters.length > 0) {
|
if (serverCharacters && serverCharacters.length > 0) {
|
||||||
for (const serverCharacter of serverCharacters) {
|
for (const serverCharacter of serverCharacters) {
|
||||||
const characterExists: boolean = CharacterRepo.isCharacterExist(userId, serverCharacter.character_id, lang);
|
const characterExists: boolean = CharacterRepo.isCharacterExist(userId, serverCharacter.character_id, lang);
|
||||||
const encryptedFirstName: string = System.encryptDataWithUserKey(serverCharacter.first_name, userEncryptionKey);
|
const characterData = {
|
||||||
const encryptedLastName: string = System.encryptDataWithUserKey(serverCharacter.last_name ? serverCharacter.last_name : '', userEncryptionKey);
|
firstName: System.encryptDataWithUserKey(serverCharacter.first_name, userEncryptionKey),
|
||||||
const encryptedCategory: string = System.encryptDataWithUserKey(serverCharacter.category, userEncryptionKey);
|
lastName: System.encryptDataWithUserKey(serverCharacter.last_name ? serverCharacter.last_name : '', userEncryptionKey),
|
||||||
const encryptedTitle: string = System.encryptDataWithUserKey(serverCharacter.title ? serverCharacter.title : '', userEncryptionKey);
|
nickname: System.encryptDataWithUserKey(serverCharacter.nickname ? serverCharacter.nickname : '', userEncryptionKey),
|
||||||
const encryptedRole: string = System.encryptDataWithUserKey(serverCharacter.role ? serverCharacter.role : '', userEncryptionKey);
|
age: System.encryptDataWithUserKey(serverCharacter.age ? serverCharacter.age : '', userEncryptionKey),
|
||||||
const encryptedImage: string = System.encryptDataWithUserKey(serverCharacter.image ? serverCharacter.image : '', userEncryptionKey);
|
gender: System.encryptDataWithUserKey(serverCharacter.gender ? serverCharacter.gender : '', userEncryptionKey),
|
||||||
const encryptedBiography: string = System.encryptDataWithUserKey(serverCharacter.biography ? serverCharacter.biography : '', userEncryptionKey);
|
species: System.encryptDataWithUserKey(serverCharacter.species ? serverCharacter.species : '', userEncryptionKey),
|
||||||
const encryptedHistory: string = System.encryptDataWithUserKey(serverCharacter.history ? serverCharacter.history : '', userEncryptionKey);
|
nationality: System.encryptDataWithUserKey(serverCharacter.nationality ? serverCharacter.nationality : '', userEncryptionKey),
|
||||||
|
status: System.encryptDataWithUserKey(serverCharacter.status ? serverCharacter.status : 'alive', userEncryptionKey),
|
||||||
|
category: System.encryptDataWithUserKey(serverCharacter.category, userEncryptionKey),
|
||||||
|
title: System.encryptDataWithUserKey(serverCharacter.title ? serverCharacter.title : '', userEncryptionKey),
|
||||||
|
image: System.encryptDataWithUserKey(serverCharacter.image ? serverCharacter.image : '', userEncryptionKey),
|
||||||
|
role: System.encryptDataWithUserKey(serverCharacter.role ? serverCharacter.role : '', userEncryptionKey),
|
||||||
|
biography: System.encryptDataWithUserKey(serverCharacter.biography ? serverCharacter.biography : '', userEncryptionKey),
|
||||||
|
history: System.encryptDataWithUserKey(serverCharacter.history ? serverCharacter.history : '', userEncryptionKey),
|
||||||
|
speechPattern: System.encryptDataWithUserKey(serverCharacter.speech_pattern ? serverCharacter.speech_pattern : '', userEncryptionKey),
|
||||||
|
catchphrase: System.encryptDataWithUserKey(serverCharacter.catchphrase ? serverCharacter.catchphrase : '', userEncryptionKey),
|
||||||
|
residence: System.encryptDataWithUserKey(serverCharacter.residence ? serverCharacter.residence : '', userEncryptionKey),
|
||||||
|
notes: System.encryptDataWithUserKey(serverCharacter.notes ? serverCharacter.notes : '', userEncryptionKey),
|
||||||
|
color: System.encryptDataWithUserKey(serverCharacter.color ? serverCharacter.color : '', userEncryptionKey)
|
||||||
|
};
|
||||||
if (characterExists) {
|
if (characterExists) {
|
||||||
const updateSuccessful: boolean = CharacterRepo.updateCharacter(userId, serverCharacter.character_id, encryptedFirstName, encryptedLastName, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, serverCharacter.last_update);
|
const updateSuccessful: boolean = CharacterRepo.updateCharacter(userId, serverCharacter.character_id, characterData, serverCharacter.last_update, lang);
|
||||||
if (!updateSuccessful) {
|
if (!updateSuccessful) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const insertSuccessful: boolean = CharacterRepo.insertSyncCharacter(serverCharacter.character_id, bookId, userId, encryptedFirstName, encryptedLastName, encryptedCategory, encryptedTitle, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, serverCharacter.last_update, lang);
|
const insertSuccessful: boolean = CharacterRepo.insertSyncCharacter(serverCharacter.character_id, bookId, userId, characterData, serverCharacter.last_update, lang);
|
||||||
if (!insertSuccessful) {
|
if (!insertSuccessful) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,11 +168,22 @@ export default class Upload {
|
|||||||
...character,
|
...character,
|
||||||
first_name: System.decryptDataWithUserKey(character.first_name, userEncryptionKey),
|
first_name: System.decryptDataWithUserKey(character.first_name, userEncryptionKey),
|
||||||
last_name: character.last_name ? System.decryptDataWithUserKey(character.last_name, userEncryptionKey) : null,
|
last_name: character.last_name ? System.decryptDataWithUserKey(character.last_name, userEncryptionKey) : null,
|
||||||
|
nickname: character.nickname ? System.decryptDataWithUserKey(character.nickname, userEncryptionKey) : null,
|
||||||
|
age: character.age ? System.decryptDataWithUserKey(character.age, userEncryptionKey) : null,
|
||||||
|
gender: character.gender ? System.decryptDataWithUserKey(character.gender, userEncryptionKey) : null,
|
||||||
|
species: character.species ? System.decryptDataWithUserKey(character.species, userEncryptionKey) : null,
|
||||||
|
nationality: character.nationality ? System.decryptDataWithUserKey(character.nationality, userEncryptionKey) : null,
|
||||||
|
status: character.status ? System.decryptDataWithUserKey(character.status, userEncryptionKey) : null,
|
||||||
category: System.decryptDataWithUserKey(character.category, userEncryptionKey),
|
category: System.decryptDataWithUserKey(character.category, userEncryptionKey),
|
||||||
title: character.title ? System.decryptDataWithUserKey(character.title, userEncryptionKey) : null,
|
title: character.title ? System.decryptDataWithUserKey(character.title, userEncryptionKey) : null,
|
||||||
role: character.role ? System.decryptDataWithUserKey(character.role, userEncryptionKey) : null,
|
role: character.role ? System.decryptDataWithUserKey(character.role, userEncryptionKey) : null,
|
||||||
biography: character.biography ? System.decryptDataWithUserKey(character.biography, userEncryptionKey) : null,
|
biography: character.biography ? System.decryptDataWithUserKey(character.biography, userEncryptionKey) : null,
|
||||||
history: character.history ? System.decryptDataWithUserKey(character.history, userEncryptionKey) : null
|
history: character.history ? System.decryptDataWithUserKey(character.history, userEncryptionKey) : null,
|
||||||
|
speech_pattern: character.speech_pattern ? System.decryptDataWithUserKey(character.speech_pattern, userEncryptionKey) : null,
|
||||||
|
catchphrase: character.catchphrase ? System.decryptDataWithUserKey(character.catchphrase, userEncryptionKey) : null,
|
||||||
|
residence: character.residence ? System.decryptDataWithUserKey(character.residence, userEncryptionKey) : null,
|
||||||
|
notes: character.notes ? System.decryptDataWithUserKey(character.notes, userEncryptionKey) : null,
|
||||||
|
color: character.color ? System.decryptDataWithUserKey(character.color, userEncryptionKey) : null
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const characterAttributes: BookCharactersAttributesTable[] = encryptedCharacterAttributes.map((attribute: BookCharactersAttributesTable): BookCharactersAttributesTable => ({
|
const characterAttributes: BookCharactersAttributesTable[] = encryptedCharacterAttributes.map((attribute: BookCharactersAttributesTable): BookCharactersAttributesTable => ({
|
||||||
|
|||||||
@@ -7,12 +7,23 @@ export interface BookCharactersTable extends Record<string, SQLiteValue> {
|
|||||||
user_id: string;
|
user_id: string;
|
||||||
first_name: string;
|
first_name: string;
|
||||||
last_name: string | null;
|
last_name: string | null;
|
||||||
|
nickname: string | null;
|
||||||
|
age: string | null;
|
||||||
|
gender: string | null;
|
||||||
|
species: string | null;
|
||||||
|
nationality: string | null;
|
||||||
|
status: string | null;
|
||||||
category: string;
|
category: string;
|
||||||
title: string | null;
|
title: string | null;
|
||||||
image: string | null;
|
image: string | null;
|
||||||
role: string | null;
|
role: string | null;
|
||||||
biography: string | null;
|
biography: string | null;
|
||||||
history: string | null;
|
history: string | null;
|
||||||
|
speech_pattern: string | null;
|
||||||
|
catchphrase: string | null;
|
||||||
|
residence: string | null;
|
||||||
|
notes: string | null;
|
||||||
|
color: string | null;
|
||||||
last_update: number;
|
last_update: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,12 +54,23 @@ export interface CharacterResult extends Record<string, SQLiteValue> {
|
|||||||
character_id: string;
|
character_id: string;
|
||||||
first_name: string;
|
first_name: string;
|
||||||
last_name: string;
|
last_name: string;
|
||||||
|
nickname: string;
|
||||||
|
age: string;
|
||||||
|
gender: string;
|
||||||
|
species: string;
|
||||||
|
nationality: string;
|
||||||
|
status: string;
|
||||||
title: string;
|
title: string;
|
||||||
category: string;
|
category: string;
|
||||||
image: string;
|
image: string;
|
||||||
role: string;
|
role: string;
|
||||||
biography: string;
|
biography: string;
|
||||||
history: string;
|
history: string;
|
||||||
|
speech_pattern: string;
|
||||||
|
catchphrase: string;
|
||||||
|
residence: string;
|
||||||
|
notes: string;
|
||||||
|
color: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AttributeResult extends Record<string, SQLiteValue> {
|
export interface AttributeResult extends Record<string, SQLiteValue> {
|
||||||
@@ -81,7 +103,7 @@ export default class CharacterRepo {
|
|||||||
public static fetchCharacters(userId: string, bookId: string, lang: 'fr' | 'en' = 'fr'): CharacterResult[] {
|
public static fetchCharacters(userId: string, bookId: string, lang: 'fr' | 'en' = 'fr'): CharacterResult[] {
|
||||||
try {
|
try {
|
||||||
const db: Database = System.getDb();
|
const db: Database = System.getDb();
|
||||||
const query: string = 'SELECT character_id, first_name, last_name, title, category, image, role, biography, history FROM book_characters WHERE book_id=? AND user_id=?';
|
const query: string = 'SELECT character_id, first_name, last_name, nickname, age, gender, species, nationality, status, title, category, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color FROM book_characters WHERE book_id=? AND user_id=?';
|
||||||
const params: SQLiteValue[] = [bookId, userId];
|
const params: SQLiteValue[] = [bookId, userId];
|
||||||
const characters: CharacterResult[] = db.all(query, params) as CharacterResult[];
|
const characters: CharacterResult[] = db.all(query, params) as CharacterResult[];
|
||||||
return characters;
|
return characters;
|
||||||
@@ -100,23 +122,48 @@ export default class CharacterRepo {
|
|||||||
* Adds a new character to the database.
|
* Adds a new character to the database.
|
||||||
* @param userId - The unique identifier of the user
|
* @param userId - The unique identifier of the user
|
||||||
* @param characterId - The unique identifier for the new character
|
* @param characterId - The unique identifier for the new character
|
||||||
* @param encryptedName - The encrypted first name of the character
|
* @param characterData - Object containing all encrypted character fields
|
||||||
* @param encryptedLastName - The encrypted last name of the character
|
|
||||||
* @param encryptedTitle - The encrypted title of the character
|
|
||||||
* @param encryptedCategory - The encrypted category of the character
|
|
||||||
* @param encryptedImage - The encrypted image path of the character
|
|
||||||
* @param encryptedRole - The encrypted role of the character
|
|
||||||
* @param encryptedBiography - The encrypted biography of the character
|
|
||||||
* @param encryptedHistory - The encrypted history of the character
|
|
||||||
* @param bookId - The unique identifier of the book
|
* @param bookId - The unique identifier of the book
|
||||||
* @param lang - The language for error messages ('fr' or 'en')
|
* @param lang - The language for error messages ('fr' or 'en')
|
||||||
* @returns The character ID if successful
|
* @returns The character ID if successful
|
||||||
*/
|
*/
|
||||||
public static addNewCharacter(userId: string, characterId: string, encryptedName: string, encryptedLastName: string, encryptedTitle: string, encryptedCategory: string, encryptedImage: string, encryptedRole: string, encryptedBiography: string, encryptedHistory: string, bookId: string, lang: 'fr' | 'en' = 'fr'): string {
|
public static addNewCharacter(userId: string, characterId: string, characterData: {
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
nickname: string;
|
||||||
|
age: string;
|
||||||
|
gender: string;
|
||||||
|
species: string;
|
||||||
|
nationality: string;
|
||||||
|
status: string;
|
||||||
|
title: string;
|
||||||
|
category: string;
|
||||||
|
image: string;
|
||||||
|
role: string;
|
||||||
|
biography: string;
|
||||||
|
history: string;
|
||||||
|
speechPattern: string;
|
||||||
|
catchphrase: string;
|
||||||
|
residence: string;
|
||||||
|
notes: string;
|
||||||
|
color: string;
|
||||||
|
}, bookId: string, lang: 'fr' | 'en' = 'fr'): string {
|
||||||
try {
|
try {
|
||||||
const db: Database = System.getDb();
|
const db: Database = System.getDb();
|
||||||
const query: string = 'INSERT INTO `book_characters` (character_id, book_id, user_id, first_name, last_name, category, title, image, role, biography, history, last_update) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)';
|
const query: string = `INSERT INTO book_characters (
|
||||||
const params: SQLiteValue[] = [characterId, bookId, userId, encryptedName, encryptedLastName, encryptedCategory, encryptedTitle, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, System.timeStampInSeconds()];
|
character_id, book_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status,
|
||||||
|
category, title, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update
|
||||||
|
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`;
|
||||||
|
const params: SQLiteValue[] = [
|
||||||
|
characterId, bookId, userId,
|
||||||
|
characterData.firstName, characterData.lastName, characterData.nickname,
|
||||||
|
characterData.age, characterData.gender, characterData.species,
|
||||||
|
characterData.nationality, characterData.status, characterData.category,
|
||||||
|
characterData.title, characterData.image, characterData.role,
|
||||||
|
characterData.biography, characterData.history, characterData.speechPattern,
|
||||||
|
characterData.catchphrase, characterData.residence, characterData.notes,
|
||||||
|
characterData.color, System.timeStampInSeconds()
|
||||||
|
];
|
||||||
const insertResult: RunResult = db.run(query, params);
|
const insertResult: RunResult = db.run(query, params);
|
||||||
if (!insertResult || insertResult.changes === 0) {
|
if (!insertResult || insertResult.changes === 0) {
|
||||||
throw new Error(lang === 'fr' ? `Une erreur s'est produite lors de l'ajout du personnage.` : `Error adding character.`);
|
throw new Error(lang === 'fr' ? `Une erreur s'est produite lors de l'ajout du personnage.` : `Error adding character.`);
|
||||||
@@ -168,23 +215,48 @@ export default class CharacterRepo {
|
|||||||
* Updates an existing character's information.
|
* Updates an existing character's information.
|
||||||
* @param userId - The unique identifier of the user
|
* @param userId - The unique identifier of the user
|
||||||
* @param id - The unique identifier of the character to update
|
* @param id - The unique identifier of the character to update
|
||||||
* @param encryptedName - The encrypted first name of the character
|
* @param characterData - Object containing all encrypted character fields
|
||||||
* @param encryptedLastName - The encrypted last name of the character
|
|
||||||
* @param encryptedTitle - The encrypted title of the character
|
|
||||||
* @param encryptedCategory - The encrypted category of the character
|
|
||||||
* @param encryptedImage - The encrypted image path of the character
|
|
||||||
* @param encryptedRole - The encrypted role of the character
|
|
||||||
* @param encryptedBiography - The encrypted biography of the character
|
|
||||||
* @param encryptedHistory - The encrypted history of the character
|
|
||||||
* @param lastUpdate - The timestamp of the last update
|
* @param lastUpdate - The timestamp of the last update
|
||||||
* @param lang - The language for error messages ('fr' or 'en')
|
* @param lang - The language for error messages ('fr' or 'en')
|
||||||
* @returns True if the update was successful, false otherwise
|
* @returns True if the update was successful, false otherwise
|
||||||
*/
|
*/
|
||||||
static updateCharacter(userId: string, id: string, encryptedName: string, encryptedLastName: string, encryptedTitle: string, encryptedCategory: string, encryptedImage: string, encryptedRole: string, encryptedBiography: string, encryptedHistory: string, lastUpdate: number, lang: 'fr' | 'en' = 'fr'): boolean {
|
static updateCharacter(userId: string, id: string, characterData: {
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
nickname: string;
|
||||||
|
age: string;
|
||||||
|
gender: string;
|
||||||
|
species: string;
|
||||||
|
nationality: string;
|
||||||
|
status: string;
|
||||||
|
title: string;
|
||||||
|
category: string;
|
||||||
|
image: string;
|
||||||
|
role: string;
|
||||||
|
biography: string;
|
||||||
|
history: string;
|
||||||
|
speechPattern: string;
|
||||||
|
catchphrase: string;
|
||||||
|
residence: string;
|
||||||
|
notes: string;
|
||||||
|
color: string;
|
||||||
|
}, lastUpdate: number, lang: 'fr' | 'en' = 'fr'): boolean {
|
||||||
try {
|
try {
|
||||||
const db: Database = System.getDb();
|
const db: Database = System.getDb();
|
||||||
const query: string = 'UPDATE `book_characters` SET `first_name`=?,`last_name`=?,`title`=?,`category`=?,`image`=?,`role`=?,`biography`=?,`history`=?,`last_update`=? WHERE `character_id`=? AND `user_id`=?';
|
const query: string = `UPDATE book_characters SET
|
||||||
const params: SQLiteValue[] = [encryptedName, encryptedLastName, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, lastUpdate, id, userId];
|
first_name=?, last_name=?, nickname=?, age=?, gender=?, species=?, nationality=?, status=?,
|
||||||
|
title=?, category=?, image=?, role=?, biography=?, history=?,
|
||||||
|
speech_pattern=?, catchphrase=?, residence=?, notes=?, color=?, last_update=?
|
||||||
|
WHERE character_id=? AND user_id=?`;
|
||||||
|
const params: SQLiteValue[] = [
|
||||||
|
characterData.firstName, characterData.lastName, characterData.nickname,
|
||||||
|
characterData.age, characterData.gender, characterData.species,
|
||||||
|
characterData.nationality, characterData.status, characterData.title,
|
||||||
|
characterData.category, characterData.image, characterData.role,
|
||||||
|
characterData.biography, characterData.history, characterData.speechPattern,
|
||||||
|
characterData.catchphrase, characterData.residence, characterData.notes,
|
||||||
|
characterData.color, lastUpdate, id, userId
|
||||||
|
];
|
||||||
const updateResult: RunResult = db.run(query, params);
|
const updateResult: RunResult = db.run(query, params);
|
||||||
return updateResult.changes > 0;
|
return updateResult.changes > 0;
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
@@ -396,7 +468,9 @@ export default class CharacterRepo {
|
|||||||
static async fetchBookCharacters(userId: string, bookId: string, lang: 'fr' | 'en'): Promise<BookCharactersTable[]> {
|
static async fetchBookCharacters(userId: string, bookId: string, lang: 'fr' | 'en'): Promise<BookCharactersTable[]> {
|
||||||
try {
|
try {
|
||||||
const db: Database = System.getDb();
|
const db: Database = System.getDb();
|
||||||
const query: string = 'SELECT character_id, book_id, user_id, first_name, last_name, category, title, image, role, biography, history, last_update FROM book_characters WHERE user_id=? AND book_id=?';
|
const query: string = `SELECT character_id, book_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status,
|
||||||
|
category, title, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update
|
||||||
|
FROM book_characters WHERE user_id=? AND book_id=?`;
|
||||||
const params: SQLiteValue[] = [userId, bookId];
|
const params: SQLiteValue[] = [userId, bookId];
|
||||||
const characters: BookCharactersTable[] = db.all(query, params) as BookCharactersTable[];
|
const characters: BookCharactersTable[] = db.all(query, params) as BookCharactersTable[];
|
||||||
return characters;
|
return characters;
|
||||||
@@ -487,24 +561,48 @@ export default class CharacterRepo {
|
|||||||
* @param characterId - The unique identifier of the character
|
* @param characterId - The unique identifier of the character
|
||||||
* @param bookId - The unique identifier of the book
|
* @param bookId - The unique identifier of the book
|
||||||
* @param userId - The unique identifier of the user
|
* @param userId - The unique identifier of the user
|
||||||
* @param firstName - The first name of the character
|
* @param characterData - Object containing all character fields
|
||||||
* @param lastName - The last name of the character (nullable)
|
|
||||||
* @param category - The category of the character
|
|
||||||
* @param title - The title of the character (nullable)
|
|
||||||
* @param image - The image path of the character (nullable)
|
|
||||||
* @param role - The role of the character (nullable)
|
|
||||||
* @param biography - The biography of the character (nullable)
|
|
||||||
* @param history - The history of the character (nullable)
|
|
||||||
* @param lastUpdate - The timestamp of the last update
|
* @param lastUpdate - The timestamp of the last update
|
||||||
* @param lang - The language for error messages ('fr' or 'en')
|
* @param lang - The language for error messages ('fr' or 'en')
|
||||||
* @returns True if the insertion was successful, false otherwise
|
* @returns True if the insertion was successful, false otherwise
|
||||||
*/
|
*/
|
||||||
static insertSyncCharacter(characterId: string, bookId: string, userId: string, firstName: string, lastName: string | null, category: string, title: string | null, image: string | null, role: string | null, biography: string | null, history: string | null, lastUpdate: number, lang: 'fr' | 'en'): boolean {
|
static insertSyncCharacter(characterId: string, bookId: string, userId: string, characterData: {
|
||||||
|
firstName: string;
|
||||||
|
lastName: string | null;
|
||||||
|
nickname: string | null;
|
||||||
|
age: string | null;
|
||||||
|
gender: string | null;
|
||||||
|
species: string | null;
|
||||||
|
nationality: string | null;
|
||||||
|
status: string | null;
|
||||||
|
category: string;
|
||||||
|
title: string | null;
|
||||||
|
image: string | null;
|
||||||
|
role: string | null;
|
||||||
|
biography: string | null;
|
||||||
|
history: string | null;
|
||||||
|
speechPattern: string | null;
|
||||||
|
catchphrase: string | null;
|
||||||
|
residence: string | null;
|
||||||
|
notes: string | null;
|
||||||
|
color: string | null;
|
||||||
|
}, lastUpdate: number, lang: 'fr' | 'en'): boolean {
|
||||||
try {
|
try {
|
||||||
const db: Database = System.getDb();
|
const db: Database = System.getDb();
|
||||||
const query: string = `INSERT INTO book_characters (character_id, book_id, user_id, first_name, last_name, category, title, image, role, biography, history, last_update)
|
const query: string = `INSERT INTO book_characters (
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
character_id, book_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status,
|
||||||
const params: SQLiteValue[] = [characterId, bookId, userId, firstName, lastName, category, title, image, role, biography, history, lastUpdate];
|
category, title, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
||||||
|
const params: SQLiteValue[] = [
|
||||||
|
characterId, bookId, userId,
|
||||||
|
characterData.firstName, characterData.lastName, characterData.nickname,
|
||||||
|
characterData.age, characterData.gender, characterData.species,
|
||||||
|
characterData.nationality, characterData.status, characterData.category,
|
||||||
|
characterData.title, characterData.image, characterData.role,
|
||||||
|
characterData.biography, characterData.history, characterData.speechPattern,
|
||||||
|
characterData.catchphrase, characterData.residence, characterData.notes,
|
||||||
|
characterData.color, lastUpdate
|
||||||
|
];
|
||||||
const insertResult: RunResult = db.run(query, params);
|
const insertResult: RunResult = db.run(query, params);
|
||||||
return insertResult.changes > 0;
|
return insertResult.changes > 0;
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
@@ -555,7 +653,8 @@ export default class CharacterRepo {
|
|||||||
static async fetchCompleteCharacterById(id: string, lang: "fr" | "en"): Promise<BookCharactersTable[]> {
|
static async fetchCompleteCharacterById(id: string, lang: "fr" | "en"): Promise<BookCharactersTable[]> {
|
||||||
try {
|
try {
|
||||||
const db: Database = System.getDb();
|
const db: Database = System.getDb();
|
||||||
const query: string = `SELECT character_id, book_id, user_id, first_name, last_name, category, title, image, role, biography, history, last_update
|
const query: string = `SELECT character_id, book_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status,
|
||||||
|
category, title, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update
|
||||||
FROM book_characters
|
FROM book_characters
|
||||||
WHERE character_id = ?`;
|
WHERE character_id = ?`;
|
||||||
const params: SQLiteValue[] = [id];
|
const params: SQLiteValue[] = [id];
|
||||||
|
|||||||
@@ -13,13 +13,26 @@ type Database = sqlite3.Database;
|
|||||||
// MIGRATIONS
|
// MIGRATIONS
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
||||||
const schemaVersion = 1;
|
const schemaVersion = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DEV ONLY - S'exécute à chaque refresh, pas besoin de version
|
* DEV ONLY - S'exécute à chaque refresh, pas besoin de version
|
||||||
* Mets ta query, test, efface après
|
* Mets ta query, test, efface après
|
||||||
*/
|
*/
|
||||||
const devQueries: string[] = [];
|
const devQueries: string[] = [
|
||||||
|
// Nouveaux champs de personnages
|
||||||
|
`ALTER TABLE book_characters ADD COLUMN nickname TEXT DEFAULT NULL`,
|
||||||
|
`ALTER TABLE book_characters ADD COLUMN age TEXT DEFAULT NULL`,
|
||||||
|
`ALTER TABLE book_characters ADD COLUMN gender TEXT DEFAULT NULL`,
|
||||||
|
`ALTER TABLE book_characters ADD COLUMN species TEXT DEFAULT NULL`,
|
||||||
|
`ALTER TABLE book_characters ADD COLUMN nationality TEXT DEFAULT NULL`,
|
||||||
|
`ALTER TABLE book_characters ADD COLUMN status TEXT DEFAULT NULL`,
|
||||||
|
`ALTER TABLE book_characters ADD COLUMN speech_pattern TEXT DEFAULT NULL`,
|
||||||
|
`ALTER TABLE book_characters ADD COLUMN catchphrase TEXT DEFAULT NULL`,
|
||||||
|
`ALTER TABLE book_characters ADD COLUMN residence TEXT DEFAULT NULL`,
|
||||||
|
`ALTER TABLE book_characters ADD COLUMN notes TEXT DEFAULT NULL`,
|
||||||
|
`ALTER TABLE book_characters ADD COLUMN color TEXT DEFAULT NULL`,
|
||||||
|
];
|
||||||
|
|
||||||
const isDev:boolean = !app.isPackaged;
|
const isDev:boolean = !app.isPackaged;
|
||||||
|
|
||||||
@@ -86,6 +99,19 @@ function migrateFromOldSystem(db: Database): void {
|
|||||||
// Add spells_enabled column to book_tools if missing
|
// Add spells_enabled column to book_tools if missing
|
||||||
addColumn(db, 'book_tools', 'spells_enabled', 'INTEGER NOT NULL DEFAULT 0');
|
addColumn(db, 'book_tools', 'spells_enabled', 'INTEGER NOT NULL DEFAULT 0');
|
||||||
|
|
||||||
|
// Add new character fields if missing
|
||||||
|
addColumn(db, 'book_characters', 'nickname', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'age', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'gender', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'species', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'nationality', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'status', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'speech_pattern', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'catchphrase', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'residence', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'notes', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'color', 'TEXT DEFAULT NULL');
|
||||||
|
|
||||||
// Create book_spell_tags table if missing
|
// Create book_spell_tags table if missing
|
||||||
db.exec(`
|
db.exec(`
|
||||||
CREATE TABLE IF NOT EXISTS book_spell_tags (
|
CREATE TABLE IF NOT EXISTS book_spell_tags (
|
||||||
@@ -208,6 +234,21 @@ export function runMigrations(db: Database): void {
|
|||||||
db.exec(`CREATE INDEX IF NOT EXISTS idx_spells_user ON book_spells(user_id)`);
|
db.exec(`CREATE INDEX IF NOT EXISTS idx_spells_user ON book_spells(user_id)`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// v2 - Add new character fields (nickname, age, gender, species, nationality, status, etc.)
|
||||||
|
if (currentVersion < 2) {
|
||||||
|
addColumn(db, 'book_characters', 'nickname', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'age', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'gender', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'species', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'nationality', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'status', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'speech_pattern', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'catchphrase', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'residence', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'notes', 'TEXT DEFAULT NULL');
|
||||||
|
addColumn(db, 'book_characters', 'color', 'TEXT DEFAULT NULL');
|
||||||
|
}
|
||||||
|
|
||||||
setDbVersion(db, schemaVersion);
|
setDbVersion(db, schemaVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,12 +387,23 @@ export function initializeSchema(db: Database): void {
|
|||||||
user_id TEXT NOT NULL,
|
user_id TEXT NOT NULL,
|
||||||
first_name TEXT NOT NULL,
|
first_name TEXT NOT NULL,
|
||||||
last_name TEXT,
|
last_name TEXT,
|
||||||
|
nickname TEXT,
|
||||||
|
age TEXT,
|
||||||
|
gender TEXT,
|
||||||
|
species TEXT,
|
||||||
|
nationality TEXT,
|
||||||
|
status TEXT,
|
||||||
category TEXT NOT NULL,
|
category TEXT NOT NULL,
|
||||||
title TEXT,
|
title TEXT,
|
||||||
image TEXT,
|
image TEXT,
|
||||||
role TEXT,
|
role TEXT,
|
||||||
biography TEXT,
|
biography TEXT,
|
||||||
history TEXT,
|
history TEXT,
|
||||||
|
speech_pattern TEXT,
|
||||||
|
catchphrase TEXT,
|
||||||
|
residence TEXT,
|
||||||
|
notes TEXT,
|
||||||
|
color TEXT,
|
||||||
last_update INTEGER DEFAULT 0,
|
last_update INTEGER DEFAULT 0,
|
||||||
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
FOREIGN KEY (book_id) REFERENCES erit_books(book_id) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -436,19 +436,47 @@
|
|||||||
"back": "Back",
|
"back": "Back",
|
||||||
"newCharacter": "New character",
|
"newCharacter": "New character",
|
||||||
"basicInfo": "Basic information",
|
"basicInfo": "Basic information",
|
||||||
"name": "Name",
|
"name": "First name",
|
||||||
"namePlaceholder": "Enter a name",
|
"namePlaceholder": "Enter a first name",
|
||||||
"lastName": "Last name",
|
"lastName": "Last name",
|
||||||
"lastNamePlaceholder": "Example: Smith",
|
"lastNamePlaceholder": "Example: Smith",
|
||||||
|
"nickname": "Nickname",
|
||||||
|
"nicknamePlaceholder": "Nickname or alias",
|
||||||
"role": "Role",
|
"role": "Role",
|
||||||
"title": "Title",
|
"title": "Title",
|
||||||
|
"titlePlaceholder": "Example: King, Captain, Doctor...",
|
||||||
|
"gender": "Gender",
|
||||||
|
"genderPlaceholder": "Character's gender",
|
||||||
|
"age": "Age",
|
||||||
|
"agePlaceholder": "Character's age",
|
||||||
"historySection": "Background",
|
"historySection": "Background",
|
||||||
"biography": "Biography",
|
"biography": "Biography",
|
||||||
"biographyPlaceholder": "Character biography.",
|
"biographyPlaceholder": "Character biography.",
|
||||||
"history": "History",
|
"history": "History",
|
||||||
"historyPlaceholder": "Character history...",
|
"historyPlaceholder": "Character history...",
|
||||||
"roleFull": "Role",
|
"roleFull": "Role in the story",
|
||||||
"roleFullPlaceholder": "Role of the character in the story",
|
"roleFullPlaceholder": "Role of the character in the story",
|
||||||
|
"advancedMode": "Advanced mode",
|
||||||
|
"showAdvanced": "Show",
|
||||||
|
"hideAdvanced": "Hide",
|
||||||
|
"identitySection": "Extended identity",
|
||||||
|
"species": "Species",
|
||||||
|
"speciesPlaceholder": "Human, Elf, Vampire...",
|
||||||
|
"nationality": "Nationality",
|
||||||
|
"nationalityPlaceholder": "Country or region of origin",
|
||||||
|
"status": "Status",
|
||||||
|
"residence": "Residence",
|
||||||
|
"residencePlaceholder": "Current place of residence",
|
||||||
|
"voiceSection": "Character voice",
|
||||||
|
"speechPattern": "Speech pattern",
|
||||||
|
"speechPatternPlaceholder": "How does this character speak? Accent, speech quirks...",
|
||||||
|
"catchphrase": "Catchphrase",
|
||||||
|
"catchphrasePlaceholder": "A signature phrase of the character",
|
||||||
|
"authorSection": "Author notes",
|
||||||
|
"notes": "Notes",
|
||||||
|
"notesPlaceholder": "Personal notes about this character...",
|
||||||
|
"colorLabel": "Color",
|
||||||
|
"colorPlaceholder": "Color associated with the character",
|
||||||
"fetchAttributesError": "Error fetching attributes.",
|
"fetchAttributesError": "Error fetching attributes.",
|
||||||
"deleteTitle": "Delete character",
|
"deleteTitle": "Delete character",
|
||||||
"deleteMessage": "Are you sure you want to delete {name}? This action cannot be undone."
|
"deleteMessage": "Are you sure you want to delete {name}? This action cannot be undone."
|
||||||
|
|||||||
@@ -436,19 +436,47 @@
|
|||||||
"back": "Retour",
|
"back": "Retour",
|
||||||
"newCharacter": "Nouveau personnage",
|
"newCharacter": "Nouveau personnage",
|
||||||
"basicInfo": "Informations de base",
|
"basicInfo": "Informations de base",
|
||||||
"name": "Nom",
|
"name": "Prénom",
|
||||||
"namePlaceholder": "Entrer un nom",
|
"namePlaceholder": "Entrer un prénom",
|
||||||
"lastName": "Nom de famille",
|
"lastName": "Nom de famille",
|
||||||
"lastNamePlaceholder": "Exemple : Smith",
|
"lastNamePlaceholder": "Exemple : Smith",
|
||||||
|
"nickname": "Surnom",
|
||||||
|
"nicknamePlaceholder": "Surnom ou alias du personnage",
|
||||||
"role": "Rôle",
|
"role": "Rôle",
|
||||||
"title": "Titre",
|
"title": "Titre",
|
||||||
"historySection": "Parcourt",
|
"titlePlaceholder": "Exemple : Roi, Capitaine, Docteur...",
|
||||||
|
"gender": "Genre",
|
||||||
|
"genderPlaceholder": "Genre du personnage",
|
||||||
|
"age": "Âge",
|
||||||
|
"agePlaceholder": "Âge du personnage",
|
||||||
|
"historySection": "Parcours",
|
||||||
"biography": "Biographie",
|
"biography": "Biographie",
|
||||||
"biographyPlaceholder": "La biographie du personnage.",
|
"biographyPlaceholder": "La biographie du personnage.",
|
||||||
"history": "Histoire",
|
"history": "Histoire",
|
||||||
"historyPlaceholder": "Histoire du personnage...",
|
"historyPlaceholder": "Histoire du personnage...",
|
||||||
"roleFull": "Rôle",
|
"roleFull": "Rôle dans l'histoire",
|
||||||
"roleFullPlaceholder": "Rôle du personnage dans l'histoire",
|
"roleFullPlaceholder": "Rôle du personnage dans l'histoire",
|
||||||
|
"advancedMode": "Mode avancé",
|
||||||
|
"showAdvanced": "Afficher",
|
||||||
|
"hideAdvanced": "Masquer",
|
||||||
|
"identitySection": "Identité étendue",
|
||||||
|
"species": "Espèce",
|
||||||
|
"speciesPlaceholder": "Humain, Elfe, Vampire...",
|
||||||
|
"nationality": "Nationalité",
|
||||||
|
"nationalityPlaceholder": "Pays ou région d'origine",
|
||||||
|
"status": "Statut",
|
||||||
|
"residence": "Résidence",
|
||||||
|
"residencePlaceholder": "Lieu de résidence actuel",
|
||||||
|
"voiceSection": "Voix du personnage",
|
||||||
|
"speechPattern": "Pattern de parole",
|
||||||
|
"speechPatternPlaceholder": "Comment parle ce personnage ? Accent, tics de langage...",
|
||||||
|
"catchphrase": "Phrase fétiche",
|
||||||
|
"catchphrasePlaceholder": "Une phrase signature du personnage",
|
||||||
|
"authorSection": "Notes de l'auteur",
|
||||||
|
"notes": "Notes",
|
||||||
|
"notesPlaceholder": "Notes personnelles sur ce personnage...",
|
||||||
|
"colorLabel": "Couleur",
|
||||||
|
"colorPlaceholder": "Couleur associée au personnage",
|
||||||
"fetchAttributesError": "Erreur lors de la récupération des attributs.",
|
"fetchAttributesError": "Erreur lors de la récupération des attributs.",
|
||||||
"deleteTitle": "Supprimer le personnage",
|
"deleteTitle": "Supprimer le personnage",
|
||||||
"deleteMessage": "Êtes-vous sûr de vouloir supprimer {name} ? Cette action est irréversible."
|
"deleteMessage": "Êtes-vous sûr de vouloir supprimer {name} ? Cette action est irréversible."
|
||||||
|
|||||||
@@ -7,6 +7,16 @@ import {
|
|||||||
faShieldAlt,
|
faShieldAlt,
|
||||||
faUsers,
|
faUsers,
|
||||||
faWrench,
|
faWrench,
|
||||||
|
faRoute,
|
||||||
|
faUserSecret,
|
||||||
|
faGhost,
|
||||||
|
faHeartBroken,
|
||||||
|
faHandHoldingHeart,
|
||||||
|
faBolt,
|
||||||
|
faQuoteLeft,
|
||||||
|
faFingerprint,
|
||||||
|
faBox,
|
||||||
|
faPeopleGroup,
|
||||||
} from '@fortawesome/free-solid-svg-icons';
|
} from '@fortawesome/free-solid-svg-icons';
|
||||||
import {SelectBoxProps} from "@/shared/interface";
|
import {SelectBoxProps} from "@/shared/interface";
|
||||||
|
|
||||||
@@ -31,100 +41,10 @@ export const characterCategories: SelectBoxProps[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const characterTitle: SelectBoxProps[] = [
|
export const characterStatus: SelectBoxProps[] = [
|
||||||
{value: 'none', label: 'Aucun'},
|
{value: 'alive', label: 'Vivant'},
|
||||||
{value: 'king', label: 'Roi'},
|
{value: 'dead', label: 'Décédé'},
|
||||||
{value: 'queen', label: 'Reine'},
|
{value: 'unknown', label: 'Inconnu'},
|
||||||
{value: 'emperor', label: 'Empereur'},
|
|
||||||
{value: 'empress', label: 'Impératrice'},
|
|
||||||
{value: 'prince', label: 'Prince'},
|
|
||||||
{value: 'princess', label: 'Princesse'},
|
|
||||||
{value: 'duke', label: 'Duc'},
|
|
||||||
{value: 'duchess', label: 'Duchesse'},
|
|
||||||
{value: 'count', label: 'Comte'},
|
|
||||||
{value: 'countess', label: 'Comtesse'},
|
|
||||||
{value: 'baron', label: 'Baron'},
|
|
||||||
{value: 'baroness', label: 'Baronne'},
|
|
||||||
{value: 'lord', label: 'Seigneur'},
|
|
||||||
{value: 'lady', label: 'Dame'},
|
|
||||||
{value: 'knight', label: 'Chevalier'},
|
|
||||||
{value: 'squire', label: 'Écuyer'},
|
|
||||||
{value: 'warrior', label: 'Guerrier'},
|
|
||||||
{value: 'general', label: 'Général'},
|
|
||||||
{value: 'commander', label: 'Commandant'},
|
|
||||||
{value: 'captain', label: 'Capitaine'},
|
|
||||||
{value: 'soldier', label: 'Soldat'},
|
|
||||||
{value: 'mercenary', label: 'Mercenaire'},
|
|
||||||
{value: 'assassin', label: 'Assassin'},
|
|
||||||
{value: 'thief', label: 'Voleur'},
|
|
||||||
{value: 'spy', label: 'Espion'},
|
|
||||||
{value: 'archmage', label: 'Archimage'},
|
|
||||||
{value: 'sorcerer', label: 'Sorcier'},
|
|
||||||
{value: 'witch', label: 'Sorcière'},
|
|
||||||
{value: 'warlock', label: 'Mage Noir'},
|
|
||||||
{value: 'druid', label: 'Druide'},
|
|
||||||
{value: 'priest', label: 'Prêtre'},
|
|
||||||
{value: 'prophet', label: 'Prophète'},
|
|
||||||
{value: 'oracle', label: 'Oracle'},
|
|
||||||
{value: 'seer', label: 'Voyant'},
|
|
||||||
{value: 'scholar', label: 'Érudit'},
|
|
||||||
{value: 'alchemist', label: 'Alchimiste'},
|
|
||||||
{value: 'healer', label: 'Guérisseur'},
|
|
||||||
{value: 'bard', label: 'Barde'},
|
|
||||||
{value: 'hermit', label: 'Ermite'},
|
|
||||||
{value: 'noble', label: 'Noble'},
|
|
||||||
{value: 'peasant', label: 'Paysan'},
|
|
||||||
{value: 'merchant', label: 'Marchand'},
|
|
||||||
{value: 'sailor', label: 'Marin'},
|
|
||||||
{value: 'pirate', label: 'Pirate'},
|
|
||||||
{value: 'slave', label: 'Esclave'},
|
|
||||||
{value: 'gladiator', label: 'Gladiateur'},
|
|
||||||
{value: 'champion', label: 'Champion'},
|
|
||||||
{value: 'outlaw', label: 'Hors-la-loi'},
|
|
||||||
{value: 'hunter', label: 'Chasseur'},
|
|
||||||
{value: 'beastmaster', label: 'Maître des Bêtes'},
|
|
||||||
{value: 'ranger', label: 'Rôdeur'},
|
|
||||||
{value: 'warden', label: 'Gardien'},
|
|
||||||
{value: 'sentinel', label: 'Sentinelle'},
|
|
||||||
{value: 'herald', label: 'Héraut'},
|
|
||||||
{value: 'messenger', label: 'Messager'},
|
|
||||||
{value: 'pilgrim', label: 'Pèlerin'},
|
|
||||||
{value: 'nomad', label: 'Nomade'},
|
|
||||||
{value: 'chieftain', label: 'Chef de Clan'},
|
|
||||||
{value: 'high-priest', label: 'Grand Prêtre'},
|
|
||||||
{value: 'inquisitor', label: 'Inquisiteur'},
|
|
||||||
{value: 'judge', label: 'Juge'},
|
|
||||||
{value: 'executioner', label: 'Bourreau'},
|
|
||||||
{value: 'warden', label: 'Gardien de Prison'},
|
|
||||||
{value: 'monk', label: 'Moine'},
|
|
||||||
{value: 'abbot', label: 'Abbé'},
|
|
||||||
{value: 'nun', label: 'Nonne'},
|
|
||||||
{value: 'diplomat', label: 'Diplomate'},
|
|
||||||
{value: 'ambassador', label: 'Ambassadeur'},
|
|
||||||
{value: 'scientist', label: 'Scientifique'},
|
|
||||||
{value: 'engineer', label: 'Ingénieur'},
|
|
||||||
{value: 'inventor', label: 'Inventeur'},
|
|
||||||
{value: 'architect', label: 'Architecte'},
|
|
||||||
{value: 'scribe', label: 'Scribe'},
|
|
||||||
{value: 'chronicler', label: 'Chroniqueur'},
|
|
||||||
{value: 'storyteller', label: 'Conteur'},
|
|
||||||
{value: 'actor', label: 'Acteur'},
|
|
||||||
{value: 'musician', label: 'Musicien'},
|
|
||||||
{value: 'artist', label: 'Artiste'},
|
|
||||||
{value: 'sculptor', label: 'Sculpteur'},
|
|
||||||
{value: 'orator', label: 'Orateur'},
|
|
||||||
{value: 'revolutionary', label: 'Révolutionnaire'},
|
|
||||||
{value: 'resistance-fighter', label: 'Résistant'},
|
|
||||||
{value: 'freedom-fighter', label: 'Combattant de la Liberté'},
|
|
||||||
{value: 'cult-leader', label: 'Chef de Secte'},
|
|
||||||
{value: 'warlock-lord', label: 'Seigneur Noir'},
|
|
||||||
{value: 'dark-prophet', label: 'Prophète du Chaos'},
|
|
||||||
{value: 'warlord', label: 'Seigneur de Guerre'},
|
|
||||||
{value: 'grandmaster', label: 'Grand Maître'},
|
|
||||||
{value: 'tactician', label: 'Tacticien'},
|
|
||||||
{value: 'archduke', label: 'Archiduc'},
|
|
||||||
{value: 'high-king', label: 'Haut Roi'},
|
|
||||||
{value: 'divine-champion', label: 'Champion Divin'},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export interface Relation {
|
export interface Relation {
|
||||||
@@ -147,6 +67,12 @@ export interface CharacterProps {
|
|||||||
id: string | null;
|
id: string | null;
|
||||||
name: string;
|
name: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
|
nickname: string;
|
||||||
|
age: string;
|
||||||
|
gender: string;
|
||||||
|
species: string;
|
||||||
|
nationality: string;
|
||||||
|
status: 'alive' | 'dead' | 'unknown';
|
||||||
category: CharacterCategory;
|
category: CharacterCategory;
|
||||||
title: string;
|
title: string;
|
||||||
image: string;
|
image: string;
|
||||||
@@ -158,9 +84,24 @@ export interface CharacterProps {
|
|||||||
strengths: Attribute[];
|
strengths: Attribute[];
|
||||||
goals: Attribute[];
|
goals: Attribute[];
|
||||||
motivations: Attribute[];
|
motivations: Attribute[];
|
||||||
|
arc: Attribute[];
|
||||||
|
secrets: Attribute[];
|
||||||
|
fears: Attribute[];
|
||||||
|
flaws: Attribute[];
|
||||||
|
beliefs: Attribute[];
|
||||||
|
conflicts: Attribute[];
|
||||||
|
quotes: Attribute[];
|
||||||
|
distinguishingMarks: Attribute[];
|
||||||
|
items: Attribute[];
|
||||||
|
affiliations: Attribute[];
|
||||||
role: string;
|
role: string;
|
||||||
biography?: string;
|
biography?: string;
|
||||||
history?: string;
|
history?: string;
|
||||||
|
speechPattern?: string;
|
||||||
|
catchphrase?: string;
|
||||||
|
residence?: string;
|
||||||
|
notes?: string;
|
||||||
|
color?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CharacterListResponse {
|
export interface CharacterListResponse {
|
||||||
@@ -175,7 +116,8 @@ export interface CharacterElement {
|
|||||||
icon: any; // Replace `any` with an appropriate type if you have a specific icon type.
|
icon: any; // Replace `any` with an appropriate type if you have a specific icon type.
|
||||||
}
|
}
|
||||||
|
|
||||||
export const characterElementCategory: CharacterElement[] = [
|
// Attributs de base (toujours visibles)
|
||||||
|
export const basicCharacterElements: CharacterElement[] = [
|
||||||
{
|
{
|
||||||
title: 'Descriptions physiques',
|
title: 'Descriptions physiques',
|
||||||
section: 'physical',
|
section: 'physical',
|
||||||
@@ -188,6 +130,58 @@ export const characterElementCategory: CharacterElement[] = [
|
|||||||
placeholder: 'Nouvelle Description Psychologique',
|
placeholder: 'Nouvelle Description Psychologique',
|
||||||
icon: faBrain,
|
icon: faBrain,
|
||||||
},
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// Attributs avancés (visibles en mode avancé)
|
||||||
|
export const advancedCharacterElements: CharacterElement[] = [
|
||||||
|
{
|
||||||
|
title: 'Signes distinctifs',
|
||||||
|
section: 'distinguishingMarks',
|
||||||
|
placeholder: 'Nouveau signe distinctif',
|
||||||
|
icon: faFingerprint,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Arc du personnage',
|
||||||
|
section: 'arc',
|
||||||
|
placeholder: 'Nouvelle étape de l\'arc',
|
||||||
|
icon: faRoute,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Secrets',
|
||||||
|
section: 'secrets',
|
||||||
|
placeholder: 'Nouveau secret',
|
||||||
|
icon: faUserSecret,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Peurs',
|
||||||
|
section: 'fears',
|
||||||
|
placeholder: 'Nouvelle peur',
|
||||||
|
icon: faGhost,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Défauts',
|
||||||
|
section: 'flaws',
|
||||||
|
placeholder: 'Nouveau défaut',
|
||||||
|
icon: faHeartBroken,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Croyances',
|
||||||
|
section: 'beliefs',
|
||||||
|
placeholder: 'Nouvelle croyance',
|
||||||
|
icon: faHandHoldingHeart,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Conflits internes',
|
||||||
|
section: 'conflicts',
|
||||||
|
placeholder: 'Nouveau conflit',
|
||||||
|
icon: faBolt,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Citations',
|
||||||
|
section: 'quotes',
|
||||||
|
placeholder: 'Nouvelle citation',
|
||||||
|
icon: faQuoteLeft,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Relations',
|
title: 'Relations',
|
||||||
section: 'relations',
|
section: 'relations',
|
||||||
@@ -224,4 +218,22 @@ export const characterElementCategory: CharacterElement[] = [
|
|||||||
placeholder: 'Nouvelle Motivation',
|
placeholder: 'Nouvelle Motivation',
|
||||||
icon: faFire,
|
icon: faFire,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Objets importants',
|
||||||
|
section: 'items',
|
||||||
|
placeholder: 'Nouvel objet',
|
||||||
|
icon: faBox,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Affiliations',
|
||||||
|
section: 'affiliations',
|
||||||
|
placeholder: 'Nouvelle affiliation',
|
||||||
|
icon: faPeopleGroup,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// Pour rétro-compatibilité, on garde characterElementCategory qui combine les deux
|
||||||
|
export const characterElementCategory: CharacterElement[] = [
|
||||||
|
...basicCharacterElements,
|
||||||
|
...advancedCharacterElements,
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user