Tres minutos: sus datos, su contrato claro, su firma — y el 1er pago. Todo sin compromiso antes de firmar.
1 · Sus datos
2 · Su contrato
3 · Firma & 1er pago
Su establecimiento
Un apunte honesto. Este sistema está pensado para un negocio, y la factura se emite
de empresa a empresa. Si contratas como particular, el IVA aplicable es el de tu país y
lo añado a la factura — no es lo mismo importe. Escríbeme antes de pagar y lo vemos juntos.
Representante que firma
Su proyecto
Para montar su aplicación — con esto ya puedo empezar.
'+arr.map(function(r){return '
'+(r[0]||'')+'
'+(r[1]||r[2]||'')+'
';}).join('')+''; }
var PR;
function refreshFormule(){
var app = !!(gid('fApp') && gid('fApp').checked);
var dir = gid('fDirect').checked;
plan = app ? 'app' : (dir ? 'founder' : 'standard');
gid('mensuWrap').style.display = (plan === 'standard') ? 'block' : 'none';
// Sin web : on ne demande ni domaine, ni photos du local, ni carte en ligne.
// Lui demander ce dont on n'a pas besoin, c'est le faire abandonner.
var bw = gid('blocWeb'); if (bw) bw.style.display = (plan === 'app') ? 'none' : 'block';
if(plan === 'standard'){ months = +gid('mRange').value; var per=Math.round(2000/months)+179;
gid('mMonths').textContent = months; gid('mPerMonth').textContent = per+' €/mes'; }
PR = planRecap();
gid('priceRecap').innerHTML = rowsHTML(PR.echeancier); // contrato Art. 2 (calendario)
gid('formuleRecap').innerHTML = rowsHTML(PR.echeancier); // resumen paso 1
var fl=gid('factureLines'); if(fl) fl.innerHTML = rowsHTML(PR.factura)+'
1er pago hoy
'+(+PR.premier).toLocaleString('es-ES')+' €
';
}
// pré-sélection depuis l'URL (le bouton cliqué sur le pitch)
if(plan==='founder'){ gid('fDirect').checked = true; }
else if(plan==='app'){ gid('fApp').checked = true; }
else { gid('fMensu').checked = true; gid('mRange').value = Math.min(20,Math.max(2,months||20)); }
gid('fApp').addEventListener('change', refreshFormule);
gid('fDirect').addEventListener('change', refreshFormule);
gid('fMensu').addEventListener('change', refreshFormule);
gid('mRange').addEventListener('input', refreshFormule);
refreshFormule();
// guarda fundador : si las 15 plazas están ocupadas, se retira la compra directa
fetch('/spots').then(function(r){return r.json();}).then(function(d){
if(d && d.spots!=null && d.spots<=0){
gid('fDirect').disabled=true;
var lbl=gid('fDirect').closest('label'); if(lbl){ lbl.style.opacity='.5'; lbl.querySelector('span').insertAdjacentHTML('beforeend',' — agotada'); }
if(gid('fDirect').checked){ gid('fMensu').checked=true; refreshFormule(); }
}
}).catch(function(){});
// ----- Envoi des photos -----
(function(){
var b=gid('sendPhotos'); if(!b) return;
b.onclick=async function(){
var inp=gid('photos'); if(!inp.files || !inp.files.length){ gid('photoStatus').textContent='Elija primero sus fotos.'; return; }
b.disabled=true; var old=b.textContent; b.textContent='Enviando…';
var fd=new FormData(); fd.append('resto', gid('resto').value.trim()||'(resto)');
for(var i=0;i✅ '+j.sent+' foto(s) enviada(s) — ¡gracias!' : 'Envío imposible — inténtelo de nuevo o envíelas por WhatsApp.';
}catch(e){ gid('photoStatus').textContent='Envío imposible — inténtelo de nuevo o envíelas por WhatsApp.'; }
b.disabled=false; b.textContent=old;
};
})();
// ----- Navigation étapes -----
function show(n){
['1','2','3'].forEach(function(i){
gid('p'+i).classList.toggle('on', i===n);
var s=gid('st'+i); s.classList.toggle('on', i===n);
s.classList.toggle('done', +i < +n);
});
if(n==='3' && sig){ setTimeout(function(){ sig.ensure(); }, 60); }
window.scrollTo({top:0,behavior:'smooth'});
}
function fillParties(){
var resto=gid('resto').value.trim()||'(nom du restaurant)';
var adr=gid('adresse').value.trim();
var rep=gid('repNom').value.trim();
var qual=gid('repQualite').value.trim();
gid('cParty').innerHTML = ''+resto+''+(adr?' '+adr:'')+(rep?' Representado por '+rep+(qual?' ('+qual+')':''):'');
// pré-remplir la signature depuis le représentant
if(rep && !gid('signNom').value) gid('signNom').value = rep;
if(qual && !gid('signQualite').value) gid('signQualite').value = qual;
}
gid('to2').onclick=function(){
if(!gid('resto').value.trim()){ gid('resto').focus(); gid('resto').style.borderColor='#f87171'; return; }
fillParties(); show('2');
};
gid('back1').onclick=function(){ show('1'); };
gid('to3').onclick=function(){ show('3'); };
gid('back2').onclick=function(){ show('2'); };
// ----- Signature -----
function val(id){ return (gid(id).value||'').trim(); }
gid('doSign').onclick=async function(){
var nom=val('signNom'), lu=gid('luApprouve').checked, signed=sig&&sig.has();
if(!nom || !lu || !signed){
gid('signErr').textContent = !signed ? 'Por favor, firme en el recuadro (con el dedo o el ratón).' : 'Por favor, rellene su nombre y marque «Leído y aprobado, conforme».';
gid('signErr').style.display='block'; return;
}
gid('signErr').style.display='none';
var btn=this; btn.disabled=true; var old=btn.textContent; btn.textContent='Firmando…';
var signImg = sig ? sig.data() : '';
var payload={
resto:val('resto'),adresse:val('adresse'),ide:val('ide'),tel:val('tel'),email:val('email'),
repNom:val('repNom'),repQualite:val('repQualite'),domaine:val('domaine'),menu:val('menu'),notes:val('notes'),
tipoLocal:val('tipoLocal'),mesas:val('mesas'),empleados:val('empleados'),reparto:val('reparto'),idioma:val('idioma'),
herramientas:[].slice.call(document.querySelectorAll('.herr')).filter(function(c){return c.checked;}).map(function(c){return c.value;}).join(', '),
plan:plan,months:String(months),prixRecap:PR.recapText,
signNom:nom,signQualite:val('signQualite'),signLieu:val('signLieu'),signDate:val('signDate'),
luApprouve:true,accepteCGV:gid('accepteCGV').checked,signImg:signImg
};
var j;
try{
var r=await fetch('/sign',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)});
j=await r.json();
if(!j.ok) throw new Error(j.error||'err');
}catch(e){
btn.disabled=false; btn.textContent=old;
gid('signErr').textContent='Algo ha fallado. Inténtelo de nuevo o escríbame por WhatsApp.';
gid('signErr').style.display='block'; return;
}
// apposer la signature (manuscrite + numérique) sur le contrat
var dte = val('signDate')||new Date().toISOString().slice(0,10);
if(signImg){ gid('sigClientImg').src=signImg; gid('sigClientImg').style.display='block'; }
gid('sigClientMeta').innerHTML = nom+(val('signQualite')?' ('+val('signQualite')+')':'')+' En '+(val('signLieu')||'—')+', a '+dte;
gid('sigClientStamp').textContent = 'Firma electrónica con sello de tiempo: '+((j&&j.ts)?new Date(j.ts).toLocaleString('es-ES'):dte);
gid('stampDate').textContent = dte;
// bascule vers paiement
gid('doSign').parentElement.parentElement.style.display='none';
gid('back2').style.display='none';
gid('afterSign').style.display='block';
gid('acompteLine').textContent='1er pago a realizar hoy: '+PR.acompte+' €.';
gid('afterSign').scrollIntoView({behavior:'smooth',block:'center'});
};
gid('dlPdf').onclick=function(){ window.print(); };
gid('payNow').onclick=async function(){
var btn=this; btn.disabled=true; var old=btn.textContent; btn.textContent='Redirigiendo al pago…';
try{
var body={plan:plan,months:months,seo:seoNom,editor:editorOn,nivel:nivel};
var r=await fetch('/checkout',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)});
var j=await r.json();
if(j.ok&&j.url){ location.href=j.url; return; }
throw new Error(j.error||'err');
}catch(e){
btn.disabled=false; btn.textContent=old;
location.href='https://wa.me/351920782244?text=Hola%2C%20he%20firmado%20mi%20contrato%2C%20quiero%20realizar%20mi%201er%20pago';
}
};