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
@@ -6,6 +6,7 @@ import {
|
||||
createPurchaseIntention,
|
||||
getPurchaseIntentionsByListing,
|
||||
hasPendingIntention,
|
||||
getPendingIntentionByBuyerAndListing,
|
||||
} from "@/lib/prisma/queries/purchase-intentions";
|
||||
import { createNotification } from "@/lib/prisma/queries/notifications";
|
||||
import { trackEvent } from "@/lib/prisma/queries/telemetry";
|
||||
@@ -94,12 +95,33 @@ export async function POST(
|
||||
}
|
||||
|
||||
// Verificar se já existe uma intenção pendente
|
||||
const alreadyHasPending = await hasPendingIntention(listingId, auth.userId);
|
||||
if (alreadyHasPending) {
|
||||
return NextResponse.json(
|
||||
{ success: false, error: "Você já possui uma intenção de compra pendente para este anúncio" },
|
||||
{ status: 400 }
|
||||
);
|
||||
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) {
|
||||
// Permite atualizar o método via endpoint específico
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
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",
|
||||
},
|
||||
{ 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",
|
||||
existing_intention_id: existingIntention.intention_id,
|
||||
},
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Criar intenção de compra
|
||||
|
||||
@@ -6,6 +6,7 @@ import { createNotification } from "@/lib/prisma/queries/notifications";
|
||||
import {
|
||||
createPurchaseIntention,
|
||||
hasPendingIntention,
|
||||
getPendingIntentionByBuyerAndListing,
|
||||
} from "@/lib/prisma/queries/purchase-intentions";
|
||||
import { trackEvent } from "@/lib/prisma/queries/telemetry";
|
||||
|
||||
@@ -98,12 +99,33 @@ export async function POST(
|
||||
}
|
||||
|
||||
// Verificar se já existe uma intenção pendente
|
||||
const alreadyHasPending = await hasPendingIntention(listingId, auth.userId);
|
||||
if (alreadyHasPending) {
|
||||
return NextResponse.json(
|
||||
{ success: false, error: "Você já possui uma intenção de compra pendente para este anúncio" },
|
||||
{ status: 400 }
|
||||
);
|
||||
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) {
|
||||
// Permite atualizar o método via endpoint específico
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
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",
|
||||
},
|
||||
{ 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",
|
||||
existing_intention_id: existingIntention.intention_id,
|
||||
},
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Criar intenção de compra ao invés de mudar status diretamente
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
updateListing,
|
||||
deleteListing,
|
||||
} from "@/lib/prisma/queries/listings";
|
||||
import { hasPendingIntention } from "@/lib/prisma/queries/purchase-intentions";
|
||||
import { updateListingSchema } from "@/lib/validation-schemas";
|
||||
|
||||
/**
|
||||
@@ -17,6 +18,7 @@ export async function GET(
|
||||
{ params }: { params: Promise<{ id: string }> }
|
||||
) {
|
||||
try {
|
||||
const auth = await optionalAuth(request);
|
||||
const { id } = await params;
|
||||
const listingId = parseInt(id, 10);
|
||||
|
||||
@@ -42,10 +44,18 @@ export async function GET(
|
||||
);
|
||||
}
|
||||
|
||||
const hasPendingForUser =
|
||||
auth && auth.userId
|
||||
? await hasPendingIntention(listingId, auth.userId)
|
||||
: false;
|
||||
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
listing,
|
||||
listing: {
|
||||
...listing,
|
||||
has_pending_intention_for_current_user: hasPendingForUser,
|
||||
},
|
||||
},
|
||||
{ status: 200 }
|
||||
);
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
getActiveListings,
|
||||
} from "@/lib/prisma/queries/listings";
|
||||
import { isServerActive } from "@/lib/prisma/queries/servers";
|
||||
import { getPendingIntentionListingIdsForBuyer } from "@/lib/prisma/queries/purchase-intentions";
|
||||
|
||||
/**
|
||||
* GET /api/listings
|
||||
@@ -20,6 +21,7 @@ import { isServerActive } from "@/lib/prisma/queries/servers";
|
||||
*/
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const auth = await optionalAuth(request);
|
||||
const { searchParams } = new URL(request.url);
|
||||
|
||||
const filters = {
|
||||
@@ -65,10 +67,26 @@ export async function GET(request: NextRequest) {
|
||||
? await getListings(filters)
|
||||
: await getActiveListings(filters);
|
||||
|
||||
let listingsResponse = listingsData.listings;
|
||||
|
||||
if (auth && listingsResponse.length > 0) {
|
||||
const listingIds = listingsResponse.map((listing) => listing.listing_id);
|
||||
const pendingListingIds = await getPendingIntentionListingIdsForBuyer(
|
||||
auth.userId,
|
||||
listingIds
|
||||
);
|
||||
const pendingSet = new Set(pendingListingIds);
|
||||
|
||||
listingsResponse = listingsResponse.map((listing) => ({
|
||||
...listing,
|
||||
has_pending_intention_for_current_user: pendingSet.has(listing.listing_id),
|
||||
}));
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: true,
|
||||
listings: listingsData.listings,
|
||||
listings: listingsResponse,
|
||||
pagination: {
|
||||
page: filters.page,
|
||||
pageSize: filters.pageSize,
|
||||
|
||||
Reference in new issue
Block a user