89 lines
2.2 KiB
TypeScript
89 lines
2.2 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
type ApiItem = {
|
|
id: string;
|
|
item_name: string;
|
|
amount: number;
|
|
price: number;
|
|
enabled: boolean;
|
|
shop: {
|
|
label: string;
|
|
};
|
|
item: {
|
|
stock: number;
|
|
};
|
|
};
|
|
|
|
const formatName = (name: string) => {
|
|
const parts = name.split(":");
|
|
if (!parts[1]) return "";
|
|
return parts[1]
|
|
.split("_")
|
|
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
.join(" ");
|
|
};
|
|
|
|
const getImage = (name: string) => {
|
|
const [mod, item] = name.split(":");
|
|
return `/textures/${mod}/${item}.png`;
|
|
};
|
|
|
|
const Items = ({ query }: { query: string }) => {
|
|
const [items, setItems] = useState<ApiItem[]>([]);
|
|
|
|
useEffect(() => {
|
|
const loadItems = async () => {
|
|
try {
|
|
const res = await fetch("/api/items");
|
|
const data = (await res.json()) as ApiItem[];
|
|
|
|
setItems(data.filter((item) => item.enabled));
|
|
} catch (err) {
|
|
console.error("Failed to load items", err);
|
|
}
|
|
};
|
|
|
|
void loadItems();
|
|
}, []);
|
|
|
|
const filteredItems = items.filter((item) =>
|
|
formatName(item.item_name).toLowerCase().includes(query.toLowerCase()),
|
|
);
|
|
|
|
return (
|
|
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-4">
|
|
{filteredItems.map((item) => (
|
|
<div
|
|
key={item.id}
|
|
className="flex gap-4 rounded-xl bg-white/10 p-4 text-white hover:bg-white/20"
|
|
>
|
|
<img
|
|
src={getImage(item.item_name)}
|
|
alt={item.item_name}
|
|
className="item-img h-12 w-12"
|
|
/>
|
|
|
|
<div className="w-70">
|
|
<h2 className="text-xl font-bold">{formatName(item.item_name)}</h2>
|
|
<p className="text-sm">{item.item.stock} available</p>
|
|
<p className="text-xs text-white/70">Shop: {item.shop.label}</p>
|
|
</div>
|
|
|
|
<div className="flex flex-col items-end">
|
|
<button className="rounded bg-blue-500 px-4 py-2 font-bold text-white hover:bg-blue-700">
|
|
Buy
|
|
</button>
|
|
<h3 className="w-fit self-center text-xl font-bold">
|
|
{item.price}$/{item.amount}
|
|
</h3>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Items;
|