156 lines
5.2 KiB
JavaScript
156 lines
5.2 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
||
import GameDataManager from "../../../services/GameDataManager";
|
||
import MeteorRegion from "../../../components/Meteor/MeteorRegion.jsx";
|
||
import { config } from "../../../config/api";
|
||
import DatapackDetailsModal from "./components/DatapackDetailsModal";
|
||
import "./styles/DatapackTab.css";
|
||
|
||
const DatapackTab = () => {
|
||
const [activeSection, setActiveSection] = useState("items");
|
||
const [searchQuery, setSearchQuery] = useState("");
|
||
const [displayList, setDisplayList] = useState([]);
|
||
const [selectedItem, setSelectedItem] = useState(null);
|
||
|
||
const sections = [
|
||
{ id: "items", label: "Items", icon: "fa-box" },
|
||
{ id: "hostiles", label: "Hostiles", icon: "fa-biohazard" },
|
||
{ id: "dungeons", label: "Dungeons", icon: "fa-dungeon" },
|
||
{ id: "recipes", label: "Recipes", icon: "fa-scroll" },
|
||
];
|
||
|
||
useEffect(() => {
|
||
let data = [];
|
||
switch (activeSection) {
|
||
case "items":
|
||
data = Array.from(GameDataManager.items.values()).map((i) =>
|
||
GameDataManager.getItem(i.id),
|
||
);
|
||
break;
|
||
case "hostiles":
|
||
data = Array.from(GameDataManager.hostiles.values()).map((h) =>
|
||
GameDataManager.getHostile(h.id),
|
||
);
|
||
break;
|
||
case "dungeons":
|
||
data = Array.from(GameDataManager.dungeons.values()).map((d) =>
|
||
GameDataManager.getDungeon(d.id),
|
||
);
|
||
break;
|
||
case "recipes":
|
||
data = Array.from(GameDataManager.recipes.values()).map((r) =>
|
||
GameDataManager.getRecipe(r.id),
|
||
);
|
||
break;
|
||
default:
|
||
data = [];
|
||
}
|
||
|
||
if (searchQuery) {
|
||
const query = searchQuery.toLowerCase();
|
||
data = data.filter(
|
||
(item) =>
|
||
item.displayName?.toLowerCase().includes(query) ||
|
||
item.id?.toLowerCase().includes(query),
|
||
);
|
||
}
|
||
setDisplayList(data);
|
||
}, [activeSection, searchQuery]);
|
||
|
||
return (
|
||
<div className="tab-content active datapack-tab-wrapper">
|
||
<div className="datapack-controls">
|
||
<div className="section-selector">
|
||
{sections.map((s) => (
|
||
<button
|
||
key={s.id}
|
||
className={`section-btn ${activeSection === s.id ? "active" : ""}`}
|
||
onClick={() => setActiveSection(s.id)}
|
||
>
|
||
<i className={`fas ${s.icon}`}></i>
|
||
<span>{s.label}</span>
|
||
</button>
|
||
))}
|
||
</div>
|
||
|
||
<div className="search-bar">
|
||
<i className="fas fa-search"></i>
|
||
<input
|
||
type="text"
|
||
placeholder="Search ID or Name..."
|
||
value={searchQuery}
|
||
onChange={(e) => setSearchQuery(e.target.value)}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<MeteorRegion className="datapack-content">
|
||
<div className="datapack-grid">
|
||
{displayList.map((item) => (
|
||
<div
|
||
key={item.id}
|
||
className={`datapack-card ${activeSection === "hostiles" ? "hostile-card" : ""}`}
|
||
onClick={() =>
|
||
setSelectedItem({ ...item, sectionType: activeSection })
|
||
}
|
||
>
|
||
<div className="card-icon">
|
||
{item.texture ? (
|
||
<img
|
||
src={`${config.serverUrl}/static/${item.texture}`}
|
||
alt=""
|
||
/>
|
||
) : (
|
||
<div className="fallback-icon">
|
||
{item.displayName?.[0] || "?"}
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<div className="card-info">
|
||
<span className="card-name">{item.displayName}</span>
|
||
<span className="card-id">{item.id}</span>
|
||
|
||
{/* Секція луту без картинок, лише текст або іконка коробки */}
|
||
{activeSection === "hostiles" &&
|
||
item.loot &&
|
||
item.loot.length > 0 && (
|
||
<div className="card-loot-preview">
|
||
{item.loot.map((lootEntry, idx) => {
|
||
const lootData = GameDataManager.getItem(lootEntry.id);
|
||
return (
|
||
<div
|
||
key={`${item.id}-loot-${idx}`}
|
||
className="loot-mini-slot-text"
|
||
title={`${lootData?.displayName || lootEntry.id} (${(lootEntry.chance * 100).toFixed(0)}%)`}
|
||
>
|
||
<i
|
||
className="fas fa-box-open"
|
||
style={{ fontSize: "10px", marginRight: "4px" }}
|
||
></i>
|
||
<span>
|
||
{lootData?.displayName ||
|
||
lootEntry.id.split(":").pop()}
|
||
</span>
|
||
</div>
|
||
);
|
||
})}
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</MeteorRegion>
|
||
|
||
{selectedItem && (
|
||
<DatapackDetailsModal
|
||
data={selectedItem}
|
||
onClose={() => setSelectedItem(null)}
|
||
/>
|
||
)}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default DatapackTab;
|