import { useMemo, useState } from 'react'; import { formatCurrency } from '../data/economy'; import { getEquipmentSlotFromItem, getEquipmentSlotLabel, isInventoryItemEquippable, } from '../data/equipmentEffects'; import { type ForgeRecipeView, getReforgeCostView } from '../data/forgeSystem'; import { resolveInventoryItemUseEffect } from '../data/inventoryEffects'; import { buildInitialPlayerInventory } from '../data/npcInteractions'; import { Character, InventoryItem, WorldType } from '../types'; import { getNineSliceStyle, UI_CHROME } from '../uiAssets'; import { InventoryItemDetailModal, InventoryItemGrid, } from './InventoryItemViews'; interface InventoryPanelProps { playerCharacter: Character; worldType: WorldType | null; playerInventory: InventoryItem[]; playerCurrency: number; playerHp: number; playerMaxHp: number; playerMana: number; playerMaxMana: number; inBattle: boolean; onUseItem: (itemId: string) => Promise; onEquipItem: (itemId: string) => Promise; forgeRecipes: ForgeRecipeView[]; onCraftRecipe: (recipeId: string) => Promise; onDismantleItem: (itemId: string) => Promise; onReforgeItem: (itemId: string) => Promise; } export function InventoryPanel({ playerCharacter, worldType, playerInventory, playerCurrency, playerHp, playerMaxHp, playerMana, playerMaxMana, inBattle, onUseItem, onEquipItem, forgeRecipes, onCraftRecipe, onDismantleItem, onReforgeItem, }: InventoryPanelProps) { const [selectedItem, setSelectedItem] = useState(null); const [isUsingItem, setIsUsingItem] = useState(false); const [equipmentActionKey, setEquipmentActionKey] = useState( null, ); const [forgeActionKey, setForgeActionKey] = useState(null); const inventoryItems = useMemo( () => playerInventory.length > 0 ? playerInventory : buildInitialPlayerInventory(playerCharacter, worldType), [playerCharacter, playerInventory, worldType], ); const selectedItemUseEffect = selectedItem ? resolveInventoryItemUseEffect(selectedItem, playerCharacter) : null; const selectedItemEquipSlot = selectedItem ? getEquipmentSlotFromItem(selectedItem) : null; const selectedItemReforgeCost = selectedItem ? getReforgeCostView(selectedItem, worldType) : null; const canUseSelectedItem = Boolean( selectedItem && selectedItemUseEffect && ((selectedItemUseEffect.hpRestore > 0 && playerHp < playerMaxHp) || (selectedItemUseEffect.manaRestore > 0 && playerMana < playerMaxMana) || selectedItemUseEffect.cooldownReduction > 0 || selectedItemUseEffect.buildBuffs.length > 0), ); const canEquipSelectedItem = Boolean( selectedItem && selectedItemEquipSlot && isInventoryItemEquippable(selectedItem) && !inBattle, ); const canDismantleSelectedItem = Boolean( selectedItem && !inBattle && (isInventoryItemEquippable(selectedItem) || selectedItem.buildProfile), ); const canReforgeSelectedItem = Boolean( selectedItem && !inBattle && isInventoryItemEquippable(selectedItem) && selectedItem.buildProfile && selectedItemReforgeCost && selectedItemReforgeCost.currencyCost <= playerCurrency, ); return (
工坊 {formatCurrency(playerCurrency, worldType)}
{forgeRecipes.map((recipe) => (
{recipe.name}
{recipe.description}
产物:{recipe.resultLabel}
花费:{recipe.currencyText}
{recipe.requirements.map((requirement) => ( = requirement.quantity ? 'border-emerald-400/20 bg-emerald-500/10 text-emerald-100' : 'border-white/10 bg-black/20 text-zinc-400' }`} > {requirement.label} {requirement.owned}/ {requirement.quantity} ))}
))}
setSelectedItem(null)} footer={ selectedItem ? (
) : undefined } />
); }