Remove CharacterComponent and CharacterDetail components

- Deleted `CharacterComponent` and `CharacterDetail` files from the project.
- Refactored related logic to improve code maintainability and reduce redundancy.
This commit is contained in:
natreex
2026-02-05 14:12:08 -05:00
parent cec5830360
commit 209dc6f85a
133 changed files with 17673 additions and 3110 deletions

View File

@@ -0,0 +1,150 @@
'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>
);
}