- wrap root layout with QueryProvider for React Query - replace market UnderConstruction placeholder with MarketClient and real data fetching - implement search, pagination, and sort via search params using getActiveListings - add necessary client components and queries - update dependencies (e.g., prisma, pkg-types)
134 lines
3.7 KiB
TypeScript
134 lines
3.7 KiB
TypeScript
"use client";
|
|
|
|
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
|
|
export interface Listing {
|
|
listing_id: number;
|
|
seller_id: number;
|
|
item_id: number;
|
|
item_name: string;
|
|
quantity: number;
|
|
server_name: string;
|
|
price_pix: number | string | null;
|
|
price_tibia_coins: number | string | null;
|
|
price_gold_coins: number | string | null;
|
|
is_auction: boolean;
|
|
description: string | null;
|
|
listing_status: string;
|
|
created_at: string;
|
|
views_count: number;
|
|
favorites_count: number;
|
|
is_featured?: boolean;
|
|
item_id_unified?: number | null;
|
|
image_local_path?: string | null;
|
|
image_url?: string | null;
|
|
item_category?: string | null;
|
|
seller_character_name?: string | null;
|
|
}
|
|
|
|
interface ListingsResponse {
|
|
listings: Listing[];
|
|
pagination?: {
|
|
total: number;
|
|
page: number;
|
|
pageSize: number;
|
|
totalPages: number;
|
|
};
|
|
}
|
|
|
|
interface ListingsParams {
|
|
search?: string;
|
|
server_name?: string;
|
|
price_min?: string;
|
|
price_max?: string;
|
|
sortBy?: string;
|
|
sortOrder?: "ASC" | "DESC";
|
|
page?: number;
|
|
pageSize?: number;
|
|
}
|
|
|
|
/**
|
|
* Hook para buscar listings do marketplace
|
|
* Atualiza automaticamente a cada 10 segundos
|
|
*/
|
|
export function useListings(params: ListingsParams = {}) {
|
|
const queryParams = new URLSearchParams();
|
|
if (params.search) queryParams.set("search", params.search);
|
|
if (params.server_name) queryParams.set("server_name", params.server_name);
|
|
if (params.price_min) queryParams.set("price_min", params.price_min);
|
|
if (params.price_max) queryParams.set("price_max", params.price_max);
|
|
queryParams.set("sortBy", params.sortBy || "created_at");
|
|
queryParams.set("sortOrder", params.sortOrder || "DESC");
|
|
queryParams.set("page", String(params.page || 1));
|
|
queryParams.set("pageSize", String(params.pageSize || 20));
|
|
|
|
const { data, isLoading, error, refetch } = useQuery<ListingsResponse>({
|
|
queryKey: ["listings", params],
|
|
queryFn: async () => {
|
|
const res = await fetch(`/api/listings?${queryParams.toString()}`);
|
|
if (!res.ok) throw new Error("Erro ao buscar anúncios");
|
|
return res.json();
|
|
},
|
|
staleTime: 1000 * 10, // 10 segundos
|
|
refetchInterval: 1000 * 10, // Refetch a cada 10 segundos
|
|
refetchOnWindowFocus: true,
|
|
refetchOnReconnect: true,
|
|
});
|
|
|
|
return {
|
|
listings: data?.listings || [],
|
|
total: data?.pagination?.total || 0,
|
|
page: data?.pagination?.page || params.page || 1,
|
|
pageSize: data?.pagination?.pageSize || params.pageSize || 20,
|
|
totalPages: data?.pagination?.totalPages || 1,
|
|
isLoading,
|
|
error,
|
|
refetch,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Hook para buscar meus anúncios
|
|
* Atualiza automaticamente a cada 10 segundos
|
|
*/
|
|
export function useMyListings(status?: string) {
|
|
const queryParams = new URLSearchParams();
|
|
if (status) queryParams.set("status", status);
|
|
|
|
const { data, isLoading, error, refetch } = useQuery<ListingsResponse>({
|
|
queryKey: ["my-listings", status],
|
|
queryFn: async () => {
|
|
const res = await fetch(`/api/listings/my?${queryParams.toString()}`);
|
|
if (!res.ok) throw new Error("Erro ao buscar meus anúncios");
|
|
return res.json();
|
|
},
|
|
staleTime: 1000 * 10, // 10 segundos
|
|
refetchInterval: 1000 * 10, // Refetch a cada 10 segundos
|
|
refetchOnWindowFocus: true,
|
|
refetchOnReconnect: true,
|
|
enabled: true, // Sempre habilitado (autenticação é verificada no backend)
|
|
});
|
|
|
|
return {
|
|
listings: data?.listings || [],
|
|
isLoading,
|
|
error,
|
|
refetch,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Hook para invalidar cache de listings
|
|
*/
|
|
export function useInvalidateListings() {
|
|
const queryClient = useQueryClient();
|
|
|
|
const invalidate = () => {
|
|
queryClient.invalidateQueries({ queryKey: ["listings"] });
|
|
queryClient.invalidateQueries({ queryKey: ["my-listings"] });
|
|
};
|
|
|
|
return invalidate;
|
|
}
|
|
|