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:
Evandro Fonseca Junior committed 2025-11-05 01:58:03 -03:00
1 parent 55eebde0ba
commit ab37b477df
106 files changed
+15261 -301

No files matched your search

+91 -4
View File
@@ -250,7 +250,8 @@ export const characterSchema = z.object({
// Schema para criar anúncio (listing)
export const createListingSchema = z.object({
item_id: z.number().int().positive("ID do item deve ser positivo"),
item_id: z.number().int().positive("ID do item deve ser positivo").optional(), // ID legado (SQLite) - opcional
item_id_unified: z.number().int().positive("ID unificado do item deve ser positivo").optional(), // ID unificado da tabela items - preferido
item_name: z
.string()
.min(1, "Nome do item é obrigatório")
@@ -296,13 +297,62 @@ export const createListingSchema = z.object({
.optional()
.nullable()
.transform((val) => val?.trim() || null),
}).refine(
// Campos para troca por item
trade_item_id: z
.number()
.int()
.positive("ID do item de troca deve ser positivo")
.optional()
.nullable(),
trade_item_name: z
.string()
.min(1, "Nome do item de troca é obrigatório se trade_item_id for fornecido")
.max(255, "Nome do item de troca deve ter no máximo 255 caracteres")
.optional()
.nullable()
.transform((name) => name?.trim() || null),
trade_item_quantity: z
.number()
.int()
.positive("Quantidade do item de troca deve ser maior que zero")
.optional()
.nullable()
.default(1),
})
.refine(
(data) => {
// Pelo menos um preço deve ser fornecido
// Pelo menos um ID (item_id ou item_id_unified) deve ser fornecido
if (!data.item_id && !data.item_id_unified) {
return false;
}
return true;
},
{
message: "Pelo menos um ID do item (item_id ou item_id_unified) deve ser fornecido",
path: ["item_id"],
}
)
.refine(
(data) => {
// Se trade_item_id for fornecido, trade_item_name também deve ser
if (data.trade_item_id && !data.trade_item_name) {
return false;
}
return true;
},
{
message: "Nome do item de troca é obrigatório quando ID é fornecido",
path: ["trade_item_name"],
}
)
.refine(
(data) => {
// Pelo menos um preço ou troca por item deve ser fornecido
return (
data.price_pix !== null ||
data.price_tibia_coins !== null ||
data.price_gold_coins !== null
data.price_gold_coins !== null ||
data.trade_item_id !== null
);
},
{
@@ -354,6 +404,41 @@ export const bidSchema = z.object({
.nullable(),
});
// ============================================
// SCHEMAS DE TELEMETRIA
// ============================================
// Schema para evento de telemetria
export const telemetryEventSchema = z.object({
event_type: z.enum([
"ad_view",
"ad_click",
"ad_exit",
"search",
"filter",
"favorite",
"unfavorite",
"purchase",
"purchase_intention_created",
"purchase_intention_viewed",
"bid_placed",
"bid_viewed",
"seller_profile_viewed",
"inquiry",
"page_view",
"price_change",
]),
ad_id: z.number().int().positive().optional().nullable(),
session_id: z.string().optional().nullable(),
metadata: z.any().optional(),
});
// Schema para batch de eventos (inclui session_id no nível do batch)
export const telemetryBatchSchema = z.object({
events: z.array(telemetryEventSchema).min(1).max(100), // Limite de 100 eventos por batch
session_id: z.string().optional().nullable(), // session_id pode estar no nível do batch
});
// Type exports para uso no código
export type CreateDonationInput = z.infer<typeof createDonationSchema>;
export type VerifyStatusInput = z.infer<typeof verifyStatusSchema>;
@@ -365,3 +450,5 @@ export type CharacterInput = z.infer<typeof characterSchema>;
export type CreateListingInput = z.infer<typeof createListingSchema>;
export type UpdateListingInput = z.infer<typeof updateListingSchema>;
export type BidInput = z.infer<typeof bidSchema>;
export type TelemetryEventInput = z.infer<typeof telemetryEventSchema>;
export type TelemetryBatchInput = z.infer<typeof telemetryBatchSchema>;