151 Dhs
PALPEBRAL Crème est un soin apaisant conçu pour les paupières et le contour des yeux sensibles, secs, irrités et à tendance atopique. Sa formule hypoallergénique, testée sous contrôle dermatologique et ophtalmologique, convient aux enfants dès 3 ans, aux adultes, ainsi qu’aux porteurs de lentilles et aux femmes enceintes ou allaitantes.
Prenez en photo ou scannez votre ordonnance, puis envoyez-la nous sur WhatsApp.
Vous avez jusqu'à 7 jours à compter de la date de livraison pour retourner gratuitement vos produits non ouverts et non endommagés, sans aucun frais supplémentaire — avec un échange ou un remboursement total ou partiel, selon votre choix.
Tous nos produits sont 100% authentiques et originaux, achetés directement auprès des laboratoires et distributeurs officiels.
Aucune contrefaçon, aucun produit reconditionné.
Non, nous sommes 100% digital — pas de point de vente physique ni de click & collect.
Tout se passe en ligne, depuis notre siège à Casablanca (Val Fleurie), avec livraison partout au Maroc.
Si vous rencontrez un souci avec votre commande ou un produit, merci de nous envoyer un email détaillant votre réclamation à l'adresse ci-dessous. Notre équipe vous répondra dans les meilleurs délais.
'); } return w; } catch (e) { return null; } } function openOverlay(){ document.getElementById('pcv-wa-overlay').classList.add('active'); document.getElementById('pcv-wa-backdrop').classList.add('active'); showView('main'); } function closeOverlay(){ document.getElementById('pcv-wa-overlay').classList.remove('active'); document.getElementById('pcv-wa-backdrop').classList.remove('active'); } function updateScrollHint(){ var body = document.querySelector('.pcv-wa-body'); var hint = document.querySelector('.pcv-wa-scroll-hint'); if (!body || !hint) return; var canScroll = body.scrollHeight > body.clientHeight + 4; var atBottom = body.scrollTop + body.clientHeight >= body.scrollHeight - 4; hint.classList.toggle('visible', canScroll && !atBottom); } var currentView = 'main'; function showView(name){ currentView = name; document.querySelectorAll('.pcv-wa-view').forEach(function(v){ v.classList.remove('active'); }); document.querySelector('.pcv-wa-view[data-view="'+name+'"]').classList.add('active');var header = document.getElementById('pcv-wa-header'); var backBtn = document.getElementById('pcv-wa-header-back'); if (name === 'main') { header.classList.remove('has-back'); } else { header.classList.add('has-back'); backBtn.onclick = function(){ showView(parentView[name] || 'main'); }; }var body = document.querySelector('.pcv-wa-body'); body.scrollTop = 0; setTimeout(updateScrollHint, 30); } document.querySelector('.pcv-wa-body').addEventListener('scroll', updateScrollHint); window.addEventListener('resize', updateScrollHint);document.getElementById('pcv-wa-btn').addEventListener('click', function(e){ e.preventDefault(); openOverlay(); }); document.querySelector('.pcv-wa-close').addEventListener('click', closeOverlay); document.getElementById('pcv-wa-backdrop').addEventListener('click', closeOverlay);// Affiche directement prix + stock dès l'ouverture du sous-menu produit (pas besoin de cliquer) function renderProduitInfo(){ var priceBox = document.getElementById('pcv-price-box'); if (isProduct && productPrice) { var priceHtml = (onSale && regularPrice) ? '' + regularPrice + '' + productPrice + '' : '' + productPrice + ''; priceBox.innerHTML = '
Le prix est de :
'; } else { priceBox.innerHTML = '
Merci de vous rendre sur la page du produit qui vous intéresse pour voir son prix ici.
'; }var stockBox = document.getElementById('pcv-stock-box'); var badge; if (isProduct && stockState === 'rupture') { badge = '
'; } else if (isProduct && (stockState === 'faible' || stockState === 'critique')) { badge = '
'; } else if (isProduct && stockState === 'ok') { badge = '
'; } if (isProduct && badge) { stockBox.innerHTML = '
État du stock :
' + badge; } else { stockBox.innerHTML = '
Merci de vous rendre sur la page du produit qui vous intéresse pour voir sa disponibilité ici.
'; } }document.getElementById('pcv-opt-produit-menu').addEventListener('click', function(){ renderProduitInfo(); showView('produit-menu'); });// Autre question produit (avec prix) document.getElementById('pcv-opt-produit').addEventListener('click', function(){ var link = isProduct ? window.location.href : prompt('Lien du produit concerné ?'); if (!link) return; // vide OU annulé var priceTxt = (isProduct && productPrice) ? (' (Prix : ' + productPrice + ')') : ''; sendWA('Bonjour, j\'ai une question concernant ce produit' + priceTxt + ' : ' + link); closeOverlay(); });// Livraison / paiement / authenticité / point de vente / réclamation (info, pas de message) document.getElementById('pcv-opt-livraison').addEventListener('click', function(){ showView('delivery'); }); document.getElementById('pcv-opt-paiement').addEventListener('click', function(){ showView('paiement'); }); document.getElementById('pcv-opt-authenticite').addEventListener('click', function(){ showView('authenticite'); }); document.getElementById('pcv-opt-pointvente').addEventListener('click', function(){ showView('pointvente'); }); document.getElementById('pcv-opt-reclamation-menu').addEventListener('click', function(){ showView('reclamation'); }); document.getElementById('pcv-opt-ordonnance').addEventListener('click', function(){ showView('ordonnance'); });// Remises / codes promo (info, pas de message) document.getElementById('pcv-opt-promo').addEventListener('click', function(){ var box = document.getElementById('pcv-promo-box'); box.innerHTML = '
' + '
Nous n\'avons pas de code promo à offrir en général — mais on a mieux :
' + '
';
showView('promo');
});// Question commande (format N + numéro) — annuler = on n'envoie rien
document.getElementById('pcv-opt-commande').addEventListener('click', function(){
var num = prompt('Numéro de commande (laissez vide si vous ne l\'avez pas) :');
if (num === null) return;
num = num.trim();
var text = num
? 'Bonjour, j\'ai une question concernant ma commande N' + num
: 'Bonjour, j\'ai une question concernant une de mes commandes (je n\'ai pas le numéro sous la main).';
sendWA(text);
closeOverlay();
});// Retour / Annulation - sous-menu
document.getElementById('pcv-opt-retour').addEventListener('click', function(){
showView('retour');
});
document.querySelectorAll('[data-retour]').forEach(function(el){
el.addEventListener('click', function(){
var action = el.getAttribute('data-retour');
var num = prompt('Numéro de la commande concernée (laissez vide si vous ne l\'avez pas) :');
if (num === null) return;
num = num.trim();
var text = 'Bonjour, je souhaite ' + action;
text += num ? (', commande N' + num) : ' (je n\'ai pas le numéro de commande sous la main)';
sendWA(text + '.');
closeOverlay();
});
});// ============================================================
// Ordonnance : disclaimer + upload + envoi (partage natif mobile / lien WhatsApp en fallback desktop)
// ============================================================
(function(){
var fileIn = document.getElementById('pcv-ordo-file');
var drop = document.getElementById('pcv-ordo-drop');
var fname = document.getElementById('pcv-ordo-filename');
var prenom = document.getElementById('pcv-ordo-prenom');
var telIn = document.getElementById('pcv-ordo-tel');
var subBtn = document.getElementById('pcv-ordo-submit');
var omsg = document.getElementById('pcv-ordo-msg');
var fnameDefault = 'Choisir un ou plusieurs fichiers';
// Les photos sont compressées côté navigateur avant l'envoi (voir ordoCompressImage), donc on
// tolère des photos brutes assez lourdes à la sélection (ex: photo 12 Mo prise au smartphone) :
// seul le poids APRÈS compression compte vraiment pour le serveur.
var ordoMaxRawSize = 25 * 1024 * 1024;function ordoCheckReady(){
subBtn.disabled = !(fileIn.files && fileIn.files.length);
}fileIn.addEventListener('change', function(){
omsg.className = 'pcv-wa-msg';
omsg.textContent = '';
if (!fileIn.files.length) { fname.textContent = fnameDefault; drop.classList.remove('has-file'); ordoCheckReady(); return; }var files = Array.prototype.slice.call(fileIn.files);if (files.length > ordoMaxFiles) {
omsg.className = 'pcv-wa-msg error';
omsg.textContent = ordoMaxFiles + ' fichiers max en une fois.';
fileIn.value = '';
fname.textContent = fnameDefault;
drop.classList.remove('has-file');
ordoCheckReady();
return;
}var tooBig = files.some(function(f){ return f.size > ordoMaxRawSize; });
if (tooBig) {
omsg.className = 'pcv-wa-msg error';
omsg.textContent = 'Un des fichiers est trop volumineux.';
fileIn.value = '';
fname.textContent = fnameDefault;
drop.classList.remove('has-file');
ordoCheckReady();
return;
}fname.textContent = (files.length === 1) ? files[0].name : (files.length + ' fichiers sélectionnés');
drop.classList.add('has-file');
ordoCheckReady();
});function ordoResetButton(){
subBtn.disabled = false;
subBtn.classList.remove('is-loading');
subBtn.innerHTML = 'Envoyer via WhatsApp';
}// Remet toute la vue à zéro (fichier, champs, message) pour un prochain envoi
function ordoResetForm(){
fileIn.value = '';
fname.textContent = fnameDefault;
drop.classList.remove('has-file');
prenom.value = '';
telIn.value = '';
omsg.className = 'pcv-wa-msg';
omsg.textContent = '';
ordoResetButton();
subBtn.disabled = true;
}function ordoMakeBatchId(){
if (window.crypto && crypto.randomUUID) return crypto.randomUUID();
return 'b' + Date.now() + Math.random().toString(16).slice(2);
}// Compresse une photo côté navigateur avant l'envoi (redimensionnement + ré-encodage JPEG) pour
// alléger fortement l'upload : plus rapide sur mobile, et moins de charge pour le serveur. Une
// photo de smartphone de 4000x3000px / 6-10 Mo devient généralement une image de ~200-500 Ko.
// Les PDF ne sont pas concernés (on les envoie tels quels).
function ordoCompressImage(file){
return new Promise(function(resolve){
if (!file.type || file.type.indexOf('image/') !== 0) { resolve(file); return; }
if (!window.createImageBitmap && !window.Image) { resolve(file); return; }var maxDim = 1600; // largeur/hauteur max - largement suffisant pour lire une ordonnance
var quality = 0.72;
var url = URL.createObjectURL(file);
var img = new Image();img.onload = function(){
URL.revokeObjectURL(url);
try {
var w = img.naturalWidth || img.width;
var h = img.naturalHeight || img.height;
if (!w || !h) { resolve(file); return; }if (w > maxDim || h > maxDim) {
if (w >= h) { h = Math.round(h * (maxDim / w)); w = maxDim; }
else { w = Math.round(w * (maxDim / h)); h = maxDim; }
}var canvas = document.createElement('canvas');
canvas.width = w;
canvas.height = h;
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, w, h);canvas.toBlob(function(blob){
// Si la compression ne fait pas gagner de poids (photo déjà petite/légère), on garde l'original.
if (!blob || blob.size >= file.size) { resolve(file); return; }
var newName = file.name.replace(/\.[^.]+$/, '') + '.jpg';
resolve(new File([blob], newName, { type: 'image/jpeg' }));
}, 'image/jpeg', quality);
} catch (e) {
resolve(file); // en cas de souci (ex: image corrompue), on envoie l'original tel quel
}
};
img.onerror = function(){ URL.revokeObjectURL(url); resolve(file); };
img.src = url;
});
}function uploadOrdonnance(file, batchId){
var fd = new FormData();
fd.append('action', 'pcv_wa_ordo_upload');
fd.append('nonce', ordoNonce);
fd.append('ordonnance', file);
fd.append('prenom', prenom.value.trim());
fd.append('tel', telIn.value.trim());
fd.append('batch_id', batchId);
return fetch(ajaxUrl, { method: 'POST', body: fd })
.then(function(r){
return r.text().then(function(bodyText){
if (!r.ok) {
throw new Error('Serveur a répondu ' + r.status + (bodyText ? (' - ' + bodyText.slice(0, 150)) : ''));
}
try {
return JSON.parse(bodyText);
} catch (parseErr) {
// La réponse n'était pas du JSON propre (souvent un warning/erreur PHP affiché avant) :
// on montre le tout début de la réponse brute pour comprendre pourquoi.
throw new Error('Réponse invalide du serveur - ' + bodyText.slice(0, 150));
}
});
})
.then(function(res){
if (!res || !res.ok) throw new Error((res && res.msg) || 'Échec de l\'envoi (raison inconnue).');
return res.url;
});
}subBtn.addEventListener('click', function(){
if (subBtn.disabled) return;var files = Array.prototype.slice.call(fileIn.files);
if (!files.length) return;// Ouvert tout de suite, de façon synchrone dans le clic, pour ne pas se faire bloquer par le
// navigateur une fois la compression/l'upload (asynchrones) terminés - voir sendWA().
var waWin = pcvOpenWaTab();subBtn.disabled = true;
subBtn.classList.add('is-loading');
subBtn.textContent = files.length > 1 ? 'Envoi en cours (0/' + files.length + ')...' : 'Envoi en cours...';
omsg.className = 'pcv-wa-msg';
omsg.textContent = '';// On upload systématiquement puis on ouvre WhatsApp avec TON numéro pré-rempli (que le client
// ait ou non déjà ce numéro en contact). Le partage natif du téléphone a été retiré : il ne permet
// pas de cibler un numéro précis, il propose juste "choisir une conversation" au client - inutile
// si le client n'a pas déjà ton numéro enregistré.
// Plusieurs fichiers = plusieurs photos/pages d'une même ordonnance : on les envoie un par un
// au serveur (même batch_id pour les regrouper côté admin), puis on met tous les liens dans un
// seul message WhatsApp.
var batchId = ordoMakeBatchId();
var urls = [];files.reduce(function(chain, file, idx){
return chain.then(function(){
subBtn.textContent = files.length > 1
? 'Compression (' + (idx + 1) + '/' + files.length + ')...'
: 'Compression...';
return ordoCompressImage(file).then(function(compressed){
subBtn.textContent = files.length > 1
? 'Envoi en cours (' + (idx + 1) + '/' + files.length + ')...'
: 'Envoi en cours...';
return uploadOrdonnance(compressed, batchId);
}).then(function(url){
urls.push(url);
});
});
}, Promise.resolve())
.then(function(){
var caption = 'Bonjour, j\'ai mis une ordonnance sur votre site, merci de me confirmer la disponibilité et le prix des produits.';
var who = [];
var p = prenom.value.trim();
var t = telIn.value.trim();
if (p) who.push('au nom de ' + p);
if (t) who.push('sur le numéro ' + t);
if (who.length) caption += ' (' + who.join(', ') + ')';
var numberedUrls = urls.map(function(u, i){ return (i + 1) + ' - ' + u; }).join('\n\n');
sendWA(caption + '\n\n' + numberedUrls, waWin);
closeOverlay();
ordoResetForm();
})
.catch(function(err){
if (window.console && console.error) console.error('Envoi ordonnance échoué :', err);
try { if (waWin && !waWin.closed) waWin.close(); } catch (e) {}
omsg.className = 'pcv-wa-msg error';
// On affiche la vraie raison technique (au lieu d'un message générique) pour pouvoir
// diagnostiquer directement depuis l'écran, sans avoir besoin d'ouvrir la console.
var reason = (err && err.message) ? err.message : 'inconnue';
omsg.textContent = 'Erreur : ' + reason;
ordoResetButton();
});
});
})();// Je veux passer commande : résumé + infos client si panier non vide, sinon message direct
document.getElementById('pcv-opt-passer').addEventListener('click', function(){
var box = document.getElementById('pcv-order-box');
box.innerHTML = '
Chargement...
'; showView('order');fetch(ajaxUrl + '?action=pcv_wa_get_cart') .then(function(r){ return r.json(); }) .then(function(data){ if (data.empty) { sendWA('Bonjour, j\'ai besoin de vous pour passer une commande.'); closeOverlay(); return; }var html = '
';var f = function(id){ var el = document.getElementById(id); return el ? el.value.trim() : ''; }; var s = (data.client || {}); var client = { prenom: (isCheckout && f('billing_first_name')) || s.prenom || '', adresse: (isCheckout && f('billing_address_1')) || s.adresse || '', quartier: (isCheckout && f('billing_quartier')) || s.quartier || '', ville: (isCheckout && f('billing_city')) || s.ville || '', tel: (isCheckout && f('billing_phone')) || s.tel || '', email: (isCheckout && f('billing_email')) || s.email || '' }; var hasClient = client.prenom || client.adresse || client.ville || client.tel || client.email || client.quartier;if (hasClient) { html += '
'; } else { html += '
Vos coordonnées n\'ont pas encore été renseignées sur le site.
'; }html += ''; box.innerHTML = html; updateScrollHint();document.getElementById('pcv-order-confirm').addEventListener('click', function(){ var btn = document.getElementById('pcv-order-confirm'); // Ouvert tout de suite (voir pcvOpenWaTab) pour éviter le blocage popup une fois le fetch // ci-dessous terminé. var waWin = pcvOpenWaTab(); btn.disabled = true; btn.classList.add('is-loading'); btn.innerHTML = 'Préparation du lien...';var params = new URLSearchParams(); params.append('action', 'pcv_wa_save_snapshot'); params.append('prenom', client.prenom); params.append('adresse', client.adresse); params.append('quartier', client.quartier); params.append('ville', client.ville); params.append('tel', client.tel); params.append('email', client.email);fetch(ajaxUrl, { method: 'POST', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, body: params.toString() }) .then(function(r){ return r.json(); }) .then(function(res){ var msg = 'Bonjour, je souhaite passer la commande suivante :\n\n'; data.items.forEach(function(it){ msg += '- ' + it.qty + 'x ' + it.name + ' (' + it.total + ')\n'; }); msg += '\nTotal : ' + data.total + '\n';if (hasClient) { msg += '\n'; if (client.prenom) msg += 'Nom : ' + client.prenom + '\n'; if (client.adresse) msg += 'Adresse : ' + client.adresse + '\n'; if (client.quartier) msg += 'Quartier : ' + client.quartier + '\n'; if (client.ville) msg += 'Ville : ' + client.ville + '\n'; if (client.tel) msg += 'Téléphone : ' + client.tel + '\n'; if (client.email) msg += 'Email : ' + client.email + '\n'; }var link = (res && res.ok) ? res.url : data.checkout_url; msg += '\nLien pour retrouver mon panier + mes coordonnées en un clic : ' + link; sendWA(msg, waWin); closeOverlay(); }) .catch(function(){ try { if (waWin && !waWin.closed) waWin.close(); } catch (e) {} }); }); }); }); })();