feat(market): add Minha Intenções tab with panel, hook, and badge
- Introduced "Minhas Intenções" tab visible only to logged-in users. - Integrated MyPurchaseIntentionsPanel and useMyPurchaseIntentions hook. - Added tab badge showing count of pending intentions. - Extended session API to include user’s main character for downstream features.
This commit is contained in:
1 parent
f35fee944d
commit
7f42def478
55 files changed
+4906
-95
No files matched your search
+1
-4
@@ -12,10 +12,7 @@ const globalForPrisma = globalThis as unknown as {
|
||||
export const prisma =
|
||||
globalForPrisma.prisma ??
|
||||
new PrismaClient({
|
||||
log:
|
||||
process.env.NODE_ENV === "development"
|
||||
? ["query", "error", "warn"]
|
||||
: ["error"],
|
||||
log: ["error"], // Apenas erros, sem queries
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
|
||||
@@ -69,6 +69,21 @@ export async function getUserCharacters(userId: number): Promise<Character[]> {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca personagem principal de um usuário
|
||||
*/
|
||||
export async function getMainCharacter(userId: number): Promise<Character | null> {
|
||||
return await prisma.userCharacter.findFirst({
|
||||
where: {
|
||||
user_id: userId,
|
||||
is_main: true,
|
||||
},
|
||||
orderBy: [
|
||||
{ created_at: "asc" },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca personagem principal de um usuário em um servidor específico
|
||||
*/
|
||||
|
||||
@@ -36,7 +36,6 @@ export interface SearchItemsParams {
|
||||
* Busca um item por ID unificado
|
||||
*/
|
||||
export async function getItemById(itemId: number): Promise<Item | null> {
|
||||
// @ts-expect-error - Prisma Client pode não ter sido gerado ainda
|
||||
const item = await prisma.item.findUnique({
|
||||
where: { item_id: itemId },
|
||||
});
|
||||
@@ -56,7 +55,6 @@ export async function getItemById(itemId: number): Promise<Item | null> {
|
||||
* Busca um item por nome (exato ou similar)
|
||||
*/
|
||||
export async function getItemByName(itemName: string): Promise<Item | null> {
|
||||
// @ts-expect-error - Prisma Client pode não ter sido gerado ainda
|
||||
const item = await prisma.item.findFirst({
|
||||
where: {
|
||||
item_name: {
|
||||
@@ -91,7 +89,6 @@ export async function searchItems(
|
||||
pageSize = 24,
|
||||
} = params;
|
||||
|
||||
// @ts-expect-error - ItemWhereInput pode não estar disponível se Prisma Client não foi gerado
|
||||
const where: Prisma.ItemWhereInput = {};
|
||||
|
||||
if (q) {
|
||||
@@ -109,10 +106,8 @@ export async function searchItems(
|
||||
where.rarity = rarity;
|
||||
}
|
||||
|
||||
// @ts-expect-error - Prisma Client pode não ter sido gerado ainda
|
||||
const total = await prisma.item.count({ where });
|
||||
|
||||
// @ts-expect-error - Prisma Client pode não ter sido gerado ainda
|
||||
const items = await prisma.item.findMany({
|
||||
where,
|
||||
orderBy: { item_name: "asc" },
|
||||
@@ -138,7 +133,6 @@ export async function getItemBySource(
|
||||
sourceTableName: string,
|
||||
sourceTableId: number
|
||||
): Promise<Item | null> {
|
||||
// @ts-expect-error - Prisma Client pode não ter sido gerado ainda
|
||||
const item = await prisma.item.findUnique({
|
||||
where: {
|
||||
source_table_name_source_table_id: {
|
||||
|
||||
@@ -20,6 +20,7 @@ export interface PurchaseIntention {
|
||||
listing_id: number;
|
||||
buyer_id: number;
|
||||
payment_method: string;
|
||||
payment_method_change_count: number;
|
||||
status: PurchaseIntentionStatus;
|
||||
buyer_message: string | null;
|
||||
seller_response: string | null;
|
||||
@@ -251,3 +252,123 @@ export async function hasPendingIntention(
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Busca intenção pendente de um comprador para um listing específico
|
||||
*/
|
||||
export async function getPendingIntentionByBuyerAndListing(
|
||||
listingId: number,
|
||||
buyerId: number
|
||||
): Promise<PurchaseIntention | null> {
|
||||
return await prisma.purchaseIntention.findFirst({
|
||||
where: {
|
||||
listing_id: listingId,
|
||||
buyer_id: buyerId,
|
||||
status: "pending",
|
||||
},
|
||||
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",
|
||||
},
|
||||
}) as PurchaseIntention | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atualiza o método de pagamento de uma intenção
|
||||
*/
|
||||
export async function updatePurchaseIntentionPaymentMethod(
|
||||
intentionId: number,
|
||||
newPaymentMethod: PaymentMethod
|
||||
): Promise<PurchaseIntention> {
|
||||
// Buscar intenção atual
|
||||
const intention = await prisma.purchaseIntention.findUnique({
|
||||
where: { intention_id: intentionId },
|
||||
});
|
||||
|
||||
if (!intention) {
|
||||
throw new Error("Intenção não encontrada");
|
||||
}
|
||||
|
||||
// Verificar se pode trocar (máximo 1 troca)
|
||||
if (intention.payment_method_change_count >= 1) {
|
||||
throw new Error("Você já atingiu o limite de trocas de método de pagamento");
|
||||
}
|
||||
|
||||
// Verificar se o novo método é diferente
|
||||
if (intention.payment_method === newPaymentMethod) {
|
||||
throw new Error("O novo método de pagamento deve ser diferente do atual");
|
||||
}
|
||||
|
||||
// Atualizar
|
||||
return await prisma.purchaseIntention.update({
|
||||
where: { intention_id: intentionId },
|
||||
data: {
|
||||
payment_method: newPaymentMethod,
|
||||
payment_method_change_count: intention.payment_method_change_count + 1,
|
||||
updated_at: new Date(),
|
||||
},
|
||||
include: {
|
||||
listing: {
|
||||
select: {
|
||||
listing_id: true,
|
||||
item_name: true,
|
||||
seller_id: true,
|
||||
},
|
||||
},
|
||||
buyer: {
|
||||
select: {
|
||||
user_id: true,
|
||||
username: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}) as PurchaseIntention;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retorna os IDs de anúncios com intenções pendentes para um comprador
|
||||
*/
|
||||
export async function getPendingIntentionListingIdsForBuyer(
|
||||
buyerId: number,
|
||||
listingIds: number[]
|
||||
): Promise<number[]> {
|
||||
if (listingIds.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const intentions = await prisma.purchaseIntention.findMany({
|
||||
where: {
|
||||
buyer_id: buyerId,
|
||||
status: "pending",
|
||||
listing_id: {
|
||||
in: listingIds,
|
||||
},
|
||||
},
|
||||
select: {
|
||||
listing_id: true,
|
||||
},
|
||||
});
|
||||
|
||||
const uniqueIds = new Set<number>();
|
||||
intentions.forEach((intention) => {
|
||||
uniqueIds.add(intention.listing_id);
|
||||
});
|
||||
|
||||
return Array.from(uniqueIds);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user