"use client"; import { Coins, DollarSign, Loader2, RefreshCw } 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 { Separator } from "@/components/ui/separator"; import { useSession } from "@/lib/hooks/use-session"; interface Listing { listing_id: number; item_name: string; quantity: number; price_pix: number | string | null; price_tibia_coins: number | string | null; price_gold_coins: number | string | null; trade_item_id?: number | null; trade_item_name?: string | null; trade_item_quantity?: number | null; highest_custom_offer_amount?: number | string | null; highest_custom_offer_currency?: string | null; } interface PurchaseModalProps { open: boolean; onOpenChange: (open: boolean) => void; listing: Listing | null; onSuccess?: () => void; } export function PurchaseModal({ open, onOpenChange, listing, onSuccess, }: PurchaseModalProps) { const { user } = useSession(); const [selectedMethod, setSelectedMethod] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [customOfferValue, setCustomOfferValue] = useState(""); useEffect(() => { if (!open) { setSelectedMethod(null); setCustomOfferValue(""); setError(null); } }, [open]); useEffect(() => { if ( selectedMethod && !["pix", "tibia_coins", "gold_coins"].includes(selectedMethod) ) { setCustomOfferValue(""); } }, [selectedMethod]); if (!listing) return null; // Determinar métodos de pagamento disponíveis const availableMethods: Array<{ type: string; label: string; value: string; icon: any; }> = []; if (listing.price_pix) { const price = typeof listing.price_pix === "string" ? parseFloat(listing.price_pix) : listing.price_pix; if (!Number.isNaN(price)) { availableMethods.push({ type: "pix", label: "PIX", value: `R$ ${price.toFixed(2)}`, icon: DollarSign, }); } } if (listing.price_tibia_coins) { const price = typeof listing.price_tibia_coins === "string" ? parseInt(listing.price_tibia_coins, 10) : listing.price_tibia_coins; if (!Number.isNaN(price)) { availableMethods.push({ type: "tibia_coins", label: "Tibia Coins", value: `${price.toLocaleString()} TC`, icon: Coins, }); } } if (listing.price_gold_coins) { const price = typeof listing.price_gold_coins === "string" ? parseInt(listing.price_gold_coins, 10) : listing.price_gold_coins; if (!Number.isNaN(price)) { availableMethods.push({ type: "gold_coins", label: "Gold Coins", value: `${price.toLocaleString()} GP`, icon: Coins, }); } } if ( listing.trade_item_id && listing.trade_item_name && listing.trade_item_quantity ) { availableMethods.push({ type: "trade", label: "Troca", value: `Troca por ${listing.trade_item_quantity}x ${listing.trade_item_name}`, icon: RefreshCw, }); } const formatOffer = ( amount: number | string | null, currency: string | null, ) => { if (amount === null || amount === undefined || !currency) { return null; } const numeric = typeof amount === "string" ? Number(amount) : amount; if (Number.isNaN(numeric)) { return null; } switch (currency) { case "pix": return `R$ ${numeric.toFixed(2)}`; case "tibia_coins": return `${Math.round(numeric).toLocaleString()} TC`; case "gold_coins": return `${Math.round(numeric).toLocaleString()} GP`; default: return `${numeric}`; } }; const highestOfferLabel = formatOffer( listing.highest_custom_offer_amount ?? null, listing.highest_custom_offer_currency ?? null, ); // Se houver apenas um método, selecionar automaticamente if (availableMethods.length === 1 && !selectedMethod) { setSelectedMethod(availableMethods[0].type); } const handlePurchase = async () => { if (!selectedMethod) { setError("Selecione um método de pagamento"); return; } const hasCustomOffer = customOfferValue.trim().length > 0; if (hasCustomOffer) { const offerNumber = Number(customOfferValue); if (Number.isNaN(offerNumber) || offerNumber <= 0) { setError("Informe um valor válido para a oferta personalizada."); return; } } setLoading(true); setError(null); try { const payload: Record = { payment_method: selectedMethod, }; if ( hasCustomOffer && ["pix", "tibia_coins", "gold_coins"].includes(selectedMethod) ) { const offerNumber = Number(customOfferValue); payload.custom_offer_amount = selectedMethod === "pix" ? Number(offerNumber.toFixed(2)) : Math.floor(offerNumber); payload.custom_offer_currency = selectedMethod; } const response = await fetch( `/api/listings/${listing.listing_id}/purchase`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(payload), }, ); const data = await response.json(); if (!response.ok || !data.success) { throw new Error(data.error || "Erro ao processar compra"); } // Sucesso if (onSuccess) { onSuccess(); } onOpenChange(false); setCustomOfferValue(""); } catch (err) { setError(err instanceof Error ? err.message : "Erro ao processar compra"); } finally { setLoading(false); } }; const getMethodClassName = (type: string) => { switch (type) { case "pix": return "bg-green-500 hover:bg-green-600 text-white"; case "tibia_coins": return "bg-blue-500 hover:bg-blue-600 text-white"; case "gold_coins": return "bg-yellow-500 hover:bg-yellow-600 text-white"; case "trade": return "bg-purple-500 hover:bg-purple-600 text-white"; default: return ""; } }; return ( Confirmar Compra Escolha o método de pagamento para finalizar a compra
{/* Resumo do item */}

{listing.item_name}

Quantidade: {listing.quantity}

Valores anunciados pelo vendedor

{availableMethods.map((method) => ( {method.label}: {method.value} ))}
{highestOfferLabel && (
Maior oferta registrada:{" "} {highestOfferLabel}
)} {/* Seleção de método de pagamento */} {availableMethods.length > 1 ? (
{availableMethods.map((method) => { const Icon = method.icon; const isSelected = selectedMethod === method.type; return ( ); })}
) : availableMethods.length === 1 ? (
{(() => { const Icon = availableMethods[0].icon; return ; })()} {availableMethods[0].label}

{availableMethods[0].value}

) : (

Nenhum método de pagamento disponível

)} {selectedMethod && ["pix", "tibia_coins", "gold_coins"].includes(selectedMethod) && (
setCustomOfferValue(event.target.value)} placeholder={ selectedMethod === "pix" ? "Ex.: 199.90" : "Ex.: 1200" } />

Esse valor será enviado ao vendedor como sua proposta. Ele pode aceitar, negar ou responder.

)} {error && (
{error}
)} {/* Botões */}
); }