feat: implement market page with QueryProvider and dynamic listings
- 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)
This commit is contained in:
1 parent
55eebde0ba
commit
ab37b477df
106 files changed
+15261
-301
No files matched your search
@@ -0,0 +1,133 @@
|
||||
"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;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user