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).
83 lines
3.0 KiB
JavaScript
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;
|
|
}
|
|
}
|