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,253 @@
|
||||
/**
|
||||
* Queries de Purchase Intentions usando Prisma
|
||||
*/
|
||||
|
||||
import { prisma } from "../app";
|
||||
|
||||
export type PurchaseIntentionStatus = "pending" | "accepted" | "rejected" | "expired" | "completed";
|
||||
export type PaymentMethod = "pix" | "tibia_coins" | "gold_coins" | "trade";
|
||||
|
||||
export interface CreatePurchaseIntentionData {
|
||||
listing_id: number;
|
||||
buyer_id: number;
|
||||
payment_method: PaymentMethod;
|
||||
buyer_message?: string;
|
||||
expires_at?: Date;
|
||||
}
|
||||
|
||||
export interface PurchaseIntention {
|
||||
intention_id: number;
|
||||
listing_id: number;
|
||||
buyer_id: number;
|
||||
payment_method: string;
|
||||
status: PurchaseIntentionStatus;
|
||||
buyer_message: string | null;
|
||||
seller_response: string | null;
|
||||
created_at: Date;
|
||||
updated_at: Date;
|
||||
expires_at: Date | null;
|
||||
accepted_at: Date | null;
|
||||
rejected_at: Date | null;
|
||||
// Relacionamentos
|
||||
listing?: {
|
||||
listing_id: number;
|
||||
item_name: string;
|
||||
seller_id: number;
|
||||
};
|
||||
buyer?: {
|
||||
user_id: number;
|
||||
username: string;
|
||||
email: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Cria uma nova intenção de compra
|
||||
*/
|
||||
export async function createPurchaseIntention(
|
||||
data: CreatePurchaseIntentionData
|
||||
): Promise<PurchaseIntention> {
|
||||
return await prisma.purchaseIntention.create({
|
||||
data: {
|
||||
listing_id: data.listing_id,
|
||||
buyer_id: data.buyer_id,
|
||||
payment_method: data.payment_method,
|
||||
buyer_message: data.buyer_message || null,
|
||||
expires_at: data.expires_at || null,
|
||||
status: "pending",
|
||||
},
|
||||
include: {
|
||||
listing: {
|
||||
select: {
|
||||
listing_id: true,
|
||||
item_name: true,
|
||||
seller_id: true,
|
||||
},
|
||||
},
|
||||
buyer: {
|
||||
select: {
|
||||
user_id: true,
|
||||
username: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}) as PurchaseIntention;
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca intenções de um anúncio específico
|
||||
*/
|
||||
export async function getPurchaseIntentionsByListing(
|
||||
listingId: number,
|
||||
filters: { status?: PurchaseIntentionStatus; limit?: number } = {}
|
||||
): Promise<PurchaseIntention[]> {
|
||||
const { status, limit = 50 } = filters;
|
||||
|
||||
const where: any = { listing_id: listingId };
|
||||
if (status) {
|
||||
where.status = status;
|
||||
}
|
||||
|
||||
return await prisma.purchaseIntention.findMany({
|
||||
where,
|
||||
include: {
|
||||
listing: {
|
||||
select: {
|
||||
listing_id: true,
|
||||
item_name: true,
|
||||
seller_id: true,
|
||||
},
|
||||
},
|
||||
buyer: {
|
||||
select: {
|
||||
user_id: true,
|
||||
username: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: { created_at: "desc" },
|
||||
take: limit,
|
||||
}) as PurchaseIntention[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca intenções de um comprador
|
||||
*/
|
||||
export async function getPurchaseIntentionsByBuyer(
|
||||
buyerId: number,
|
||||
filters: { status?: PurchaseIntentionStatus; limit?: number } = {}
|
||||
): Promise<PurchaseIntention[]> {
|
||||
const { status, limit = 50 } = filters;
|
||||
|
||||
const where: any = { buyer_id: buyerId };
|
||||
if (status) {
|
||||
where.status = status;
|
||||
}
|
||||
|
||||
return await prisma.purchaseIntention.findMany({
|
||||
where,
|
||||
include: {
|
||||
listing: {
|
||||
select: {
|
||||
listing_id: true,
|
||||
item_name: true,
|
||||
seller_id: true,
|
||||
},
|
||||
},
|
||||
buyer: {
|
||||
select: {
|
||||
user_id: true,
|
||||
username: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: { created_at: "desc" },
|
||||
take: limit,
|
||||
}) as PurchaseIntention[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca uma intenção específica por ID
|
||||
*/
|
||||
export async function getPurchaseIntentionById(
|
||||
intentionId: number
|
||||
): Promise<PurchaseIntention | null> {
|
||||
return await prisma.purchaseIntention.findUnique({
|
||||
where: { intention_id: intentionId },
|
||||
include: {
|
||||
listing: {
|
||||
select: {
|
||||
listing_id: true,
|
||||
item_name: true,
|
||||
seller_id: true,
|
||||
},
|
||||
},
|
||||
buyer: {
|
||||
select: {
|
||||
user_id: true,
|
||||
username: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}) as PurchaseIntention | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atualiza o status de uma intenção
|
||||
*/
|
||||
export async function updatePurchaseIntentionStatus(
|
||||
intentionId: number,
|
||||
status: PurchaseIntentionStatus,
|
||||
sellerResponse?: string
|
||||
): Promise<PurchaseIntention> {
|
||||
const updateData: any = {
|
||||
status,
|
||||
updated_at: new Date(),
|
||||
};
|
||||
|
||||
if (status === "accepted") {
|
||||
updateData.accepted_at = new Date();
|
||||
updateData.seller_response = sellerResponse || null;
|
||||
} else if (status === "rejected") {
|
||||
updateData.rejected_at = new Date();
|
||||
updateData.seller_response = sellerResponse || null;
|
||||
} else if (sellerResponse) {
|
||||
updateData.seller_response = sellerResponse;
|
||||
}
|
||||
|
||||
return await prisma.purchaseIntention.update({
|
||||
where: { intention_id: intentionId },
|
||||
data: updateData,
|
||||
include: {
|
||||
listing: {
|
||||
select: {
|
||||
listing_id: true,
|
||||
item_name: true,
|
||||
seller_id: true,
|
||||
},
|
||||
},
|
||||
buyer: {
|
||||
select: {
|
||||
user_id: true,
|
||||
username: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}) as PurchaseIntention;
|
||||
}
|
||||
|
||||
/**
|
||||
* Conta intenções pendentes de um anúncio
|
||||
*/
|
||||
export async function getPendingIntentionsCount(listingId: number): Promise<number> {
|
||||
return await prisma.purchaseIntention.count({
|
||||
where: {
|
||||
listing_id: listingId,
|
||||
status: "pending",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifica se já existe uma intenção pendente para um listing+buyer
|
||||
*/
|
||||
export async function hasPendingIntention(
|
||||
listingId: number,
|
||||
buyerId: number
|
||||
): Promise<boolean> {
|
||||
const count = await prisma.purchaseIntention.count({
|
||||
where: {
|
||||
listing_id: listingId,
|
||||
buyer_id: buyerId,
|
||||
status: "pending",
|
||||
},
|
||||
});
|
||||
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user