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:
Evandro Fonseca Junior committed 2025-11-07 17:25:51 -03:00
1 parent f35fee944d
commit 7f42def478
55 files changed
+4906 -95

No files matched your search

+15
View File
@@ -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
*/
-6
View File
@@ -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: {
+121
View File
@@ -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);
}