From 52df56d7476408d2c2ac5b729b6e02202524a0f3 Mon Sep 17 00:00:00 2001 From: daniel Date: Wed, 7 Oct 2026 14:10:51 +0200 Subject: - Modul SmartCheckout um Abschlussoptionen erweitert --- views/css/smartcheckout.css | 11 + views/js/smartcheckout.js | 115 +++++- views/mods/mod_smartcheckout/checkout.phtml | 441 +++++++++++++---------- views/mods/mod_smartcheckout/settings_edit.phtml | 13 +- 4 files changed, 372 insertions(+), 208 deletions(-) (limited to 'views') diff --git a/views/css/smartcheckout.css b/views/css/smartcheckout.css index aed9849..6b1f0ec 100644 --- a/views/css/smartcheckout.css +++ b/views/css/smartcheckout.css @@ -43,6 +43,11 @@ html body.content-style-boxed .entry-content .wpsg_smartcheckout_after.alignwide .wpsg_smartcheckout .sc_layout { display:grid; grid-template-columns:minmax(0, 1fr) calc(21 * var(--sc-u, 1rem)); gap:var(--sc-gap); align-items:start; } .wpsg_smartcheckout_single .sc_layout { grid-template-columns:minmax(0, 1fr); } .wpsg_smartcheckout .sc_main { display:flex; flex-direction:column; min-width:0; } +/* Hülle der Eingaben, im Bestätigungsschritt gesperrt; ohne die Rahmen und Abstände, die Browser einem fieldset geben */ +.wpsg_smartcheckout .sc_fieldset { display:flex; flex-direction:column; min-width:0; margin:0; padding:0; border:0; } +.wpsg_smartcheckout .sc_fieldset:disabled .sc_box { opacity:0.75; } +.wpsg_smartcheckout .sc_confirm_note { margin-bottom:var(--sc-gap); padding:calc(0.9 * var(--sc-u, 1rem)); border-left:3px solid var(--sc-accent); background:var(--sc-flat); scroll-margin-top:calc(1.5 * var(--sc-u, 1rem)); } +.wpsg_smartcheckout .sc_confirm_note p { margin:calc(0.4 * var(--sc-u, 1rem)) 0 calc(0.75 * var(--sc-u, 1rem)) 0; } .wpsg_smartcheckout .sc_side { position:sticky; top:calc(1.5 * var(--sc-u, 1rem)); } .wpsg_smartcheckout_single .sc_side { position:static; } .wpsg_smartcheckout .sc_layout.sc_busy { opacity:0.6; pointer-events:none; transition:opacity 0.15s ease-out; } @@ -259,6 +264,11 @@ html body.content-style-boxed .entry-content .wpsg_smartcheckout_after.alignwide /* Zusammenfassung */ .wpsg_smartcheckout .sc_summary { position:relative; padding:calc(1.25 * var(--sc-u, 1rem)); border:1px solid var(--sc-line-soft); border-radius:var(--sc-radius); } .wpsg_smartcheckout_single .sc_side { margin-top:var(--sc-gap); } +.wpsg_smartcheckout .sc_sum_products { display:flex; flex-direction:column; gap:calc(0.3 * var(--sc-u, 1rem)); margin-bottom:calc(0.75 * var(--sc-u, 1rem)); padding-bottom:calc(0.75 * var(--sc-u, 1rem)); border-bottom:1px solid var(--sc-line-soft); font-size:calc(0.85 * var(--sc-u, 1rem)); } +.wpsg_smartcheckout .sc_sum_products:empty { display:none; } +.wpsg_smartcheckout .sc_sum_product { display:flex; justify-content:space-between; gap:var(--sc-u, 1rem); align-items:baseline; } +.wpsg_smartcheckout .sc_sum_product_name { min-width:0; overflow-wrap:anywhere; } +.wpsg_smartcheckout .sc_sum_product_price { white-space:nowrap; } .wpsg_smartcheckout .sc_sum_rows { display:flex; flex-direction:column; gap:calc(0.4 * var(--sc-u, 1rem)); } .wpsg_smartcheckout .sc_sum_row { display:flex; justify-content:space-between; gap:var(--sc-u, 1rem); align-items:baseline; font-size:calc(0.95 * var(--sc-u, 1rem)); } .wpsg_smartcheckout .sc_sum_value { white-space:nowrap; } @@ -298,6 +308,7 @@ html body.content-style-boxed .entry-content .wpsg_smartcheckout_after.alignwide .wpsg_smartcheckout .sc_button:disabled { opacity:0.5; cursor:default; } .wpsg_smartcheckout .sc_button_secondary { padding:calc(0.5 * var(--sc-u, 1rem)) calc(0.9 * var(--sc-u, 1rem)); border-color:var(--sc-line); font-size:calc(0.9 * var(--sc-u, 1rem)); } .wpsg_smartcheckout .sc_button_order { width:100%; margin-top:calc(1.1 * var(--sc-u, 1rem)); font-weight:600; } +.wpsg_smartcheckout .sc_button_edit { width:100%; margin-top:calc(0.5 * var(--sc-u, 1rem)); } /* Ladeanzeige */ .wpsg_smartcheckout .sc_spinner { position:absolute; top:calc(1.25 * var(--sc-u, 1rem)); right:calc(1.25 * var(--sc-u, 1rem)); } diff --git a/views/js/smartcheckout.js b/views/js/smartcheckout.js index 20674f8..9c4f4f1 100644 --- a/views/js/smartcheckout.js +++ b/views/js/smartcheckout.js @@ -46,11 +46,25 @@ queued: false, queuedUpload: null, submitting: false, + confirm: false, timer: null }; }, + computed: { + + /** + * Sind Bestellbedingungen und Bestellbutton zu sehen? Beim Bestellabschluss „Zusammenfassung vor Abschluss“ erst im Bestätigungsschritt + */ + showFinal: function() { + + return (this.state.finish !== 'confirm' || this.confirm); + + } // showFinal() + + }, + created: function() { this.syncForm(true); @@ -65,8 +79,8 @@ // Nach einem abgelehnten Bestellversuch steht der Kunde vor dem ersten Fehler if (this.state.errors.length !== 0) this.$nextTick(this.focusError); - // Das GARAN-Gewährleistungslabel erscheint wie in der klassischen Zusammenfassung beim Betreten der Seite - if (this.state.warranty && this.state.warranty.popup === true && this.state.empty !== true) this.garanPopup = true; + // Das GARAN-Gewährleistungslabel erscheint wie in der klassischen Zusammenfassung beim Betreten der Seite, mit Bestätigungsschritt erst dort + if (this.state.warranty && this.state.warranty.popup === true && this.state.empty !== true && this.state.finish !== 'confirm') this.garanPopup = true; // Die Lightbox des Gewährleistungslabels lässt sich mit Esc schließen var self = this; @@ -77,10 +91,13 @@ }); - // Zurück aus dem Seiten-Cache des Browsers (z.B. Zurück-Button nach dem Zahlungsanbieter): Layer wieder entfernen + // Zurück aus dem Seiten-Cache des Browsers (z.B. Zurück-Button nach dem Zahlungsanbieter): Layer entfernen, Eingaben wieder bearbeitbar window.addEventListener('pageshow', function(event) { - if (event.persisted) self.submitting = false; + if (!event.persisted) return; + + self.submitting = false; + self.confirm = false; }); @@ -157,7 +174,7 @@ selectChoice: function(type, id, event) { if (event && event.target && typeof event.target.closest === 'function' && event.target.closest('.sc_choice_head') !== null) return; - if (this.form[type] === id) return; + if (this.form[type] === id || this.confirm) return; this.form[type] = id; this.refresh(); @@ -242,7 +259,8 @@ var el_form = document.getElementById('wpsg_smartcheckout_form'); - if (el_form === null) return; + // Im Bestätigungsschritt sind die Eingaben gesperrt und würden ohne sie übertragen + if (el_form === null || this.confirm) return; // Dateien der direkt hochzuladenden Felder sofort sichern: der Block wird mit der nächsten Antwort neu aufgebaut var arUpload = []; @@ -358,6 +376,8 @@ } + if (action === 'confirm') self.afterConfirm(result.confirm === true); + if (self.queuedUpload !== null) { var upload = self.queuedUpload; @@ -477,8 +497,75 @@ }, // focusError() /** - * Blockt das Absenden, solange der Server noch rechnet + * Prüft die Angaben und wechselt in den Bestätigungsschritt (Bestellabschluss „Zusammenfassung vor Abschluss“) + * + * Die Pflichtfelder der Eingaben prüft zuerst der Browser, Bestellbedingungen und AGB erst der Bestätigungsschritt. */ + startConfirm: function() { + + if (this.busy) return; + + var el_fieldset = el_root.querySelector('.sc_fieldset'); + + if (el_fieldset !== null && typeof el_fieldset.reportValidity === 'function' && !el_fieldset.reportValidity()) return; + + // Eine noch ausstehende Änderung geht in derselben Anfrage mit + if (this.timer !== null) { + + window.clearTimeout(this.timer); + this.timer = null; + + } + + this.send('confirm'); + + }, // startConfirm() + + /** + * Antwort auf startConfirm(): bei bestandener Prüfung Eingaben sperren, sonst zum ersten Fehler + */ + afterConfirm: function(bConfirm) { + + var self = this; + + if (!bConfirm) { + + this.$nextTick(this.focusError); + + return; + + } + + this.confirm = true; + + // Das GARAN-Gewährleistungslabel erscheint wie in der klassischen Zusammenfassung + if (this.state.warranty && this.state.warranty.popup === true && this.garanConfirmed !== true) this.garanPopup = true; + + this.$nextTick(function() { + + var el_note = el_root.querySelector('.sc_confirm_note'); + + if (el_note !== null) el_note.scrollIntoView({ behavior: 'smooth', block: 'start' }); + + }); + + }, // afterConfirm(bConfirm) + + /** + * Verlässt den Bestätigungsschritt, die Eingaben sind wieder bearbeitbar + */ + editConfirm: function() { + + this.confirm = false; + + this.$nextTick(function() { + + el_root.scrollIntoView({ behavior: 'smooth', block: 'start' }); + + }); + + }, // editConfirm() + /** * Berechnet neu, wenn sich eine Eingabe in einem Block der Module ändert (z.B. Lieferadresse, Produktvariablen) * @@ -698,6 +785,20 @@ } + /* + * Gesperrte Felder würden nicht übertragen. Der Browser stellt die Formulardaten erst nach diesem Ereignis + * zusammen, deshalb hier direkt im DOM freigeben und nicht über Vue (das aktualisiert erst später). + */ + if (this.confirm) { + + el_root.querySelectorAll('fieldset.sc_fieldset').forEach(function(el) { + + el.disabled = false; + + }); + + } + // Ab hier wird tatsächlich bestellt: Layer über die Seite, bis der Browser die nächste Seite lädt this.submitting = true; diff --git a/views/mods/mod_smartcheckout/checkout.phtml b/views/mods/mod_smartcheckout/checkout.phtml index 947f3d8..043b151 100644 --- a/views/mods/mod_smartcheckout/checkout.phtml +++ b/views/mods/mod_smartcheckout/checkout.phtml @@ -46,269 +46,281 @@
- -
-

1

- -
+ +
+ +

+ +
-
+ +
-
+ +
+

1

-
- -
+
-
+
- -
+
-
- {{ product.name }} - {{ product.name }} +
+
-
-
-
-
+
-
- {{ product.tax_value }} -
+ +
-
+
+ {{ product.name }} + {{ product.name }} +
-
+
+
+
+
+ +
+ {{ product.tax_value }} +
-
- - -
-
- - {{ product.amount }} +
+ +
+ + + +
+ +
+ + {{ product.amount }} +
+ + +
- +
+
{{ product.price_total }}
+
{{ product.price }}
+
-
+ +
-
-
{{ product.price_total }}
-
{{ product.price }}
- -
-
-
+
-
- - hasMod('wpsg_mod_gutschein')) { ?> -
- - - -
- - -
+ hasMod('wpsg_mod_gutschein')) { ?> +
+ + -
-
- {{ item.code }} - - {{ item.value }} - +
+ +
+ +
+
+ {{ item.code }} + + {{ item.value }} + +
+
+
+ -
- +
-
+ +
+

2

- -
-

2

+ + - - +
-
- -
- - - - - - - + +
-
+ +
+ + + + +
- -
- - - - -
+
+ *'); ?> +
-
- *'); ?> -
+
-
+ + view]); ?> + +
+ +
+ - - view]); ?> - -
- -
- + +
- -
+ +
+

3

- -
-

3

+
-
+ +
- -
+ + +
- - -
+
-
+
-
+ +
+

4

- -
-

4

+
-
+ +
- -
+ + +
+
- - -
-
+
-
+ +
- -
+
-
+ +
+

- -
-

+ + - - +
-
+
@@ -319,6 +331,14 @@

+ +
+
+ {{ product.amount }} × {{ product.name }} + {{ product.price_total }} +
+
+
@@ -398,11 +418,11 @@
-
+