Files
obc-terrassement/app/api/admin/candidatures/[id]/reject/route.ts
Claude 6c33406e13 feat(email): wire all forms to Resend — contact, devis, candidature notifs
- Create /api/contact → sends admin notification email on audit request
- Create /api/devis → sends admin notification email on macon devis request
- Contact.tsx: make inputs controlled, call /api/contact on submit
- MaconClient.tsx DevisForm: add controlled state + submit handler calling /api/devis, add success/error states
- /api/candidature: add admin notification email alongside candidate confirmation
- /api/admin/candidatures/[id]/reject: fetch candidate info + send rejection email

All routes read ADMIN_EMAIL env var for admin notifications (fallback to RESEND_FROM_EMAIL).

https://claude.ai/code/session_01PzA98VhLMmsHpzs7gnLHGs
2026-02-23 07:36:00 +00:00

86 lines
3.4 KiB
TypeScript

import { NextResponse } from "next/server";
import { createAdminClient } from "@/lib/supabase/server";
import { verifyAdmin, isAdminError } from "@/lib/admin";
export const runtime = "nodejs";
// POST /api/admin/candidatures/[id]/reject - Rejeter une candidature
export async function POST(
_request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const auth = await verifyAdmin();
if (isAdminError(auth)) {
return NextResponse.json({ error: auth.error }, { status: auth.status });
}
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)
.eq("id", id);
if (error) {
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 <onboarding@resend.dev>";
await resend.emails.send({
from: fromEmail,
to: candidature.email,
subject: "Résultat de ta candidature HookLab",
html: `
<!DOCTYPE html>
<html>
<head><meta charset="utf-8"></head>
<body style="margin:0;padding:0;background-color:#0B0F19;font-family:Arial,Helvetica,sans-serif;">
<div style="max-width:600px;margin:0 auto;padding:40px 20px;">
<div style="text-align:center;margin-bottom:40px;">
<div style="display:inline-block;background:linear-gradient(135deg,#6D5EF6,#9D8FF9);width:48px;height:48px;border-radius:12px;line-height:48px;color:#fff;font-weight:800;font-size:20px;">H</div>
<span style="display:inline-block;vertical-align:top;margin-left:10px;line-height:48px;font-size:24px;font-weight:800;color:#ffffff;">Hook<span style="color:#6D5EF6;">Lab</span></span>
</div>
<div style="background:#1A1F2E;border:1px solid #2A2F3F;border-radius:20px;padding:40px 32px;">
<h1 style="color:#ffffff;font-size:22px;margin:0 0 16px 0;">Salut ${candidature.firstname},</h1>
<p style="color:#ffffffcc;font-size:15px;line-height:1.6;margin:0 0 16px 0;">
Merci d'avoir pris le temps de candidater au programme HookLab.
</p>
<p style="color:#ffffffcc;font-size:15px;line-height:1.6;margin:0 0 16px 0;">
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.
</p>
<p style="color:#ffffffcc;font-size:15px;line-height:1.6;margin:0 0 0 0;">
Nous te souhaitons le meilleur dans ta progression. N'hésite pas à recandidater dans quelques mois si ta situation évolue.
</p>
</div>
<div style="text-align:center;margin-top:32px;">
<p style="color:#ffffff40;font-size:12px;margin:0;">HookLab - Programme TikTok Shop</p>
</div>
</div>
</body>
</html>
`,
});
} catch (emailError) {
console.error("Erreur envoi email rejet:", emailError);
}
}
return NextResponse.json({ success: true, message: "Candidature rejetée." });
}