Files
asaas-checkout/components/product-buy-form.tsx
Felipe Carvalho 038ce3f556 feat: initial commit — asaas-checkout template white-label
Template genérico de checkout com ASAAS, parametrizado via env vars.
Inclui fluxo completo: checkout → pedido → polling → webhook → admin.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 06:40:41 +02:00

123 lines
3.5 KiB
TypeScript

"use client"
import { useState } from "react"
import { useRouter } from "next/navigation"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { useToast } from "@/components/ui/use-toast"
import { criarCheckout } from "@/lib/actions"
type Metodo = "PIX" | "BOLETO" | "CREDIT_CARD"
export function ProductBuyForm({
produtoId,
}: {
produtoId: string
}) {
const router = useRouter()
const { toast } = useToast()
const [isLoading, setIsLoading] = useState(false)
const [metodo, setMetodo] = useState<Metodo>("PIX")
const [form, setForm] = useState({
nome: "",
email: "",
cpfCnpj: "",
telefone: "",
})
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setIsLoading(true)
try {
const res = await criarCheckout({
produtoId,
cliente: {
nome: form.nome,
email: form.email,
cpfCnpj: form.cpfCnpj.replace(/\D/g, ""),
telefone: form.telefone,
},
metodo,
})
router.push(`/pedido/${res.pedidoId}`)
} catch (error) {
toast({
title: "Erro ao processar pagamento",
description: error instanceof Error ? error.message : "Tente novamente.",
variant: "destructive",
})
setIsLoading(false)
}
}
return (
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="nome">Nome completo</Label>
<Input
id="nome"
required
value={form.nome}
onChange={(e) => setForm({ ...form, nome: e.target.value })}
/>
</div>
<div className="space-y-2">
<Label htmlFor="email">E-mail</Label>
<Input
id="email"
type="email"
required
value={form.email}
onChange={(e) => setForm({ ...form, email: e.target.value })}
/>
</div>
<div className="space-y-2">
<Label htmlFor="cpfCnpj">CPF / CNPJ</Label>
<Input
id="cpfCnpj"
required
placeholder="000.000.000-00"
value={form.cpfCnpj}
onChange={(e) => setForm({ ...form, cpfCnpj: e.target.value })}
/>
</div>
<div className="space-y-2">
<Label htmlFor="telefone">Telefone</Label>
<Input
id="telefone"
placeholder="(11) 99999-9999"
value={form.telefone}
onChange={(e) => setForm({ ...form, telefone: e.target.value })}
/>
</div>
<div className="space-y-2">
<Label>Forma de pagamento</Label>
<div className="flex gap-2">
{(["PIX", "BOLETO", "CREDIT_CARD"] as Metodo[]).map((m) => (
<button
key={m}
type="button"
onClick={() => setMetodo(m)}
className={`flex-1 py-2 rounded-lg border text-sm font-medium transition-colors ${
metodo === m
? "border-primary bg-primary text-white"
: "border-gray-300 hover:border-primary"
}`}
>
{m === "PIX" ? "PIX" : m === "BOLETO" ? "Boleto" : "Cartão"}
</button>
))}
</div>
</div>
<Button type="submit" className="w-full" disabled={isLoading}>
{isLoading ? "Processando..." : `Pagar com ${metodo === "PIX" ? "PIX" : metodo === "BOLETO" ? "Boleto" : "Cartão"}`}
</Button>
</form>
)
}