diff --git a/src/components/modal/InventoryModal.tsx b/src/components/modal/InventoryModal.tsx index 377b2f8..2e0d02b 100644 --- a/src/components/modal/InventoryModal.tsx +++ b/src/components/modal/InventoryModal.tsx @@ -1,19 +1,60 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { Inventory, InvItemInteraction, Pet } from '../../types/Pet'; -import { putPetItemInteract } from '../../services/api/api'; +import { putPetItemInteract, getItemIcon } from '../../services/api/api'; +import { Loader2 } from 'lucide-react'; interface InventoryModalProps { inventory: Inventory; petId: string; onClose: () => void; - onPetUpdate: (updatedPet: Pet) => void; // Add this prop + onPetUpdate: (updatedPet: Pet) => void; } export default function InventoryModal({ inventory, petId, onClose, onPetUpdate }: InventoryModalProps) { - const capacity = inventory.capacity; // Expected to be 20 for 4 rows x 5 cols + const capacity = inventory.capacity; const items = inventory.items; const gridSlots = Array.from({ length: capacity }, (_, i) => items[i]); const [selectedItemIndex, setSelectedItemIndex] = useState(null); + const [itemIcons, setItemIcons] = useState>(new Map()); + const [loadingIcons, setLoadingIcons] = useState>(new Set()); + + useEffect(() => { + const fetchItemIcons = async () => { + const newIcons = new Map(); + const loadingItems = new Set(); + + for (const itemId of items) { + if (itemId !== undefined && !itemIcons.has(itemId)) { + loadingItems.add(itemId); + } + } + setLoadingIcons(loadingItems); + + for (const itemId of loadingItems) { + if (itemId !== undefined && !itemIcons.has(itemId)) { + try { + const blob = await getItemIcon(itemId); + const imageUrl = URL.createObjectURL(blob); + newIcons.set(itemId, imageUrl); + } catch (error) { + console.error(`Failed to load icon for item ${itemId}:`, error); + } finally { + loadingItems.delete(itemId); + setLoadingIcons(new Set(loadingItems)); + } + } + } + + setItemIcons(new Map([...itemIcons, ...newIcons])); + }; + + fetchItemIcons(); + + return () => { + // Cleanup object URLs on unmount + itemIcons.forEach(url => URL.revokeObjectURL(url)); + }; + }, [items]); const handleItemClick = (index: number) => { if (selectedItemIndex === index || gridSlots[index] === undefined) { @@ -47,15 +88,27 @@ export default function InventoryModal({ inventory, petId, onClose, onPetUpdate
- {gridSlots.map((item, index) => ( + {gridSlots.map((itemId, index) => (
handleItemClick(index)} - className={`border rounded p-4 flex items-center justify-center h-16 - ${item !== undefined ? 'bg-gray-700 cursor-pointer' : 'bg-gray-800 text-gray-500'} + className={`border rounded p-2 flex items-center justify-center h-24 w-24 + ${itemId !== undefined ? 'bg-gray-700 cursor-pointer' : 'bg-gray-800 text-gray-500'} ${selectedItemIndex === index ? 'border-blue-500 animate-pulse' : 'border-gray-600'}`} > - {item !== undefined ? {item} : Empty} + {itemId !== undefined ? ( + loadingIcons.has(itemId) ? ( + + ) : ( + {`Item + ) + ) : ( + Empty + )}
))}
diff --git a/src/services/api/api.ts b/src/services/api/api.ts index 92a2c6c..2d0ed35 100644 --- a/src/services/api/api.ts +++ b/src/services/api/api.ts @@ -50,4 +50,14 @@ export async function postAllocatePetSkill(petId: string, skillId: number): Prom export async function putPetItemInteract(petId: string, itemId: number, inter: InvItemInteraction): Promise { const response = await api.put(`/api/v1/inventory/${petId}/${itemId}/${inter.toLowerCase()}`); return response.data; +} + +export async function getItemIcon(itemId: number): Promise { + const response = await api.get(`/api/v1/gamedata/item/icon/${itemId}`, { + responseType: 'blob', + headers: { + Accept: 'image/png' + } + }); + return response.data; } \ No newline at end of file diff --git a/src/services/api/types.ts b/src/services/api/types.ts index 32f9181..b2d85a4 100755 --- a/src/services/api/types.ts +++ b/src/services/api/types.ts @@ -29,4 +29,5 @@ export interface RequestOptions { headers?: Record; params?: Record; timeout?: number; + responseType? : 'json' | 'blob' | 'text'; } \ No newline at end of file