site-mva-global-fret/js/confirmation.js
Serge RAKOTO HARRY-NAIVO 7217f12bd2 feat(api): migrate Worker mva-hubspot-proxy → mva-api /leads/* routes
Le Cloudflare Worker hubspot-proxy était une solution temporaire car
le panel admin AdminJS n'était pas encore disponible. Maintenant qu'
AdminJS marche, on rapatrie tout le flow inscription côté MVA backend.

## Changements

- `js/form-handler.js`
  - WORKER_PROXY_URL → API_BASE_URL = https://api.mva.mind4solutions.com
  - checkExistingContact : POST /leads/check-email
    (response shape : {exists, firstname, reference_client})
  - setupContactForm : POST /leads/request-verification
  - sendWelcomeBackEmail : POST /leads/welcome-back

- `js/confirmation.js`
  - WORKER_PROXY_URL → API_BASE_URL
  - POST /leads/verify-token (= au lieu de Worker action verifyToken)
  - Detection token expiré/invalide via code INVALID_OR_EXPIRED

## Aucun changement HTML

Les forms HTML, IDs des éléments, validation côté client, gestion
Turnstile sont tous inchangés. Seules les URLs API changent.

## Côté backend (PR #44 mva-prestige-v2)

Les routes mva-api /leads/* sont déployées séparément avec :
- Validation Zod + Turnstile + rate limit
- DB Postgres (table leads + leads_pending) remplace HubSpot Contacts + KV
- Resend pour les emails (= unification écosystème M4S)
- AdminJS Resource leads pour Mélissa CRUD

## Cutover

Cette PR doit être merged + déployée APRÈS la migration backend
(PR #44) + après le run du script migrate-hubspot-to-postgres.js
(= les 4 contacts HubSpot existants en DB).
2026-05-10 11:34:07 +02:00

83 lines
3.0 KiB
JavaScript

// ============================================================
// MVA Global Fret — Page de confirmation post-validation email
// ============================================================
// Cette page est la cible du lien dans l'email de validation envoyé
// par mva-api (= Resend) lors d'une inscription via contact.html.
//
// URL : https://mva-globalfret.com/confirmation.html?token=XXX
//
// Étapes :
// 1. Lire le token depuis l'URL
// 2. POST mva-api /leads/verify-token avec { token }
// 3. mva-api INSERT le lead en DB, génère la ref MVA-NNN, envoie le
// welcome email (= ref + adresse Paris) via Resend, puis renvoie
// { ok: true, firstname, reference_client }
// 4. Page affiche "Inscription confirmée !" + la ref
//
// Si le token est invalide / expiré / déjà consommé : affichage d'un
// message d'erreur avec invitation à contacter le support.
//
// Migration 2026-05-10 : remplace l'ancien Cloudflare Worker
// `mva-hubspot-proxy.sergemind4s.workers.dev` (= décommissionné).
// ============================================================
const API_BASE_URL = 'https://api.mva.mind4solutions.com';
document.addEventListener('DOMContentLoaded', async () => {
const token = new URLSearchParams(window.location.search).get('token');
if (!token) {
showError('Lien de confirmation invalide. Veuillez vérifier votre email ou nous contacter.');
return;
}
try {
const res = await fetch(`${API_BASE_URL}/leads/verify-token`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token }),
});
const data = await res.json();
if (data.ok) {
showSuccess(data.reference_client || null);
} else {
// Token invalide, expiré, ou inconnu
const isInvalid = data.code === 'INVALID_OR_EXPIRED'
|| data.message === 'Token invalide ou expiré';
showError(isInvalid
? 'Ce lien de confirmation a expiré ou a déjà été utilisé.'
: 'Une erreur est survenue lors de la confirmation.');
}
} catch (err) {
console.warn('[confirmation]', err);
showError('Impossible de joindre le serveur. Vérifiez votre connexion et réessayez.');
}
});
function showSuccess(ref) {
const loading = document.getElementById('cardLoading');
const success = document.getElementById('cardSuccess');
if (loading) loading.style.display = 'none';
if (success) {
success.style.display = '';
if (ref) {
const refDisplay = document.getElementById('refDisplay');
const refBlock = document.getElementById('refBlock');
if (refDisplay) refDisplay.textContent = ref;
if (refBlock) refBlock.style.display = '';
}
}
}
function showError(msg) {
const loading = document.getElementById('cardLoading');
const error = document.getElementById('cardError');
if (loading) loading.style.display = 'none';
if (error) {
error.style.display = '';
const desc = error.querySelector('p');
if (desc && msg) desc.textContent = msg;
}
}