From 243c50a1a026dae74591db0cd20221214d81525a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Henrique?= Date: Wed, 5 Feb 2025 20:36:59 -0300 Subject: [PATCH] feat: add inventory and skill tree modals, enhance pet display with update handling --- src/App.tsx | 5 +- src/components/PetDisplay.tsx | 49 +++++++++++-- src/components/modal/InventoryModal.tsx | 95 +++++++++++++++++++++++++ src/components/modal/SkillTreeModal.tsx | 26 +++++++ src/services/api/api.ts | 11 ++- src/types/Pet.ts | 1 + 6 files changed, 177 insertions(+), 10 deletions(-) create mode 100644 src/components/modal/InventoryModal.tsx create mode 100644 src/components/modal/SkillTreeModal.tsx diff --git a/src/App.tsx b/src/App.tsx index 177d7a3..c6e5fff 100755 --- a/src/App.tsx +++ b/src/App.tsx @@ -48,7 +48,10 @@ export default function App() {
- + void; // Add this prop } -export default function PetDisplay({ pet }: PetDisplayProps) { +export default function PetDisplay({ pet, onPetUpdate }: PetDisplayProps) { const StatBar = ({ value, maxValue, label, icon: Icon }: { value: number; maxValue: number; label: string; icon: any }) => (
@@ -28,6 +32,9 @@ export default function PetDisplay({ pet }: PetDisplayProps) {
); + const [showInventoryModal, setShowInventoryModal] = useState(false); + const [showSkillTreeModal, setShowSkillTreeModal] = useState(false); + return (
@@ -67,12 +74,42 @@ export default function PetDisplay({ pet }: PetDisplayProps) { />
-
- - - - +
+
+ + + + +
+
+ + +
+ + {showInventoryModal && ( + setShowInventoryModal(false)} + onPetUpdate={onPetUpdate} + /> + )} + {showSkillTreeModal && ( + setShowSkillTreeModal(false)} + /> + )}
); } \ No newline at end of file diff --git a/src/components/modal/InventoryModal.tsx b/src/components/modal/InventoryModal.tsx new file mode 100644 index 0000000..cc8f9f4 --- /dev/null +++ b/src/components/modal/InventoryModal.tsx @@ -0,0 +1,95 @@ +import React, { useState } from 'react'; +import { Inventory, InvItemInteraction, Pet } from '../../types/Pet'; +import { putPetItemInteract } from '../../services/api/api'; + +interface InventoryModalProps { + inventory: Inventory; + petId: string; + onClose: () => void; + onPetUpdate: (updatedPet: Pet) => void; // Add this prop +} + +export default function InventoryModal({ inventory, petId, onClose, onPetUpdate }: InventoryModalProps) { + const capacity = inventory.capacity; // Expected to be 20 for 4 rows x 5 cols + const items = inventory.items; + const gridSlots = Array.from({ length: capacity }, (_, i) => items[i]); + const [selectedItemIndex, setSelectedItemIndex] = useState(null); + + const handleItemClick = (index: number) => { + if (selectedItemIndex === index || gridSlots[index] === undefined) { + setSelectedItemIndex(null); + } + else { + setSelectedItemIndex(index); + } + }; + + const handleInteraction = async (interaction: InvItemInteraction) => { + if (selectedItemIndex === null || gridSlots[selectedItemIndex] === undefined) return; + try { + const updatedPet = await putPetItemInteract(petId, gridSlots[selectedItemIndex], interaction); + onPetUpdate(updatedPet); + } catch (error) { + console.error('Item interaction failed:', error); + } + }; + + return ( +
+
+
+

Inventory

+ +
+
+ {gridSlots.map((item, 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'} + ${selectedItemIndex === index ? 'border-blue-500 animate-pulse' : 'border-gray-600'}`} + > + {item !== undefined ? {item} : Empty} +
+ ))} +
+
+ + + + +
+
+
+ ); +} diff --git a/src/components/modal/SkillTreeModal.tsx b/src/components/modal/SkillTreeModal.tsx new file mode 100644 index 0000000..381f1dc --- /dev/null +++ b/src/components/modal/SkillTreeModal.tsx @@ -0,0 +1,26 @@ +import React from 'react'; + +interface SkillTreeModalProps { + onClose: () => void; +} + +export default function SkillTreeModal({ onClose }: SkillTreeModalProps) { + return ( +
+
+

Skill Tree

+

Skill tree modal under development.

+
+ +
+
+
+ ); +} diff --git a/src/services/api/api.ts b/src/services/api/api.ts index 7bfd02d..e2722f0 100644 --- a/src/services/api/api.ts +++ b/src/services/api/api.ts @@ -1,5 +1,5 @@ import { ApiService } from './index'; -import { Pet, Resources } from '../../types/Pet'; +import { InvItemInteraction, Pet, Resources } from '../../types/Pet'; import { PetCreationRequest } from '../../types/PetCreationRequest'; import { PetUpdateActionRequest } from '../../types/PetUpdateActionRequest'; import { PetSkill, Skill } from '../../types/Skills'; @@ -42,7 +42,12 @@ export async function getPetSkills(petId: string): Promise { return response.data; } -export async function postAllocatePetSkill(petId: string, skillId: int): Promise { - const response = await api.get(`/api/v1/skill/${petId}/allocate/${skillId}`); +export async function postAllocatePetSkill(petId: string, skillId: number): Promise { + const response = await api.post(`/api/v1/skill/${petId}/allocate/${skillId}`); + return response.data; +} + +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; } \ No newline at end of file diff --git a/src/types/Pet.ts b/src/types/Pet.ts index 37f68d8..0dc6904 100755 --- a/src/types/Pet.ts +++ b/src/types/Pet.ts @@ -35,6 +35,7 @@ export interface Pet { inventory: Inventory; } +export type InvItemInteraction = 'EQUIP' | 'UNEQUIP' | 'USE' | 'DROP'; export interface Inventory { items: number[]; capacity: number;