- Deleted `CharacterComponent` and `CharacterDetail` files from the project. - Refactored related logic to improve code maintainability and reduce redundancy.
151 lines
7.2 KiB
TypeScript
151 lines
7.2 KiB
TypeScript
'use client';
|
|
import React from 'react';
|
|
import {SpellEditState, spellPowerLevels, SpellTagProps} from '@/lib/models/Spell';
|
|
import {SeriesSpellDetailResponse} from '@/lib/models/Series';
|
|
import {SelectBoxProps} from '@/shared/interface';
|
|
import SpellTagChip from '@/components/book/settings/spells/SpellTagChip';
|
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
|
import {
|
|
faBolt,
|
|
faEye,
|
|
faHatWizard,
|
|
faPuzzlePiece,
|
|
faStickyNote,
|
|
faTags,
|
|
faTriangleExclamation,
|
|
faWandMagicSparkles
|
|
} from '@fortawesome/free-solid-svg-icons';
|
|
import {useTranslations} from 'next-intl';
|
|
|
|
interface SpellSettingsDetailProps {
|
|
spell: SpellEditState;
|
|
availableTags: SpellTagProps[];
|
|
seriesSpell?: SeriesSpellDetailResponse | null;
|
|
}
|
|
|
|
export default function SpellSettingsDetail({
|
|
spell,
|
|
availableTags,
|
|
seriesSpell,
|
|
}: SpellSettingsDetailProps): React.JSX.Element {
|
|
const t = useTranslations();
|
|
|
|
function getSelectedTags(): SpellTagProps[] {
|
|
return availableTags.filter(function (tag: SpellTagProps): boolean {
|
|
return spell.tags.includes(tag.id);
|
|
});
|
|
}
|
|
|
|
function getLocalizedPowerLevel(): string {
|
|
if (!spell.powerLevel || spell.powerLevel === 'none') {
|
|
return t('spellPowerLevels.none');
|
|
}
|
|
const level: SelectBoxProps | undefined = spellPowerLevels.find(function (l: SelectBoxProps): boolean {
|
|
return l.value === spell.powerLevel;
|
|
});
|
|
return level ? t(level.label) : spell.powerLevel;
|
|
}
|
|
|
|
function getPowerLevelColor(): string {
|
|
switch (spell.powerLevel) {
|
|
case 'weak': return 'bg-green-500/20 text-green-400 border-green-500/30';
|
|
case 'moderate': return 'bg-blue-500/20 text-blue-400 border-blue-500/30';
|
|
case 'strong': return 'bg-orange-500/20 text-orange-400 border-orange-500/30';
|
|
case 'legendary': return 'bg-purple-500/20 text-purple-400 border-purple-500/30';
|
|
default: return 'bg-secondary/50 text-text-secondary border-secondary/50';
|
|
}
|
|
}
|
|
|
|
const selectedTags: SpellTagProps[] = getSelectedTags();
|
|
|
|
return (
|
|
<div className="space-y-6 px-2 pb-4">
|
|
{/* Hero Section */}
|
|
<div className="p-6 bg-gradient-to-r from-primary/10 via-secondary/20 to-transparent rounded-2xl border border-secondary/30">
|
|
<div className="flex items-start gap-4">
|
|
<div className="w-16 h-16 rounded-xl bg-primary/20 flex items-center justify-center shrink-0">
|
|
<FontAwesomeIcon icon={faWandMagicSparkles} className="w-8 h-8 text-primary"/>
|
|
</div>
|
|
<div className="flex-1 min-w-0">
|
|
<h2 className="text-2xl font-bold text-text-primary">{spell.name || '—'}</h2>
|
|
|
|
{/* Power Level Badge */}
|
|
<div className="flex items-center gap-3 mt-3">
|
|
<span className={`inline-flex items-center gap-2 px-3 py-1 rounded-lg text-sm border ${getPowerLevelColor()}`}>
|
|
<FontAwesomeIcon icon={faBolt} className="w-3 h-3"/>
|
|
{getLocalizedPowerLevel()}
|
|
</span>
|
|
</div>
|
|
|
|
{/* Tags */}
|
|
{selectedTags.length > 0 && (
|
|
<div className="flex flex-wrap gap-2 mt-4">
|
|
{selectedTags.map(function (tag: SpellTagProps): React.JSX.Element {
|
|
return <SpellTagChip key={tag.id} tag={tag}/>;
|
|
})}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Description & Appearance - Side by side */}
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
<div className="p-5 bg-secondary/20 rounded-xl border border-secondary/30">
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<FontAwesomeIcon icon={faHatWizard} className="w-4 h-4 text-primary"/>
|
|
<h3 className="text-text-primary font-semibold">{t('spellDetail.description')}</h3>
|
|
</div>
|
|
<p className={`whitespace-pre-wrap ${spell.description ? 'text-text-primary' : 'text-text-secondary/50 italic'}`}>
|
|
{spell.description || '—'}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="p-5 bg-secondary/20 rounded-xl border border-secondary/30">
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<FontAwesomeIcon icon={faEye} className="w-4 h-4 text-primary"/>
|
|
<h3 className="text-text-primary font-semibold">{t('spellDetail.appearance')}</h3>
|
|
</div>
|
|
<p className={`whitespace-pre-wrap ${spell.appearance ? 'text-text-primary' : 'text-text-secondary/50 italic'}`}>
|
|
{spell.appearance || '—'}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Components & Limitations - Side by side */}
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
<div className="p-5 bg-secondary/20 rounded-xl border border-secondary/30">
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<FontAwesomeIcon icon={faPuzzlePiece} className="w-4 h-4 text-primary"/>
|
|
<h3 className="text-text-primary font-semibold">{t('spellDetail.components')}</h3>
|
|
</div>
|
|
<p className={`whitespace-pre-wrap ${spell.components ? 'text-text-primary' : 'text-text-secondary/50 italic'}`}>
|
|
{spell.components || '—'}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="p-5 bg-error/10 rounded-xl border border-error/30">
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<FontAwesomeIcon icon={faTriangleExclamation} className="w-4 h-4 text-error"/>
|
|
<h3 className="text-text-primary font-semibold">{t('spellDetail.limitations')}</h3>
|
|
</div>
|
|
<p className={`whitespace-pre-wrap ${spell.limitations ? 'text-text-primary' : 'text-text-secondary/50 italic'}`}>
|
|
{spell.limitations || '—'}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Notes - Full width */}
|
|
<div className="p-5 bg-secondary/20 rounded-xl border border-secondary/30">
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<FontAwesomeIcon icon={faStickyNote} className="w-4 h-4 text-primary"/>
|
|
<h3 className="text-text-primary font-semibold">{t('spellDetail.notes')}</h3>
|
|
</div>
|
|
<p className={`whitespace-pre-wrap ${spell.notes ? 'text-text-primary' : 'text-text-secondary/50 italic'}`}>
|
|
{spell.notes || '—'}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|