diff --git a/app/api/admin/candidatures/[id]/reject/route.ts b/app/api/admin/candidatures/[id]/reject/route.ts index 1276295..b11918b 100644 --- a/app/api/admin/candidatures/[id]/reject/route.ts +++ b/app/api/admin/candidatures/[id]/reject/route.ts @@ -17,6 +17,13 @@ export async function POST( const { id } = await params; const supabase = createAdminClient(); + // Récupérer les infos du candidat avant de rejeter + const { data: candidature } = await supabase + .from("candidatures") + .select("firstname, email") + .eq("id", id) + .single() as { data: { firstname: string; email: string } | null }; + const { error } = await supabase .from("candidatures") .update({ status: "rejected" } as never) @@ -26,5 +33,53 @@ export async function POST( return NextResponse.json({ error: error.message }, { status: 500 }); } + // Email de rejet au candidat + if (candidature && process.env.RESEND_API_KEY) { + try { + const { Resend } = await import("resend"); + const resend = new Resend(process.env.RESEND_API_KEY); + const fromEmail = + process.env.RESEND_FROM_EMAIL || "HookLab "; + + await resend.emails.send({ + from: fromEmail, + to: candidature.email, + subject: "Résultat de ta candidature HookLab", + html: ` + + + + +
+
+
H
+ HookLab +
+
+

Salut ${candidature.firstname},

+

+ Merci d'avoir pris le temps de candidater au programme HookLab. +

+

+ Après étude de ton dossier, nous ne pouvons pas retenir ta candidature pour le moment. + Le programme est très sélectif et nous cherchons des profils très spécifiques. +

+

+ Nous te souhaitons le meilleur dans ta progression. N'hésite pas à recandidater dans quelques mois si ta situation évolue. +

+
+
+

HookLab - Programme TikTok Shop

+
+
+ + + `, + }); + } catch (emailError) { + console.error("Erreur envoi email rejet:", emailError); + } + } + return NextResponse.json({ success: true, message: "Candidature rejetée." }); } diff --git a/app/api/candidature/route.ts b/app/api/candidature/route.ts index 554b4b1..a6ae7bf 100644 --- a/app/api/candidature/route.ts +++ b/app/api/candidature/route.ts @@ -107,14 +107,16 @@ export async function POST(request: Request) { ); } - // Envoi email de confirmation (Resend) + // Envoi emails (Resend) if (process.env.RESEND_API_KEY && process.env.RESEND_API_KEY !== "re_your-api-key") { - try { - const { Resend } = await import("resend"); - const resend = new Resend(process.env.RESEND_API_KEY); + const { Resend } = await import("resend"); + const resend = new Resend(process.env.RESEND_API_KEY); + const fromEmail = process.env.RESEND_FROM_EMAIL || "HookLab "; + // Email de confirmation au candidat + try { await resend.emails.send({ - from: process.env.RESEND_FROM_EMAIL || "HookLab ", + from: fromEmail, to: body.email, subject: "Candidature HookLab reçue !", html: ` @@ -128,7 +130,45 @@ export async function POST(request: Request) { `, }); } catch (emailError) { - console.error("Erreur envoi email:", emailError); + console.error("Erreur envoi email candidat:", emailError); + } + + // Notification admin + const adminEmail = process.env.ADMIN_EMAIL || fromEmail; + try { + await resend.emails.send({ + from: fromEmail, + to: adminEmail, + subject: `Nouvelle candidature - ${body.firstname} (${body.persona})`, + html: ` + + + + +
+
+

Nouvelle candidature HookLab

+

À traiter dans les 24h

+ + + + + + + + + + +
Prénom${body.firstname}
Email${body.email}
Téléphone${body.phone}
Âge${body.age} ans
Profil${body.persona}
Expérience${body.experience}
Temps / jour${body.time_daily}
Objectif mensuel${body.monthly_goal}
Motivation${body.motivation}
+ Voir dans l'admin +
+
+ + + `, + }); + } catch (emailError) { + console.error("Erreur envoi email admin:", emailError); } } diff --git a/app/api/contact/route.ts b/app/api/contact/route.ts new file mode 100644 index 0000000..9571ba4 --- /dev/null +++ b/app/api/contact/route.ts @@ -0,0 +1,82 @@ +import { NextResponse } from "next/server"; + +export const runtime = "nodejs"; + +export async function POST(request: Request) { + try { + const body = await request.json(); + const { name, phone, metier, ville } = body as { + name?: string; + phone?: string; + metier?: string; + ville?: string; + }; + + if (!name || !phone || !metier || !ville) { + return NextResponse.json( + { error: "Tous les champs sont requis." }, + { status: 400 } + ); + } + + if (!process.env.RESEND_API_KEY) { + return NextResponse.json( + { error: "Service email non configuré." }, + { status: 500 } + ); + } + + const { Resend } = await import("resend"); + const resend = new Resend(process.env.RESEND_API_KEY); + + const fromEmail = + process.env.RESEND_FROM_EMAIL || "HookLab "; + const adminEmail = process.env.ADMIN_EMAIL || fromEmail; + + await resend.emails.send({ + from: fromEmail, + to: adminEmail, + subject: `Nouvelle demande d'audit - ${name} (${metier})`, + html: ` + + + + +
+
+

Nouvelle demande d'audit gratuit

+ + + + + + + + + + + + + + + + + +
Nom${name}
Téléphone${phone}
Métier${metier}
Ville / Zone${ville}
+

Reçu le ${new Date().toLocaleDateString("fr-FR", { day: "2-digit", month: "long", year: "numeric", hour: "2-digit", minute: "2-digit" })}

+
+
+ + + `, + }); + + return NextResponse.json({ success: true }, { status: 200 }); + } catch (err) { + console.error("Erreur API contact:", err); + return NextResponse.json( + { error: "Erreur serveur. Veuillez réessayer." }, + { status: 500 } + ); + } +} diff --git a/app/api/devis/route.ts b/app/api/devis/route.ts new file mode 100644 index 0000000..bc99057 --- /dev/null +++ b/app/api/devis/route.ts @@ -0,0 +1,91 @@ +import { NextResponse } from "next/server"; + +export const runtime = "nodejs"; + +export async function POST(request: Request) { + try { + const body = await request.json(); + const { name, phone, ville, description, projectType } = body as { + name?: string; + phone?: string; + ville?: string; + description?: string; + projectType?: string; + }; + + if (!name || !phone || !ville || !projectType) { + return NextResponse.json( + { error: "Les champs nom, téléphone, ville et type de projet sont requis." }, + { status: 400 } + ); + } + + if (!process.env.RESEND_API_KEY) { + return NextResponse.json( + { error: "Service email non configuré." }, + { status: 500 } + ); + } + + const { Resend } = await import("resend"); + const resend = new Resend(process.env.RESEND_API_KEY); + + const fromEmail = + process.env.RESEND_FROM_EMAIL || "HookLab "; + const adminEmail = process.env.ADMIN_EMAIL || fromEmail; + + await resend.emails.send({ + from: fromEmail, + to: adminEmail, + subject: `Nouvelle demande de devis - ${projectType} (${ville})`, + html: ` + + + + +
+
+

Nouvelle demande de devis maçonnerie

+ + + + + + + + + + + + + + + + + + ${ + description + ? ` + + + ` + : "" + } +
Nom${name}
Téléphone${phone}
Type de projet${projectType}
Ville${ville}
Description${description}
+

Reçu le ${new Date().toLocaleDateString("fr-FR", { day: "2-digit", month: "long", year: "numeric", hour: "2-digit", minute: "2-digit" })}

+
+
+ + + `, + }); + + return NextResponse.json({ success: true }, { status: 200 }); + } catch (err) { + console.error("Erreur API devis:", err); + return NextResponse.json( + { error: "Erreur serveur. Veuillez réessayer." }, + { status: 500 } + ); + } +} diff --git a/app/macon/MaconClient.tsx b/app/macon/MaconClient.tsx index 02dcb0c..bd8db4a 100644 --- a/app/macon/MaconClient.tsx +++ b/app/macon/MaconClient.tsx @@ -90,8 +90,50 @@ function FaqAccordion({ faqs }: { faqs: { q: string; a: string }[] }) { SMART DEVIS FORM ============================================================ */ function DevisForm() { - const [step, setStep] = useState<"type" | "details">("type"); + const [step, setStep] = useState<"type" | "details" | "done">("type"); const [projectType, setProjectType] = useState(""); + const [fields, setFields] = useState({ name: "", phone: "", ville: "", description: "" }); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const updateField = (key: keyof typeof fields, value: string) => + setFields((prev) => ({ ...prev, [key]: value })); + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setLoading(true); + setError(null); + try { + const res = await fetch("/api/devis", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ ...fields, projectType }), + }); + if (!res.ok) { + const data = await res.json(); + throw new Error(data.error || "Erreur lors de l'envoi"); + } + setStep("done"); + } catch (err) { + setError(err instanceof Error ? err.message : "Erreur inattendue"); + } finally { + setLoading(false); + } + }; + + if (step === "done") { + return ( +
+
+ + + +
+

Demande envoyée !

+

Nous vous recontactons sous 24h pour votre devis.

+
+ ); + } if (step === "details") { return ( @@ -103,12 +145,15 @@ function DevisForm() {

Projet : {projectType}

-
+
updateField("name", e.target.value)} className="w-full px-4 py-3 bg-[#f8f6f3] border border-gray-200 rounded-xl text-text text-sm placeholder:text-text-muted focus:border-orange focus:ring-1 focus:ring-orange outline-none" />
@@ -116,7 +161,10 @@ function DevisForm() { updateField("phone", e.target.value)} className="w-full px-4 py-3 bg-[#f8f6f3] border border-gray-200 rounded-xl text-text text-sm placeholder:text-text-muted focus:border-orange focus:ring-1 focus:ring-orange outline-none" />
@@ -124,7 +172,10 @@ function DevisForm() { updateField("ville", e.target.value)} className="w-full px-4 py-3 bg-[#f8f6f3] border border-gray-200 rounded-xl text-text text-sm placeholder:text-text-muted focus:border-orange focus:ring-1 focus:ring-orange outline-none" /> @@ -133,19 +184,23 @@ function DevisForm() {