116 lines
3.5 KiB
JavaScript
116 lines
3.5 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
|
import { useSocket } from "../../../hooks/useSocket";
|
|
import GameDataManager from "../../../services/GameDataManager";
|
|
import "./styles/SkillsTab.css";
|
|
import CategorySelector from "../components/CategorySelector";
|
|
import MeteorRegion from "../../../components/Meteor/MeteorRegion.jsx";
|
|
import { SkillCard } from "./components/SkillsCard.jsx";
|
|
|
|
const SkillsTab = () => {
|
|
const { socket } = useSocket();
|
|
|
|
const [categories, setCategories] = useState([]);
|
|
const [activeCategory, setActiveCategory] = useState("");
|
|
const [skills, setSkills] = useState([]);
|
|
const [playerSkills, setPlayerSkills] = useState({});
|
|
const [skillPoints, setSkillPoints] = useState(0);
|
|
|
|
useEffect(() => {
|
|
const manifestCategories = GameDataManager.getSkillCategories();
|
|
setCategories(manifestCategories);
|
|
|
|
if (manifestCategories.length > 0) {
|
|
setActiveCategory(manifestCategories[0].id);
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (activeCategory) {
|
|
const filtered = GameDataManager.getSkillsByCategory(activeCategory);
|
|
setSkills(filtered);
|
|
}
|
|
}, [activeCategory]);
|
|
|
|
useEffect(() => {
|
|
if (!socket) return;
|
|
|
|
socket.emit("player:get_skill_points");
|
|
socket.emit("player:get_skills");
|
|
|
|
const handleSkillPoints = (data) => setSkillPoints(data.points || 0);
|
|
const handleSkillsData = (data) => setPlayerSkills(data.skills || {});
|
|
|
|
socket.on("player:skill_points_data", handleSkillPoints);
|
|
socket.on("player:skills_data", handleSkillsData);
|
|
|
|
return () => {
|
|
socket.off("player:skill_points_data", handleSkillPoints);
|
|
socket.off("player:skills_data", handleSkillsData);
|
|
};
|
|
}, [socket]);
|
|
|
|
const handleUpgrade = (skillId) => {
|
|
socket.emit("player:upgrade_skill", { skillId });
|
|
};
|
|
|
|
return (
|
|
<div
|
|
className="tab-content active"
|
|
style={{ height: "100%", display: "flex", flexDirection: "column" }}
|
|
>
|
|
<MeteorRegion className="skills-container">
|
|
<div className="skills-header">
|
|
<div className="header-main">
|
|
<h2>
|
|
<i className="fas fa-microchip"></i> Neural Core
|
|
</h2>
|
|
<div className="skill-points-badge">
|
|
<span className="label">Uplink Points:</span>
|
|
<span className="value">{skillPoints}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<CategorySelector
|
|
categories={categories}
|
|
activeCategory={activeCategory}
|
|
onCategoryChange={setActiveCategory}
|
|
/>
|
|
|
|
<div className="skills-grid custom-scroll">
|
|
{skills.length > 0 ? (
|
|
skills.map((skill) => {
|
|
const progress = playerSkills[skill.id] || {
|
|
level: 0,
|
|
experience: 0,
|
|
};
|
|
const maxLv = skill.meta?.topLevel || 10;
|
|
|
|
const cost = progress.level === 0 ? 2 : 1;
|
|
|
|
return (
|
|
<SkillCard
|
|
key={skill.id}
|
|
skill={skill}
|
|
level={progress.level}
|
|
maxLevel={maxLv}
|
|
experience={progress.experience}
|
|
canAfford={skillPoints >= cost}
|
|
onUpgrade={() => handleUpgrade(skill.id)}
|
|
/>
|
|
);
|
|
})
|
|
) : (
|
|
<div className="empty-category">
|
|
<i className="fas fa-xs fa-terminal"></i>
|
|
<p>No active modules found in this sector.</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</MeteorRegion>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default SkillsTab;
|