diff --git a/css/swieta.css b/css/swieta.css index 80f18f1..2fee73b 100644 --- a/css/swieta.css +++ b/css/swieta.css @@ -255,6 +255,24 @@ } } +#order-form form.submitting button[type=submit] { + pointer-events: none; + opacity: .7; +} +#order-form form.submitting button[type=submit]::after { + content: ""; + display: inline-block; + width: 1em; + height: 1em; + margin-left: .5rem; + vertical-align: -.15em; + border: 2px solid currentColor; + border-right-color: transparent; + border-radius: 50%; + animation: spin .7s linear infinite; +} +@keyframes spin { to { transform: rotate(360deg); } } + #confirmation { text-align: center; min-height: calc(100vh - var(--nav-height)); diff --git a/js/order.js b/js/order.js index 9941ea0..50fc278 100644 --- a/js/order.js +++ b/js/order.js @@ -29,12 +29,57 @@ function decrease(id) { input.value= min(parseFloat(input.value)-step, 0) calculate_total() } +const busyText = 'Przechodzę do płatności…'; +function lockForm(form) { + console.log("locking form") + console.log(form.querySelector('button')) + console.log(form.querySelector('button[type=submit]')) + const btn = form.querySelector('button[type=submit]'); + form.classList.add('submitting'); + form.setAttribute('aria-busy', 'true'); + btn.dataset.label = btn.dataset.label || btn.textContent; + btn.textContent = busyText; +} + +function unlockForms() { + document.querySelectorAll('form.submitting').forEach(form => { + const btn = form.querySelector('button[type=submit]'); + form.classList.remove('submitting'); + form.removeAttribute('aria-busy'); + if (btn.dataset.label) btn.textContent = btn.dataset.label; + }); +} + +document.body.addEventListener('htmx:beforeRequest', e => { + console.log("form clicked") + const form = e.target; + if (!form.matches('#order-form form')) return; + if (form.classList.contains('submitting')) { e.preventDefault(); return; } // blocks double submit, incl. Enter key + lockForm(form); +}); + +// Replace your existing beforeSwap handler with this one: validation errors and 5xx unlock the form document.body.addEventListener('htmx:beforeSwap', e => { if (e.detail.xhr.status >= 400) { e.detail.shouldSwap = true; e.detail.isError = false; + unlockForms(); } }); +// network failure or timeout: nothing gets swapped, so say something +['htmx:sendError', 'htmx:timeout'].forEach(ev => + document.body.addEventListener(ev, () => { + unlockForms(); + const box = document.getElementById('form-errors'); + if (box) box.textContent = 'Nie udało się połączyć z serwerem. Spróbuj ponownie lub zadzwoń: 690 214 515.'; + }) +); + +// Back button from Stripe can restore the page from cache with the button still locked +window.addEventListener('pageshow', e => { if (e.persisted) unlockForms(); }); + +htmx.config.timeout = 30000; // default is no timeout, so a hung request would spin forever + calculate_total() diff --git a/main.go b/main.go index 17b5ab9..a22ac1f 100644 --- a/main.go +++ b/main.go @@ -22,7 +22,6 @@ import ( "github.com/tdewolff/minify/v2" mcss "github.com/tdewolff/minify/v2/css" - mhtml "github.com/tdewolff/minify/v2/html" mjs "github.com/tdewolff/minify/v2/js" ) @@ -32,10 +31,6 @@ type ComponentRenderer interface { var minifier = sync.OnceValue(func() *minify.M { m := minify.New() - m.Add("text/html", &mhtml.Minifier{ - KeepDocumentTags: true, - KeepEndTags: true, - }) m.Add("text/css", &mcss.Minifier{}) m.Add("application/javascript", &mjs.Minifier{}) return m @@ -66,7 +61,7 @@ func saveFile(name string, comp ComponentRenderer) { if err != nil { log.Fatal(err) } - minified := minifyData("text/html", buf.Bytes()) + minified := buf.Bytes() if name == "index" { err = os.WriteFile("www/index.html", minified, 0666) diff --git a/orders/stripe.go b/orders/stripe.go index 4cd3490..aaea2cd 100644 --- a/orders/stripe.go +++ b/orders/stripe.go @@ -31,10 +31,6 @@ func init() { func startCheckout(w http.ResponseWriter, r *http.Request, o order) { log.Println("ORDER_PENDING", o) - - url := r.URL.RequestURI() - log.Println(url) - s, err := session.New(&stripe.CheckoutSessionParams{ Mode: stripe.String("payment"), ClientReferenceID: stripe.String(o.id), diff --git a/piekarnikgosipl b/piekarnikgosipl new file mode 100755 index 0000000..70225df Binary files /dev/null and b/piekarnikgosipl differ