From b7efe92a980009b2627d36cd9d5156c748a97a71 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Patrick=20M=C3=BCller?= <p.mueller@pcsg.de>
Date: Wed, 24 Jul 2024 10:00:47 +0200
Subject: [PATCH] feat: checkout form validation

---
 bin/frontend/controls/SimpleCheckout.js       | 64 +++++++++++--------
 .../controls/SimpleCheckoutPayment.js         |  9 ++-
 bin/frontend/controls/SimpleCheckoutWindow.js | 33 ++++++----
 .../ERP/Order/SimpleCheckout/Checkout.html    |  2 +-
 4 files changed, 66 insertions(+), 42 deletions(-)

diff --git a/bin/frontend/controls/SimpleCheckout.js b/bin/frontend/controls/SimpleCheckout.js
index 8027ece..e11c630 100644
--- a/bin/frontend/controls/SimpleCheckout.js
+++ b/bin/frontend/controls/SimpleCheckout.js
@@ -32,20 +32,22 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
         ],
 
         options: {
-            orderHash        : false,
-            loadHashFromUrl  : false,
-            showPayToOrderBtn: true,
+            orderHash           : false,
+            loadHashFromUrl     : false,
+            showPayToOrderBtn   : true,
+            showOrderSuccessInfo: true
         },
 
         initialize: function (options) {
             this.parent(options);
 
-            this.$Delivery      = null;
-            this.$Billing       = null;
-            this.$Shipping      = null;
-            this.$Payment       = null;
-            this.Loader         = null;
-            this.$PayToOrderBtn = null;
+            this.$Form              = null;
+            this.$Delivery          = null;
+            this.$Billing           = null;
+            this.$Shipping          = null;
+            this.$Payment           = null;
+            this.Loader             = null;
+            this.$PayToOrderBtn     = null;
             this.ScrollToPaymentBtn = null;
 
             this.showAllProductsBtn = null;
@@ -65,13 +67,17 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
         },
 
         $onImport: function () {
-            this.Loader = new QUILoader().inject(this.getElm());
+            const Elm = this.getElm();
+
+            this.Loader = new QUILoader().inject(Elm);
             this.$setAnchor();
 
             if (parseInt(this.getElm().get('data-qui-load-hash-from-url')) === 1) {
                 this.setAttribute('loadHashFromUrl', true);
             }
 
+            this.$Form = Elm.getElement('form');
+
             this.getElm().getElements('a.log-in').addEvent('click', (e) => {
                 e.stop();
 
@@ -303,7 +309,7 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
                     this.$PayToOrderBtn = null;
                 }
 
-                this.ScrollToPaymentBtn =  this.getElm().querySelector('.quiqqer-simple-checkout__scrollToPaymentBtn');
+                this.ScrollToPaymentBtn = this.getElm().querySelector('.quiqqer-simple-checkout__scrollToPaymentBtn');
 
                 if (this.ScrollToPaymentBtn) {
                     this.ScrollToPaymentBtn.addEvent('click', this.scrollToPayment);
@@ -325,9 +331,9 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
                         const Container = this.getElm().getElement('.quiqqer-simple-checkout-container');
 
                         // for the OrderProcess.js
-                        if (this.getElm().getElement('form')) {
-                            this.getElm().getElement('form').set('data-order-hash', result.orderHash);
-                            this.getElm().getElement('form').set('data-products-count', result.productCount);
+                        if (this.$Form) {
+                            this.$Form.set('data-order-hash', result.orderHash);
+                            this.$Form.set('data-products-count', result.productCount);
                         }
 
                         moofx(Container).animate({
@@ -445,6 +451,10 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
             this.Loader.show();
 
             return this.update().then(() => {
+                if (!this.$Form.reportValidity()) {
+                    return;
+                }
+
                 this.Loader.show();
                 const Terms = this.getElm().getElement('[name="termsAndConditions"]');
 
@@ -478,6 +488,12 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
                         this.getElm().getElement('form').set('data-products-count', result.productCount);
                     }
 
+                    this.fireEvent('orderSuccessful', [this]);
+
+                    if (!this.getAttribute('showOrderSuccessInfo')) {
+                        return;
+                    }
+
                     moofx(Container).animate({
                         opacity: 0
                     }, {
@@ -499,7 +515,7 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
                                             });
                                         }
 
-                                        this.fireEvent('orderSuccessful', [this]);
+                                        this.fireEvent('showOrderSuccessInfo', [this]);
                                     }
                                 });
                             });
@@ -603,10 +619,6 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
                         this.fireEvent('orderInvalid', [this]);
                     }
 
-                    if (this.$PayToOrderBtn) {
-                        this.$PayToOrderBtn.disabled = !isValid;
-                    }
-
                     const Delivery = this.getElm().getElement('.quiqqer-simple-checkout-data-delivery');
                     const Shipping = this.getElm().getElement('.quiqqer-simple-checkout-data-shipping');
                     const Payment  = this.getElm().getElement('.quiqqer-simple-checkout-data-payment');
