279 lines
12 KiB
Plaintext
279 lines
12 KiB
Plaintext
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
|
|
<title>Ethica — Consentement</title>
|
|
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&display=swap" rel="stylesheet">
|
|
<style>
|
|
:root{--teal:#0d7c66;--teal-light:#10a37f;--teal-dark:#065a4a;--bg:#f0f5f3;--white:#fff;--text:#1a2e35;--text2:#5a7a84;--text3:#8aa4ac;--border:#d4e4de;--green:#10b981;--red:#ef4444;--orange:#f59e0b}
|
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
body{font-family:'DM Sans',sans-serif;background:var(--bg);color:var(--text);min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px}
|
|
.card{background:var(--white);border-radius:20px;box-shadow:0 8px 40px rgba(13,124,102,.12);max-width:520px;width:100%;overflow:hidden}
|
|
.card-header{background:linear-gradient(135deg,var(--teal),var(--teal-light));padding:32px 36px;text-align:center;color:#fff}
|
|
.card-header .pill{display:inline-block;font-size:32px;margin-bottom:8px}
|
|
.card-header h1{font-size:22px;font-weight:700;margin-bottom:4px}
|
|
.card-header p{font-size:13px;opacity:.8}
|
|
.card-body{padding:32px 36px}
|
|
.welcome{font-size:15px;line-height:1.6;color:var(--text);margin-bottom:24px}
|
|
.welcome b{color:var(--teal-dark)}
|
|
.info-box{background:#f7faf9;border:1px solid var(--border);border-radius:12px;padding:16px;margin-bottom:24px;font-size:13px;line-height:1.6;color:var(--text2)}
|
|
.info-box ul{padding-left:18px;margin-top:8px}
|
|
.info-box li{margin-bottom:4px}
|
|
|
|
/* Consent checkboxes */
|
|
.consent-group{margin-bottom:24px}
|
|
.consent-group h3{font-size:14px;font-weight:700;color:var(--text);margin-bottom:14px;display:flex;align-items:center;gap:8px}
|
|
.consent-item{display:flex;align-items:flex-start;gap:12px;padding:14px 16px;border:1px solid var(--border);border-radius:10px;margin-bottom:10px;cursor:pointer;transition:.15s}
|
|
.consent-item:hover{border-color:var(--teal-light);background:#f7faf9}
|
|
.consent-item.checked{border-color:var(--teal);background:rgba(13,124,102,.05)}
|
|
.consent-item input[type=checkbox]{width:20px;height:20px;accent-color:var(--teal);cursor:pointer;flex-shrink:0;margin-top:2px}
|
|
.consent-item label{cursor:pointer;font-size:13px;line-height:1.5;color:var(--text)}
|
|
.consent-item label b{display:block;font-size:14px;margin-bottom:2px}
|
|
|
|
/* Buttons */
|
|
.btn-row{display:flex;gap:10px;margin-bottom:20px}
|
|
.btn{flex:1;padding:14px;border:none;border-radius:10px;font-family:inherit;font-size:15px;font-weight:700;cursor:pointer;transition:.15s;display:flex;align-items:center;justify-content:center;gap:8px}
|
|
.btn-accept{background:var(--teal);color:#fff}.btn-accept:hover{background:var(--teal-dark)}
|
|
.btn-refuse{background:#f1f5f4;color:var(--text2);border:1px solid var(--border)}.btn-refuse:hover{background:#e8efec}
|
|
.btn:disabled{opacity:.5;cursor:not-allowed}
|
|
|
|
/* Legal */
|
|
.legal{font-size:11px;color:var(--text3);line-height:1.6;border-top:1px solid var(--border);padding-top:16px;margin-top:8px}
|
|
.legal a{color:var(--teal);text-decoration:none}
|
|
|
|
/* Footer */
|
|
.card-footer{background:#f7faf9;padding:14px 36px;text-align:center;border-top:1px solid var(--border)}
|
|
.card-footer p{font-size:10px;color:var(--text3)}
|
|
|
|
/* States */
|
|
.state{display:none;text-align:center;padding:40px 36px}
|
|
.state.active{display:block}
|
|
.state .icon{font-size:48px;margin-bottom:16px}
|
|
.state h2{font-size:20px;margin-bottom:10px}
|
|
.state p{font-size:14px;color:var(--text2);line-height:1.6}
|
|
|
|
/* Loading */
|
|
.loading{text-align:center;padding:60px 36px}
|
|
.spinner{width:36px;height:36px;border:3px solid var(--border);border-top-color:var(--teal);border-radius:50%;animation:spin .8s linear infinite;margin:0 auto 16px}
|
|
@keyframes spin{to{transform:rotate(360deg)}}
|
|
|
|
@media(max-width:480px){.card-body,.state{padding:24px 20px}.card-header{padding:24px 20px}.btn-row{flex-direction:column}}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<div class="pill">💊</div>
|
|
<h1>Ethica Pharma</h1>
|
|
<p>Communication professionnelle de santé</p>
|
|
</div>
|
|
|
|
<!-- Loading State -->
|
|
<div class="state active" id="s-loading">
|
|
<div class="spinner"></div>
|
|
<p>Chargement de votre fiche...</p>
|
|
</div>
|
|
|
|
<!-- Consent Form -->
|
|
<div class="state" id="s-form">
|
|
<div class="card-body" style="padding:0;text-align:left">
|
|
<p class="welcome" id="welcome-msg">Bonjour Dr <b id="hcp-name">—</b>,</p>
|
|
<div class="info-box">
|
|
En donnant votre accord, vous recevrez des communications ciblées et pertinentes pour votre pratique :
|
|
<ul>
|
|
<li>Nouvelles publications et études cliniques</li>
|
|
<li>Informations produits et mises à jour thérapeutiques</li>
|
|
<li>Invitations à des webinaires et événements médicaux</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="consent-group">
|
|
<h3>📋 Vos préférences de communication</h3>
|
|
<div class="consent-item" onclick="toggle('c-email')">
|
|
<input type="checkbox" id="c-email" checked>
|
|
<label for="c-email">
|
|
<b>✉ Communications par email</b>
|
|
Recevoir des informations médicales et scientifiques par email
|
|
</label>
|
|
</div>
|
|
<div class="consent-item" onclick="toggle('c-sms')">
|
|
<input type="checkbox" id="c-sms">
|
|
<label for="c-sms">
|
|
<b>📱 Communications par SMS</b>
|
|
Recevoir des alertes et invitations par SMS
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="btn-row">
|
|
<button class="btn btn-accept" id="btn-accept" onclick="submitConsent('optin')">✓ J'accepte</button>
|
|
<button class="btn btn-refuse" onclick="submitConsent('optout')">✕ Je refuse</button>
|
|
</div>
|
|
|
|
<div class="legal">
|
|
Conformément aux législations en vigueur — <b>Loi 09-08</b> (Maroc/CNDP), <b>Loi organique 63-2004</b> (Tunisie/INPDP), <b>Loi 18-07</b> (Algérie/ANPDP) — votre consentement est <b>libre, éclairé et révocable</b> à tout moment.<br><br>
|
|
<b>Responsable du traitement :</b> WEVAL Consulting pour le compte d'Ethica Group (CFAO Healthcare).<br>
|
|
<b>Finalité :</b> envoi de communications médicales et scientifiques professionnelles.<br>
|
|
<b>Données traitées :</b> nom, prénom, email, téléphone, spécialité, ville d'exercice.<br>
|
|
<b>Durée de conservation :</b> jusqu'au retrait du consentement.<br>
|
|
<b>Droits :</b> accès, rectification, suppression, opposition — contactez <a href="mailto:dpo@weval-consulting.com">dpo@weval-consulting.com</a><br><br>
|
|
Vous pouvez retirer votre consentement à tout moment en cliquant sur le lien de désinscription présent dans chaque communication ou en accédant à cette page.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Success State -->
|
|
<div class="state" id="s-success">
|
|
<div class="icon">✅</div>
|
|
<h2>Merci pour votre confiance !</h2>
|
|
<p id="success-msg">Votre consentement a été enregistré. Vous recevrez prochainement des informations médicales pertinentes pour votre pratique.</p>
|
|
</div>
|
|
|
|
<!-- Optout State -->
|
|
<div class="state" id="s-optout">
|
|
<div class="icon">📭</div>
|
|
<h2>Désinscription enregistrée</h2>
|
|
<p>Vous ne recevrez plus de communications de notre part. Vous pouvez modifier vos préférences à tout moment en accédant à cette page.</p>
|
|
</div>
|
|
|
|
<!-- Error State -->
|
|
<div class="state" id="s-error">
|
|
<div class="icon">⚠️</div>
|
|
<h2>Lien expiré ou invalide</h2>
|
|
<p>Ce lien de consentement n'est pas valide ou a déjà été utilisé. Si vous souhaitez gérer vos préférences, veuillez utiliser le lien le plus récent reçu par email.</p>
|
|
<div style="margin-top:20px">
|
|
<div class="info-box" style="text-align:left">
|
|
<b>Vous pouvez aussi rechercher votre fiche :</b>
|
|
<div style="display:flex;gap:8px;margin-top:10px">
|
|
<input type="text" id="search-input" placeholder="Email ou téléphone..." style="flex:1;padding:10px 14px;border:1px solid var(--border);border-radius:8px;font-family:inherit;font-size:13px">
|
|
<button class="btn btn-accept" style="flex:0;padding:10px 20px;font-size:13px" onclick="searchHCP()">🔍</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Not Found State -->
|
|
<div class="state" id="s-notfound">
|
|
<div class="icon">🔍</div>
|
|
<h2>Aucun résultat</h2>
|
|
<p>Aucun professionnel de santé trouvé avec cette adresse. Vérifiez votre email ou contactez-nous.</p>
|
|
</div>
|
|
|
|
<div class="card-footer">
|
|
<p>🔒 Ethica Group · WEVAL Consulting — Connexion sécurisée — Vos données sont protégées</p>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
const API = window.location.origin + '/api/ethica-consent.php';
|
|
const params = new URLSearchParams(window.location.search);
|
|
const token = params.get('token');
|
|
const action = params.get('action');
|
|
|
|
function show(id){ document.querySelectorAll('.state').forEach(s=>s.classList.remove('active')); document.getElementById('s-'+id).classList.add('active'); }
|
|
function toggle(id){ const cb=document.getElementById(id); cb.checked=!cb.checked; cb.closest('.consent-item').classList.toggle('checked',cb.checked); }
|
|
|
|
// Init: check token
|
|
async function init(){
|
|
if(!token || token==='TEST'){
|
|
// No token or test → show error/search
|
|
show('error');
|
|
return;
|
|
}
|
|
|
|
try{
|
|
// Validate token + get HCP info
|
|
const r = await fetch(API + '?action=validate_token&token=' + encodeURIComponent(token));
|
|
const d = await r.json();
|
|
|
|
if(d.ok && d.hcp){
|
|
// Show form with HCP info
|
|
document.getElementById('hcp-name').textContent = (d.hcp.prenom||'') + ' ' + (d.hcp.nom||'');
|
|
if(d.hcp.specialite) {
|
|
document.querySelector('.welcome').innerHTML = 'Bonjour Dr <b>' + (d.hcp.prenom||'') + ' ' + (d.hcp.nom||'') + '</b>,<br><span style="font-size:13px;color:var(--text2)">' + d.hcp.specialite + ' — ' + (d.hcp.ville||'') + ', ' + (d.hcp.pays||'') + '</span>';
|
|
}
|
|
|
|
// If action=optin in URL, auto-check email
|
|
if(action==='optin') document.getElementById('c-email').checked = true;
|
|
if(action==='optout'){
|
|
// Direct optout
|
|
submitConsent('optout');
|
|
return;
|
|
}
|
|
|
|
show('form');
|
|
} else {
|
|
show('error');
|
|
}
|
|
} catch(e){
|
|
show('error');
|
|
}
|
|
}
|
|
|
|
async function submitConsent(type){
|
|
const btn = document.getElementById('btn-accept');
|
|
btn.disabled = true; btn.textContent = 'Enregistrement...';
|
|
|
|
const channels = [];
|
|
if(document.getElementById('c-email').checked) channels.push('email');
|
|
if(document.getElementById('c-sms').checked) channels.push('sms');
|
|
|
|
try{
|
|
const r = await fetch(API + '?action=submit_consent', {
|
|
method: 'POST',
|
|
headers: {'Content-Type':'application/json'},
|
|
body: JSON.stringify({
|
|
token: token,
|
|
consent: type,
|
|
channels: channels,
|
|
ip: '', // Server will capture
|
|
timestamp: new Date().toISOString()
|
|
})
|
|
});
|
|
const d = await r.json();
|
|
|
|
if(type==='optin'){
|
|
const ch = channels.length ? channels.join(' + ') : 'email';
|
|
document.getElementById('success-msg').textContent = 'Votre consentement a été enregistré pour les communications par ' + ch + '. Vous recevrez prochainement des informations médicales pertinentes pour votre pratique.';
|
|
show('success');
|
|
} else {
|
|
show('optout');
|
|
}
|
|
} catch(e){
|
|
alert('Erreur de connexion. Veuillez réessayer.');
|
|
btn.disabled = false; btn.textContent = '✓ J\'accepte';
|
|
}
|
|
}
|
|
|
|
async function searchHCP(){
|
|
const q = document.getElementById('search-input').value.trim();
|
|
if(!q) return;
|
|
|
|
try{
|
|
const r = await fetch(API + '?action=search&q=' + encodeURIComponent(q));
|
|
const d = await r.json();
|
|
if(d.ok && d.token){
|
|
// Redirect with found token
|
|
window.location.href = '/?token=' + d.token + '&action=optin';
|
|
} else {
|
|
show('notfound');
|
|
}
|
|
} catch(e){
|
|
show('notfound');
|
|
}
|
|
}
|
|
|
|
// Enter key for search
|
|
document.addEventListener('keydown', function(e){
|
|
if(e.key==='Enter' && document.getElementById('s-error').classList.contains('active')){
|
|
searchHCP();
|
|
}
|
|
});
|
|
|
|
init();
|
|
</script>
|
|
</body>
|
|
</html>
|