style: clean up code formatting and remove trailing whitespace

refactor: reorganize imports and fix type imports
This commit is contained in:
Evandro Fonseca Junior committed 2025-11-11 03:08:36 -03:00
1 parent d3704602fd
commit 47c04de6fe
232 files changed
+7140 -4798

No files matched your search

+11 -12
View File
@@ -1,7 +1,7 @@
import { NextRequest, NextResponse } from "next/server";
import { secureLogger } from "@/lib/secure-logger";
import { type NextRequest, NextResponse } from "next/server";
import { requireAuth } from "@/lib/auth/middleware";
import { getListingById, updateListing } from "@/lib/prisma/queries/listings";
import { secureLogger } from "@/lib/secure-logger";
/**
* POST /api/listings/:id/activate
@@ -9,7 +9,7 @@ import { getListingById, updateListing } from "@/lib/prisma/queries/listings";
*/
export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
{ params }: { params: Promise<{ id: string }> },
) {
try {
// Autenticação obrigatória
@@ -24,13 +24,13 @@ export async function POST(
const { id } = await params;
const listingId = parseInt(id, 10);
if (isNaN(listingId)) {
if (Number.isNaN(listingId)) {
return NextResponse.json(
{
success: false,
error: "ID de anúncio inválido",
},
{ status: 400 }
{ status: 400 },
);
}
@@ -43,7 +43,7 @@ export async function POST(
success: false,
error: "Anúncio não encontrado",
},
{ status: 404 }
{ status: 404 },
);
}
@@ -53,7 +53,7 @@ export async function POST(
success: false,
error: "Você não tem permissão para reativar este anúncio",
},
{ status: 403 }
{ status: 403 },
);
}
@@ -63,7 +63,7 @@ export async function POST(
success: false,
error: "Apenas anúncios pausados podem ser reativados",
},
{ status: 400 }
{ status: 400 },
);
}
@@ -78,7 +78,7 @@ export async function POST(
success: false,
error: "Erro ao reativar anúncio",
},
{ status: 500 }
{ status: 500 },
);
}
@@ -93,7 +93,7 @@ export async function POST(
listing: updated,
message: "Anúncio reativado com sucesso",
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao reativar anúncio", {
@@ -105,8 +105,7 @@ export async function POST(
success: false,
error: "Erro ao reativar anúncio",
},
{ status: 500 }
{ status: 500 },
);
}
}
+29 -18
View File
@@ -1,8 +1,8 @@
import { NextRequest, NextResponse } from "next/server";
import { secureLogger } from "@/lib/secure-logger";
import { type NextRequest, NextResponse } from "next/server";
import { requireAuth } from "@/lib/auth/middleware";
import { placeBid } from "@/lib/prisma/queries/listings";
import { createNotification } from "@/lib/prisma/queries/notifications";
import { secureLogger } from "@/lib/secure-logger";
/**
* POST /api/listings/[id]/bid
@@ -10,7 +10,7 @@ import { createNotification } from "@/lib/prisma/queries/notifications";
*/
export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
{ params }: { params: Promise<{ id: string }> },
) {
try {
const authResult = await requireAuth(request);
@@ -19,10 +19,10 @@ export async function POST(
const { id } = await params;
const listingId = parseInt(id, 10);
if (isNaN(listingId)) {
if (Number.isNaN(listingId)) {
return NextResponse.json(
{ success: false, error: "ID de anúncio inválido" },
{ status: 400 }
{ status: 400 },
);
}
@@ -31,34 +31,42 @@ export async function POST(
if (!amount || typeof amount !== "number" || amount <= 0) {
return NextResponse.json(
{ success: false, error: "Valor do lance é obrigatório e deve ser maior que zero" },
{ status: 400 }
{
success: false,
error: "Valor do lance é obrigatório e deve ser maior que zero",
},
{ status: 400 },
);
}
if (!payment_method || !["pix", "tc", "gp"].includes(payment_method)) {
return NextResponse.json(
{ success: false, error: "Método de pagamento inválido" },
{ status: 400 }
{ status: 400 },
);
}
// Colocar lance
const result = await placeBid(listingId, auth.userId, amount, payment_method);
const result = await placeBid(
listingId,
auth.userId,
amount,
payment_method,
);
if (!result.success) {
return NextResponse.json(
{ success: false, error: result.error },
{ status: 400 }
{ status: 400 },
);
}
// Criar notificação para o vendedor
await createNotification({
user_id: result.listing!.seller_id,
user_id: result.listing?.seller_id,
notification_type: "bid",
title: "Novo lance!",
message: `Novo lance de R$ ${amount.toFixed(2)} no item "${result.listing!.item_name}"`,
message: `Novo lance de R$ ${amount.toFixed(2)} no item "${result.listing?.item_name}"`,
related_id: listingId,
send_whatsapp: false,
});
@@ -69,7 +77,7 @@ export async function POST(
user_id: result.previousBidderId,
notification_type: "bid",
title: "Lance superado",
message: `Seu lance foi superado no item "${result.listing!.item_name}"`,
message: `Seu lance foi superado no item "${result.listing?.item_name}"`,
related_id: listingId,
send_whatsapp: false,
});
@@ -84,8 +92,12 @@ export async function POST(
metadata: {
bid_amount: amount,
payment_method: payment_method,
previous_bid: result.listing!.current_bid_amount ? Number(result.listing!.current_bid_amount) : null,
min_increment: result.listing!.min_bid_increment ? Number(result.listing!.min_bid_increment) : null,
previous_bid: result.listing?.current_bid_amount
? Number(result.listing?.current_bid_amount)
: null,
min_increment: result.listing?.min_bid_increment
? Number(result.listing?.min_bid_increment)
: null,
},
});
@@ -102,7 +114,7 @@ export async function POST(
listing: result.listing,
message: "Lance realizado com sucesso",
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao processar lance", {
@@ -112,8 +124,7 @@ export async function POST(
return NextResponse.json(
{ success: false, error: "Erro ao processar lance" },
{ status: 500 }
{ status: 500 },
);
}
}
+10 -11
View File
@@ -1,9 +1,9 @@
import { NextRequest, NextResponse } from "next/server";
import { secureLogger } from "@/lib/secure-logger";
import { type NextRequest, NextResponse } from "next/server";
import { requireAuth } from "@/lib/auth/middleware";
import { getListingById } from "@/lib/prisma/queries/listings";
import { prisma } from "@/lib/prisma/app";
import { getListingById } from "@/lib/prisma/queries/listings";
import { trackEvent } from "@/lib/prisma/queries/telemetry";
import { secureLogger } from "@/lib/secure-logger";
/**
* GET /api/listings/[id]/bids
@@ -11,7 +11,7 @@ import { trackEvent } from "@/lib/prisma/queries/telemetry";
*/
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
{ params }: { params: Promise<{ id: string }> },
) {
try {
const authResult = await requireAuth(request);
@@ -19,10 +19,10 @@ export async function GET(
const { id } = await params;
const listingId = parseInt(id, 10);
if (isNaN(listingId)) {
if (Number.isNaN(listingId)) {
return NextResponse.json(
{ success: false, error: "ID de anúncio inválido" },
{ status: 400 }
{ status: 400 },
);
}
@@ -31,14 +31,14 @@ export async function GET(
if (!listing) {
return NextResponse.json(
{ success: false, error: "Anúncio não encontrado" },
{ status: 404 }
{ status: 404 },
);
}
if (!listing.is_auction) {
return NextResponse.json(
{ success: false, error: "Este anúncio não é um leilão" },
{ status: 400 }
{ status: 400 },
);
}
@@ -92,7 +92,7 @@ export async function GET(
bids: formattedBids,
total: formattedBids.length,
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao buscar histórico de lances", {
@@ -102,8 +102,7 @@ export async function GET(
return NextResponse.json(
{ success: false, error: "Erro ao buscar histórico de lances" },
{ status: 500 }
{ status: 500 },
);
}
}
+21 -19
View File
@@ -1,8 +1,8 @@
import { NextRequest, NextResponse } from "next/server";
import { secureLogger } from "@/lib/secure-logger";
import { type NextRequest, NextResponse } from "next/server";
import { requireAuth } from "@/lib/auth/middleware";
import { getListingById } from "@/lib/prisma/queries/listings";
import { isFavorite, toggleFavorite } from "@/lib/prisma/queries/favorites";
import { getListingById } from "@/lib/prisma/queries/listings";
import { secureLogger } from "@/lib/secure-logger";
/**
* POST /api/listings/:id/favorite
@@ -10,7 +10,7 @@ import { isFavorite, toggleFavorite } from "@/lib/prisma/queries/favorites";
*/
export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
{ params }: { params: Promise<{ id: string }> },
) {
try {
// Autenticação obrigatória
@@ -25,13 +25,13 @@ export async function POST(
const { id } = await params;
const listingId = parseInt(id, 10);
if (isNaN(listingId)) {
if (Number.isNaN(listingId)) {
return NextResponse.json(
{
success: false,
error: "ID de anúncio inválido",
},
{ status: 400 }
{ status: 400 },
);
}
@@ -44,17 +44,20 @@ export async function POST(
success: false,
error: "Anúncio não encontrado",
},
{ status: 404 }
{ status: 404 },
);
}
// Toggle favorite
const favorited = await toggleFavorite(auth.userId, listingId);
secureLogger.info(`✅ Anúncio ${favorited ? "favoritado" : "desfavoritado"}`, {
listingId,
userId: auth.userId,
});
secureLogger.info(
`✅ Anúncio ${favorited ? "favoritado" : "desfavoritado"}`,
{
listingId,
userId: auth.userId,
},
);
return NextResponse.json(
{
@@ -62,7 +65,7 @@ export async function POST(
favorited,
message: favorited ? "Anúncio favoritado" : "Anúncio desfavoritado",
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao favoritar/desfavoritar anúncio", {
@@ -75,7 +78,7 @@ export async function POST(
success: false,
error: "Erro ao favoritar/desfavoritar anúncio",
},
{ status: 500 }
{ status: 500 },
);
}
}
@@ -86,7 +89,7 @@ export async function POST(
*/
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
{ params }: { params: Promise<{ id: string }> },
) {
try {
// Autenticação obrigatória
@@ -101,13 +104,13 @@ export async function GET(
const { id } = await params;
const listingId = parseInt(id, 10);
if (isNaN(listingId)) {
if (Number.isNaN(listingId)) {
return NextResponse.json(
{
success: false,
error: "ID de anúncio inválido",
},
{ status: 400 }
{ status: 400 },
);
}
@@ -118,7 +121,7 @@ export async function GET(
success: true,
favorited,
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao verificar favorito", {
@@ -130,8 +133,7 @@ export async function GET(
success: false,
error: "Erro ao verificar favorito",
},
{ status: 500 }
{ status: 500 },
);
}
}
@@ -1,17 +1,17 @@
import { NextRequest, NextResponse } from "next/server";
import { secureLogger } from "@/lib/secure-logger";
import { type NextRequest, NextResponse } from "next/server";
import { requireAuth } from "@/lib/auth/middleware";
import { connectMongoDB } from "@/lib/mongodb/connection";
import { Chat } from "@/lib/mongodb/models/Chat";
import { Message } from "@/lib/mongodb/models/Message";
import { getMainCharacter } from "@/lib/prisma/queries/characters";
import { getListingById } from "@/lib/prisma/queries/listings";
import { createNotification } from "@/lib/prisma/queries/notifications";
import {
getPurchaseIntentionById,
updatePurchaseIntentionStatus,
} from "@/lib/prisma/queries/purchase-intentions";
import { createNotification } from "@/lib/prisma/queries/notifications";
import { connectMongoDB } from "@/lib/mongodb/connection";
import { Chat } from "@/lib/mongodb/models/Chat";
import { Message } from "@/lib/mongodb/models/Message";
import { getUserById } from "@/lib/prisma/queries/users";
import { getMainCharacter } from "@/lib/prisma/queries/characters";
import { secureLogger } from "@/lib/secure-logger";
/**
* GET /api/listings/[id]/intentions/[intentionId]
@@ -19,7 +19,7 @@ import { getMainCharacter } from "@/lib/prisma/queries/characters";
*/
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string; intentionId: string }> }
{ params }: { params: Promise<{ id: string; intentionId: string }> },
) {
try {
const authResult = await requireAuth(request);
@@ -27,10 +27,10 @@ export async function GET(
const { intentionId: intentionIdParam } = await params;
const intentionId = parseInt(intentionIdParam, 10);
if (isNaN(intentionId)) {
if (Number.isNaN(intentionId)) {
return NextResponse.json(
{ success: false, error: "ID de intenção inválido" },
{ status: 400 }
{ status: 400 },
);
}
@@ -38,15 +38,21 @@ export async function GET(
if (!intention) {
return NextResponse.json(
{ success: false, error: "Intenção não encontrada" },
{ status: 404 }
{ status: 404 },
);
}
// Verificar permissões: vendedor ou comprador
if (intention.listing?.seller_id !== authResult.userId && intention.buyer_id !== authResult.userId) {
if (
intention.listing?.seller_id !== authResult.userId &&
intention.buyer_id !== authResult.userId
) {
return NextResponse.json(
{ success: false, error: "Você não tem permissão para ver esta intenção" },
{ status: 403 }
{
success: false,
error: "Você não tem permissão para ver esta intenção",
},
{ status: 403 },
);
}
@@ -55,7 +61,7 @@ export async function GET(
success: true,
intention,
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao buscar intenção", {
@@ -65,7 +71,7 @@ export async function GET(
return NextResponse.json(
{ success: false, error: "Erro ao buscar intenção" },
{ status: 500 }
{ status: 500 },
);
}
}
@@ -76,7 +82,7 @@ export async function GET(
*/
export async function PATCH(
request: NextRequest,
{ params }: { params: Promise<{ id: string; intentionId: string }> }
{ params }: { params: Promise<{ id: string; intentionId: string }> },
) {
try {
const authResult = await requireAuth(request);
@@ -84,10 +90,10 @@ export async function PATCH(
const { intentionId: intentionIdParam } = await params;
const intentionId = parseInt(intentionIdParam, 10);
if (isNaN(intentionId)) {
if (Number.isNaN(intentionId)) {
return NextResponse.json(
{ success: false, error: "ID de intenção inválido" },
{ status: 400 }
{ status: 400 },
);
}
@@ -100,8 +106,11 @@ export async function PATCH(
if (!status || !["accepted", "rejected"].includes(status)) {
return NextResponse.json(
{ success: false, error: "Status inválido. Use 'accepted' ou 'rejected'" },
{ status: 400 }
{
success: false,
error: "Status inválido. Use 'accepted' ou 'rejected'",
},
{ status: 400 },
);
}
@@ -110,15 +119,18 @@ export async function PATCH(
if (!intention) {
return NextResponse.json(
{ success: false, error: "Intenção não encontrada" },
{ status: 404 }
{ status: 404 },
);
}
// Verificar se o usuário é o vendedor
if (intention.listing?.seller_id !== authResult.userId) {
return NextResponse.json(
{ success: false, error: "Apenas o vendedor pode aceitar ou rejeitar intenções" },
{ status: 403 }
{
success: false,
error: "Apenas o vendedor pode aceitar ou rejeitar intenções",
},
{ status: 403 },
);
}
@@ -126,16 +138,20 @@ export async function PATCH(
if (intention.status !== "pending") {
return NextResponse.json(
{ success: false, error: `Esta intenção já foi ${intention.status}` },
{ status: 400 }
{ status: 400 },
);
}
// Verificar se o anúncio ainda está disponível (ativo ou em escrow)
const listing = await getListingById(intention.listing_id);
if (!listing || (listing.listing_status !== "active" && listing.listing_status !== "in_escrow")) {
if (
!listing ||
(listing.listing_status !== "active" &&
listing.listing_status !== "in_escrow")
) {
return NextResponse.json(
{ success: false, error: "Anúncio não está mais disponível" },
{ status: 400 }
{ status: 400 },
);
}
@@ -143,7 +159,7 @@ export async function PATCH(
const updatedIntention = await updatePurchaseIntentionStatus(
intentionId,
status,
sellerResponse
sellerResponse,
);
await sendSellerResponseToChat({
@@ -159,19 +175,23 @@ export async function PATCH(
user_id: intention.buyer_id,
notification_type: status === "accepted" ? "purchase" : "system",
title: status === "accepted" ? "Intenção aceita!" : "Intenção rejeitada",
message: status === "accepted"
? `O vendedor aceitou sua intenção de compra do item "${intention.listing?.item_name}"`
: `O vendedor rejeitou sua intenção de compra do item "${intention.listing?.item_name}"`,
message:
status === "accepted"
? `O vendedor aceitou sua intenção de compra do item "${intention.listing?.item_name}"`
: `O vendedor rejeitou sua intenção de compra do item "${intention.listing?.item_name}"`,
related_id: intention.listing_id,
send_whatsapp: false,
});
secureLogger.info(`✅ Intenção ${status === "accepted" ? "aceita" : "rejeitada"}`, {
userId: authResult.userId,
intentionId,
listingId: intention.listing_id,
buyerId: intention.buyer_id,
});
secureLogger.info(
`✅ Intenção ${status === "accepted" ? "aceita" : "rejeitada"}`,
{
userId: authResult.userId,
intentionId,
listingId: intention.listing_id,
buyerId: intention.buyer_id,
},
);
return NextResponse.json(
{
@@ -179,7 +199,7 @@ export async function PATCH(
intention: updatedIntention,
message: `Intenção ${status === "accepted" ? "aceita" : "rejeitada"} com sucesso`,
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao atualizar intenção", {
@@ -189,7 +209,7 @@ export async function PATCH(
return NextResponse.json(
{ success: false, error: "Erro ao atualizar intenção" },
{ status: 500 }
{ status: 500 },
);
}
}
@@ -202,7 +222,10 @@ async function sendSellerResponseToChat({
sellerId,
}: {
listing: Awaited<ReturnType<typeof getListingById>>;
intention: Exclude<Awaited<ReturnType<typeof getPurchaseIntentionById>>, null>;
intention: Exclude<
Awaited<ReturnType<typeof getPurchaseIntentionById>>,
null
>;
status: "accepted" | "rejected";
sellerResponse?: string;
sellerId: number;
@@ -225,12 +248,13 @@ async function sendSellerResponseToChat({
let chat = await Chat.findOne({ chat_id: chatId });
if (!chat) {
const [buyer, seller, buyerCharacter, sellerCharacter] = await Promise.all([
getUserById(intention.buyer_id),
getUserById(listing.seller_id),
getMainCharacter(intention.buyer_id),
getMainCharacter(listing.seller_id),
]);
const [buyer, seller, buyerCharacter, sellerCharacter] =
await Promise.all([
getUserById(intention.buyer_id),
getUserById(listing.seller_id),
getMainCharacter(intention.buyer_id),
getMainCharacter(listing.seller_id),
]);
chat = new Chat({
chat_id: chatId,
@@ -284,4 +308,3 @@ async function sendSellerResponseToChat({
});
}
}
+67 -43
View File
@@ -1,15 +1,14 @@
import { NextRequest, NextResponse } from "next/server";
import { secureLogger } from "@/lib/secure-logger";
import { type NextRequest, NextResponse } from "next/server";
import { requireAuth } from "@/lib/auth/middleware";
import { getListingById } from "@/lib/prisma/queries/listings";
import { createNotification } from "@/lib/prisma/queries/notifications";
import {
createPurchaseIntention,
getPurchaseIntentionsByListing,
hasPendingIntention,
getPendingIntentionByBuyerAndListing,
getPurchaseIntentionsByListing,
} from "@/lib/prisma/queries/purchase-intentions";
import { createNotification } from "@/lib/prisma/queries/notifications";
import { trackEvent } from "@/lib/prisma/queries/telemetry";
import { secureLogger } from "@/lib/secure-logger";
/**
* POST /api/listings/[id]/intentions
@@ -17,7 +16,7 @@ import { trackEvent } from "@/lib/prisma/queries/telemetry";
*/
export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
{ params }: { params: Promise<{ id: string }> },
) {
try {
const authResult = await requireAuth(request);
@@ -26,10 +25,10 @@ export async function POST(
const { id } = await params;
const listingId = parseInt(id, 10);
if (isNaN(listingId)) {
if (Number.isNaN(listingId)) {
return NextResponse.json(
{ success: false, error: "ID de anúncio inválido" },
{ status: 400 }
{ status: 400 },
);
}
@@ -41,10 +40,13 @@ export async function POST(
custom_offer_currency,
} = body;
if (!payment_method || !["pix", "tibia_coins", "gold_coins", "trade"].includes(payment_method)) {
if (
!payment_method ||
!["pix", "tibia_coins", "gold_coins", "trade"].includes(payment_method)
) {
return NextResponse.json(
{ success: false, error: "Método de pagamento inválido" },
{ status: 400 }
{ status: 400 },
);
}
@@ -53,15 +55,19 @@ export async function POST(
if (!listing) {
return NextResponse.json(
{ success: false, error: "Anúncio não encontrado" },
{ status: 404 }
{ status: 404 },
);
}
// Validar se não é o vendedor
if (listing.seller_id === auth.userId) {
return NextResponse.json(
{ success: false, error: "Você não pode criar uma intenção de compra para seu próprio anúncio" },
{ status: 403 }
{
success: false,
error:
"Você não pode criar uma intenção de compra para seu próprio anúncio",
},
{ status: 403 },
);
}
@@ -69,15 +75,18 @@ export async function POST(
if (listing.listing_status !== "active") {
return NextResponse.json(
{ success: false, error: "Anúncio não está disponível para compra" },
{ status: 400 }
{ status: 400 },
);
}
// Validar se é leilão (leilões não podem ter intenções, apenas lances)
if (listing.is_auction) {
return NextResponse.json(
{ success: false, error: "Este item está em leilão. Use a funcionalidade de lance." },
{ status: 400 }
{
success: false,
error: "Este item está em leilão. Use a funcionalidade de lance.",
},
{ status: 400 },
);
}
@@ -95,7 +104,7 @@ export async function POST(
error: `Método de pagamento "${payment_method}" não está disponível para este anúncio`,
available_methods: availableMethods,
},
{ status: 400 }
{ status: 400 },
);
}
@@ -107,9 +116,10 @@ export async function POST(
return NextResponse.json(
{
success: false,
error: "Ofertas personalizadas só são permitidas para métodos monetários (PIX, Tibia Coins ou Gold Coins).",
error:
"Ofertas personalizadas só são permitidas para métodos monetários (PIX, Tibia Coins ou Gold Coins).",
},
{ status: 400 }
{ status: 400 },
);
}
@@ -118,14 +128,16 @@ export async function POST(
return NextResponse.json(
{
success: false,
error: "Valor da oferta personalizada deve ser numérico e maior que zero.",
error:
"Valor da oferta personalizada deve ser numérico e maior que zero.",
},
{ status: 400 }
{ status: 400 },
);
}
normalizedOfferCurrency =
custom_offer_currency && ["pix", "tibia_coins", "gold_coins"].includes(custom_offer_currency)
custom_offer_currency &&
["pix", "tibia_coins", "gold_coins"].includes(custom_offer_currency)
? custom_offer_currency
: payment_method;
@@ -136,7 +148,10 @@ export async function POST(
}
// Verificar se já existe uma intenção pendente
const existingIntention = await getPendingIntentionByBuyerAndListing(listingId, auth.userId);
const existingIntention = await getPendingIntentionByBuyerAndListing(
listingId,
auth.userId,
);
if (existingIntention) {
// Se já existe e ainda pode trocar o método
if (existingIntention.payment_method_change_count < 1) {
@@ -144,23 +159,27 @@ export async function POST(
return NextResponse.json(
{
success: false,
error: "Você já possui uma intenção de compra pendente para este anúncio",
error:
"Você já possui uma intenção de compra pendente para este anúncio",
existing_intention_id: existingIntention.intention_id,
can_change_payment_method: true,
payment_method_change_count: existingIntention.payment_method_change_count,
message: "Use o endpoint PATCH /api/purchase-intentions/[intentionId]/payment-method para trocar o método de pagamento",
payment_method_change_count:
existingIntention.payment_method_change_count,
message:
"Use o endpoint PATCH /api/purchase-intentions/[intentionId]/payment-method para trocar o método de pagamento",
},
{ status: 400 }
{ status: 400 },
);
} else {
// Já atingiu o limite de trocas
return NextResponse.json(
{
success: false,
error: "Você já possui uma intenção de compra pendente para este anúncio e atingiu o limite de trocas de método de pagamento",
error:
"Você já possui uma intenção de compra pendente para este anúncio e atingiu o limite de trocas de método de pagamento",
existing_intention_id: existingIntention.intention_id,
},
{ status: 400 }
{ status: 400 },
);
}
}
@@ -197,7 +216,9 @@ export async function POST(
payment_method,
listing_price_pix: listing.price_pix ? Number(listing.price_pix) : null,
listing_price_tc: listing.price_tibia_coins || null,
listing_price_gp: listing.price_gold_coins ? Number(listing.price_gold_coins) : null,
listing_price_gp: listing.price_gold_coins
? Number(listing.price_gold_coins)
: null,
custom_offer_amount: normalizedOfferValue,
custom_offer_currency: normalizedOfferCurrency,
},
@@ -214,9 +235,10 @@ export async function POST(
{
success: true,
intention,
message: "Intenção de compra criada com sucesso. O vendedor será notificado.",
message:
"Intenção de compra criada com sucesso. O vendedor será notificado.",
},
{ status: 201 }
{ status: 201 },
);
} catch (error) {
secureLogger.error("❌ Erro ao criar intenção de compra", {
@@ -226,7 +248,7 @@ export async function POST(
return NextResponse.json(
{ success: false, error: "Erro ao criar intenção de compra" },
{ status: 500 }
{ status: 500 },
);
}
}
@@ -237,19 +259,19 @@ export async function POST(
*/
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
{ params }: { params: Promise<{ id: string }> },
) {
try {
const authResult = await requireAuth(request);
if (authResult instanceof NextResponse) return authResult;
const auth = authResult;
const { id } = await params;
const listingId = parseInt(id, 10);
if (isNaN(listingId)) {
if (Number.isNaN(listingId)) {
return NextResponse.json(
{ success: false, error: "ID de anúncio inválido" },
{ status: 400 }
{ status: 400 },
);
}
@@ -258,15 +280,18 @@ export async function GET(
if (!listing) {
return NextResponse.json(
{ success: false, error: "Anúncio não encontrado" },
{ status: 404 }
{ status: 404 },
);
}
// Apenas o vendedor pode ver as intenções
if (listing.seller_id !== auth.userId) {
return NextResponse.json(
{ success: false, error: "Você não tem permissão para ver as intenções deste anúncio" },
{ status: 403 }
{
success: false,
error: "Você não tem permissão para ver as intenções deste anúncio",
},
{ status: 403 },
);
}
@@ -297,7 +322,7 @@ export async function GET(
intentions,
count: intentions.length,
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao buscar intenções de compra", {
@@ -307,8 +332,7 @@ export async function GET(
return NextResponse.json(
{ success: false, error: "Erro ao buscar intenções de compra" },
{ status: 500 }
{ status: 500 },
);
}
}
+36 -21
View File
@@ -1,7 +1,7 @@
import { NextRequest, NextResponse } from "next/server";
import { secureLogger } from "@/lib/secure-logger";
import { type NextRequest, NextResponse } from "next/server";
import { requireAuth } from "@/lib/auth/middleware";
import { getListingById, updateListing } from "@/lib/prisma/queries/listings";
import { getListingById } from "@/lib/prisma/queries/listings";
import { secureLogger } from "@/lib/secure-logger";
/**
* POST /api/listings/:id/mark-sold
@@ -9,7 +9,7 @@ import { getListingById, updateListing } from "@/lib/prisma/queries/listings";
*/
export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
{ params }: { params: Promise<{ id: string }> },
) {
try {
// Autenticação obrigatória
@@ -24,13 +24,13 @@ export async function POST(
const { id } = await params;
const listingId = parseInt(id, 10);
if (isNaN(listingId)) {
if (Number.isNaN(listingId)) {
return NextResponse.json(
{
success: false,
error: "ID de anúncio inválido",
},
{ status: 400 }
{ status: 400 },
);
}
@@ -43,7 +43,7 @@ export async function POST(
success: false,
error: "Anúncio não encontrado",
},
{ status: 404 }
{ status: 404 },
);
}
@@ -53,18 +53,22 @@ export async function POST(
success: false,
error: "Você não tem permissão para marcar este anúncio como vendido",
},
{ status: 403 }
{ status: 403 },
);
}
// Verificar se o anúncio pode ser marcado como vendido
if (listing.listing_status !== "active" && listing.listing_status !== "in_escrow") {
if (
listing.listing_status !== "active" &&
listing.listing_status !== "in_escrow"
) {
return NextResponse.json(
{
success: false,
error: "Apenas anúncios ativos ou em escrow podem ser marcados como vendidos",
error:
"Apenas anúncios ativos ou em escrow podem ser marcados como vendidos",
},
{ status: 400 }
{ status: 400 },
);
}
@@ -90,12 +94,24 @@ export async function POST(
// Converter campos para formato esperado
const updated = {
...updatedListing,
price_pix: updatedListing.price_pix ? Number(updatedListing.price_pix) : null,
current_bid_amount: updatedListing.current_bid_amount ? Number(updatedListing.current_bid_amount) : null,
min_bid_increment: updatedListing.min_bid_increment ? Number(updatedListing.min_bid_increment) : null,
initial_price_pix: updatedListing.initial_price_pix ? Number(updatedListing.initial_price_pix) : null,
price_gold_coins: updatedListing.price_gold_coins ? Number(updatedListing.price_gold_coins) : null,
initial_price_gold_coins: updatedListing.initial_price_gold_coins ? Number(updatedListing.initial_price_gold_coins) : null,
price_pix: updatedListing.price_pix
? Number(updatedListing.price_pix)
: null,
current_bid_amount: updatedListing.current_bid_amount
? Number(updatedListing.current_bid_amount)
: null,
min_bid_increment: updatedListing.min_bid_increment
? Number(updatedListing.min_bid_increment)
: null,
initial_price_pix: updatedListing.initial_price_pix
? Number(updatedListing.initial_price_pix)
: null,
price_gold_coins: updatedListing.price_gold_coins
? Number(updatedListing.price_gold_coins)
: null,
initial_price_gold_coins: updatedListing.initial_price_gold_coins
? Number(updatedListing.initial_price_gold_coins)
: null,
seller_character_name: character?.character_name || null,
};
@@ -105,7 +121,7 @@ export async function POST(
success: false,
error: "Erro ao marcar anúncio como vendido",
},
{ status: 500 }
{ status: 500 },
);
}
@@ -120,7 +136,7 @@ export async function POST(
listing: updated,
message: "Anúncio marcado como vendido com sucesso",
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao marcar anúncio como vendido", {
@@ -132,8 +148,7 @@ export async function POST(
success: false,
error: "Erro ao marcar anúncio como vendido",
},
{ status: 500 }
{ status: 500 },
);
}
}
+11 -12
View File
@@ -1,7 +1,7 @@
import { NextRequest, NextResponse } from "next/server";
import { secureLogger } from "@/lib/secure-logger";
import { type NextRequest, NextResponse } from "next/server";
import { requireAuth } from "@/lib/auth/middleware";
import { getListingById, updateListing } from "@/lib/prisma/queries/listings";
import { secureLogger } from "@/lib/secure-logger";
/**
* POST /api/listings/:id/pause
@@ -9,7 +9,7 @@ import { getListingById, updateListing } from "@/lib/prisma/queries/listings";
*/
export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
{ params }: { params: Promise<{ id: string }> },
) {
try {
// Autenticação obrigatória
@@ -24,13 +24,13 @@ export async function POST(
const { id } = await params;
const listingId = parseInt(id, 10);
if (isNaN(listingId)) {
if (Number.isNaN(listingId)) {
return NextResponse.json(
{
success: false,
error: "ID de anúncio inválido",
},
{ status: 400 }
{ status: 400 },
);
}
@@ -43,7 +43,7 @@ export async function POST(
success: false,
error: "Anúncio não encontrado",
},
{ status: 404 }
{ status: 404 },
);
}
@@ -53,7 +53,7 @@ export async function POST(
success: false,
error: "Você não tem permissão para pausar este anúncio",
},
{ status: 403 }
{ status: 403 },
);
}
@@ -63,7 +63,7 @@ export async function POST(
success: false,
error: "Apenas anúncios ativos podem ser pausados",
},
{ status: 400 }
{ status: 400 },
);
}
@@ -79,7 +79,7 @@ export async function POST(
success: false,
error: "Erro ao pausar anúncio",
},
{ status: 500 }
{ status: 500 },
);
}
@@ -94,7 +94,7 @@ export async function POST(
listing: updated,
message: "Anúncio pausado com sucesso",
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao pausar anúncio", {
@@ -106,8 +106,7 @@ export async function POST(
success: false,
error: "Erro ao pausar anúncio",
},
{ status: 500 }
{ status: 500 },
);
}
}
+44 -30
View File
@@ -1,14 +1,13 @@
import { NextRequest, NextResponse } from "next/server";
import { secureLogger } from "@/lib/secure-logger";
import { type NextRequest, NextResponse } from "next/server";
import { requireAuth } from "@/lib/auth/middleware";
import { getListingById } from "@/lib/prisma/queries/listings";
import { createNotification } from "@/lib/prisma/queries/notifications";
import {
createPurchaseIntention,
hasPendingIntention,
getPendingIntentionByBuyerAndListing,
} from "@/lib/prisma/queries/purchase-intentions";
import { trackEvent } from "@/lib/prisma/queries/telemetry";
import { secureLogger } from "@/lib/secure-logger";
/**
* POST /api/listings/[id]/purchase
@@ -16,7 +15,7 @@ import { trackEvent } from "@/lib/prisma/queries/telemetry";
*/
export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
{ params }: { params: Promise<{ id: string }> },
) {
try {
const authResult = await requireAuth(request);
@@ -25,10 +24,10 @@ export async function POST(
const { id } = await params;
const listingId = parseInt(id, 10);
if (isNaN(listingId)) {
if (Number.isNaN(listingId)) {
return NextResponse.json(
{ success: false, error: "ID de anúncio inválido" },
{ status: 400 }
{ status: 400 },
);
}
@@ -43,7 +42,7 @@ export async function POST(
if (!payment_method) {
return NextResponse.json(
{ success: false, error: "Método de pagamento é obrigatório" },
{ status: 400 }
{ status: 400 },
);
}
@@ -52,7 +51,7 @@ export async function POST(
if (!listing) {
return NextResponse.json(
{ success: false, error: "Anúncio não encontrado" },
{ status: 404 }
{ status: 404 },
);
}
@@ -60,7 +59,7 @@ export async function POST(
if (listing.seller_id === auth.userId) {
return NextResponse.json(
{ success: false, error: "Você não pode comprar seu próprio anúncio" },
{ status: 403 }
{ status: 403 },
);
}
@@ -68,15 +67,18 @@ export async function POST(
if (listing.listing_status !== "active") {
return NextResponse.json(
{ success: false, error: "Anúncio não está disponível para compra" },
{ status: 400 }
{ status: 400 },
);
}
// Validar se é leilão (leilões não podem ser comprados diretamente, apenas com lances)
if (listing.is_auction) {
return NextResponse.json(
{ success: false, error: "Este item está em leilão. Use a funcionalidade de lance." },
{ status: 400 }
{
success: false,
error: "Este item está em leilão. Use a funcionalidade de lance.",
},
{ status: 400 },
);
}
@@ -99,7 +101,7 @@ export async function POST(
error: `Método de pagamento "${payment_method}" não está disponível para este anúncio`,
available_methods: availableMethods,
},
{ status: 400 }
{ status: 400 },
);
}
@@ -111,9 +113,10 @@ export async function POST(
return NextResponse.json(
{
success: false,
error: "Ofertas personalizadas só são permitidas para métodos monetários (PIX, Tibia Coins ou Gold Coins).",
error:
"Ofertas personalizadas só são permitidas para métodos monetários (PIX, Tibia Coins ou Gold Coins).",
},
{ status: 400 }
{ status: 400 },
);
}
@@ -122,14 +125,16 @@ export async function POST(
return NextResponse.json(
{
success: false,
error: "Valor da oferta personalizada deve ser numérico e maior que zero.",
error:
"Valor da oferta personalizada deve ser numérico e maior que zero.",
},
{ status: 400 }
{ status: 400 },
);
}
normalizedOfferCurrency =
custom_offer_currency && ["pix", "tibia_coins", "gold_coins"].includes(custom_offer_currency)
custom_offer_currency &&
["pix", "tibia_coins", "gold_coins"].includes(custom_offer_currency)
? custom_offer_currency
: normalizedMethod;
@@ -140,7 +145,10 @@ export async function POST(
}
// Verificar se já existe uma intenção pendente
const existingIntention = await getPendingIntentionByBuyerAndListing(listingId, auth.userId);
const existingIntention = await getPendingIntentionByBuyerAndListing(
listingId,
auth.userId,
);
if (existingIntention) {
// Se já existe e ainda pode trocar o método
if (existingIntention.payment_method_change_count < 1) {
@@ -148,23 +156,27 @@ export async function POST(
return NextResponse.json(
{
success: false,
error: "Você já possui uma intenção de compra pendente para este anúncio",
error:
"Você já possui uma intenção de compra pendente para este anúncio",
existing_intention_id: existingIntention.intention_id,
can_change_payment_method: true,
payment_method_change_count: existingIntention.payment_method_change_count,
message: "Use o endpoint PATCH /api/purchase-intentions/[intentionId]/payment-method para trocar o método de pagamento",
payment_method_change_count:
existingIntention.payment_method_change_count,
message:
"Use o endpoint PATCH /api/purchase-intentions/[intentionId]/payment-method para trocar o método de pagamento",
},
{ status: 400 }
{ status: 400 },
);
} else {
// Já atingiu o limite de trocas
return NextResponse.json(
{
success: false,
error: "Você já possui uma intenção de compra pendente para este anúncio e atingiu o limite de trocas de método de pagamento",
error:
"Você já possui uma intenção de compra pendente para este anúncio e atingiu o limite de trocas de método de pagamento",
existing_intention_id: existingIntention.intention_id,
},
{ status: 400 }
{ status: 400 },
);
}
}
@@ -201,7 +213,9 @@ export async function POST(
payment_method: normalizedMethod,
listing_price_pix: listing.price_pix ? Number(listing.price_pix) : null,
listing_price_tc: listing.price_tibia_coins || null,
listing_price_gp: listing.price_gold_coins ? Number(listing.price_gold_coins) : null,
listing_price_gp: listing.price_gold_coins
? Number(listing.price_gold_coins)
: null,
custom_offer_amount: normalizedOfferValue,
custom_offer_currency: normalizedOfferCurrency,
},
@@ -218,9 +232,10 @@ export async function POST(
{
success: true,
intention,
message: "Intenção de compra criada com sucesso. O vendedor será notificado.",
message:
"Intenção de compra criada com sucesso. O vendedor será notificado.",
},
{ status: 201 }
{ status: 201 },
);
} catch (error) {
secureLogger.error("❌ Erro ao criar intenção de compra", {
@@ -230,8 +245,7 @@ export async function POST(
return NextResponse.json(
{ success: false, error: "Erro ao criar intenção de compra" },
{ status: 500 }
{ status: 500 },
);
}
}
+58 -39
View File
@@ -1,12 +1,12 @@
import { NextRequest, NextResponse } from "next/server";
import { secureLogger } from "@/lib/secure-logger";
import { requireAuth, optionalAuth } from "@/lib/auth/middleware";
import { type NextRequest, NextResponse } from "next/server";
import { optionalAuth, requireAuth } from "@/lib/auth/middleware";
import {
deleteListing,
getListingById,
updateListing,
deleteListing,
} from "@/lib/prisma/queries/listings";
import { hasPendingIntention } from "@/lib/prisma/queries/purchase-intentions";
import { secureLogger } from "@/lib/secure-logger";
import { updateListingSchema } from "@/lib/validation-schemas";
/**
@@ -15,20 +15,20 @@ import { updateListingSchema } from "@/lib/validation-schemas";
*/
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
{ params }: { params: Promise<{ id: string }> },
) {
try {
const auth = await optionalAuth(request);
const { id } = await params;
const listingId = parseInt(id, 10);
if (isNaN(listingId)) {
if (Number.isNaN(listingId)) {
return NextResponse.json(
{
success: false,
error: "ID de anúncio inválido",
},
{ status: 400 }
{ status: 400 },
);
}
@@ -40,14 +40,13 @@ export async function GET(
success: false,
error: "Anúncio não encontrado",
},
{ status: 404 }
{ status: 404 },
);
}
const hasPendingForUser =
auth && auth.userId
? await hasPendingIntention(listingId, auth.userId)
: false;
const hasPendingForUser = auth?.userId
? await hasPendingIntention(listingId, auth.userId)
: false;
return NextResponse.json(
{
@@ -57,7 +56,7 @@ export async function GET(
has_pending_intention_for_current_user: hasPendingForUser,
},
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao buscar anúncio", {
@@ -70,7 +69,7 @@ export async function GET(
success: false,
error: "Erro ao buscar anúncio",
},
{ status: 500 }
{ status: 500 },
);
}
}
@@ -81,7 +80,7 @@ export async function GET(
*/
export async function PATCH(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
{ params }: { params: Promise<{ id: string }> },
) {
try {
// Autenticação obrigatória
@@ -96,13 +95,13 @@ export async function PATCH(
const { id } = await params;
const listingId = parseInt(id, 10);
if (isNaN(listingId)) {
if (Number.isNaN(listingId)) {
return NextResponse.json(
{
success: false,
error: "ID de anúncio inválido",
},
{ status: 400 }
{ status: 400 },
);
}
@@ -115,7 +114,7 @@ export async function PATCH(
success: false,
error: "Anúncio não encontrado",
},
{ status: 404 }
{ status: 404 },
);
}
@@ -125,7 +124,7 @@ export async function PATCH(
success: false,
error: "Você não tem permissão para editar este anúncio",
},
{ status: 403 }
{ status: 403 },
);
}
@@ -146,7 +145,7 @@ export async function PATCH(
error: "Dados de entrada inválidos",
details: errors,
},
{ status: 400 }
{ status: 400 },
);
}
@@ -159,16 +158,37 @@ export async function PATCH(
price_tibia_coins?: number;
price_gold_coins?: number;
description?: string;
listing_status?: "active" | "sold" | "cancelled" | "in_escrow" | "expired";
listing_status?:
| "active"
| "sold"
| "cancelled"
| "in_escrow"
| "expired";
current_bid_amount?: number;
current_bidder_id?: number;
} = {
...(validatedData.quantity !== undefined && { quantity: validatedData.quantity }),
...(validatedData.price_pix !== null && validatedData.price_pix !== undefined && { price_pix: validatedData.price_pix }),
...(validatedData.price_tibia_coins !== null && validatedData.price_tibia_coins !== undefined && { price_tibia_coins: validatedData.price_tibia_coins }),
...(validatedData.price_gold_coins !== null && validatedData.price_gold_coins !== undefined && { price_gold_coins: validatedData.price_gold_coins }),
...(validatedData.description !== null && validatedData.description !== undefined && { description: validatedData.description }),
...(validatedData.listing_status !== undefined && { listing_status: validatedData.listing_status }),
...(validatedData.quantity !== undefined && {
quantity: validatedData.quantity,
}),
...(validatedData.price_pix !== null &&
validatedData.price_pix !== undefined && {
price_pix: validatedData.price_pix,
}),
...(validatedData.price_tibia_coins !== null &&
validatedData.price_tibia_coins !== undefined && {
price_tibia_coins: validatedData.price_tibia_coins,
}),
...(validatedData.price_gold_coins !== null &&
validatedData.price_gold_coins !== undefined && {
price_gold_coins: validatedData.price_gold_coins,
}),
...(validatedData.description !== null &&
validatedData.description !== undefined && {
description: validatedData.description,
}),
...(validatedData.listing_status !== undefined && {
listing_status: validatedData.listing_status,
}),
};
// Atualizar anúncio
@@ -180,7 +200,7 @@ export async function PATCH(
success: false,
error: "Erro ao atualizar anúncio",
},
{ status: 500 }
{ status: 500 },
);
}
@@ -195,7 +215,7 @@ export async function PATCH(
success: true,
listing: updatedListing,
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao atualizar anúncio", {
@@ -208,7 +228,7 @@ export async function PATCH(
success: false,
error: "Erro ao atualizar anúncio",
},
{ status: 500 }
{ status: 500 },
);
}
}
@@ -219,7 +239,7 @@ export async function PATCH(
*/
export async function DELETE(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
{ params }: { params: Promise<{ id: string }> },
) {
try {
// Autenticação obrigatória
@@ -234,13 +254,13 @@ export async function DELETE(
const { id } = await params;
const listingId = parseInt(id, 10);
if (isNaN(listingId)) {
if (Number.isNaN(listingId)) {
return NextResponse.json(
{
success: false,
error: "ID de anúncio inválido",
},
{ status: 400 }
{ status: 400 },
);
}
@@ -253,7 +273,7 @@ export async function DELETE(
success: false,
error: "Anúncio não encontrado",
},
{ status: 404 }
{ status: 404 },
);
}
@@ -263,7 +283,7 @@ export async function DELETE(
success: false,
error: "Você não tem permissão para cancelar este anúncio",
},
{ status: 403 }
{ status: 403 },
);
}
@@ -276,7 +296,7 @@ export async function DELETE(
success: false,
error: "Erro ao cancelar anúncio",
},
{ status: 500 }
{ status: 500 },
);
}
@@ -291,7 +311,7 @@ export async function DELETE(
success: true,
message: "Anúncio cancelado com sucesso",
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao cancelar anúncio", {
@@ -304,8 +324,7 @@ export async function DELETE(
success: false,
error: "Erro ao cancelar anúncio",
},
{ status: 500 }
{ status: 500 },
);
}
}
+14 -12
View File
@@ -1,23 +1,23 @@
import { NextRequest, NextResponse } from "next/server";
import { secureLogger } from "@/lib/secure-logger";
import { getListingById } from "@/lib/prisma/queries/listings";
import { type NextRequest, NextResponse } from "next/server";
import { getMainCharacterByUserId } from "@/lib/prisma/queries/characters";
import { getListingById } from "@/lib/prisma/queries/listings";
import { secureLogger } from "@/lib/secure-logger";
/**
* GET /api/listings/[id]/seller
* Retorna informações do vendedor (nome do personagem)
*/
export async function GET(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
_request: NextRequest,
{ params }: { params: Promise<{ id: string }> },
) {
try {
const { id } = await params;
const listingId = parseInt(id, 10);
if (isNaN(listingId)) {
if (Number.isNaN(listingId)) {
return NextResponse.json(
{ success: false, error: "ID de anúncio inválido" },
{ status: 400 }
{ status: 400 },
);
}
@@ -25,12 +25,15 @@ export async function GET(
if (!listing) {
return NextResponse.json(
{ success: false, error: "Anúncio não encontrado" },
{ status: 404 }
{ status: 404 },
);
}
// Buscar personagem principal do vendedor no servidor do listing
const character = await getMainCharacterByUserId(listing.seller_id, listing.server_name);
const character = await getMainCharacterByUserId(
listing.seller_id,
listing.server_name,
);
return NextResponse.json(
{
@@ -41,7 +44,7 @@ export async function GET(
server_name: listing.server_name,
},
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao buscar informações do vendedor", {
@@ -51,8 +54,7 @@ export async function GET(
return NextResponse.json(
{ success: false, error: "Erro ao buscar informações do vendedor" },
{ status: 500 }
{ status: 500 },
);
}
}
+8 -9
View File
@@ -1,6 +1,6 @@
import { NextRequest, NextResponse } from "next/server";
import { secureLogger } from "@/lib/secure-logger";
import { type NextRequest, NextResponse } from "next/server";
import { incrementViews } from "@/lib/prisma/queries/listings";
import { secureLogger } from "@/lib/secure-logger";
/**
* POST /api/listings/[id]/views
@@ -8,20 +8,20 @@ import { incrementViews } from "@/lib/prisma/queries/listings";
* Não requer autenticação (público)
*/
export async function POST(
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
_request: NextRequest,
{ params }: { params: Promise<{ id: string }> },
) {
try {
const { id } = await params;
const listingId = parseInt(id, 10);
if (isNaN(listingId)) {
if (Number.isNaN(listingId)) {
return NextResponse.json(
{
success: false,
error: "ID de anúncio inválido",
},
{ status: 400 }
{ status: 400 },
);
}
@@ -33,7 +33,7 @@ export async function POST(
success: true,
message: "View incrementada",
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
secureLogger.error("❌ Erro ao incrementar views", {
@@ -46,8 +46,7 @@ export async function POST(
success: false,
error: "Erro ao incrementar views",
},
{ status: 500 }
{ status: 500 },
);
}
}