ZeroToShip

Docs/Componenti

// componente

Button Lead

Form da una riga per raccogliere email: input + bottone. Lo usi quando il prodotto non è ancora pronto e vuoi una waitlist, o per regalare un lead magnet. Al submit fa un POST su /api/lead, mostra un toast di conferma e si disabilita da solo. È un client component (ha "use client", usa useState e useRef).

File

components/ButtonLead.tsx

Uso base

app/page.tsx
tsx
import ButtonLead from "@/components/ButtonLead";

<ButtonLead />

// oppure centrato e più largo
<ButtonLead extraStyle="mx-auto max-w-sm" />

Props

  • extraStyle?: string — classi extra appese al <form>. Il form ha già w-full max-w-xs space-y-3, quindi qui ci metti allineamento, margini o un max-w- diverso.

Non ci sono altre props: il testo del bottone (“Entra in waitlist”), il placeholder (“La tua email”) e il messaggio di successo sono scritti dentro il componente.

Il giro completo

Il submit chiama apiClient.post("/lead", { email }). apiClient è l'istanza axios in libs/api.ts con baseURL: "/api": gli errori vengono già mostrati come toast, quindi il componente non gestisce il caso di errore a mano.

Dall'altra parte, app/api/lead/route.ts valida solo la presenza dell'email (400 se manca) e poi restituisce un oggetto vuoto. La riga che salva il lead è commentata: di default l'email non viene scritta da nessuna parte. Sta a te decommentarla.

app/api/lead/route.ts
ts
export async function POST(req: NextRequest) {
  const body = await req.json();

  if (!body.email) {
    return NextResponse.json({ error: "Email is required" }, { status: 400 });
  }

  try {
    // scommenta per salvare davvero il lead
    const supabase = createClient();
    await supabase.from("leads").insert({ email: body.email });

    return NextResponse.json({});
  } catch (e) {
    console.error(e);
    return NextResponse.json({ error: e.message }, { status: 500 });
  }
}

Personalizzare

  • Salvare il lead: crea una tabella leads su Supabase e decommenta le due righe qui sopra (compreso l'import di createClient in cima al file). Vedi Database.
  • Email di benvenuto: dentro il try puoi chiamare sendEmail da libs/resend. Vedi Email.
  • Copy: cambia il testo del bottone, il placeholder e il messaggio di toast.success direttamente nel componente.
  • Stile: l'input usa input-brutal e il bottone btn-brutal-primary, entrambe definite in app/globals.css. Passa a btn-brutal-mustard se ti serve più contrasto.
  • Riabilitare il form: dopo un invio riuscito isDisabled resta true per sempre. Se vuoi permettere più invii, togli quella riga.