Files
discord-rpg-concept/panel/src/lib/useItems.ts

100 lines
2.3 KiB
TypeScript

import { useCallback, useEffect, useState } from "react";
import { get } from "./api";
export interface Item {
id: number;
name: string;
description: string | null;
type: string;
rarity: string;
price: string | null;
iconUrl: string;
imageUrl: string;
}
export interface ItemFilters {
search: string;
type: string | null;
rarity: string | null;
}
export function useItems() {
const [items, setItems] = useState<Item[]>([]);
const [total, setTotal] = useState(0);
const [currentPage, setCurrentPage] = useState(1);
const [limit, setLimit] = useState(50);
const [filters, setFiltersState] = useState<ItemFilters>({
search: "",
type: null,
rarity: null,
});
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const fetchItems = useCallback(async () => {
try {
setLoading(true);
setError(null);
const params = new URLSearchParams();
if (filters.search) params.set("search", filters.search);
if (filters.type) params.set("type", filters.type);
if (filters.rarity) params.set("rarity", filters.rarity);
params.set("limit", String(limit));
params.set("offset", String((currentPage - 1) * limit));
const data = await get<{ items: Item[]; total: number }>(
`/api/items?${params.toString()}`
);
setItems(data.items);
setTotal(data.total);
} catch (e) {
setError(e instanceof Error ? e.message : "Failed to load items");
} finally {
setLoading(false);
}
}, [filters, currentPage, limit]);
const setFilters = useCallback((newFilters: Partial<ItemFilters>) => {
setFiltersState((prev) => ({ ...prev, ...newFilters }));
setCurrentPage(1);
}, []);
const setSearchDebounced = useCallback(
(() => {
let timeoutId: NodeJS.Timeout;
return (search: string) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
setFilters({ search });
}, 300);
};
})(),
[setFilters]
);
const setPage = useCallback((page: number) => {
setCurrentPage(page);
}, []);
useEffect(() => {
fetchItems();
}, [fetchItems]);
return {
items,
total,
currentPage,
limit,
setLimit,
filters,
setFilters,
setSearchDebounced,
setPage,
loading,
error,
refetch: fetchItems,
};
}