171 lines
5.8 KiB
JavaScript
171 lines
5.8 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
|
import GameDataManager from "../../../services/GameDataManager.js";
|
|
import "./styles/ItemListTab.css";
|
|
|
|
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 ASSET_BASE_URL = "http://localhost:5003/static/";
|
|
|
|
useEffect(() => {
|
|
const itemsArray = Array.from(GameDataManager.items.keys()).map((id) =>
|
|
GameDataManager.getItem(id),
|
|
);
|
|
setAllItems(itemsArray);
|
|
setFilteredItems(itemsArray);
|
|
}, []);
|
|
|
|
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)),
|
|
];
|
|
|
|
return (
|
|
<div className="item-list-container">
|
|
<div className="item-list-sidebar">
|
|
<div className="search-box">
|
|
<i className="fas fa-search"></i>
|
|
<input
|
|
type="text"
|
|
placeholder="FILTER_BY_DATABASE_ID..."
|
|
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 className="item-row-rarity-indicator"></div>
|
|
</div>
|
|
))}
|
|
{filteredItems.length === 0 && (
|
|
<div className="no-results">NO_RECORDS_FOUND</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="item-inspector">
|
|
{selectedItem ? (
|
|
<div className="inspector-content">
|
|
<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>
|
|
<div className="rarity-label">
|
|
{selectedItem.meta?.rarity?.toUpperCase()}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="inspector-grid">
|
|
<div className="inspector-section main-desc">
|
|
<div className="section-title">DATA_DESCRIPTION</div>
|
|
<p>{selectedItem.description}</p>
|
|
</div>
|
|
|
|
{selectedItem.stats &&
|
|
Object.keys(selectedItem.stats).length > 0 && (
|
|
<div className="inspector-section stats">
|
|
<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 className="p-label">
|
|
{GameDataManager.getStatName(k)}
|
|
</span>
|
|
<span className="p-value">+{v}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<div className="inspector-section meta">
|
|
<div className="section-title">OBJECT_METADATA</div>
|
|
<div className="meta-list">
|
|
<div className="meta-item">
|
|
<span>CATEGORY</span>
|
|
<span>{selectedItem.meta?.category || "general"}</span>
|
|
</div>
|
|
<div className="meta-item">
|
|
<span>EQUIP_SLOT</span>
|
|
<span>{selectedItem.meta?.equipmentSlot || "none"}</span>
|
|
</div>
|
|
<div className="meta-item">
|
|
<span>STACK_LIMIT</span>
|
|
<span>{selectedItem.meta?.stackable ? "64" : "1"}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<div className="inspector-placeholder">
|
|
<div className="scanner-line"></div>
|
|
<p>AWAITING_OBJECT_SELECTION...</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ItemListTab;
|