From cbe4e1d06800529326328b4a68c4e5c3d060d8bd Mon Sep 17 00:00:00 2001 From: Peaceultime Date: Mon, 8 Dec 2025 18:50:49 +0100 Subject: [PATCH] Add Item flavoring --- app/types/character.d.ts | 1 + shared/feature.util.ts | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/app/types/character.d.ts b/app/types/character.d.ts index bcb91d2..687eced 100644 --- a/app/types/character.d.ts +++ b/app/types/character.d.ts @@ -89,6 +89,7 @@ export type ItemConfig = CommonItemConfig & (ArmorConfig | WeaponConfig | Wondro type CommonItemConfig = { id: string; name: string; //TODO -> TextID + flavoring: i18nID; description: i18nID; rarity: 'common' | 'uncommon' | 'rare' | 'legendary'; weight?: number; //Optionnal but highly recommended diff --git a/shared/feature.util.ts b/shared/feature.util.ts index dc38f15..5103090 100644 --- a/shared/feature.util.ts +++ b/shared/feature.util.ts @@ -721,25 +721,31 @@ export class FeaturePanel } export class ItemPanel { + static descriptionEditor: MarkdownEditor = new MarkdownEditor(); + static flavoringEditor: MarkdownEditor = new MarkdownEditor(); static render(item: ItemConfig, success: (item: ItemConfig) => void, failure: (item: ItemConfig) => void) { const _item = JSON.parse(JSON.stringify(item)) as ItemConfig; - MarkdownEditor.singleton.content = getText(_item.description); - MarkdownEditor.singleton.onChange = (value) => config.texts[_item.description]!.default = value; + ItemPanel.descriptionEditor.content = getText(_item.description); + ItemPanel.descriptionEditor.onChange = (value) => config.texts[_item.description]!.default = value; + ItemPanel.flavoringEditor.content = getText(_item.flavoring); + ItemPanel.flavoringEditor.onChange = (value) => config.texts[_item.flavoring]!.default = value; const effectContainer = div('grid grid-cols-2 gap-4 px-2 flex-1', _item.effects?.map(e => new FeatureEditor(_item.effects!, e.id, false).container)); return dom('div', { attributes: { 'data-state': 'inactive' }, class: 'border-light-35 dark:border-dark-35 bg-light-10 dark:bg-dark-10 border-l absolute top-0 bottom-0 right-0 w-[10%] data-[state=active]:w-1/2 flex flex-col gap-2 text-light-100 dark:text-dark-100 p-8 transition-[width] transition-delay-[150ms]' }, [ div('flex flex-row justify-between items-center', [ tooltip(button(icon('radix-icons:check', { width: 20, height: 20 }), () => { success!(_item); - MarkdownEditor.singleton.onChange = undefined; + ItemPanel.descriptionEditor.onChange = undefined; + ItemPanel.flavoringEditor.onChange = undefined; }, 'p-1'), 'Valider', 'left'), dom('label', { class: 'flex justify-center items-center my-2' }, [ dom('span', { class: 'pb-1 md:p-0', text: "Nom" }), - input('text', { defaultValue: _item.name, input: (v) => _item.name = v }) + input('text', { defaultValue: _item.name, input: (v) => { _item.name = v }}) ]), tooltip(button(icon('radix-icons:cross-1', { width: 20, height: 20 }), () => { failure!(item); - MarkdownEditor.singleton.onChange = undefined; + ItemPanel.descriptionEditor.onChange = undefined; + ItemPanel.flavoringEditor.onChange = undefined; }, 'p-1'), 'Annuler', 'left'), ]), foldable([ @@ -760,13 +766,13 @@ export class ItemPanel div('flex flex-row gap-2 items-center justify-between', [ div('flex flex-row gap-2 items-center', [ span('', 'Type de dégâts'), ]), select(Object.keys(damageTypeTexts).map(e => ({ text: damageTypeTexts[e as DamageType], value: e as DamageType })), { defaultValue: _item.damage.type, change: (v) => _item.damage.type = v, class: { container: '!w-1/3' } }), ]), div('flex flex-row gap-2 items-center justify-between', [ div('flex flex-row gap-2 items-center', [ span('', 'Dégats'), ]), input('text', { defaultValue: _item.damage.value, input: (v) => _item.damage.value = v, class: '!w-1/3' }), ]), ], [ span('text-lg font-bold', "Propriétés"), div('flex flex-row gap-2 items-center justify-between', [ div('flex flex-row gap-2 items-center', [ span('', 'Rareté'), ]), multiselect(Object.keys(weaponTypeTexts).map(e => ({ text: weaponTypeTexts[e as WeaponType], value: e as WeaponType })), { defaultValue: _item.type, change: (v) => _item.type = v, class: { container: '!w-1/2' } }), ]) ], { class: { content: 'group-data-[active]:grid grid-cols-2 my-2 gap-4', title: 'grid grid-cols-2 gap-4 mx-2', container: 'pb-2 border-b border-light-35 dark:border-dark-35' }, open: true } ) : undefined, - foldable([div('p-1 border border-light-40 dark:border-dark-40 w-full bg-light-25 dark:bg-dark-25 min-h-48 max-h-[32rem]', [ MarkdownEditor.singleton.dom ])], [ span('text-lg font-bold px-2', "Description") ], { class: { container: 'gap-4 pb-2 border-b border-light-35 dark:border-dark-35' }, open: true, }), + foldable([div('p-1 border border-light-40 dark:border-dark-40 w-full bg-light-25 dark:bg-dark-25 min-h-48 max-h-[32rem]', [ ItemPanel.descriptionEditor.dom ])], [ span('text-lg font-bold px-2', "Description des effets") ], { class: { container: 'gap-4 pb-2 border-b border-light-35 dark:border-dark-35' }, open: true, }), + foldable([div('p-1 border border-light-40 dark:border-dark-40 w-full bg-light-25 dark:bg-dark-25 min-h-48 max-h-[32rem]', [ ItemPanel.flavoringEditor.dom ])], [ span('text-lg font-bold px-2', "Lore") ], { class: { container: 'gap-4 pb-2 border-b border-light-35 dark:border-dark-35' }, open: true, }), foldable([ effectContainer ], [ dom('h3', { class: 'text-lg font-bold', text: 'Effets' }), tooltip(button(icon('radix-icons:plus', { width: 20, height: 20 }), () => { const f = { id: getID(), }; _item.effects ??= []; - //@ts-expect-error - _item.effects.push(f); + _item.effects.push(f as any as FeatureValue | FeatureEquipment | FeatureList); effectContainer.appendChild(new FeatureEditor(_item.effects, f.id, true).container); }, 'p-1 hidden group-data-[active]:block'), 'Ajouter', 'left'), ], { class: { container: 'flex flex-col gap-2 w-full', title: 'flex flex-row justify-between px-2' } })