"use client"; import { Loader2, TrendingUp } from "lucide-react"; import { useEffect, useState } from "react"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Separator } from "@/components/ui/separator"; import { useSession } from "@/lib/hooks/use-session"; interface Listing { listing_id: number; item_name: string; quantity: number; current_bid_amount: number | null; min_bid_increment: number | null; initial_price_pix: number | null; initial_price_tibia_coins: number | null; initial_price_gold_coins: number | null; price_pix: number | null; price_tibia_coins: number | null; price_gold_coins: number | null; auction_ends_at: Date | null; } interface BidModalProps { open: boolean; onOpenChange: (open: boolean) => void; listing: Listing | null; onSuccess?: () => void; } export function BidModal({ open, onOpenChange, listing, onSuccess, }: BidModalProps) { const { user } = useSession(); const [bidAmount, setBidAmount] = useState(""); const [paymentMethod, setPaymentMethod] = useState(""); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [bidHistory, setBidHistory] = useState< Array<{ bid_id: number; bidder_id: number; bidder_name: string; bid_amount: number; bid_type: string | null; created_at: Date; }> >([]); const [loadingHistory, setLoadingHistory] = useState(false); if (!listing) return null; // Calcular valores const currentBid = listing.current_bid_amount || 0; const minIncrement = listing.min_bid_increment || 10; const minBid = currentBid + minIncrement; const initialPrice = listing.initial_price_pix || listing.initial_price_tibia_coins || listing.initial_price_gold_coins || 0; // Determinar métodos de pagamento disponíveis para lance const availableMethods: string[] = []; if (listing.price_pix || listing.initial_price_pix) availableMethods.push("pix"); if (listing.price_tibia_coins || listing.initial_price_tibia_coins) availableMethods.push("tc"); if (listing.price_gold_coins || listing.initial_price_gold_coins) availableMethods.push("gp"); // Selecionar primeiro método disponível por padrão useEffect(() => { if (availableMethods.length > 0 && !paymentMethod) { setPaymentMethod(availableMethods[0]); } }, [paymentMethod]); // Atualizar valor do lance quando mudar useEffect(() => { if (bidAmount === "" && minBid > 0) { setBidAmount(minBid.toFixed(2)); } }, [minBid, bidAmount]); // Buscar histórico de lances quando abrir modal useEffect(() => { if (open && listing) { fetchBidHistory(); } }, [open, listing?.listing_id, fetchBidHistory, listing]); const fetchBidHistory = async () => { if (!listing) return; setLoadingHistory(true); try { const res = await fetch( `/api/listings/${listing.listing_id}/bids?limit=5`, ); if (res.ok) { const data = await res.json(); if (data.success) { setBidHistory(data.bids || []); } } } catch (error) { console.error("Erro ao buscar histórico de lances:", error); } finally { setLoadingHistory(false); } }; const handleBid = async () => { const amount = parseFloat(bidAmount); if (Number.isNaN(amount) || amount <= 0) { setError("Valor do lance inválido"); return; } if (amount < minBid) { setError( `Lance mínimo é ${minBid.toFixed(2)} (lance atual: ${currentBid.toFixed(2)} + incremento: ${minIncrement.toFixed(2)})`, ); return; } if (!paymentMethod) { setError("Selecione um método de pagamento"); return; } setLoading(true); setError(null); try { const response = await fetch(`/api/listings/${listing.listing_id}/bid`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ amount, payment_method: paymentMethod, }), }); const data = await response.json(); if (!response.ok || !data.success) { throw new Error(data.error || "Erro ao processar lance"); } // Sucesso - atualizar histórico await fetchBidHistory(); if (onSuccess) { onSuccess(); } onOpenChange(false); setBidAmount(""); } catch (err) { setError(err instanceof Error ? err.message : "Erro ao processar lance"); } finally { setLoading(false); } }; const formatPrice = (price: number | null) => { if (!price) return "N/A"; return `R$ ${price.toFixed(2)}`; }; return ( Dar Lance Informe o valor do seu lance para este leilão
{/* Resumo do item */}

{listing.item_name}

Quantidade: {listing.quantity}

{/* Informações do leilão */}

{formatPrice(initialPrice)}

{currentBid > 0 ? formatPrice(currentBid) : "Sem lances"}

{formatPrice(minIncrement)}

{formatPrice(minBid)}

{listing.auction_ends_at && (

{new Date(listing.auction_ends_at).toLocaleString("pt-BR")}

)}
{/* Histórico de lances */} {bidHistory.length > 0 && (
{bidHistory.map((bid, index) => { const isCurrentUser = user?.userId === bid.bidder_id; const isHighest = index === 0; return (
{isCurrentUser ? "Você" : bid.bidder_name} {isHighest && ( Líder )} {isCurrentUser && ( Seu lance )}

{new Date(bid.created_at).toLocaleString("pt-BR")}

R$ {bid.bid_amount.toFixed(2)}
); })}
)} {loadingHistory && (
Carregando histórico...
)} {/* Input do lance */}
setBidAmount(e.target.value)} placeholder={minBid.toFixed(2)} className="text-lg" />

Valor mínimo: {formatPrice(minBid)}

{/* Seleção de método de pagamento */} {availableMethods.length > 0 && (
)} {error && (
{error}
)} {/* Botões */}
); }