@@ -684,9 +696,9 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
         toggleAllProducts: function (event) {
             event.stop();
 
-            const Elm = this.getElm();
-            const HiddenList = Elm.querySelector('.articleList__hidden'),
-                InnerContainer = Elm.querySelector('.articleList__hiddenInner');
+            const Elm            = this.getElm();
+            const HiddenList     = Elm.querySelector('.articleList__hidden'),
+                  InnerContainer = Elm.querySelector('.articleList__hiddenInner');
 
             if (!HiddenList || !InnerContainer) {
                 return;
@@ -716,7 +728,7 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
          */
         showHiddenArticles: function (ListNode, InnerNode) {
             moofx(ListNode).animate({
-                height: InnerNode.offsetHeight,
+                height : InnerNode.offsetHeight,
                 opacity: 1
             }, {
                 callback: () => {
@@ -732,7 +744,7 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
          */
         hideHiddenArticles: function (ListNode) {
             moofx(ListNode).animate({
-                height: 0,
+                height : 0,
                 opacity: 0
             });
         },
@@ -746,8 +758,8 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
         scrollToPayment: function (event) {
             event.stop();
 
-            const Elm = this.getElm();
-            const SumNode = Elm.querySelector('.articles-sum-container');
+            const Elm           = this.getElm();
+            const SumNode       = Elm.querySelector('.articles-sum-container');
             const RequiredField = Elm.querySelector('.quiqqer-simple-checkout-require');
 
             if (RequiredField) {
diff --git a/bin/frontend/controls/SimpleCheckoutPayment.js b/bin/frontend/controls/SimpleCheckoutPayment.js
index 3213a11..88ad0fb 100644
--- a/bin/frontend/controls/SimpleCheckoutPayment.js
+++ b/bin/frontend/controls/SimpleCheckoutPayment.js
@@ -29,8 +29,13 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
         },
 
         $registerEvents: function() {
-            this.getElm().getElements('[type="radio"]').addEvent('change', this.$onChange);
-            this.getElm().getElements('[type="radio"]').forEach((Node) => {
+            const Elm = this.getElm();
+            const PaymentOptionElms = Elm.getElements('[name="payment"]');
+
+            PaymentOptionElms.addEvent('change', this.$onChange);
+            PaymentOptionElms.forEach((Node) => {
+                Node.required = true;
+
                 Node.getParent('.quiqqer-order-step-payments-list-entry').addEvent('click', (e) => {
                     let Target = e.target;
 
diff --git a/bin/frontend/controls/SimpleCheckoutWindow.js b/bin/frontend/controls/SimpleCheckoutWindow.js
index a2317a8..de32bf2 100644
--- a/bin/frontend/controls/SimpleCheckoutWindow.js
+++ b/bin/frontend/controls/SimpleCheckoutWindow.js
@@ -1,6 +1,7 @@
 /**
  * @event onCancel [this] - Fires if the users cancels the order process
  * @event onCloseOrderSuccessful [this] - Fires if the user closes the checkout window after a successful order
+ * @event showOrderSuccessInfo [SimpleCheckoutControl, this] - Fires if last step of successful order is shown
  */
 define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleCheckoutWindow', [
 
@@ -24,19 +25,20 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
         ],
 
         options: {
-            'class': 'SimpleCheckoutWindow',
-            closeButton: true
+            'class'             : 'SimpleCheckoutWindow',
+            closeButton         : true,
+            showOrderSuccessInfo: true
         },
 
         initialize: function (options) {
             this.setAttributes({
-                maxHeight: 10000, // workaround, qui popup
-                maxWidth : 10000, // does not support full screen
-                draggable: false,
-                resizable: false,
-                buttons: false,
+                maxHeight  : 10000, // workaround, qui popup
+                maxWidth   : 10000, // does not support full screen
+                draggable  : false,
+                resizable  : false,
+                buttons    : false,
                 closeButton: false,
-                title: false
+                title      : false
             });
 
             this.parent(options);
@@ -58,8 +60,8 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
 
             new Element('button', {
                 'class': 'SimpleCheckoutWindow__btnClose',
-                html: '<i class="fa fa-times"></i>',
-                events: {
+                html   : '<i class="fa fa-times"></i>',
+                events : {
                     click: () => {
                         this.close();
                     }
@@ -71,14 +73,19 @@ define('package/quiqqer/order-simple-checkout/bin/frontend/controls/SimpleChecko
             }).inject(this.getContent());
 
             this.$Checkout = new SimpleCheckout({
-                products         : this.getAttribute('products'),
-                showPayToOrderBtn: true,
-                events           : {
+                products            : this.getAttribute('products'),
+                showPayToOrderBtn   : true,
+                showOrderSuccessInfo: this.getAttribute('showOrderSuccessInfo'),
+                events              : {
                     onLoaded         : () => {
                         this.Loader.hide();
                     },
                     onOrderSuccessful: () => {
                         new Fx.Scroll(CheckoutWrapper).toTop();
+                        this.fireEvent('orderSuccessful', [this]);
+                    },
+                    onShowOrderSuccessInfo: (SimpleCheckoutControl) => {
+                        this.fireEvent('showOrderSuccessInfo', [SimpleCheckoutControl, this]);
                     },
                     onLoadedError    : () => {
                         require([
diff --git a/src/QUI/ERP/Order/SimpleCheckout/Checkout.html b/src/QUI/ERP/Order/SimpleCheckout/Checkout.html
index 473c458..e1e27d9 100644
--- a/src/QUI/ERP/Order/SimpleCheckout/Checkout.html
+++ b/src/QUI/ERP/Order/SimpleCheckout/Checkout.html
@@ -108,7 +108,7 @@
                     </label>
                 </div>
 
-                <button name="pay" disabled class="btn btn-primary btn-lg btn-large">
+                <button name="pay" class="btn btn-primary btn-lg btn-large">
                     {locale group="quiqqer/order" var="ordering.btn.pay.to.order"}
                 </button>
             </div>
-- 
GitLab