"use client"; import { useState, useEffect, useCallback } from "react"; import Link from "next/link"; interface Candidature { id: string; email: string; firstname: string; phone: string; persona: string; age: number; experience: string; time_daily: string; availability: string; start_date: string; motivation: string; monthly_goal: string; biggest_fear: string; tiktok_username: string | null; status: "pending" | "approved" | "rejected"; created_at: string; } export default function AdminPage() { const [secret, setSecret] = useState(""); const [authenticated, setAuthenticated] = useState(false); const [candidatures, setCandidatures] = useState([]); const [loading, setLoading] = useState(false); const [actionLoading, setActionLoading] = useState(null); const [checkoutUrls, setCheckoutUrls] = useState>({}); const [expandedId, setExpandedId] = useState(null); const [error, setError] = useState(null); const fetchCandidatures = useCallback(async () => { setLoading(true); setError(null); try { const res = await fetch(`/api/admin/candidatures?secret=${encodeURIComponent(secret)}`); const data = await res.json(); if (!res.ok) throw new Error(data.error); setCandidatures(data.candidatures); setAuthenticated(true); } catch (err) { setError(err instanceof Error ? err.message : "Erreur de chargement"); } finally { setLoading(false); } }, [secret]); useEffect(() => { // Vérifier si le secret est dans l'URL const params = new URLSearchParams(window.location.search); const urlSecret = params.get("secret"); if (urlSecret) { setSecret(urlSecret); } }, []); useEffect(() => { if (secret && !authenticated) { fetchCandidatures(); } }, [secret, authenticated, fetchCandidatures]); const handleApprove = async (id: string) => { setActionLoading(id); try { const res = await fetch(`/api/admin/candidatures/${id}/approve`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ secret }), }); const data = await res.json(); if (!res.ok) throw new Error(data.error); if (data.checkoutUrl) { setCheckoutUrls((prev) => ({ ...prev, [id]: data.checkoutUrl })); } // Rafraîchir la liste await fetchCandidatures(); } catch (err) { setError(err instanceof Error ? err.message : "Erreur"); } finally { setActionLoading(null); } }; const handleReject = async (id: string) => { if (!confirm("Rejeter cette candidature ?")) return; setActionLoading(id); try { const res = await fetch(`/api/admin/candidatures/${id}/reject`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ secret }), }); const data = await res.json(); if (!res.ok) throw new Error(data.error); await fetchCandidatures(); } catch (err) { setError(err instanceof Error ? err.message : "Erreur"); } finally { setActionLoading(null); } }; const statusColors: Record = { pending: "bg-warning/10 text-warning", approved: "bg-success/10 text-success", rejected: "bg-error/10 text-error", }; const statusLabels: Record = { pending: "En attente", approved: "Approuvée", rejected: "Rejetée", }; // Login form if (!authenticated) { return (

Admin HookLab

{ e.preventDefault(); fetchCandidatures(); }} > setSecret(e.target.value)} className="w-full px-4 py-3 bg-dark-lighter border border-dark-border rounded-xl text-white placeholder-white/30 text-sm mb-4 focus:outline-none focus:border-primary" /> {error && (

{error}

)}
); } const pending = candidatures.filter((c) => c.status === "pending"); const approved = candidatures.filter((c) => c.status === "approved"); const rejected = candidatures.filter((c) => c.status === "rejected"); return (
{/* Header */}
← Retour au site

Gestion des candidatures

{pending.length} en attente {approved.length} approuvées {rejected.length} rejetées
{error && (

{error}

)} {/* Liste des candidatures */} {candidatures.length === 0 ? (

Aucune candidature pour le moment.

) : (
{candidatures.map((c) => (
{/* Header row */}
setExpandedId(expandedId === c.id ? null : c.id)} >
{c.firstname.charAt(0).toUpperCase()}

{c.firstname}

{c.email}

{new Date(c.created_at).toLocaleDateString("fr-FR", { day: "numeric", month: "short", year: "numeric", hour: "2-digit", minute: "2-digit", })} {statusLabels[c.status]}
{/* Expanded details */} {expandedId === c.id && (

Téléphone

{c.phone}

Âge

{c.age} ans

Profil

{c.persona}

Expérience

{c.experience}

Temps disponible

{c.time_daily}

Disponibilité

{c.availability}

Début souhaité

{c.start_date}

Objectif mensuel

{c.monthly_goal}

{c.tiktok_username && (

TikTok

{c.tiktok_username}

)}

Motivation

{c.motivation}

Plus grande peur

{c.biggest_fear}

{/* Checkout URL si disponible */} {checkoutUrls[c.id] && (

Lien de paiement généré :

)} {/* Actions */} {c.status === "pending" && (
)} {c.status === "approved" && !checkoutUrls[c.id] && (
)}
)}
))}
)}
); }