API/client/src/views/GameInterface/tabs/ItemListTab.jsx

158 lines
5.2 KiB
JavaScript

import React, { useState, useEffect } from "react";
import GameDataManager from "../../../services/GameDataManager.js";
import "./styles/ItemListTab.css";
import { config } from "../../../config/api.js";
const ItemListTab = () => {
const [allItems, setAllItems] = useState([]);
const [filteredItems, setFilteredItems] = useState([]);
const [searchQuery, setSearchQuery] = useState("");
const [selectedCategory, setSelectedCategory] = useState("all");
const [selectedItem, setSelectedItem] = useState(null);
const [isMobile, setIsMobile] = useState(window.innerWidth <= 768);
const ASSET_BASE_URL = `${config.serverUrl}/static/`;
useEffect(() => {
const handleResize = () => setIsMobile(window.innerWidth <= 768);
window.addEventListener("resize", handleResize);
const itemsArray = Array.from(GameDataManager.items.keys()).map((id) =>
GameDataManager.getItem(id),
);
setAllItems(itemsArray);
setFilteredItems(itemsArray);
return () => window.removeEventListener("resize", handleResize);
}, []);
useEffect(() => {
let result = allItems;
if (selectedCategory !== "all") {
result = result.filter(
(item) => item.meta?.category === selectedCategory,
);
}
if (searchQuery) {
const q = searchQuery.toLowerCase();
result = result.filter(
(item) =>
item.displayName.toLowerCase().includes(q) ||
item.id.toLowerCase().includes(q),
);
}
setFilteredItems(result);
}, [searchQuery, selectedCategory, allItems]);
const getFullTextureUrl = (path) => {
if (!path) return "/assets/no-image.png";
return path.startsWith("http") ? path : `${ASSET_BASE_URL}${path}`;
};
const categories = [
"all",
...new Set(allItems.map((i) => i.meta?.category).filter(Boolean)),
];
const renderInspector = () => (
<div
className={`item-inspector ${isMobile && selectedItem ? "mobile-modal" : ""}`}
onClick={() => isMobile && setSelectedItem(null)}
>
{selectedItem && (
<div className="inspector-content" onClick={(e) => e.stopPropagation()}>
{isMobile && (
<button
className="close-inspector"
onClick={() => setSelectedItem(null)}
>
&times;
</button>
)}
<div className={`inspector-header ${selectedItem.meta?.rarity}`}>
<div className="header-visual">
<img src={getFullTextureUrl(selectedItem.texture)} alt="" />
</div>
<div className="header-info">
<div className="id-tag">{selectedItem.id}</div>
<h1>{selectedItem.displayName}</h1>
<span className="rarity-label">
{selectedItem.meta?.rarity?.toUpperCase()}
</span>
</div>
</div>
<div className="inspector-grid">
<div className="inspector-section">
<div className="section-title">DATA_DESCRIPTION</div>
<p>{selectedItem.description}</p>
</div>
{selectedItem.stats &&
Object.keys(selectedItem.stats).length > 0 && (
<div className="inspector-section">
<div className="section-title">PARAMETER_READOUT</div>
<div className="stat-pills">
{Object.entries(selectedItem.stats).map(([k, v]) => (
<div key={k} className="stat-pill">
<span>{GameDataManager.getStatName(k)}</span>
<span>+{v}</span>
</div>
))}
</div>
</div>
)}
</div>
</div>
)}
</div>
);
return (
<div className="item-list-container">
<div className="item-list-sidebar">
<div className="search-box">
<input
type="text"
placeholder="SEARCH_ID_OR_NAME..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
</div>
<div className="category-filters">
{categories.map((cat) => (
<button
key={cat}
className={`filter-btn ${selectedCategory === cat ? "active" : ""}`}
onClick={() => setSelectedCategory(cat)}
>
{cat.toUpperCase()}
</button>
))}
</div>
<div className="items-list-scroll">
{filteredItems.map((item) => (
<div
key={item.id}
className={`item-row ${selectedItem?.id === item.id ? "selected" : ""} ${item.meta?.rarity}`}
onClick={() => setSelectedItem(item)}
>
<div className="item-row-icon">
<img src={getFullTextureUrl(item.texture)} alt="" />
</div>
<div className="item-row-content">
<div className="item-row-title">{item.displayName}</div>
<div className="item-row-subtitle">{item.id}</div>
</div>
</div>
))}
</div>
</div>
{(!isMobile || (isMobile && selectedItem)) && renderInspector()}
</div>
);
};
export default ItemListTab;