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>
This commit is contained in:
71
app/produtos/[id]/page.tsx
Normal file
71
app/produtos/[id]/page.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import { getProdutoById } from "@/lib/actions"
|
||||
import { ProductBuyForm } from "@/components/product-buy-form"
|
||||
import { notFound } from "next/navigation"
|
||||
import type { Metadata } from "next"
|
||||
import { appConfig } from "@/lib/config"
|
||||
|
||||
type Props = { params: Promise<{ id: string }> }
|
||||
|
||||
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
||||
try {
|
||||
const { id } = await params
|
||||
const produto = await getProdutoById(id)
|
||||
if (!produto) return { title: "Produto não encontrado" }
|
||||
return {
|
||||
title: `${produto.nome} — ${appConfig.name}`,
|
||||
description: produto.descricao ?? produto.nome,
|
||||
}
|
||||
} catch {
|
||||
return { title: "Erro ao carregar produto" }
|
||||
}
|
||||
}
|
||||
|
||||
export default async function ProductPage({ params }: Props) {
|
||||
const { id } = await params
|
||||
const produto = await getProdutoById(id)
|
||||
if (!produto) notFound()
|
||||
|
||||
const precoFormatado = (produto.preco_centavos / 100).toLocaleString("pt-BR", {
|
||||
style: "currency",
|
||||
currency: "BRL",
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="bg-gradient-to-b from-gray-50 to-white min-h-screen">
|
||||
<div className="container mx-auto py-16 px-4 sm:px-6 lg:px-8 max-w-5xl">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12">
|
||||
{/* Detalhes do produto */}
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold text-primary mb-4">{produto.nome}</h1>
|
||||
{produto.descricao && (
|
||||
<p className="text-gray-600 text-lg mb-6">{produto.descricao}</p>
|
||||
)}
|
||||
<div className="flex flex-wrap gap-3 text-sm text-gray-500">
|
||||
{produto.tipo && (
|
||||
<span className="bg-gray-100 px-3 py-1 rounded-full">
|
||||
Tipo: <strong>{produto.tipo}</strong>
|
||||
</span>
|
||||
)}
|
||||
{produto.validade && (
|
||||
<span className="bg-gray-100 px-3 py-1 rounded-full">
|
||||
Validade: <strong>{produto.validade}</strong>
|
||||
</span>
|
||||
)}
|
||||
{produto.midia && (
|
||||
<span className="bg-gray-100 px-3 py-1 rounded-full">
|
||||
Mídia: <strong>{produto.midia}</strong>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Formulário de compra */}
|
||||
<div className="bg-white p-8 rounded-2xl shadow-lg">
|
||||
<p className="text-4xl font-bold mb-6 text-primary">{precoFormatado}</p>
|
||||
<ProductBuyForm produtoId={produto.id} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
5
app/produtos/page.tsx
Normal file
5
app/produtos/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import { redirect } from "next/navigation"
|
||||
|
||||
export default function ProdutosPage() {
|
||||
redirect("/comprar")
|
||||
}
|
||||
Reference in New Issue
Block a user