Files
pagodera/lib/hooks/use-listings.ts
2025-11-11 03:08:36 -03:00

134 lines
3.8 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;
has_pending_intention_for_current_user?: boolean;
}
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;
}