Pre-combat-rewrite: Backup current state before comprehensive combat frontend rewrite

This commit is contained in:
Joan
2026-01-09 11:07:37 +01:00
parent dc438ae4c1
commit 2875e72b20
29 changed files with 1827 additions and 332 deletions

View File

@@ -50,7 +50,7 @@ function Workbench({
onRepair,
onUncraft
}: WorkbenchProps) {
useTranslation()
const { t } = useTranslation()
const [selectedItem, setSelectedItem] = useState<any>(null)
@@ -116,8 +116,8 @@ function Workbench({
return (
<div className="workbench-empty-state">
<div style={{ fontSize: '4rem', marginBottom: '1rem' }}>🔧</div>
<h3>Select an item to view details</h3>
<p>Choose an item from the list on the left</p>
<h3>{t('crafting.selectItem')}</h3>
<p>{t('crafting.chooseFromList')}</p>
</div>
)
}
@@ -155,13 +155,13 @@ function Workbench({
<div className="item-stats" style={{ display: 'flex', gap: '1rem', justifyContent: 'center', flexWrap: 'wrap' }}>
{Object.entries(item.base_stats || item.stats).map(([key, value]) => {
const icons: Record<string, string> = {
weight_capacity: '⚖️ Weight',
volume_capacity: '📦 Volume',
armor: '🛡️ Armor',
hp_max: '❤️ Max HP',
stamina_max: '⚡ Max Stamina',
damage_min: '⚔️ Damage Min',
damage_max: '⚔️ Damage Max'
weight_capacity: `⚖️ ${t('game.weight')}`,
volume_capacity: `📦 ${t('game.volume')}`,
armor: `🛡️ ${t('stats.armor')}`,
hp_max: `❤️ ${t('stats.maxHp')}`,
stamina_max: `${t('stats.maxStamina')}`,
damage_min: `⚔️ ${t('stats.damage')} Min`,
damage_max: `⚔️ ${t('stats.damage')} Max`
}
const label = icons[key] || key.replace('_', ' ')
const unit = key.includes('weight') ? 'kg' : key.includes('volume') ? 'L' : ''
@@ -173,7 +173,7 @@ function Workbench({
})}
</div>
<p style={{ fontSize: '0.8rem', color: '#888', fontStyle: 'italic', marginTop: '0.5rem', textAlign: 'center' }}>
* Potential base stats. Actual stats may vary.
* {t('crafting.potentialBaseStats')}
</p>
</div>
)}
@@ -183,13 +183,13 @@ function Workbench({
<div className="item-stats" style={{ display: 'flex', gap: '1rem', justifyContent: 'center', marginTop: '1rem', flexWrap: 'wrap' }}>
{Object.entries(item.unique_item_data?.unique_stats ?? item.unique_item_data ?? item.base_stats ?? item.stats ?? {}).filter(([k]) => !['id', 'item_id', 'durability', 'max_durability', 'created_at', 'tier'].includes(k)).map(([key, value]) => {
const icons: Record<string, string> = {
weight_capacity: '⚖️ Weight',
volume_capacity: '📦 Volume',
armor: '🛡️ Armor',
hp_max: '❤️ Max HP',
stamina_max: '⚡ Max Stamina',
damage_min: '⚔️ Damage Min',
damage_max: '⚔️ Damage Max'
weight_capacity: `⚖️ ${t('game.weight')}`,
volume_capacity: `📦 ${t('game.volume')}`,
armor: `🛡️ ${t('stats.armor')}`,
hp_max: `❤️ ${t('stats.maxHp')}`,
stamina_max: `${t('stats.maxStamina')}`,
damage_min: `⚔️ ${t('stats.damage')} Min`,
damage_max: `⚔️ ${t('stats.damage')} Max`
}
const label = icons[key] || key.replace('_', ' ')
const unit = key.includes('weight') ? 'kg' : key.includes('volume') ? 'L' : ''
@@ -206,30 +206,28 @@ function Workbench({
{workbenchTab === 'craft' && (
<>
<div className="detail-requirements">
<h4>📊 Requirements</h4>
<h4>{t('crafting.requirements')}</h4>
{item.craft_level && item.craft_level > 1 && (
<div className={`requirement-item ${item.meets_level ? 'met' : 'missing'}`}>
<span>Level {item.craft_level} Required</span>
<span>{item.meets_level ? '✅' : `❌ (Lv. ${profile?.level || 1})`}</span>
</div>
)}
<div className={`requirement-item ${item.meets_level ? 'met' : 'missing'}`}>
<span>{t('crafting.levelRequired', { level: item.craft_level })}</span>
<span>{item.meets_level ? '✅' : `❌ (Lv. ${profile?.level || 1})`}</span>
</div>
{item.tools && item.tools.length > 0 && (
<>
<h5 style={{ marginTop: '1rem', marginBottom: '0.5rem', color: '#aaa' }}>Tools</h5>
<h5 style={{ marginTop: '1rem', marginBottom: '0.5rem', color: '#aaa' }}>{t('crafting.tools')}</h5>
{item.tools.map((tool: any, i: number) => (
<div key={i} className={`requirement-item ${tool.has_tool ? 'met' : 'missing'}`}>
<span>{tool.emoji} {getTranslatedText(tool.name)}</span>
<span>
{tool.has_tool ? `${tool.tool_durability}/${tool.max_durability} (Cost: ${tool.durability_cost})` : `Missing (Cost: ${tool.durability_cost})`}
{tool.has_tool ? `${tool.tool_durability}/${tool.max_durability} (${t('crafting.cost')}: ${tool.durability_cost})` : `${t('crafting.missing')} (${t('crafting.cost')}: ${tool.durability_cost})`}
</span>
</div>
))}
</>
)}
<h5 style={{ marginTop: '1rem', marginBottom: '0.5rem', color: '#aaa' }}>Materials</h5>
<h5 style={{ marginTop: '1rem', marginBottom: '0.5rem', color: '#aaa' }}>{t('crafting.materials')}</h5>
{item.materials && item.materials.length > 0 ? (
item.materials.map((mat: any, i: number) => (
<div key={i} className={`requirement-item ${mat.has_enough ? 'met' : 'missing'}`}>
@@ -239,7 +237,7 @@ function Workbench({
))
) : (
<div className="requirement-item met">
<span>No materials required</span>
<span>{t('crafting.noMaterialsRequired')}</span>
</div>
)}
</div>
@@ -252,12 +250,12 @@ function Workbench({
style={{ width: '100%', padding: '1rem', fontSize: '1.2rem', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '0.5rem' }}
>
<span>
{!item.meets_level ? `Need Level ${item.craft_level}` :
!item.can_craft ? 'Missing Requirements' : '🔨 Craft Item'}
{!item.meets_level ? t('crafting.levelRequired', { level: item.craft_level }) :
!item.can_craft ? t('crafting.missingRequirements') : t('crafting.craftItem')}
</span>
{item.can_craft && (
<span style={{ fontSize: '0.9rem', opacity: 0.9 }}>
{item.stamina_cost || 5} Stamina
{t('crafting.staminaCost', { cost: item.stamina_cost || 5 })}
</span>
)}
</button>
@@ -268,10 +266,10 @@ function Workbench({
{workbenchTab === 'repair' && (
<>
<div className="detail-requirements">
<h4>🔧 Repair Status</h4>
<h4>🔧 {workbenchTab === 'repair' ? t('game.repair') : t('game.salvage')}</h4>
{!item.needs_repair ? (
<p className="repair-info full-durability" style={{ textAlign: 'center', marginBottom: '1rem' }}> Item is in perfect condition</p>
<p className="repair-info full-durability" style={{ textAlign: 'center', marginBottom: '1rem' }}>{t('crafting.perfectCondition')}</p>
) : (
<>
<div className="repair-preview-text">
@@ -333,12 +331,12 @@ function Workbench({
style={{ width: '100%', padding: '1rem', fontSize: '1.2rem', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '0.5rem' }}
>
<span>
{!item.needs_repair ? 'Already Full' :
!item.can_repair ? 'Missing Requirements' : '🛠️ Repair Item'}
{!item.needs_repair ? t('crafting.alreadyFull') :
!item.can_repair ? t('crafting.missingRequirements') : t('crafting.repairItem')}
</span>
{item.needs_repair && item.can_repair && (
<span style={{ fontSize: '0.9rem', opacity: 0.9 }}>
{item.stamina_cost || 3} Stamina
{t('crafting.staminaCost', { cost: item.stamina_cost || 3 })}
</span>
)}
</button>
@@ -349,7 +347,7 @@ function Workbench({
{workbenchTab === 'uncraft' && (
<>
<div className="detail-requirements">
<h4> Salvage Preview</h4>
<h4> {t('game.salvage')}</h4>
{/* Show durability bar if we have durability data */}
{(item.unique_item_data || item.durability_percent !== undefined) && (
@@ -382,7 +380,7 @@ function Workbench({
<>
{durabilityRatio < 1.0 && (
<div className="uncraft-warning" style={{ marginBottom: '1rem', color: '#ffc107' }}>
Yield reduced by {Math.round((1 - durabilityRatio) * 100)}% due to damage
{t('crafting.yieldReduced', { percent: Math.round((1 - durabilityRatio) * 100) })}
</div>
)}
@@ -409,15 +407,15 @@ function Workbench({
className="uncraft-btn"
disabled={(profile?.stamina || 0) < (item.stamina_cost || 1)}
onClick={() => {
if (window.confirm(`Are you sure you want to salvage ${getTranslatedText(item.name)}? This cannot be undone.`)) {
if (window.confirm(t('crafting.confirmSalvage', { name: getTranslatedText(item.name) }))) {
onUncraft(item.unique_item_id, item.inventory_id)
}
}}
style={{ width: '100%', padding: '1rem', fontSize: '1.2rem', backgroundColor: '#d32f2f', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '0.5rem' }}
>
<span> Salvage Item</span>
<span> {t('game.salvage')}</span>
<span style={{ fontSize: '0.9rem', opacity: 0.9 }}>
{item.stamina_cost || 2} Stamina
{t('crafting.staminaCost', { cost: item.stamina_cost || 2 })}
</span>
</button>
</div>
@@ -429,14 +427,14 @@ function Workbench({
}
const categories = [
{ id: 'all', label: 'All', icon: '🎒' },
{ id: 'weapon', label: 'Weapons', icon: '⚔️' },
{ id: 'armor', label: 'Armor', icon: '🛡️' },
{ id: 'clothing', label: 'Clothing', icon: '👕' },
{ id: 'tool', label: 'Tools', icon: '🛠️' },
{ id: 'consumable', label: 'Consumables', icon: '🍖' },
{ id: 'resource', label: 'Resources', icon: '📦' },
{ id: 'misc', label: 'Misc', icon: '📦' }
{ id: 'all', label: t('categories.all'), icon: '🎒' },
{ id: 'weapon', label: t('categories.weapon'), icon: '⚔️' },
{ id: 'armor', label: t('categories.armor'), icon: '🛡️' },
{ id: 'clothing', label: t('categories.clothing'), icon: '👕' },
{ id: 'tool', label: t('categories.tool'), icon: '🛠️' },
{ id: 'consumable', label: t('categories.consumable'), icon: '🍖' },
{ id: 'resource', label: t('categories.resource'), icon: '📦' },
{ id: 'misc', label: t('categories.misc'), icon: '📦' }
]
return (
@@ -445,25 +443,25 @@ function Workbench({
}}>
<div className="workbench-menu">
<div className="workbench-header">
<h3>🔧 Workbench</h3>
<h3>{t('game.workbench')}</h3>
<div className="workbench-tabs">
<button
className={`tab-btn ${workbenchTab === 'craft' ? 'active' : ''}`}
onClick={() => onSwitchTab('craft')}
>
🔨 Craft
{t('game.craft')}
</button>
<button
className={`tab-btn ${workbenchTab === 'repair' ? 'active' : ''}`}
onClick={() => onSwitchTab('repair')}
>
🛠 Repair
{t('game.repair')}
</button>
<button
className={`tab-btn ${workbenchTab === 'uncraft' ? 'active' : ''}`}
onClick={() => onSwitchTab('uncraft')}
>
Salvage
{t('game.salvage')}
</button>
</div>
<button className="close-btn" onClick={onCloseCrafting}></button>
@@ -472,7 +470,7 @@ function Workbench({
<div className="workbench-content-grid">
{/* Column 1: Categories Sidebar */}
<div className="workbench-sidebar">
<h4 className="sidebar-title">Categories</h4>
<h4 className="sidebar-title">{t('location.lootableItems').replace(':', '')}</h4>
<div className="category-list">
{categories.map(cat => (
<button
@@ -492,7 +490,7 @@ function Workbench({
<div className="workbench-filters">
<input
type="text"
placeholder="🔍 Filter items..."
placeholder={t('game.searchItems')}
value={workbenchTab === 'craft' ? craftFilter : workbenchTab === 'repair' ? repairFilter : uncraftFilter}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
if (workbenchTab === 'craft') onSetCraftFilter(e.target.value)
@@ -519,9 +517,7 @@ function Workbench({
return matchesSearch && matchesCategory
}).length === 0 ? (
<div className="empty-state">
{workbenchTab === 'craft' ? 'No craftable items found.' :
workbenchTab === 'repair' ? 'No repairable items found.' :
'No salvageable items found.'}
{t('game.noItemsFound')}
</div>
) : (
items
@@ -573,7 +569,7 @@ function Workbench({
>
{getTranslatedText(item.name)}
</span>
{item.location === 'equipped' && <span className="item-card-equipped" style={{ marginLeft: '0.5rem' }}>Equipped</span>}
{item.location === 'equipped' && <span className="item-card-equipped" style={{ marginLeft: '0.5rem' }}>{t('game.equipped')}</span>}
</div>
<div className="item-meta-row">