d2d28887b1
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m9s
- Refactored page.tsx (613→252 lines) with GameOverScreen and LeftPanel extracted - Refactored StatsTab.tsx (584→92 lines) with section components - Refactored SkillsTab.tsx (434→54 lines) with sub-components - Created modular structure for GameContext, LootInventory, and other components - All extracted components organized into feature directories
87 lines
2.6 KiB
TypeScript
87 lines
2.6 KiB
TypeScript
'use client';
|
|
|
|
import type { LootInventory } from '@/lib/game/types';
|
|
// For backward compatibility
|
|
type LootInventoryType = LootInventory;
|
|
import { LOOT_DROPS } from '@/lib/game/data/loot-drops';
|
|
import { RARITY_CSS_VAR, RARITY_GLOW_CSS_VAR } from './types';
|
|
import { Sparkles, Trash2 } from 'lucide-react';
|
|
import { ActionButton } from '@/components/ui/action-button';
|
|
|
|
interface MaterialItemProps {
|
|
materialId: string;
|
|
count: number;
|
|
onDelete?: (materialId: string) => void;
|
|
}
|
|
|
|
export function MaterialItem({ materialId, count, onDelete }: MaterialItemProps) {
|
|
const drop = LOOT_DROPS[materialId];
|
|
if (!drop) return null;
|
|
|
|
const rarityColor = RARITY_CSS_VAR[drop.rarity] || 'var(--rarity-common)';
|
|
const rarityGlow = RARITY_GLOW_CSS_VAR[drop.rarity] || 'var(--rarity-common-glow)';
|
|
|
|
return (
|
|
<div
|
|
className="p-2 rounded border bg-[var(--bg-sunken)] group relative"
|
|
style={{
|
|
borderColor: rarityColor,
|
|
backgroundColor: rarityGlow,
|
|
}}
|
|
>
|
|
<div className="flex items-start justify-between">
|
|
<div>
|
|
<div className="text-xs font-semibold" style={{ color: rarityColor }}>
|
|
{drop.name}
|
|
</div>
|
|
<div className="text-xs text-[var(--text-secondary)]">
|
|
x{count}
|
|
</div>
|
|
<div className="text-xs text-[var(--text-muted)] capitalize">
|
|
{drop.rarity}
|
|
</div>
|
|
</div>
|
|
{onDelete && (
|
|
<ActionButton
|
|
variant="ghost"
|
|
size="sm"
|
|
className="h-5 w-5 p-0 opacity-0 group-hover:opacity-100 text-[var(--color-danger)] hover:text-[var(--interactive-danger-hover)] hover:bg-[var(--interactive-danger)]/20"
|
|
onClick={() => onDelete(materialId)}
|
|
aria-label={`Delete ${drop.name}`}
|
|
>
|
|
<Trash2 className="w-3 h-3" />
|
|
</ActionButton>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
interface MaterialsSectionProps {
|
|
materials: [string, number][];
|
|
onDeleteMaterial?: (materialId: string) => void;
|
|
}
|
|
|
|
export function MaterialsSection({ materials, onDeleteMaterial }: MaterialsSectionProps) {
|
|
if (materials.length === 0) return null;
|
|
|
|
return (
|
|
<div>
|
|
<div className="text-xs text-[var(--text-muted)] mb-2 flex items-center gap-1">
|
|
<Sparkles className="w-3 h-3" />
|
|
Materials
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-2">
|
|
{materials.map(([id, count]) => (
|
|
<MaterialItem
|
|
key={id}
|
|
materialId={id}
|
|
count={count}
|
|
onDelete={onDeleteMaterial}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|