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,798 @@
|
||||
# 📋 Plano Detalhado: Melhorias do Marketplace
|
||||
|
||||
## 🎯 Objetivo Geral
|
||||
|
||||
Implementar um sistema completo de intenções de compra, melhorias na interface de gerenciamento de anúncios, sistema de notificações visual, exibição de vendedores, sistema de lances e telemetria completa.
|
||||
|
||||
---
|
||||
|
||||
## 📊 Análise de Requisitos
|
||||
|
||||
### Requisitos Explícitos
|
||||
|
||||
1. **Sistema de Intenção de Compra**
|
||||
- Compra não remove item do mercado
|
||||
- Criar "intenção de compra" com método de pagamento escolhido
|
||||
- Notificar vendedor sobre cada intenção
|
||||
|
||||
2. **Melhorias na Página "Meus Anúncios"**
|
||||
- Exibir dados de compradores interessados
|
||||
- Mostrar informações de cada intenção de compra
|
||||
|
||||
3. **Ícone de Notificações**
|
||||
- Badge com contador de notificações não lidas
|
||||
- Visual no header/navbar
|
||||
|
||||
4. **Exibição de Vendedor**
|
||||
- Nome do vendedor nos cards
|
||||
- Avatar/imagem do vendedor (preparar para integração futura)
|
||||
|
||||
5. **Sistema de Lances (Bids)**
|
||||
- Permitir que usuários deem lances
|
||||
- Atualizar valor do item conforme lances
|
||||
- Integração completa no frontend
|
||||
|
||||
6. **Telemetria Completa**
|
||||
- Rastrear lances (valor, horário, usuário)
|
||||
- Acessos por dia/hora
|
||||
- Anúncios mais clicados
|
||||
- Análises de comportamento
|
||||
|
||||
### Requisitos Implícitos
|
||||
|
||||
- Sistema deve ser escalável
|
||||
- Performance não deve degradar com muitos dados
|
||||
- Interface responsiva e intuitiva
|
||||
- Notificações em tempo real (ou polling eficiente)
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ Arquivos Afetados
|
||||
|
||||
### Backend (API + Queries)
|
||||
|
||||
1. **Novos Arquivos:**
|
||||
- `lib/db/migrations/015_add_purchase_intentions.sql`
|
||||
- `lib/prisma/queries/purchase-intentions.ts`
|
||||
- `app/api/listings/[id]/intentions/route.ts`
|
||||
- `app/api/listings/[id]/intentions/[intentionId]/route.ts`
|
||||
- `app/api/notifications/unread-count/route.ts`
|
||||
|
||||
2. **Arquivos Modificados:**
|
||||
- `app/api/listings/[id]/purchase/route.ts` (mudar para criar intenção)
|
||||
- `lib/prisma/queries/listings.ts` (adicionar queries relacionadas)
|
||||
- `lib/prisma/queries/notifications.ts` (melhorar queries)
|
||||
- `lib/prisma/queries/telemetry.ts` (adicionar eventos de lance)
|
||||
|
||||
### Frontend (Components)
|
||||
|
||||
1. **Novos Arquivos:**
|
||||
- `components/notifications/NotificationBell.tsx`
|
||||
- `components/notifications/NotificationDropdown.tsx`
|
||||
- `components/marketplace/PurchaseIntentionModal.tsx`
|
||||
- `components/marketplace/MyAdsIntentionList.tsx`
|
||||
- `components/marketplace/SellerInfo.tsx`
|
||||
|
||||
2. **Arquivos Modificados:**
|
||||
- `components/marketplace/PurchaseModal.tsx` (mudar para intenção)
|
||||
- `components/marketplace/MyAdsPanel.tsx` (adicionar seção de intenções)
|
||||
- `components/marketplace/AdCard.tsx` (adicionar SellerInfo, melhorar bids)
|
||||
- `components/Header.tsx` (adicionar NotificationBell)
|
||||
- `components/marketplace/BidModal.tsx` (melhorar UI e telemetria)
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ Estrutura de Banco de Dados
|
||||
|
||||
### Nova Tabela: `purchase_intentions`
|
||||
|
||||
```sql
|
||||
CREATE TABLE purchase_intentions (
|
||||
intention_id SERIAL PRIMARY KEY,
|
||||
listing_id INTEGER NOT NULL REFERENCES listings(listing_id) ON DELETE CASCADE,
|
||||
buyer_id INTEGER NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
|
||||
payment_method VARCHAR(20) NOT NULL CHECK (payment_method IN ('pix', 'tibia_coins', 'gold_coins', 'trade')),
|
||||
status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'accepted', 'rejected', 'expired', 'completed')),
|
||||
buyer_message TEXT,
|
||||
seller_response TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
expires_at TIMESTAMP,
|
||||
accepted_at TIMESTAMP,
|
||||
rejected_at TIMESTAMP,
|
||||
|
||||
UNIQUE(listing_id, buyer_id, status) WHERE status = 'pending',
|
||||
INDEX idx_listing_id (listing_id),
|
||||
INDEX idx_buyer_id (buyer_id),
|
||||
INDEX idx_status (status),
|
||||
INDEX idx_created_at (created_at)
|
||||
);
|
||||
```
|
||||
|
||||
**Campos:**
|
||||
- `intention_id`: ID único
|
||||
- `listing_id`: Anúncio relacionado
|
||||
- `buyer_id`: Comprador interessado
|
||||
- `payment_method`: Método de pagamento escolhido
|
||||
- `status`: Estado da intenção (pending, accepted, rejected, expired, completed)
|
||||
- `buyer_message`: Mensagem opcional do comprador
|
||||
- `seller_response`: Resposta do vendedor
|
||||
- `expires_at`: Quando a intenção expira (opcional)
|
||||
- Timestamps para rastreamento
|
||||
|
||||
---
|
||||
|
||||
## 📝 Plano de Implementação
|
||||
|
||||
## FASE 1: Sistema de Intenções de Compra (Backend)
|
||||
|
||||
### Etapa 1.1: Migração de Banco de Dados
|
||||
|
||||
**Arquivo:** `lib/db/migrations/015_add_purchase_intentions.sql`
|
||||
|
||||
```sql
|
||||
-- Migration 015: Sistema de Intenções de Compra
|
||||
-- Criado em: 2025-01-29
|
||||
|
||||
CREATE TABLE IF NOT EXISTS purchase_intentions (
|
||||
intention_id SERIAL PRIMARY KEY,
|
||||
listing_id INTEGER NOT NULL REFERENCES listings(listing_id) ON DELETE CASCADE,
|
||||
buyer_id INTEGER NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
|
||||
payment_method VARCHAR(20) NOT NULL CHECK (payment_method IN ('pix', 'tibia_coins', 'gold_coins', 'trade')),
|
||||
status VARCHAR(20) DEFAULT 'pending' CHECK (status IN ('pending', 'accepted', 'rejected', 'expired', 'completed')),
|
||||
buyer_message TEXT,
|
||||
seller_response TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
expires_at TIMESTAMP,
|
||||
accepted_at TIMESTAMP,
|
||||
rejected_at TIMESTAMP
|
||||
);
|
||||
|
||||
-- Índices para performance
|
||||
CREATE INDEX IF NOT EXISTS idx_purchase_intentions_listing_id ON purchase_intentions(listing_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_purchase_intentions_buyer_id ON purchase_intentions(buyer_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_purchase_intentions_status ON purchase_intentions(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_purchase_intentions_created_at ON purchase_intentions(created_at DESC);
|
||||
|
||||
-- Constraint: apenas uma intenção pendente por listing+buyer
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_purchase_intentions_unique_pending
|
||||
ON purchase_intentions(listing_id, buyer_id)
|
||||
WHERE status = 'pending';
|
||||
|
||||
-- Trigger para atualizar updated_at
|
||||
CREATE OR REPLACE FUNCTION update_purchase_intentions_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = CURRENT_TIMESTAMP;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trigger_update_purchase_intentions_updated_at
|
||||
BEFORE UPDATE ON purchase_intentions
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_purchase_intentions_updated_at();
|
||||
|
||||
-- Comentários para documentação
|
||||
COMMENT ON TABLE purchase_intentions IS 'Intenções de compra de anúncios - permite múltiplos compradores interessados';
|
||||
COMMENT ON COLUMN purchase_intentions.status IS 'pending: aguardando resposta do vendedor, accepted: aceita, rejected: rejeitada, expired: expirada, completed: concluída';
|
||||
```
|
||||
|
||||
**Tarefas:**
|
||||
- [ ] Criar arquivo de migração
|
||||
- [ ] Adicionar à lista de migrations em `run-migrations.ts`
|
||||
- [ ] Executar migração
|
||||
- [ ] Atualizar schema Prisma
|
||||
|
||||
---
|
||||
|
||||
### Etapa 1.2: Schema Prisma
|
||||
|
||||
**Arquivo:** `prisma/schema.prisma`
|
||||
|
||||
```prisma
|
||||
model PurchaseIntention {
|
||||
intention_id Int @id @default(autoincrement())
|
||||
listing_id Int
|
||||
buyer_id Int
|
||||
payment_method String @db.VarChar(20)
|
||||
status String @default("pending") @db.VarChar(20)
|
||||
buyer_message String? @db.Text
|
||||
seller_response String? @db.Text
|
||||
created_at DateTime @default(now())
|
||||
updated_at DateTime @updatedAt
|
||||
expires_at DateTime?
|
||||
accepted_at DateTime?
|
||||
rejected_at DateTime?
|
||||
|
||||
listing Listing @relation(fields: [listing_id], references: [listing_id], onDelete: Cascade)
|
||||
buyer User @relation("BuyerIntentions", fields: [buyer_id], references: [user_id], onDelete: Cascade)
|
||||
|
||||
@@index([listing_id])
|
||||
@@index([buyer_id])
|
||||
@@index([status])
|
||||
@@index([created_at(sort: Desc)])
|
||||
@@unique([listing_id, buyer_id], where: { status: "pending" })
|
||||
@@map("purchase_intentions")
|
||||
}
|
||||
```
|
||||
|
||||
**Também atualizar:**
|
||||
- Adicionar relação `purchaseIntentions` no model `Listing`
|
||||
- Adicionar relação `purchaseIntentions` no model `User` (como `BuyerIntentions`)
|
||||
|
||||
---
|
||||
|
||||
### Etapa 1.3: Queries Prisma
|
||||
|
||||
**Arquivo:** `lib/prisma/queries/purchase-intentions.ts`
|
||||
|
||||
**Funções a criar:**
|
||||
1. `createPurchaseIntention(data)` - Criar intenção
|
||||
2. `getPurchaseIntentionsByListing(listingId, filters)` - Listar intenções de um anúncio
|
||||
3. `getPurchaseIntentionsByBuyer(buyerId, filters)` - Listar intenções de um comprador
|
||||
4. `getPurchaseIntentionById(intentionId)` - Buscar intenção específica
|
||||
5. `updatePurchaseIntentionStatus(intentionId, status, sellerResponse)` - Atualizar status
|
||||
6. `getPendingIntentionsCount(listingId)` - Contar intenções pendentes
|
||||
|
||||
**Detalhamento:**
|
||||
|
||||
```typescript
|
||||
export interface CreatePurchaseIntentionData {
|
||||
listing_id: number;
|
||||
buyer_id: number;
|
||||
payment_method: "pix" | "tibia_coins" | "gold_coins" | "trade";
|
||||
buyer_message?: string;
|
||||
expires_at?: Date;
|
||||
}
|
||||
|
||||
export interface PurchaseIntention {
|
||||
intention_id: number;
|
||||
listing_id: number;
|
||||
buyer_id: number;
|
||||
payment_method: string;
|
||||
status: "pending" | "accepted" | "rejected" | "expired" | "completed";
|
||||
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;
|
||||
buyer?: User;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Etapa 1.4: API Routes
|
||||
|
||||
**Arquivo:** `app/api/listings/[id]/intentions/route.ts`
|
||||
|
||||
**Endpoints:**
|
||||
- `POST /api/listings/[id]/intentions` - Criar intenção de compra
|
||||
- `GET /api/listings/[id]/intentions` - Listar intenções (apenas vendedor)
|
||||
|
||||
**Arquivo:** `app/api/listings/[id]/intentions/[intentionId]/route.ts`
|
||||
|
||||
**Endpoints:**
|
||||
- `GET /api/listings/[id]/intentions/[intentionId]` - Buscar intenção
|
||||
- `PATCH /api/listings/[id]/intentions/[intentionId]` - Atualizar status (aceitar/rejeitar)
|
||||
|
||||
**Arquivo:** `app/api/listings/[id]/purchase/route.ts` (MODIFICAR)
|
||||
|
||||
**Mudança:**
|
||||
- Ao invés de mudar `listing_status` para "sold", criar uma `PurchaseIntention`
|
||||
- Notificar vendedor sobre nova intenção
|
||||
|
||||
---
|
||||
|
||||
## FASE 2: Sistema de Notificações Visual
|
||||
|
||||
### Etapa 2.1: API de Contagem de Notificações Não Lidas
|
||||
|
||||
**Arquivo:** `app/api/notifications/unread-count/route.ts`
|
||||
|
||||
```typescript
|
||||
// GET /api/notifications/unread-count
|
||||
// Retorna: { count: number }
|
||||
```
|
||||
|
||||
**Já existe função `getUnreadCount()` em `lib/prisma/queries/notifications.ts` - apenas criar rota**
|
||||
|
||||
---
|
||||
|
||||
### Etapa 2.2: Componente NotificationBell
|
||||
|
||||
**Arquivo:** `components/notifications/NotificationBell.tsx`
|
||||
|
||||
**Funcionalidades:**
|
||||
- Badge com contador de não lidas
|
||||
- Ícone de sino (Bell do lucide-react)
|
||||
- Dropdown ao clicar (usar `NotificationDropdown`)
|
||||
- Polling automático a cada 30 segundos
|
||||
- Animações quando há novas notificações
|
||||
|
||||
**Props:**
|
||||
```typescript
|
||||
interface NotificationBellProps {
|
||||
userId?: number;
|
||||
className?: string;
|
||||
}
|
||||
```
|
||||
|
||||
**Estado:**
|
||||
- `unreadCount: number`
|
||||
- `isOpen: boolean`
|
||||
- `notifications: Notification[]`
|
||||
|
||||
---
|
||||
|
||||
### Etapa 2.3: Componente NotificationDropdown
|
||||
|
||||
**Arquivo:** `components/notifications/NotificationDropdown.tsx`
|
||||
|
||||
**Funcionalidades:**
|
||||
- Lista de notificações recentes (últimas 10)
|
||||
- Link "Ver todas" para página completa
|
||||
- Marcar como lida ao clicar
|
||||
- Diferentes tipos de notificação (compra, lance, etc.)
|
||||
- Timestamps formatados
|
||||
|
||||
---
|
||||
|
||||
### Etapa 2.4: Integrar no Header
|
||||
|
||||
**Arquivo:** `components/Header.tsx`
|
||||
|
||||
**Mudanças:**
|
||||
- Adicionar `NotificationBell` no navbar
|
||||
- Posicionar ao lado do menu de usuário
|
||||
- Apenas exibir se usuário estiver logado
|
||||
|
||||
---
|
||||
|
||||
## FASE 3: Exibição de Vendedor
|
||||
|
||||
### Etapa 3.1: Componente SellerInfo
|
||||
|
||||
**Arquivo:** `components/marketplace/SellerInfo.tsx`
|
||||
|
||||
**Funcionalidades:**
|
||||
- Avatar do vendedor (placeholder inicial, preparado para imagem)
|
||||
- Nome do personagem
|
||||
- Badge "Verificado" se aplicável
|
||||
- Link para perfil do vendedor (futuro)
|
||||
|
||||
**Props:**
|
||||
```typescript
|
||||
interface SellerInfoProps {
|
||||
sellerId: number;
|
||||
sellerName: string;
|
||||
sellerImage?: string | null;
|
||||
verified?: boolean;
|
||||
serverName: string;
|
||||
}
|
||||
```
|
||||
|
||||
**Design:**
|
||||
- Avatar circular com fallback (iniciais do nome)
|
||||
- Layout horizontal compacto
|
||||
- Responsivo
|
||||
|
||||
---
|
||||
|
||||
### Etapa 3.2: Integrar no AdCard
|
||||
|
||||
**Arquivo:** `components/marketplace/AdCard.tsx`
|
||||
|
||||
**Mudanças:**
|
||||
- Adicionar `SellerInfo` no card (modo grid e list)
|
||||
- Posicionar acima ou abaixo do preço
|
||||
- Estilizar consistentemente
|
||||
|
||||
---
|
||||
|
||||
## FASE 4: Sistema de Lances (Bids) - Frontend Completo
|
||||
|
||||
### Etapa 4.1: Melhorar BidModal
|
||||
|
||||
**Arquivo:** `components/marketplace/BidModal.tsx`
|
||||
|
||||
**Melhorias:**
|
||||
- Exibir histórico de lances (últimos 5)
|
||||
- Mostrar "Seu lance atual" se usuário já deu lance
|
||||
- Indicador visual de lance mínimo
|
||||
- Feedback imediato após dar lance
|
||||
- Refresh automático do valor do anúncio
|
||||
|
||||
**Novos campos:**
|
||||
- Histórico de lances
|
||||
- Timestamp do lance
|
||||
- Informações do último lanceador
|
||||
|
||||
---
|
||||
|
||||
### Etapa 4.2: API de Histórico de Lances
|
||||
|
||||
**Arquivo:** `app/api/listings/[id]/bids/route.ts`
|
||||
|
||||
**Endpoint:**
|
||||
- `GET /api/listings/[id]/bids` - Listar lances de um anúncio
|
||||
|
||||
**Resposta:**
|
||||
```typescript
|
||||
{
|
||||
bids: Array<{
|
||||
bid_id: number;
|
||||
bidder_id: number;
|
||||
bidder_name: string;
|
||||
bid_amount: number;
|
||||
bid_type: string | null;
|
||||
created_at: Date;
|
||||
}>;
|
||||
total: number;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Etapa 4.3: Atualizar BidModal com Histórico
|
||||
|
||||
**Mudanças:**
|
||||
- Buscar histórico ao abrir modal
|
||||
- Exibir lista de lances anteriores
|
||||
- Mostrar "Você está na liderança" se aplicável
|
||||
- Atualizar valor mínimo dinamicamente
|
||||
|
||||
---
|
||||
|
||||
### Etapa 4.4: Melhorar AdCard para Bids
|
||||
|
||||
**Arquivo:** `components/marketplace/AdCard.tsx`
|
||||
|
||||
**Melhorias:**
|
||||
- Exibir "X lances" ao invés de apenas valor atual
|
||||
- Indicador visual de leilão ativo
|
||||
- Contador regressivo se `auction_ends_at` estiver definido
|
||||
- Badge "Novo lance" se houver lance recente
|
||||
|
||||
---
|
||||
|
||||
## FASE 5: Telemetria Completa
|
||||
|
||||
### Etapa 5.1: Expandir Eventos de Telemetria
|
||||
|
||||
**Arquivo:** `lib/prisma/queries/telemetry.ts`
|
||||
|
||||
**Novos tipos de eventos:**
|
||||
- `bid_placed` - Lance realizado
|
||||
- `bid_viewed` - Histórico de lances visualizado
|
||||
- `purchase_intention_created` - Intenção de compra criada
|
||||
- `purchase_intention_viewed` - Intenção visualizada
|
||||
- `seller_profile_viewed` - Perfil do vendedor visualizado
|
||||
|
||||
**Atualizar interface:**
|
||||
```typescript
|
||||
export type TelemetryEventType =
|
||||
| "ad_view"
|
||||
| "ad_click"
|
||||
| "ad_exit"
|
||||
| "search"
|
||||
| "filter"
|
||||
| "favorite"
|
||||
| "unfavorite"
|
||||
| "purchase"
|
||||
| "purchase_intention_created" // NOVO
|
||||
| "purchase_intention_viewed" // NOVO
|
||||
| "bid_placed" // NOVO
|
||||
| "bid_viewed" // NOVO
|
||||
| "seller_profile_viewed" // NOVO
|
||||
| "inquiry"
|
||||
| "page_view"
|
||||
| "price_change";
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Etapa 5.2: Tracking de Lances
|
||||
|
||||
**Arquivo:** `app/api/listings/[id]/bid/route.ts`
|
||||
|
||||
**Mudanças:**
|
||||
- Após criar lance com sucesso, registrar telemetria:
|
||||
```typescript
|
||||
await trackEvent({
|
||||
event_type: "bid_placed",
|
||||
ad_id: listingId,
|
||||
user_id: bidderId,
|
||||
metadata: {
|
||||
bid_amount: amount,
|
||||
payment_method: paymentMethod,
|
||||
previous_bid: listing.current_bid_amount,
|
||||
min_increment: listing.min_bid_increment,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Etapa 5.3: Tracking de Intenções de Compra
|
||||
|
||||
**Arquivo:** `app/api/listings/[id]/intentions/route.ts`
|
||||
|
||||
**Mudanças:**
|
||||
- Após criar intenção, registrar telemetria:
|
||||
```typescript
|
||||
await trackEvent({
|
||||
event_type: "purchase_intention_created",
|
||||
ad_id: listingId,
|
||||
user_id: buyerId,
|
||||
metadata: {
|
||||
payment_method: paymentMethod,
|
||||
listing_price_pix: listing.price_pix,
|
||||
listing_price_tc: listing.price_tibia_coins,
|
||||
listing_price_gp: listing.price_gold_coins,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Etapa 5.4: Tracking de Visualizações de Vendedor
|
||||
|
||||
**Arquivo:** `components/marketplace/SellerInfo.tsx`
|
||||
|
||||
**Mudanças:**
|
||||
- Ao montar componente, registrar telemetria:
|
||||
```typescript
|
||||
useEffect(() => {
|
||||
trackEvent({
|
||||
event_type: "seller_profile_viewed",
|
||||
ad_id: listingId,
|
||||
metadata: {
|
||||
seller_id: sellerId,
|
||||
seller_name: sellerName,
|
||||
},
|
||||
});
|
||||
}, [sellerId, listingId]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Etapa 5.5: Analytics Dashboard (Opcional - Futuro)
|
||||
|
||||
**Arquivo:** `components/marketplace/AnalyticsDashboard.tsx` (já existe)
|
||||
|
||||
**Melhorias futuras:**
|
||||
- Gráfico de lances ao longo do tempo
|
||||
- Anúncios mais clicados
|
||||
- Horários de pico de acesso
|
||||
- Taxa de conversão de intenções
|
||||
|
||||
---
|
||||
|
||||
## FASE 6: Melhorias na Página "Meus Anúncios"
|
||||
|
||||
### Etapa 6.1: Componente MyAdsIntentionList
|
||||
|
||||
**Arquivo:** `components/marketplace/MyAdsIntentionList.tsx`
|
||||
|
||||
**Funcionalidades:**
|
||||
- Lista de intenções de compra para um anúncio específico
|
||||
- Filtros (pendentes, aceitas, rejeitadas)
|
||||
- Ações: aceitar, rejeitar, ver detalhes
|
||||
- Badge com contador de pendentes
|
||||
|
||||
**Props:**
|
||||
```typescript
|
||||
interface MyAdsIntentionListProps {
|
||||
listingId: number;
|
||||
sellerId: number;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Etapa 6.2: Atualizar MyAdsPanel
|
||||
|
||||
**Arquivo:** `components/marketplace/MyAdsPanel.tsx`
|
||||
|
||||
**Mudanças:**
|
||||
- Adicionar seção de intenções em cada card de anúncio
|
||||
- Expandir/colapsar intenções
|
||||
- Mostrar resumo: "X intenções pendentes"
|
||||
- Link para ver todas as intenções
|
||||
|
||||
**Layout:**
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ [Anúncio: Item X] │
|
||||
│ Status: Active │
|
||||
│ │
|
||||
│ 📊 Intenções de Compra │
|
||||
│ └─ 3 pendentes │
|
||||
│ [Ver todas] [Expandir] │
|
||||
│ │
|
||||
│ 💰 Lances (se for leilão) │
|
||||
│ └─ 5 lances, atual: R$ 100 │
|
||||
│ [Ver histórico] │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Etapa 6.3: Modal de Detalhes de Intenção
|
||||
|
||||
**Arquivo:** `components/marketplace/IntentionDetailModal.tsx`
|
||||
|
||||
**Funcionalidades:**
|
||||
- Exibir informações completas da intenção
|
||||
- Dados do comprador (nome, personagem)
|
||||
- Método de pagamento escolhido
|
||||
- Mensagem do comprador (se houver)
|
||||
- Botões: Aceitar / Rejeitar
|
||||
- Campo para resposta do vendedor
|
||||
|
||||
---
|
||||
|
||||
## 📊 Sequência de Implementação Recomendada
|
||||
|
||||
### Sprint 1: Fundação (Backend)
|
||||
1. ✅ Migração de banco de dados (Fase 1.1)
|
||||
2. ✅ Schema Prisma (Fase 1.2)
|
||||
3. ✅ Queries Prisma (Fase 1.3)
|
||||
4. ✅ API Routes básicas (Fase 1.4)
|
||||
|
||||
### Sprint 2: Frontend Core
|
||||
5. ✅ Componente SellerInfo (Fase 3.1)
|
||||
6. ✅ Integrar SellerInfo no AdCard (Fase 3.2)
|
||||
7. ✅ NotificationBell e Dropdown (Fase 2.1-2.3)
|
||||
8. ✅ Integrar no Header (Fase 2.4)
|
||||
|
||||
### Sprint 3: Sistema de Intenções
|
||||
9. ✅ PurchaseIntentionModal (Fase 1 - Frontend)
|
||||
10. ✅ Modificar PurchaseModal para criar intenção
|
||||
11. ✅ MyAdsIntentionList (Fase 6.1)
|
||||
12. ✅ Atualizar MyAdsPanel (Fase 6.2)
|
||||
|
||||
### Sprint 4: Sistema de Lances
|
||||
13. ✅ API de histórico de lances (Fase 4.2)
|
||||
14. ✅ Melhorar BidModal com histórico (Fase 4.1, 4.3)
|
||||
15. ✅ Melhorar AdCard para bids (Fase 4.4)
|
||||
|
||||
### Sprint 5: Telemetria
|
||||
16. ✅ Expandir eventos (Fase 5.1)
|
||||
17. ✅ Tracking de lances (Fase 5.2)
|
||||
18. ✅ Tracking de intenções (Fase 5.3)
|
||||
19. ✅ Tracking de vendedor (Fase 5.4)
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Design e UX
|
||||
|
||||
### Componentes Visuais
|
||||
|
||||
1. **NotificationBell:**
|
||||
- Ícone: `Bell` do lucide-react
|
||||
- Badge vermelho com contador
|
||||
- Animação de pulse quando há novas
|
||||
- Dropdown com sombra e bordas arredondadas
|
||||
|
||||
2. **SellerInfo:**
|
||||
- Avatar: 40x40px, circular
|
||||
- Nome: texto médio, bold
|
||||
- Badge verificado: ícone de check, verde
|
||||
- Layout: flex horizontal, espaçamento adequado
|
||||
|
||||
3. **IntentionList:**
|
||||
- Cards compactos por intenção
|
||||
- Badge de status (pendente: amarelo, aceita: verde, rejeitada: vermelho)
|
||||
- Avatar do comprador
|
||||
- Método de pagamento com ícone
|
||||
|
||||
4. **BidHistory:**
|
||||
- Lista vertical com timestamps
|
||||
- Destaque para lance atual
|
||||
- Indicador de "seu lance"
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Considerações e Riscos
|
||||
|
||||
### Riscos Identificados
|
||||
|
||||
1. **Performance:**
|
||||
- Muitas intenções por anúncio pode degradar performance
|
||||
- **Mitigação:** Paginação e lazy loading
|
||||
|
||||
2. **Notificações:**
|
||||
- Polling pode sobrecarregar servidor
|
||||
- **Mitigação:** Polling inteligente (mais frequente quando há novas notificações)
|
||||
|
||||
3. **Concorrência:**
|
||||
- Múltiplos lances simultâneos
|
||||
- **Mitigação:** Transações e validação de incremento mínimo
|
||||
|
||||
4. **Telemetria:**
|
||||
- Muitos eventos podem sobrecarregar banco
|
||||
- **Mitigação:** Batch de eventos, agregação periódica
|
||||
|
||||
### Validações Necessárias
|
||||
|
||||
- ✅ Verificar se método de pagamento escolhido está disponível no anúncio
|
||||
- ✅ Validar que comprador não é o vendedor
|
||||
- ✅ Validar incremento mínimo de lance
|
||||
- ✅ Validar que anúncio ainda está ativo
|
||||
- ✅ Validar que leilão não expirou
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testes Necessários
|
||||
|
||||
### Testes Unitários
|
||||
|
||||
- [ ] Queries de purchase_intentions
|
||||
- [ ] Validação de métodos de pagamento
|
||||
- [ ] Cálculo de incremento mínimo de lance
|
||||
|
||||
### Testes de Integração
|
||||
|
||||
- [ ] Fluxo completo de criação de intenção
|
||||
- [ ] Notificação ao vendedor
|
||||
- [ ] Aceitar/rejeitar intenção
|
||||
- [ ] Sistema de lances com múltiplos usuários
|
||||
|
||||
### Testes E2E
|
||||
|
||||
- [ ] Comprador cria intenção → Vendedor recebe notificação
|
||||
- [ ] Vendedor aceita intenção → Comprador é notificado
|
||||
- [ ] Múltiplos lances → Valor atualiza corretamente
|
||||
- [ ] Telemetria registra todos os eventos
|
||||
|
||||
---
|
||||
|
||||
## 📈 Métricas de Sucesso
|
||||
|
||||
1. **Funcionalidade:**
|
||||
- ✅ Intenções de compra funcionando
|
||||
- ✅ Notificações aparecendo corretamente
|
||||
- ✅ Lances atualizando valor
|
||||
- ✅ Vendedores aparecendo nos cards
|
||||
|
||||
2. **Performance:**
|
||||
- Página de marketplace carrega em < 2s
|
||||
- Notificações atualizam em < 1s
|
||||
- Queries de intenções em < 500ms
|
||||
|
||||
3. **UX:**
|
||||
- Interface intuitiva e responsiva
|
||||
- Feedback visual claro
|
||||
- Mensagens de erro compreensíveis
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Próximos Passos
|
||||
|
||||
1. **Revisar este plano** e ajustar conforme necessário
|
||||
2. **Priorizar fases** baseado em necessidade do negócio
|
||||
3. **Iniciar Fase 1** (Backend de intenções)
|
||||
4. **Testar incrementalmente** cada fase antes de avançar
|
||||
|
||||
---
|
||||
|
||||
## 📚 Referências
|
||||
|
||||
- [Prisma Relations](https://www.prisma.io/docs/concepts/components/prisma-schema/relations)
|
||||
- [Next.js Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations)
|
||||
- [React Query/Polling](https://tanstack.com/query/latest/docs/react/guides/window-focus-refetching)
|
||||
|
||||
---
|
||||
|
||||
**Plano criado em:** 2025-01-29
|
||||
**Versão:** 1.0
|
||||
**Status:** Pronto para implementação
|
||||
|
||||
Reference in new issue
Block a user