feat: fix accents, improve candidature API, add legal pages

- Fix all missing French accents across 16 files (é, è, ê, à, ô, ç)
- Improve candidature API error handling: check env vars, better messages
- Add Mentions légales page (/mentions-legales)
- Add CGV page (/cgv)
- Add Politique de confidentialité page (/confidentialite)
- Business info: Enguerrand Ozano, SIREN 994538932, TVA FR16994538932

https://claude.ai/code/session_01H2aRGDaKgarPvhay2HxN6Y
This commit is contained in:
Claude
2026-02-08 20:49:54 +00:00
parent dd6ec0816b
commit 231667c2c6
19 changed files with 475 additions and 124 deletions

View File

@@ -55,7 +55,7 @@ export default async function DashboardPage() {
Bonjour {profile?.full_name?.split(" ")[0] || "!"} 👋
</h1>
<p className="text-white/60">
Voici un apercu de ta progression dans le programme.
Voici un aperçu de ta progression dans le programme.
</p>
</div>
@@ -69,7 +69,7 @@ export default async function DashboardPage() {
<ProgressBar value={progressPercent} showPercentage={false} />
</Card>
<Card>
<p className="text-white/40 text-sm mb-1">Modules completes</p>
<p className="text-white/40 text-sm mb-1">Modules complétés</p>
<p className="text-2xl font-bold text-white">
{completedModules}
<span className="text-white/30 text-lg font-normal">
@@ -122,11 +122,11 @@ export default async function DashboardPage() {
<Card className="text-center py-12">
<div className="text-4xl mb-4">🚀</div>
<h3 className="text-white font-semibold text-lg mb-2">
Le programme arrive bientot !
Le programme arrive bientôt !
</h3>
<p className="text-white/40 text-sm max-w-md mx-auto">
Les modules de formation sont en cours de preparation. Tu seras
notifie des qu&apos;ils seront disponibles.
Les modules de formation sont en cours de préparation. Tu seras
notifié dès qu&apos;ils seront disponibles.
</p>
</Card>
)}

View File

@@ -86,7 +86,7 @@ export default async function ModulePage({ params }: ModulePageProps) {
d="M5 13l4 4L19 7"
/>
</svg>
Complete
Complété
</span>
)}
</div>
@@ -133,7 +133,7 @@ export default async function ModulePage({ params }: ModulePageProps) {
d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
/>
</svg>
Telecharger le PDF
Télécharger le PDF
</a>
</div>
)}
@@ -144,7 +144,7 @@ export default async function ModulePage({ params }: ModulePageProps) {
<div className="text-center">
<div className="text-4xl mb-3">🎬</div>
<p className="text-white/40 text-sm">
Le contenu sera bientot disponible
Le contenu sera bientôt disponible
</p>
</div>
</div>

View File

@@ -53,7 +53,7 @@ export default async function FormationsPage() {
</p>
<ProgressBar
value={progressPercent}
label={`${completedModules} modules completes sur ${totalModules}`}
label={`${completedModules} modules complétés sur ${totalModules}`}
/>
</div>
@@ -72,7 +72,7 @@ export default async function FormationsPage() {
Semaine {week}
</h2>
<span className="text-white/30 text-sm">
{weekCompleted}/{weekTotal} completes
{weekCompleted}/{weekTotal} complétés
</span>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
@@ -101,7 +101,7 @@ export default async function FormationsPage() {
Aucun module disponible
</h3>
<p className="text-white/40 text-sm">
Les modules de formation seront bientot disponibles.
Les modules de formation seront bientôt disponibles.
</p>
</div>
)}

View File

@@ -42,14 +42,26 @@ export async function POST(request: Request) {
);
}
// Validation age
// Validation âge
if (body.age < 18 || body.age > 65) {
return NextResponse.json(
{ error: "L'age doit etre entre 18 et 65 ans." },
{ error: "L'âge doit être entre 18 et 65 ans." },
{ status: 400 }
);
}
// Vérifier que les variables d'environnement Supabase sont configurées
if (!process.env.NEXT_PUBLIC_SUPABASE_URL || !process.env.SUPABASE_SERVICE_ROLE_KEY) {
console.error("Variables Supabase manquantes:", {
url: !!process.env.NEXT_PUBLIC_SUPABASE_URL,
serviceRole: !!process.env.SUPABASE_SERVICE_ROLE_KEY,
});
return NextResponse.json(
{ error: "Configuration serveur incomplète. Contactez l'administrateur." },
{ status: 500 }
);
}
const supabase = createAdminClient();
// Vérifier si une candidature existe déjà avec cet email
@@ -61,7 +73,7 @@ export async function POST(request: Request) {
if (existing) {
return NextResponse.json(
{ error: "Une candidature avec cet email existe deja." },
{ error: "Une candidature avec cet email existe déjà." },
{ status: 409 }
);
}
@@ -90,7 +102,7 @@ export async function POST(request: Request) {
if (insertError) {
console.error("Erreur insertion candidature:", insertError);
return NextResponse.json(
{ error: "Erreur lors de l'enregistrement de la candidature." },
{ error: "Erreur lors de l'enregistrement. Vérifiez que la base de données est configurée." },
{ status: 500 }
);
}
@@ -104,30 +116,30 @@ export async function POST(request: Request) {
await resend.emails.send({
from: "HookLab <noreply@hooklab.fr>",
to: body.email,
subject: "Candidature HookLab recue !",
subject: "Candidature HookLab reçue !",
html: `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h1 style="color: #6D5EF6;">Candidature recue !</h1>
<h1 style="color: #6D5EF6;">Candidature reçue !</h1>
<p>Salut ${body.firstname},</p>
<p>Merci pour ta candidature au programme HookLab !</p>
<p>Notre equipe va etudier ton profil et te repondre sous <strong>24 heures</strong>.</p>
<p>A tres vite,<br/>L'equipe HookLab</p>
<p>Notre équipe va étudier ton profil et te répondre sous <strong>24 heures</strong>.</p>
<p>À très vite,<br/>L'équipe HookLab</p>
</div>
`,
});
} catch (emailError) {
// Log l'erreur mais ne bloque pas la candidature
console.error("Erreur envoi email:", emailError);
}
}
return NextResponse.json(
{ message: "Candidature enregistree avec succes." },
{ message: "Candidature enregistrée avec succès." },
{ status: 201 }
);
} catch {
} catch (err) {
console.error("Erreur serveur candidature:", err);
return NextResponse.json(
{ error: "Erreur serveur. Veuillez reessayer." },
{ error: "Erreur serveur. Veuillez réessayer." },
{ status: 500 }
);
}

View File

@@ -128,18 +128,18 @@ export async function POST(request: Request) {
await resend.emails.send({
from: "HookLab <noreply@hooklab.fr>",
to: email,
subject: "Bienvenue dans HookLab ! Tes acces sont prets",
subject: "Bienvenue dans HookLab ! Tes accès sont prêts",
html: `
<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h1 style="color: #6D5EF6;">Bienvenue dans HookLab !</h1>
<p>Ton paiement a ete confirme. Voici tes acces :</p>
<p>Ton paiement a été confirmé. Voici tes accès :</p>
<div style="background: #1A1F2E; padding: 20px; border-radius: 12px; margin: 20px 0;">
<p style="color: #fff; margin: 5px 0;"><strong>Email :</strong> ${email}</p>
<p style="color: #fff; margin: 5px 0;"><strong>Mot de passe :</strong> ${tempPassword}</p>
</div>
<p>Connecte-toi sur <a href="${process.env.NEXT_PUBLIC_APP_URL}/login" style="color: #6D5EF6;">hooklab.fr/login</a> pour commencer.</p>
<p><strong>Pense a changer ton mot de passe apres ta premiere connexion !</strong></p>
<p>A tres vite,<br/>L'equipe HookLab</p>
<p><strong>Pense à changer ton mot de passe après ta première connexion !</strong></p>
<p>À très vite,<br/>L'équipe HookLab</p>
</div>
`,
});
@@ -204,7 +204,7 @@ export async function POST(request: Request) {
}
default:
console.log(`Webhook non gere: ${event.type}`);
console.log(`Webhook non géré: ${event.type}`);
}
return NextResponse.json({ received: true });

View File

@@ -124,7 +124,7 @@ export default function CandidaturePage() {
Candidature <span className="gradient-text">HookLab</span>
</h1>
<p className="text-white/60">
Reponds a quelques questions pour qu&apos;on puisse evaluer ton
Réponds à quelques questions pour qu&apos;on puisse évaluer ton
profil.
</p>
</div>
@@ -151,8 +151,8 @@ export default function CandidaturePage() {
</h2>
<Input
id="firstname"
label="Prenom"
placeholder="Ton prenom"
label="Prénom"
placeholder="Ton prénom"
value={formData.firstname}
onChange={(e) => updateField("firstname", e.target.value)}
/>
@@ -166,7 +166,7 @@ export default function CandidaturePage() {
/>
<Input
id="phone"
label="Telephone"
label="Téléphone"
type="tel"
placeholder="06 12 34 56 78"
value={formData.phone}
@@ -174,7 +174,7 @@ export default function CandidaturePage() {
/>
<Input
id="age"
label="Age"
label="Âge"
type="number"
placeholder="25"
min="18"
@@ -186,13 +186,13 @@ export default function CandidaturePage() {
{/* Persona selection */}
<div className="space-y-1.5">
<label className="block text-sm font-medium text-white/80">
Tu es plutot...
Tu es plutôt...
</label>
<div className="grid grid-cols-2 gap-3">
{[
{
id: "jeune",
label: "Etudiant / Jeune",
label: "Étudiant / Jeune",
emoji: "🎓",
},
{
@@ -231,13 +231,13 @@ export default function CandidaturePage() {
<div className="space-y-1.5">
<label className="block text-sm font-medium text-white/80">
Experience e-commerce / reseaux sociaux
Expérience e-commerce / réseaux sociaux
</label>
<div className="space-y-2">
{[
"Debutant complet",
"J'ai deja teste des choses",
"Je genere deja des revenus en ligne",
"Débutant complet",
"J'ai déjà testé des choses",
"Je génère déjà des revenus en ligne",
].map((opt) => (
<button
key={opt}
@@ -281,11 +281,11 @@ export default function CandidaturePage() {
<div className="space-y-1.5">
<label className="block text-sm font-medium text-white/80">
Disponibilite pour commencer
Disponibilité pour commencer
</label>
<div className="space-y-2">
{[
"Immediatement",
"Immédiatement",
"Dans 1-2 semaines",
"Dans 1 mois",
].map((opt) => (
@@ -360,7 +360,7 @@ export default function CandidaturePage() {
<Textarea
id="biggest_fear"
label="Quelle est ta plus grande peur ?"
placeholder="Qu'est-ce qui pourrait t'empecher de reussir ?"
placeholder="Qu'est-ce qui pourrait t'empêcher de réussir ?"
rows={3}
value={formData.biggest_fear}
onChange={(e) => updateField("biggest_fear", e.target.value)}
@@ -419,7 +419,7 @@ export default function CandidaturePage() {
{/* Step indicator text */}
<p className="text-center text-white/30 text-sm mt-4">
Etape {step} sur 3
Étape {step} sur 3
</p>
</div>
</main>

126
app/cgv/page.tsx Normal file
View File

@@ -0,0 +1,126 @@
import Link from "next/link";
export default function CGV() {
return (
<main className="min-h-screen py-20 md:py-32">
<div className="max-w-3xl mx-auto px-4 sm:px-6">
<Link href="/" className="inline-flex items-center gap-2 mb-10 text-white/40 hover:text-white text-sm transition-colors">
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
Retour à l&apos;accueil
</Link>
<h1 className="text-3xl md:text-4xl font-bold text-white mb-10">Conditions Générales de Vente</h1>
<div className="space-y-8 text-white/70 text-sm leading-relaxed">
<section>
<h2 className="text-xl font-semibold text-white mb-3">Article 1 - Objet</h2>
<p>
Les présentes Conditions Générales de Vente (CGV) régissent la vente du programme de formation
en ligne &ldquo;HookLab&rdquo; proposé par Enguerrand Ozano, entrepreneur individuel, SIREN 994 538 932,
situé au 35 rue Moïse Lambert, 59148 Flines-lez-Raches, France.
</p>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">Article 2 - Description du service</h2>
<p>
HookLab est un programme de coaching en ligne d&apos;une durée de 8 semaines, comprenant :
</p>
<ul className="mt-3 space-y-1 list-disc list-inside">
<li>Des modules vidéo hebdomadaires</li>
<li>Des appels de groupe hebdomadaires</li>
<li>Un support WhatsApp illimité</li>
<li>L&apos;accès à une communauté privée d&apos;entrepreneurs</li>
<li>Des templates et scripts de contenu</li>
<li>Une certification HookLab</li>
</ul>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">Article 3 - Prix et modalités de paiement</h2>
<p>
Le prix du programme est de <strong className="text-white">980 TTC</strong>, payable en 2 mensualités
de 490. Le premier paiement est exigé lors de l&apos;inscription et donne accès immédiat au programme.
Le second paiement est prélevé automatiquement 30 jours après le premier.
</p>
<p className="mt-3">
TVA applicable : FR16994538932. Les paiements sont sécurisés via la plateforme Stripe.
</p>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">Article 4 - Processus de candidature</h2>
<p>
L&apos;accès au programme est soumis à la validation d&apos;un formulaire de candidature. L&apos;éditeur
se réserve le droit de refuser toute candidature sans avoir à en justifier les raisons. En cas de
refus, aucun paiement n&apos;est effectué.
</p>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">Article 5 - Droit de rétractation</h2>
<p>
Conformément à l&apos;article L221-18 du Code de la consommation, le client dispose d&apos;un délai de
<strong className="text-white"> 14 jours</strong> à compter de la date d&apos;achat pour exercer son droit
de rétractation, sans avoir à justifier de motifs ni à payer de pénalités.
</p>
<p className="mt-3">
Pour exercer ce droit, le client doit envoyer un email à <strong className="text-white">contact@hooklab.fr</strong> en
indiquant sa volonté de se rétracter. Le remboursement sera effectué dans un délai de 14 jours
suivant la réception de la demande.
</p>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">Article 6 - Accès au programme</h2>
<p>
L&apos;accès au programme est personnel et non cessible. Le client s&apos;engage à ne pas partager ses
identifiants de connexion ni le contenu du programme avec des tiers. Tout manquement à cette
obligation pourra entraîner la résiliation immédiate de l&apos;accès sans remboursement.
</p>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">Article 7 - Limitation de responsabilité</h2>
<p>
HookLab est un programme de formation et de coaching. Les résultats obtenus dépendent de
l&apos;implication et des actions de chaque participant. Aucune garantie de revenus n&apos;est formulée.
Les témoignages présentés sur le site sont des exemples individuels et ne constituent pas une
promesse de résultats similaires.
</p>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">Article 8 - Protection des données</h2>
<p>
Les données personnelles collectées sont traitées conformément à notre{" "}
<Link href="/confidentialite" className="text-primary hover:underline">
Politique de confidentialité
</Link>.
</p>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">Article 9 - Droit applicable et litiges</h2>
<p>
Les présentes CGV sont soumises au droit français. En cas de litige, une solution amiable sera
recherchée avant toute action judiciaire. À défaut, les tribunaux compétents seront ceux du
ressort du siège social de l&apos;éditeur.
</p>
<p className="mt-3">
Conformément à l&apos;article L612-1 du Code de la consommation, le consommateur peut recourir
gratuitement au service de médiation MEDICYS, par voie électronique à{" "}
<span className="text-white">www.medicys.fr</span> ou par courrier.
</p>
</section>
<p className="text-white/40 pt-4 border-t border-dark-border">
Dernière mise à jour : février 2026
</p>
</div>
</div>
</main>
);
}

View File

@@ -0,0 +1,129 @@
import Link from "next/link";
export default function Confidentialite() {
return (
<main className="min-h-screen py-20 md:py-32">
<div className="max-w-3xl mx-auto px-4 sm:px-6">
<Link href="/" className="inline-flex items-center gap-2 mb-10 text-white/40 hover:text-white text-sm transition-colors">
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
Retour à l&apos;accueil
</Link>
<h1 className="text-3xl md:text-4xl font-bold text-white mb-10">Politique de confidentialité</h1>
<div className="space-y-8 text-white/70 text-sm leading-relaxed">
<section>
<h2 className="text-xl font-semibold text-white mb-3">1. Responsable du traitement</h2>
<p>
Le responsable du traitement des données personnelles est :
</p>
<ul className="mt-3 space-y-1">
<li><strong className="text-white">Enguerrand Ozano</strong></li>
<li>SIREN : 994 538 932</li>
<li>35 rue Moïse Lambert, 59148 Flines-lez-Raches, France</li>
<li>Email : contact@hooklab.fr</li>
</ul>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">2. Données collectées</h2>
<p>Nous collectons les données suivantes :</p>
<ul className="mt-3 space-y-1 list-disc list-inside">
<li><strong className="text-white">Formulaire de candidature :</strong> prénom, email, téléphone, âge, profil (étudiant/parent), expérience, disponibilité, motivation, objectifs, pseudo TikTok</li>
<li><strong className="text-white">Inscription :</strong> email, mot de passe (chiffré)</li>
<li><strong className="text-white">Paiement :</strong> les données bancaires sont traitées directement par Stripe et ne sont jamais stockées sur nos serveurs</li>
<li><strong className="text-white">Navigation :</strong> cookies techniques nécessaires au fonctionnement du site</li>
</ul>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">3. Finalités du traitement</h2>
<p>Les données personnelles sont collectées pour :</p>
<ul className="mt-3 space-y-1 list-disc list-inside">
<li>Traiter les candidatures au programme HookLab</li>
<li>Gérer l&apos;accès à la plateforme de formation</li>
<li>Traiter les paiements et la facturation</li>
<li>Envoyer des communications relatives au programme (emails transactionnels)</li>
<li>Améliorer nos services</li>
</ul>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">4. Base légale</h2>
<p>
Le traitement des données est fondé sur :
</p>
<ul className="mt-3 space-y-1 list-disc list-inside">
<li>L&apos;exécution du contrat (accès au programme après paiement)</li>
<li>Le consentement (formulaire de candidature)</li>
<li>L&apos;intérêt légitime (amélioration des services)</li>
</ul>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">5. Durée de conservation</h2>
<ul className="space-y-1 list-disc list-inside">
<li>Données de candidature : 2 ans à compter de la collecte</li>
<li>Données de compte utilisateur : durée de l&apos;abonnement + 3 ans</li>
<li>Données de facturation : 10 ans (obligation légale)</li>
</ul>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">6. Sous-traitants</h2>
<p>Vos données peuvent être transmises aux sous-traitants suivants :</p>
<ul className="mt-3 space-y-1 list-disc list-inside">
<li><strong className="text-white">Supabase</strong> (hébergement base de données et authentification) - Singapour/UE</li>
<li><strong className="text-white">Stripe</strong> (paiement sécurisé) - États-Unis, certifié Privacy Shield</li>
<li><strong className="text-white">Vercel</strong> (hébergement du site) - États-Unis</li>
<li><strong className="text-white">Resend</strong> (envoi d&apos;emails transactionnels) - États-Unis</li>
</ul>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">7. Vos droits</h2>
<p>
Conformément au RGPD, vous disposez des droits suivants :
</p>
<ul className="mt-3 space-y-1 list-disc list-inside">
<li><strong className="text-white">Droit d&apos;accès :</strong> obtenir une copie de vos données</li>
<li><strong className="text-white">Droit de rectification :</strong> corriger vos données inexactes</li>
<li><strong className="text-white">Droit à l&apos;effacement :</strong> demander la suppression de vos données</li>
<li><strong className="text-white">Droit à la portabilité :</strong> récupérer vos données dans un format structuré</li>
<li><strong className="text-white">Droit d&apos;opposition :</strong> vous opposer au traitement de vos données</li>
<li><strong className="text-white">Droit de limitation :</strong> restreindre le traitement de vos données</li>
</ul>
<p className="mt-3">
Pour exercer vos droits, contactez-nous à <strong className="text-white">contact@hooklab.fr</strong>.
Vous pouvez également adresser une réclamation à la CNIL (www.cnil.fr).
</p>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">8. Cookies</h2>
<p>
Le site utilise uniquement des cookies techniques nécessaires au fonctionnement de la plateforme
(authentification, préférences de session). Aucun cookie publicitaire ou de tracking tiers n&apos;est
utilisé.
</p>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">9. Sécurité</h2>
<p>
Nous mettons en œuvre des mesures techniques et organisationnelles appropriées pour protéger
vos données personnelles : chiffrement des mots de passe, connexions HTTPS, accès restreint
aux données, hébergement sécurisé.
</p>
</section>
<p className="text-white/40 pt-4 border-t border-dark-border">
Dernière mise à jour : février 2026
</p>
</div>
</div>
</main>
);
}

View File

@@ -38,7 +38,7 @@ export default function LoginPage() {
router.push("/dashboard");
router.refresh();
} catch {
setError("Erreur de connexion. Veuillez reessayer.");
setError("Erreur de connexion. Veuillez réessayer.");
} finally {
setLoading(false);
}
@@ -61,7 +61,7 @@ export default function LoginPage() {
Content de te revoir
</h1>
<p className="text-white/60 text-sm">
Connecte-toi pour acceder a tes formations.
Connecte-toi pour accéder à tes formations.
</p>
</div>

View File

@@ -0,0 +1,84 @@
import Link from "next/link";
export default function MentionsLegales() {
return (
<main className="min-h-screen py-20 md:py-32">
<div className="max-w-3xl mx-auto px-4 sm:px-6">
<Link href="/" className="inline-flex items-center gap-2 mb-10 text-white/40 hover:text-white text-sm transition-colors">
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
Retour à l&apos;accueil
</Link>
<h1 className="text-3xl md:text-4xl font-bold text-white mb-10">Mentions légales</h1>
<div className="space-y-8 text-white/70 text-sm leading-relaxed">
<section>
<h2 className="text-xl font-semibold text-white mb-3">1. Éditeur du site</h2>
<p>
Le site <strong className="text-white">hooklab.fr</strong> est édité par :
</p>
<ul className="mt-3 space-y-1">
<li><strong className="text-white">Nom :</strong> Enguerrand Ozano</li>
<li><strong className="text-white">Statut :</strong> Entrepreneur individuel</li>
<li><strong className="text-white">SIREN :</strong> 994 538 932</li>
<li><strong className="text-white">Numéro de TVA :</strong> FR16994538932</li>
<li><strong className="text-white">Adresse :</strong> 35 rue Moïse Lambert, 59148 Flines-lez-Raches, France</li>
<li><strong className="text-white">Email :</strong> contact@hooklab.fr</li>
</ul>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">2. Hébergement</h2>
<p>Le site est hébergé par :</p>
<ul className="mt-3 space-y-1">
<li><strong className="text-white">Vercel Inc.</strong></li>
<li>440 N Barranca Ave #4133, Covina, CA 91723, États-Unis</li>
<li>Site web : vercel.com</li>
</ul>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">3. Propriété intellectuelle</h2>
<p>
L&apos;ensemble des contenus présents sur le site hooklab.fr (textes, images, vidéos, logos, éléments graphiques)
sont protégés par le droit d&apos;auteur et le droit de la propriété intellectuelle. Toute reproduction,
représentation, modification ou exploitation non autorisée est interdite.
</p>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">4. Responsabilité</h2>
<p>
L&apos;éditeur s&apos;efforce de fournir des informations aussi précises que possible. Toutefois, il ne
pourra être tenu responsable des omissions, des inexactitudes ou des carences dans la mise à jour.
Les résultats présentés dans les témoignages sont des exemples individuels et ne constituent pas une
garantie de résultats similaires.
</p>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">5. Liens hypertextes</h2>
<p>
Le site peut contenir des liens vers d&apos;autres sites. L&apos;éditeur ne dispose d&apos;aucun moyen
de contrôle du contenu de ces sites tiers et décline toute responsabilité quant à leur contenu.
</p>
</section>
<section>
<h2 className="text-xl font-semibold text-white mb-3">6. Droit applicable</h2>
<p>
Les présentes mentions légales sont soumises au droit français. En cas de litige, les tribunaux
français seront seuls compétents.
</p>
</section>
<p className="text-white/40 pt-4 border-t border-dark-border">
Dernière mise à jour : février 2026
</p>
</div>
</div>
</main>
);
}

View File

@@ -23,38 +23,38 @@ export default function MerciPage() {
</div>
<h1 className="text-3xl md:text-4xl font-bold tracking-[-0.02em] mb-4">
Candidature <span className="gradient-text">envoyee !</span>
Candidature <span className="gradient-text">envoyée !</span>
</h1>
<p className="text-white/60 text-lg mb-2">
Merci pour ta candidature. Notre equipe va etudier ton profil
Merci pour ta candidature. Notre équipe va étudier ton profil
attentivement.
</p>
<p className="text-white/40 mb-8">
Tu recevras une reponse par email sous 24 heures. Pense a verifier
Tu recevras une réponse par email sous 24 heures. Pense à vérifier
tes spams !
</p>
{/* Étapes suivantes */}
<div className="bg-dark-light border border-dark-border rounded-[20px] p-6 mb-8 text-left">
<h2 className="text-white font-semibold mb-4">Prochaines etapes</h2>
<h2 className="text-white font-semibold mb-4">Prochaines étapes</h2>
<div className="space-y-4">
{[
{
step: "1",
title: "Analyse de ton profil",
desc: "Notre equipe evalue ta candidature",
desc: "Notre équipe évalue ta candidature",
},
{
step: "2",
title: "Email de confirmation",
desc: "Tu recois un email avec le lien de paiement",
desc: "Tu reçois un email avec le lien de paiement",
},
{
step: "3",
title: "Acces au programme",
desc: "Tu commences ta formation immediatement",
title: "Accès au programme",
desc: "Tu commences ta formation immédiatement",
},
].map((item) => (
<div key={item.step} className="flex items-start gap-3">
@@ -71,7 +71,7 @@ export default function MerciPage() {
</div>
<Link href="/">
<Button variant="secondary">Retour a l&apos;accueil</Button>
<Button variant="secondary">Retour à l&apos;accueil</Button>
</Link>
</div>
</main>

View File

@@ -28,7 +28,7 @@ export default function RegisterPage() {
}
if (password.length < 8) {
setError("Le mot de passe doit contenir au moins 8 caracteres.");
setError("Le mot de passe doit contenir au moins 8 caractères.");
setLoading(false);
return;
}
@@ -47,7 +47,7 @@ export default function RegisterPage() {
if (authError) {
if (authError.message.includes("already registered")) {
setError("Un compte avec cet email existe deja.");
setError("Un compte avec cet email existe déjà.");
} else {
setError(authError.message);
}
@@ -57,7 +57,7 @@ export default function RegisterPage() {
router.push("/dashboard");
router.refresh();
} catch {
setError("Erreur lors de l'inscription. Veuillez reessayer.");
setError("Erreur lors de l'inscription. Veuillez réessayer.");
} finally {
setLoading(false);
}
@@ -77,10 +77,10 @@ export default function RegisterPage() {
</span>
</Link>
<h1 className="text-2xl font-bold text-white mb-2">
Creer ton compte
Créer ton compte
</h1>
<p className="text-white/60 text-sm">
Inscris-toi pour acceder au programme.
Inscris-toi pour accéder au programme.
</p>
</div>
@@ -108,7 +108,7 @@ export default function RegisterPage() {
id="password"
label="Mot de passe"
type="password"
placeholder="Minimum 8 caracteres"
placeholder="Minimum 8 caractères"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
@@ -130,13 +130,13 @@ export default function RegisterPage() {
)}
<Button type="submit" loading={loading} className="w-full">
Creer mon compte
Créer mon compte
</Button>
</form>
<div className="mt-6 text-center">
<p className="text-white/40 text-sm">
Deja un compte ?{" "}
Déjà un compte ?{" "}
<Link
href="/login"
className="text-primary hover:text-primary-hover transition-colors"

View File

@@ -4,44 +4,44 @@ import { useState } from "react";
const faqs = [
{
question: "Ai-je besoin d'experience sur TikTok ?",
question: "Ai-je besoin d'expérience sur TikTok ?",
answer:
"Non, aucune experience n'est requise. Notre programme part de zero et t'accompagne etape par etape. Beaucoup de nos eleves n'avaient jamais poste de video avant de commencer.",
"Non, aucune expérience n'est requise. Notre programme part de zéro et t'accompagne étape par étape. Beaucoup de nos élèves n'avaient jamais posté de vidéo avant de commencer.",
},
{
question: "Combien de temps dois-je consacrer par jour ?",
answer:
"Nous recommandons un minimum de 2 heures par jour pour des resultats optimaux. Le programme est concu pour etre flexible et s'adapter a ton emploi du temps, que tu sois etudiant ou parent.",
"Nous recommandons un minimum de 2 heures par jour pour des résultats optimaux. Le programme est conçu pour être flexible et s'adapter à ton emploi du temps, que tu sois étudiant ou parent.",
},
{
question: "Quand vais-je voir mes premiers resultats ?",
question: "Quand vais-je voir mes premiers résultats ?",
answer:
"La plupart de nos eleves generent leurs premieres commissions dans les 2 a 4 premieres semaines. Les resultats varient selon ton implication et le temps consacre.",
"La plupart de nos élèves génèrent leurs premières commissions dans les 2 à 4 premières semaines. Les résultats varient selon ton implication et le temps consacré.",
},
{
question: "Dois-je investir de l'argent en plus du programme ?",
answer:
"Non. L'affiliation TikTok Shop ne necessite aucun stock ni investissement supplementaire. Tu gagnes des commissions sur les ventes generees par tes videos.",
"Non. L'affiliation TikTok Shop ne nécessite aucun stock ni investissement supplémentaire. Tu gagnes des commissions sur les ventes générées par tes vidéos.",
},
{
question: "Le programme est-il adapte a tous les ages ?",
question: "Le programme est-il adapté à tous les âges ?",
answer:
"Oui, nos eleves ont entre 18 et 55 ans. Le programme propose deux parcours adaptes : un pour les jeunes (18-25 ans) et un pour les parents/reconversion (25-45 ans).",
"Oui, nos élèves ont entre 18 et 55 ans. Le programme propose deux parcours adaptés : un pour les jeunes (18-25 ans) et un pour les parents/reconversion (25-45 ans).",
},
{
question: "Comment se deroule le coaching ?",
question: "Comment se déroule le coaching ?",
answer:
"Le coaching comprend des modules video hebdomadaires, des appels de groupe chaque semaine, un support WhatsApp illimite, et l'acces a une communaute privee d'entrepreneurs.",
"Le coaching comprend des modules vidéo hebdomadaires, des appels de groupe chaque semaine, un support WhatsApp illimité, et l'accès à une communauté privée d'entrepreneurs.",
},
{
question: "Puis-je payer en plusieurs fois ?",
answer:
"Oui, le paiement se fait en 2 mensualites de 490€. Le premier paiement donne acces immediat au programme, le second est preleve automatiquement le mois suivant.",
"Oui, le paiement se fait en 2 mensualités de 490€. Le premier paiement donne accès immédiat au programme, le second est prélevé automatiquement le mois suivant.",
},
{
question: "Y a-t-il une garantie de remboursement ?",
answer:
"Oui, nous offrons une garantie satisfait ou rembourse de 14 jours. Si le programme ne te convient pas, tu es rembourse integralement, sans condition.",
"Oui, nous offrons une garantie satisfait ou remboursé de 14 jours. Si le programme ne te convient pas, tu es remboursé intégralement, sans condition.",
},
];
@@ -57,7 +57,7 @@ export default function FAQ() {
FAQ
</span>
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold tracking-[-0.02em] mb-4">
Questions <span className="gradient-text">frequentes</span>
Questions <span className="gradient-text">fréquentes</span>
</h2>
<p className="text-white/60 text-lg">
Tout ce que tu dois savoir avant de te lancer.

View File

@@ -32,7 +32,7 @@ export default function Footer() {
href="#methode"
className="text-white/40 hover:text-white text-sm transition-colors"
>
La methode
La méthode
</a>
</li>
<li>
@@ -40,7 +40,7 @@ export default function Footer() {
href="#temoignages"
className="text-white/40 hover:text-white text-sm transition-colors"
>
Temoignages
Témoignages
</a>
</li>
<li>
@@ -63,14 +63,14 @@ export default function Footer() {
</div>
<div>
<h4 className="text-white font-semibold text-sm mb-4">Legal</h4>
<h4 className="text-white font-semibold text-sm mb-4">Légal</h4>
<ul className="space-y-2.5">
<li>
<Link
href="/mentions-legales"
className="text-white/40 hover:text-white text-sm transition-colors"
>
Mentions legales
Mentions légales
</Link>
</li>
<li>
@@ -86,7 +86,7 @@ export default function Footer() {
href="/confidentialite"
className="text-white/40 hover:text-white text-sm transition-colors"
>
Confidentialite
Confidentialité
</Link>
</li>
</ul>
@@ -96,7 +96,7 @@ export default function Footer() {
{/* Bottom */}
<div className="border-t border-dark-border mt-12 pt-8 flex flex-col md:flex-row items-center justify-between gap-4">
<p className="text-white/30 text-sm">
&copy; {new Date().getFullYear()} HookLab. Tous droits reserves.
&copy; {new Date().getFullYear()} HookLab. Tous droits réservés.
</p>
<div className="flex items-center gap-4">
<a

View File

@@ -15,7 +15,7 @@ export default function Hero() {
<div className="flex flex-wrap justify-center gap-3 mb-8">
<span className="inline-flex items-center gap-1.5 px-3 py-1.5 bg-primary/10 border border-primary/20 rounded-full text-primary text-xs font-medium">
<span className="w-1.5 h-1.5 bg-success rounded-full animate-pulse" />
Places limitees - Promo en cours
Places limitées - Promo en cours
</span>
<span className="inline-flex items-center gap-1.5 px-3 py-1.5 bg-dark-light border border-dark-border rounded-full text-white/60 text-xs font-medium">
Programme 8 semaines
@@ -30,8 +30,8 @@ export default function Hero() {
{/* Sous-titre */}
<p className="text-lg md:text-xl text-white/60 max-w-2xl mx-auto mb-10 leading-relaxed">
Le programme de coaching complet pour devenir createur affilie
TikTok Shop et generer tes premiers revenus en ligne.
Le programme de coaching complet pour devenir créateur affilié
TikTok Shop et générer tes premiers revenus en ligne.
</p>
{/* CTAs */}
@@ -43,7 +43,7 @@ export default function Hero() {
</Link>
<a href="#methode">
<Button variant="secondary" size="lg">
Decouvrir la methode
Découvrir la méthode
</Button>
</a>
</div>
@@ -63,8 +63,8 @@ export default function Hero() {
))}
</div>
<span className="text-sm text-white/60">
<span className="text-white font-semibold">+120</span> eleves
formes
<span className="text-white font-semibold">+120</span> éves
formés
</span>
</div>
<div className="flex items-center gap-1.5">

View File

@@ -5,7 +5,7 @@ const steps = [
number: "01",
title: "Apprends les bases",
description:
"Maitrise les fondamentaux de TikTok Shop, l'algorithme, et les techniques de creation de contenu qui convertissent.",
"Maîtrise les fondamentaux de TikTok Shop, l'algorithme, et les techniques de création de contenu qui convertissent.",
icon: (
<svg
className="w-6 h-6"
@@ -25,9 +25,9 @@ const steps = [
},
{
number: "02",
title: "Lance ton activite",
title: "Lance ton activité",
description:
"Configure ton shop, selectionne tes produits gagnants, et publie tes premieres videos avec notre methode eprouvee.",
"Configure ton shop, sélectionne tes produits gagnants, et publie tes premières vidéos avec notre méthode éprouvée.",
icon: (
<svg
className="w-6 h-6"
@@ -49,7 +49,7 @@ const steps = [
number: "03",
title: "Scale tes revenus",
description:
"Optimise tes performances, automatise tes process, et developpe une strategie de contenu rentable sur le long terme.",
"Optimise tes performances, automatise tes process, et développe une stratégie de contenu rentable sur le long terme.",
icon: (
<svg
className="w-6 h-6"
@@ -76,15 +76,15 @@ export default function Method() {
{/* Header */}
<div className="text-center max-w-2xl mx-auto mb-16">
<span className="inline-block px-3 py-1.5 bg-primary/10 border border-primary/20 rounded-full text-primary text-xs font-medium mb-4">
La methode
La méthode
</span>
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold tracking-[-0.02em] mb-4">
3 etapes vers tes{" "}
3 étapes vers tes{" "}
<span className="gradient-text">premiers revenus</span>
</h2>
<p className="text-white/60 text-lg">
Un programme structure semaine par semaine pour te guider vers la
rentabilite.
Un programme structuré semaine par semaine pour te guider vers la
rentabilité.
</p>
</div>

View File

@@ -4,15 +4,15 @@ const personas = [
{
id: "jeune",
emoji: "🎓",
title: "Etudiant / Jeune actif",
title: "Étudiant / Jeune actif",
subtitle: "18-25 ans",
description:
"Tu veux generer tes premiers revenus en ligne tout en etudiant ou en debut de carriere. TikTok Shop est le levier parfait.",
"Tu veux générer tes premiers revenus en ligne tout en étudiant ou en début de carrière. TikTok Shop est le levier parfait.",
benefits: [
"Flexibilite totale, travaille quand tu veux",
"Flexibilité totale, travaille quand tu veux",
"Pas besoin de stock ni d'investissement",
"Competences marketing valorisables sur ton CV",
"Communaute de jeunes entrepreneurs motives",
"Compétences marketing valorisables sur ton CV",
"Communauté de jeunes entrepreneurs motivés",
],
},
{
@@ -21,12 +21,12 @@ const personas = [
title: "Parent / Reconversion",
subtitle: "25-45 ans",
description:
"Tu cherches un complement de revenus ou une reconversion flexible depuis chez toi. TikTok Shop s'adapte a ton emploi du temps.",
"Tu cherches un complément de revenus ou une reconversion flexible depuis chez toi. TikTok Shop s'adapte à ton emploi du temps.",
benefits: [
"2h par jour suffisent pour demarrer",
"Travaille depuis chez toi, a ton rythme",
"Revenus complementaires des le premier mois",
"Accompagnement personnalise et bienveillant",
"2h par jour suffisent pour démarrer",
"Travaille depuis chez toi, à ton rythme",
"Revenus complémentaires dès le premier mois",
"Accompagnement personnalisé et bienveillant",
],
},
];
@@ -41,11 +41,11 @@ export default function PersonaCards() {
Pour qui ?
</span>
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold tracking-[-0.02em] mb-4">
Un programme adapte a{" "}
Un programme adapté à{" "}
<span className="gradient-text">ton profil</span>
</h2>
<p className="text-white/60 text-lg">
Que tu sois etudiant ou parent, notre methode s&apos;adapte a toi.
Que tu sois étudiant ou parent, notre méthode s&apos;adapte à toi.
</p>
</div>

View File

@@ -4,12 +4,12 @@ import Card from "@/components/ui/Card";
const features = [
"8 semaines de coaching intensif",
"Acces a tous les modules video",
"Accès à tous les modules vidéo",
"Templates et scripts de contenu",
"Appels de groupe hebdomadaires",
"Support WhatsApp illimite",
"Communaute privee d'entrepreneurs",
"Mises a jour a vie du contenu",
"Support WhatsApp illimité",
"Communauté privée d'entrepreneurs",
"Mises à jour à vie du contenu",
"Certification HookLab",
];
@@ -37,7 +37,7 @@ export default function Pricing() {
{/* Popular badge */}
<div className="absolute top-0 left-0 right-0 gradient-bg py-2 text-center">
<span className="text-white text-sm font-semibold">
Offre de lancement - Places limitees
Offre de lancement - Places limitées
</span>
</div>
@@ -51,7 +51,7 @@ export default function Pricing() {
<span className="text-white/40 text-lg">/mois</span>
</div>
<p className="text-white/40 mt-2">
x2 mois (980 total) - Paiement securise via Stripe
x2 mois (980 total) - Paiement sécurisé via Stripe
</p>
</div>
@@ -91,9 +91,9 @@ export default function Pricing() {
{/* Disclaimer */}
<p className="text-center text-white/30 text-xs mt-4">
Candidature soumise a validation. Reponse sous 24h.
Candidature soumise à validation. Réponse sous 24h.
<br />
Satisfait ou rembourse pendant 14 jours.
Satisfait ou remboursé pendant 14 jours.
</p>
</div>
</Card>

View File

@@ -3,25 +3,25 @@ import Card from "@/components/ui/Card";
const testimonials = [
{
name: "Sarah M.",
role: "Etudiante, 22 ans",
role: "Étudiante, 22 ans",
content:
"En 4 semaines, j'ai genere mes premiers 800€ sur TikTok Shop. Le programme m'a donne une methode claire et un accompagnement top.",
"En 4 semaines, j'ai généré mes premiers 800€ sur TikTok Shop. Le programme m'a donné une méthode claire et un accompagnement top.",
revenue: "2 400€/mois",
avatar: "S",
},
{
name: "Thomas D.",
role: "Ex-salarie, 34 ans",
role: "Ex-salarié, 34 ans",
content:
"J'hesitais a me lancer, mais le coaching m'a permis de structurer mon activite. Aujourd'hui je vis de TikTok Shop a plein temps.",
"J'hésitais à me lancer, mais le coaching m'a permis de structurer mon activité. Aujourd'hui je vis de TikTok Shop à plein temps.",
revenue: "4 200€/mois",
avatar: "T",
},
{
name: "Amina K.",
role: "Mere au foyer, 29 ans",
role: "Mère au foyer, 29 ans",
content:
"Je cherchais un complement de revenus flexible. Grace a HookLab, je gagne un SMIC supplementaire en travaillant 2h par jour.",
"Je cherchais un complément de revenus flexible. Grâce à HookLab, je gagne un SMIC supplémentaire en travaillant 2h par jour.",
revenue: "1 600€/mois",
avatar: "A",
},
@@ -34,13 +34,13 @@ export default function Testimonials() {
{/* Header */}
<div className="text-center max-w-2xl mx-auto mb-16">
<span className="inline-block px-3 py-1.5 bg-primary/10 border border-primary/20 rounded-full text-primary text-xs font-medium mb-4">
Temoignages
Témoignages
</span>
<h2 className="text-3xl md:text-4xl lg:text-5xl font-bold tracking-[-0.02em] mb-4">
Ils ont <span className="gradient-text">transforme</span> leur vie
Ils ont <span className="gradient-text">transformé</span> leur vie
</h2>
<p className="text-white/60 text-lg">
Decouvre les resultats de nos eleves apres le programme.
Découvre les résultats de nos éves après le programme.
</p>
</div>