v1.4.0 — 16 servizi reali Ianni, sala unica, ricevuta PDF
- Migration: services.price_cents, services.availability_text
- Migration: bookings.receipt_number (trigger annuale IANNI-YYYY-NNNN) + receipt_token
- Constraint EXCLUDE bookings_no_overlap (sala unica, status confirmed/completed)
- availability.py: calcolo slot globale (non più per-provider)
- 16 servizi reali da Servizi.xls inseriti, 9 demo archiviati con FK preservata
- provider_services: 3 profili orari (lun-sab 9-19, lun-mar 9-13, lun-gio 9-13)
- Endpoint GET /api/receipts/{token} → PDF WeasyPrint
- Template HTML ricevuta con palette Ianni
- Dockerfile: deps sistema weasyprint (pango/cairo/fonts)
- requirements: +weasyprint>=63.0
- Frontend index.html: prezzo + fascia oraria nelle card servizio, link Scarica ricevuta nella conferma
This commit is contained in:
@@ -148,11 +148,15 @@ function renderServices(m) {
|
||||
for (const [cat, list] of Object.entries(g)) {
|
||||
html += '<div class="text-xs font-bold uppercase tracking-widest text-teal-600 mb-2 mt-5">'+cat+'</div>';
|
||||
for (const s of list) {
|
||||
html += '<div class="svc-card flex items-center justify-between p-4 mb-2 rounded-2xl bg-white/50 border-2 border-transparent" onclick="pickSvc('+s.id+')">';
|
||||
html += '<div><div class="font-semibold text-[15px] text-gray-900">'+s.name+'</div>';
|
||||
html += '<div class="svc-card flex items-start justify-between p-4 mb-2 rounded-2xl bg-white/50 border-2 border-transparent" onclick="pickSvc('+s.id+')">';
|
||||
html += '<div class="flex-1 pr-3"><div class="font-semibold text-[15px] text-gray-900">'+s.name+'</div>';
|
||||
if(s.description) html += '<div class="text-[13px] text-gray-500 mt-0.5">'+s.description+'</div>';
|
||||
if(s.availability_text) html += '<div class="text-[12px] text-gray-400 mt-1">⏱ '+s.availability_text+'</div>';
|
||||
html += '</div>';
|
||||
html += '<div class="flex flex-col items-end gap-1 ml-2 whitespace-nowrap">';
|
||||
if(s.price_cents != null) html += '<span class="text-[15px] font-bold text-gray-900">€ '+(s.price_cents/100).toFixed(2).replace(".",",")+'</span>';
|
||||
html += '<span class="text-xs font-semibold text-teal-600 bg-teal-50 px-2.5 py-1 rounded-full">'+s.duration_min+' min</span>';
|
||||
html += '</div>';
|
||||
html += '<span class="text-xs font-semibold text-teal-600 bg-teal-50 px-3 py-1.5 rounded-full ml-4 whitespace-nowrap">'+s.duration_min+' min</span>';
|
||||
html += '</div>';
|
||||
}
|
||||
}
|
||||
@@ -310,6 +314,7 @@ async function submitBooking() {
|
||||
})
|
||||
});
|
||||
if(!r.ok) { const e = await r.json(); throw new Error(e.detail || 'Errore'); }
|
||||
lastBooking = await r.json();
|
||||
go(3);
|
||||
} catch(e) {
|
||||
document.getElementById('err').innerHTML = '<div class="text-red-600 text-sm mb-4 p-3 bg-red-50 rounded-xl">'+e.message+'</div>';
|
||||
@@ -326,9 +331,9 @@ function renderConfirm(m) {
|
||||
'<p class="text-sm text-gray-500 leading-relaxed">' +
|
||||
'<strong class="text-gray-900">'+sel.name+'</strong><br>' +
|
||||
fl(selDate)+' alle <strong class="text-gray-900">'+selSlot.start+'</strong><br><br>' +
|
||||
'Riceverai conferma su WhatsApp<br>al numero <strong class="text-gray-900">'+lastPhone+'</strong>' +
|
||||
'Riceverai conferma su WhatsApp<br>al numero <strong class="text-gray-900">'+lastPhone+'</strong>' +(lastBooking && lastBooking.receipt_number ? '<br><br><span class="text-[11px] uppercase tracking-wider text-gray-400">Ricevuta</span><br><strong class="text-gray-900 text-sm">'+lastBooking.receipt_number+'</strong>' : '') +
|
||||
'</p>' +
|
||||
'<a href="https://wa.me/393930579002" target="_blank" class="inline-flex items-center gap-2 mt-6 px-6 py-3 rounded-xl text-white font-semibold text-sm" style="background:#25d366;text-decoration:none">💬 Contattaci su WhatsApp</a>' +
|
||||
'<div class="mt-6 flex flex-col items-center gap-3">' +(lastBooking && lastBooking.receipt_token ? '<a href="'+API+'/api/receipts/'+lastBooking.receipt_token+'" target="_blank" class="inline-flex items-center gap-2 px-6 py-3 rounded-xl font-semibold text-sm" style="background:#002C50;color:white;text-decoration:none">📄 Scarica la ricevuta (PDF)</a>' : '') +'<a href="https://wa.me/393930579002" target="_blank" class="inline-flex items-center gap-2 px-6 py-3 rounded-xl text-white font-semibold text-sm" style="background:#25d366;text-decoration:none">💬 Contattaci su WhatsApp</a>' +'</div>' +
|
||||
'<div class="mt-5"><button onclick="location.reload()" class="text-teal-600 text-sm font-semibold hover:underline cursor-pointer" style="background:none;border:none">Prenota un altro servizio</button></div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user