From 78c0f52c39acf926c2ef549a55685aa4619b2347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Henrique?= Date: Sat, 8 Feb 2025 20:52:44 -0300 Subject: [PATCH] feat: enhance SkillTreeModal with skill allocation logic and custom scrollbar styles --- src/components/PetDisplay.tsx | 5 +- src/components/modal/InventoryModal.tsx | 2 +- .../modal/SkillTreeModal.module.css | 22 +++ src/components/modal/SkillTreeModal.tsx | 177 +++++++++++++++++- src/services/api/api.ts | 2 +- src/types/Skills.ts | 11 +- 6 files changed, 205 insertions(+), 14 deletions(-) create mode 100644 src/components/modal/SkillTreeModal.module.css diff --git a/src/components/PetDisplay.tsx b/src/components/PetDisplay.tsx index f43988d..c9b8b06 100755 --- a/src/components/PetDisplay.tsx +++ b/src/components/PetDisplay.tsx @@ -107,7 +107,10 @@ export default function PetDisplay({ pet, onPetUpdate }: PetDisplayProps) { )} {showSkillTreeModal && ( setShowSkillTreeModal(false)} + petId={pet.id} + onPetUpdate={onPetUpdate} + onClose={() => setShowSkillTreeModal(false) + } /> )} diff --git a/src/components/modal/InventoryModal.tsx b/src/components/modal/InventoryModal.tsx index cc8f9f4..377b2f8 100644 --- a/src/components/modal/InventoryModal.tsx +++ b/src/components/modal/InventoryModal.tsx @@ -35,7 +35,7 @@ export default function InventoryModal({ inventory, petId, onClose, onPetUpdate }; return ( -
+

Inventory

diff --git a/src/components/modal/SkillTreeModal.module.css b/src/components/modal/SkillTreeModal.module.css new file mode 100644 index 0000000..5c89e90 --- /dev/null +++ b/src/components/modal/SkillTreeModal.module.css @@ -0,0 +1,22 @@ +.customScroll { + scrollbar-width: thin; + scrollbar-color: #4B5563 #1F2937; +} + +.customScroll::-webkit-scrollbar { + width: 8px; +} + +.customScroll::-webkit-scrollbar-track { + background: #1F2937; + border-radius: 4px; +} + +.customScroll::-webkit-scrollbar-thumb { + background-color: #4B5563; + border-radius: 4px; +} + +.customScroll::-webkit-scrollbar-thumb:hover { + background-color: #6B7280; +} diff --git a/src/components/modal/SkillTreeModal.tsx b/src/components/modal/SkillTreeModal.tsx index 381f1dc..47db427 100644 --- a/src/components/modal/SkillTreeModal.tsx +++ b/src/components/modal/SkillTreeModal.tsx @@ -1,17 +1,180 @@ -import React from 'react'; +import { useEffect, useState } from 'react'; +import { Pet } from '../../types/Pet'; +import { Skill, PetSkill, SkillType } from '../../types/Skills'; +import { fetchPets, getAllSkills, getPetSkills, postAllocatePetSkill } from '../../services/api/api'; +import { Loader2 } from 'lucide-react'; +import styles from './SkillTreeModal.module.css'; interface SkillTreeModalProps { onClose: () => void; + petId: string; + onPetUpdate: (updatedPet: Pet) => void; } -export default function SkillTreeModal({ onClose }: SkillTreeModalProps) { +export default function SkillTreeModal({ onClose, petId, onPetUpdate }: SkillTreeModalProps) { + const [skills, setSkills] = useState([]); + const [petSkills, setPetSkills] = useState([]); + const [loading, setLoading] = useState(true); + const [allocating, setAllocating] = useState(false); + + useEffect(() => { + const fetchData = async () => { + try { + const [allSkills, ownedSkills] = await Promise.all([ + getAllSkills(), + getPetSkills(petId) + ]); + setSkills(allSkills); + setPetSkills(ownedSkills); + } catch (error) { + console.error('Error fetching skills:', error); + } finally { + setLoading(false); + } + }; + fetchData(); + }, [petId]); + + const handleAllocateSkill = async (skillId: number) => { + try { + setAllocating(true); + const updatedPetSkill = await postAllocatePetSkill(petId, skillId); + setPetSkills([...petSkills, updatedPetSkill]); + // Refresh pet data to update skill points + const updatedPet = await fetchPets(); + onPetUpdate(updatedPet[0]); + } catch (error) { + console.error('Error allocating skill:', error); + } finally { + setAllocating(false); + } + }; + + const getSkillTier = (skillId: number) => { + return petSkills.find(ps => ps.skillId === skillId)?.currentTier; + }; + + const canAllocateSkill = (skill: Skill) => { + if (!skill.skillsIdRequired) return true; + return petSkills.some(ps => ps.skillId === skill.skillsIdRequired![0]); + }; + + const getRequiredSkillName = (skillId: number[] | null) => { + if (!skillId) return null; + return skills.find(s => s.id === skillId[0])?.name; + }; + + const renderSkillNode = (skill: Skill) => { + console.log('Rendering skill:', skill); + + const owned = petSkills.some(ps => ps.skillId === skill.id); + const tier = getSkillTier(skill.id); + const canAllocate = canAllocateSkill(skill); + const requiredSkillName = getRequiredSkillName(skill.skillsIdRequired); + + return ( +
+
+ {/* {skill.name} */} + {skill.icon} +

{skill.name}

+ {tier && ( + + Tier {tier} + + )} +
+

{skill.description}

+ {!canAllocate && requiredSkillName && ( +

Required skill: {requiredSkillName}

+ )} +
+ {skill.effects.map((effect, idx) => ( +
+ Tier {effect.tier}: {effect.effect} ({effect.value}) +
+ ))} +
+ {!owned && ( + + )} + {owned && ( + + )} +
+ ); + }; + + const renderSkillTree = () => { + const groundSkills = skills.filter(s => s.type === 'GROUND'); + const grandSkills = skills.filter(s => s.type === 'GRAND'); + + return ( +
+
+ {groundSkills.map(renderSkillNode)} +
+
+

Advanced Skills

+
+ {grandSkills.map(renderSkillNode)} +
+
+
+ ); + }; + return ( -
-
+
+

Skill Tree

-

Skill tree modal under development.

+ + {loading ? ( +
+ +
+ ) : ( + renderSkillTree() + )} +