From 0bbb5ff05146def5e190efb162620a190bc0f165 Mon Sep 17 00:00:00 2001 From: Josh Dassinger Date: Thu, 24 Oct 2024 09:31:56 -0500 Subject: [PATCH] SSR-1522 Add Apple Pay --- public/css/hop-styling.css | 141 ++++++- public/css/site-2020Styling.css | 398 ++++++++++++++++++ public/scss/hop-styling.scss | 215 +++++++++- public/scss/site-2020Styling.scss | 358 ++++++++++++++++ src/constants/payment-method-constants.js | 12 +- src/helpers/browser-helper.js | 3 + .../order-confirmation.spec.js | 3 +- .../order-confirmation/order-confirmation.vue | 12 +- .../payment-method/payment-method.spec.js | 18 +- src/layouts/payment-method/payment-method.vue | 32 +- src/layouts/payment-page/payment-page.spec.js | 127 ++---- src/layouts/payment-page/payment-page.vue | 111 +++-- src/layouts/payment-return/payment-return.vue | 11 +- src/store/index.js | 31 +- src/store/store.spec.js | 26 +- vue.config.js | 2 +- 16 files changed, 1238 insertions(+), 262 deletions(-) create mode 100644 src/helpers/browser-helper.js diff --git a/public/css/hop-styling.css b/public/css/hop-styling.css index 3598e48c..018fb90b 100644 --- a/public/css/hop-styling.css +++ b/public/css/hop-styling.css @@ -21,7 +21,7 @@ body span { line-height: 24px; } body a { - color: #1574A1; + color: #0070D1; text-decoration: none; } body .form-group { @@ -41,7 +41,7 @@ body select { } body input, body select { - border-radius: 8px; + border-radius: 4px; border: 1px solid #8E9292; padding: 16px; font-size: 16px; @@ -73,7 +73,7 @@ body select:hover { box-shadow: 0 0 0 4px #9fcee6; } body select { - border-radius: 8px; + border-radius: 4px; border: 1px solid #8E9292; padding: 16px; width: 100%; @@ -128,17 +128,6 @@ body .optional-label:after { } body .buttonContainer { height: 48px; - position: relative; -} -body .buttonContainer:after { - content: ""; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - pointer-events: auto; - cursor: pointer; } body .buttonContainer button { position: relative; @@ -154,6 +143,7 @@ body .buttonContainer button { @media (hover: hover) { body .buttonContainer button { background: linear-gradient(270deg, #1574a1 0%, #003d58 100%); + cursor: pointer; } } body .buttonContainer button:focus { @@ -173,6 +163,7 @@ body .buttonContainer button:disabled { height: 48px; border: none; border-radius: 8px; + cursor: pointer; pointer-events: all; } body .buttonContainer button.has-loader { @@ -213,3 +204,125 @@ body .cc-error-container #alert-message { background-color: #fcbfbb; border: 1px solid #d4281c; } + +#fmg-checkout-shared .form-group .list-group.radio .list-group-item { + border-radius: 5px; +} +#fmg-checkout-shared .form-group .list-group.radio .list-group-item label { + padding: 12px 20px; +} +#fmg-checkout-shared #applepay-and-paypal-container { + display: inline-flex; + width: 100%; + justify-content: space-between; +} +#fmg-checkout-shared #applepay-and-paypal-container #paypalParentDiv { + padding-left: 10px; +} +#fmg-checkout-shared #applepay-and-paypal-container .form-group { + margin: 0; + width: 100%; +} +#fmg-checkout-shared #applepay-and-paypal-container .form-group .list-group.paymentSelection #applepayParentLink { + margin: 0; + padding: 10px 0; + background-color: #000000; +} +#fmg-checkout-shared #applepay-and-paypal-container .form-group .list-group.paymentSelection #applepayParentLink label { + padding: 0; +} +#fmg-checkout-shared #applepay-and-paypal-container .form-group .list-group.paymentSelection #applepayParentLink label apple-pay-button { + vertical-align: middle; +} +#fmg-checkout-shared #applepay-and-paypal-container .form-group .list-group.paymentSelection #applepayParentLink.list-group-item { + box-shadow: none; + border-radius: 10px; + border: 1px solid #8E9292; +} +#fmg-checkout-shared #applepay-and-paypal-container .form-group .list-group.paymentSelection #applepayParentLink:host { + --apple-pay-button-width: auto; +} +#fmg-checkout-shared #applepay-and-paypal-container .form-group .list-group #paypalParentLink { + margin: 0; + padding: 2px 0; +} +#fmg-checkout-shared #applepay-and-paypal-container .form-group .list-group #paypalParentLink #paypalImage { + max-width: 50%; +} +#fmg-checkout-shared #applepay-and-paypal-container .form-group .list-group #paypalParentLink.list-group-item { + box-shadow: none; + border-radius: 10px; + border: 1px solid #8E9292; +} +#fmg-checkout-shared #applepay-and-paypal-container.no-applepay .form-group { + width: 100%; +} +#fmg-checkout-shared #applepay-and-paypal-container.no-applepay .form-group#applepayParentDiv { + display: none; +} +#fmg-checkout-shared #applepay-and-paypal-container.no-applepay .form-group#paypalParentDiv { + padding-left: 0; +} +#fmg-checkout-shared #applepay-and-paypal-container.no-applepay .form-group .list-group.paymentSelection { + width: 100%; +} +#fmg-checkout-shared #applepay-and-paypal-container.no-applepay .form-group .list-group #paypalParentLink #paypalImage { + max-width: 25%; +} +#fmg-checkout-shared #other-payments-container label { + display: inline-flex; + text-align: left; + align-items: flex-start; + justify-content: space-between; + font-size: 16px; + font-weight: 500; +} +#fmg-checkout-shared #other-payments-container label span.paymentOptionText { + margin: auto 0; + padding-left: 0; + font-weight: 600; +} +#fmg-checkout-shared #other-payments-container #afterpayParentLink label > span:first-of-type { + width: 100%; +} +#fmg-checkout-shared #other-payments-container #afterpayParentLink label > span:last-of-type { + width: 0; +} +#fmg-checkout-shared #other-payments-container #creditCardParentDiv.active { + margin-bottom: 32px; + border: 1px solid #0070D1; + border-radius: 10px; +} +#fmg-checkout-shared #other-payments-container #creditCardParentDiv.active > .paymentSelection #creditCardParentLink { + border-width: 0 0 2px 0; + border-bottom-color: #0070D1; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +#fmg-checkout-shared #other-payments-container #creditCardParentDiv .paymentSelection #creditCardImages { + width: 50%; + text-align: right; +} +#fmg-checkout-shared #other-payments-container #creditCardParentDiv .paymentSelection #creditCardImages > img { + width: 20%; +} +#fmg-checkout-shared #other-payments-container #creditCardParentDiv .creditCardSpecific { + padding: 0 16px; +} +#fmg-checkout-shared #other-payments-container #creditCardParentDiv .creditCardSpecific > .form-group { + width: 100%; +} +#fmg-checkout-shared #other-payments-container .italicSmall { + margin-top: 10px; +} +#fmg-checkout-shared #other-payments-container .disclaimerContainerv2 { + margin-bottom: 32px; +} +@media only screen and (max-device-width: 767px) { + #fmg-checkout-shared #applepay-and-paypal-container { + width: 100%; + } + #fmg-checkout-shared #other-payments-container > .form-group { + width: 100%; + } +} diff --git a/public/css/site-2020Styling.css b/public/css/site-2020Styling.css index 07d33158..ae2f004f 100644 --- a/public/css/site-2020Styling.css +++ b/public/css/site-2020Styling.css @@ -112,3 +112,401 @@ .creditCardSpecific { display: none; } + +* { + box-sizing: border-box; +} + +*:before, +*:after { + box-sizing: border-box; +} + +.form-group.radio .list-group .list-group-item { + border-radius: 22px; + text-align: center; + box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2); +} + +.form-group.radio .list-group .list-group-item .radio .list-group, +.form-group.radio .list-group .list-group-item .radio.list-group { + margin: 0 0 22px 0; +} + +.form-group.radio .list-group .list-group-item > label { + padding: 10px 32px 10px 32px; +} + +.form-group.radio .list-group .list-group-item .checkbox .list-group .list-group-item label, +.form-group.radio .list-group .list-group-item .radio .list-group .list-group-item label, +.form-group.radio .list-group .list-group-item .checkbox.list-group .list-group-item label, +.form-group.radio .list-group .list-group-item .radio.list-group .list-group-item label { + padding-left: 55px; +} + +.list-group.radio .list-group-item { + border-radius: 22px; + text-align: center; + box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2); +} + +.list-group.radio .list-group-item .radio .list-group, +.list-group.radio .list-group-item .radio.list-group { + margin: 0 0 22px 0; +} + +.list-group.radio .list-group-item > label { + padding: 10px 32px 10px 32px; +} + +@media (max-width: 992px) { + .list-group.radio .list-group-item > label { + padding: 12px 20px 12px 20px; + } +} +html .list-group .list-group-item .list-group.radio .list-group-item { + text-align: left; + border-radius: 0; +} + +html .list-group .list-group-item .list-group.radio .list-group-item input[type=radio] { + visibility: visible; +} + +html .in-shop.vspacing .list-group.radio.vspacing .list-group-item { + border-radius: 48px; +} + +.row > .form-group > .glyphicon { + right: 15px; +} + +.form-group { + margin-bottom: 10px; +} + +.form-group .control-label { + display: block; + margin-bottom: 2px; +} + +.form-group .form-control { + margin-bottom: 2px; + box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2); +} + +@media (min-width: 500px) { + .form-group { + width: 80%; + } +} +@media (min-width: 800px) { + .form-group { + width: 60%; + } +} +.list-group { + margin-bottom: 20px; + padding-left: 0; +} + +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #ffffff; + border: 1px solid #dddddd; +} + +.list-group-item:first-child { + border-top-right-radius: 5px; + border-top-left-radius: 5px; +} + +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 5px; + border-bottom-left-radius: 5px; +} + +a.list-group-item { + color: #555555; +} + +a.list-group-item .list-group-item-heading { + color: #333333; +} + +a.list-group-item:hover, +a.list-group-item:focus { + text-decoration: none; + color: #555555; + background-color: #f5f5f5; +} + +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + background-color: #f0f1f2; + color: #9aa1a3; + cursor: not-allowed; +} + +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} + +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #9aa1a3; +} + +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #ffffff; + background-color: #167cac; + border-color: #167cac; +} + +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} + +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #9cd7f2; +} + +.list-group-item-success { + color: #cacbcc; + background-color: #e6f2ec; +} + +a.list-group-item-success { + color: #cacbcc; +} + +a.list-group-item-success .list-group-item-heading { + color: inherit; +} + +a.list-group-item-success:hover, +a.list-group-item-success:focus { + color: #cacbcc; + background-color: #d5e9df; +} + +a.list-group-item-success.active, +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + color: #fff; + background-color: #cacbcc; + border-color: #cacbcc; +} + +.list-group-item-info { + color: #125b7e; + background-color: #e7f1f6; +} + +a.list-group-item-info { + color: #125b7e; +} + +a.list-group-item-info .list-group-item-heading { + color: inherit; +} + +a.list-group-item-info:hover, +a.list-group-item-info:focus { + color: #125b7e; + background-color: #d4e6ef; +} + +a.list-group-item-info.active, +a.list-group-item-info.active:hover, +a.list-group-item-info.active:focus { + color: #fff; + background-color: #125b7e; + border-color: #125b7e; +} + +.list-group-item-warning { + color: #f8af1c; + background-color: #fef6e8; +} + +a.list-group-item-warning { + color: #f8af1c; +} + +a.list-group-item-warning .list-group-item-heading { + color: inherit; +} + +a.list-group-item-warning:hover, +a.list-group-item-warning:focus { + color: #f8af1c; + background-color: #fdecd0; +} + +a.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + color: #fff; + background-color: #f8af1c; + border-color: #f8af1c; +} + +.list-group-item-danger { + color: #da291c; + background-color: #fbe9e8; +} + +a.list-group-item-danger { + color: #da291c; +} + +a.list-group-item-danger .list-group-item-heading { + color: inherit; +} + +a.list-group-item-danger:hover, +a.list-group-item-danger:focus { + color: #da291c; + background-color: #f7d4d2; +} + +a.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + color: #fff; + background-color: #da291c; + border-color: #da291c; +} + +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} + +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} + +.radio .list-group.paymentSelection, .radio.list-group.paymentSelection { + margin-top: 0; + margin-bottom: 0; +} +@media (max-width: 33.9em) { + .radio .list-group.paymentSelection label, .radio .list-group.paymentSelection a, .radio.list-group.paymentSelection label, .radio.list-group.paymentSelection a { + max-height: 52px; + } +} + +.radio, +.checkbox, +.form-group.checkbox .list-group, +.form-group.checkbox .list-group, +.form-group.radio .list-group, +.form-group.radio .list-group, +.checkbox.list-group, +.checkbox.list-group, +.radio.list-group, +.radio.list-group { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} + +.form-group.checkbox .list-group .list-group-item > label, +.form-group.radio .list-group .list-group-item > label, +.checkbox.list-group .list-group-item > label, +.radio.list-group .list-group-item > label { + margin-bottom: initial; + width: 100%; + font-weight: normal; + padding: 12px 27px 12px 33px; + color: #525656; +} + +.form-group.checkbox .list-group .list-group-item, +.form-group.radio .list-group .list-group-item, +.checkbox.list-group .list-group-item, +.radio.list-group .list-group-item { + margin-bottom: 12px; + border-width: 1px; + /* border-color: #cacbcc; */ + border-radius: 5px; + padding: 0; +} + +.form-group.checkbox .list-group .list-group-item.active, +.form-group.radio .list-group .list-group-item.active, +.checkbox.list-group .list-group-item.active, +.radio.list-group .list-group-item.active { + background-color: #e7f1f6; + color: #000000; +} + +.radio label, +.checkbox label { + min-height: 23px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; + color: #525656; +} + +img { + vertical-align: middle; +} + +#paypalParentLink label, +#afterpayParentLink label, +#creditCardParentLink label { + padding-top: 9px; + padding-bottom: 9px; +} + +#paypalParentLink label .paymentOptionText, +#creditCardParentLink label .paymentOptionText { + padding-left: 20px; + text-align: left; +} + +html #creditCardParentLink.list-group-item { + border-radius: 48px; + text-align: center; +} + +@media (max-width: 992px) { + .list-group.radio .list-group-item > label { + padding: 12px 20px 12px 20px; + } +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: 500; + color: #000000; +} diff --git a/public/scss/hop-styling.scss b/public/scss/hop-styling.scss index 0ab9dc9f..ef051802 100644 --- a/public/scss/hop-styling.scss +++ b/public/scss/hop-styling.scss @@ -24,7 +24,7 @@ body { } a { - color: #1574A1; + color: #0070D1; text-decoration: none; } @@ -50,7 +50,7 @@ body { input, select { - border-radius: 8px; + border-radius: 4px; border: 1px solid #8E9292; padding: 16px; font-size: 16px; @@ -78,7 +78,7 @@ body { } select { - border-radius: 8px; + border-radius: 4px; border: 1px solid #8E9292; padding: 16px; width: 100%; @@ -139,17 +139,6 @@ body { .buttonContainer { height: 48px; - position: relative; - &:after { - content: ''; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - pointer-events: auto; - cursor: pointer; - } button { position: relative; background: linear-gradient(270deg, #1574a1 0%, #003d58 100%); @@ -162,6 +151,7 @@ body { height: 48px; @media (hover: hover) { background: linear-gradient(270deg, #1574a1 0%, #003d58 100%); + cursor: pointer; } &:focus { box-shadow: 0 0 0 3px, 0 0 0 5.5px #06577c; @@ -182,6 +172,7 @@ body { height: 48px; border: none; border-radius: 8px; + cursor: pointer; pointer-events: all; } &.has-loader { @@ -230,5 +221,199 @@ body { border: 1px solid #d4281c; } } - } + +#fmg-checkout-shared { + .form-group { + .list-group { + &.radio { + .list-group-item { + border-radius: 5px; + + label { + padding: 12px 20px; + } + } + } + } + } + + #applepay-and-paypal-container { + display: inline-flex; + width: 100%; + + justify-content: space-between; + + #paypalParentDiv { + padding-left: 10px; + } + + .form-group { + margin: 0; + width: 100%; + + .list-group { + &.paymentSelection { + + #applepayParentLink { + + margin: 0; + padding: 10px 0; + background-color: #000000; + + label { + padding: 0; + + apple-pay-button { + vertical-align: middle; + } + } + + &.list-group-item { + box-shadow: none; + border-radius: 10px; + border: 1px solid #8E9292; + } + + &:host { + --apple-pay-button-width: auto; + } + } + } + + #paypalParentLink { + margin: 0; + padding: 2px 0; + + #paypalImage { + max-width: 50%; + } + + &.list-group-item { + box-shadow: none; + border-radius: 10px; + border: 1px solid #8E9292; + } + } + } + } + + &.no-applepay { + .form-group { + width: 100%; + + &#applepayParentDiv { + display: none; + } + + &#paypalParentDiv { + padding-left: 0; + } + + .list-group { + &.paymentSelection { + width: 100%; + } + + #paypalParentLink { + + #paypalImage { + max-width: 25%; + } + } + } + } + } + } + + #other-payments-container { + label { + display: inline-flex; + text-align: left; + + align-items: flex-start; + justify-content: space-between; + + font-size: 16px; + font-weight: 500; + + span { + &.paymentOptionText { + margin: auto 0; + padding-left: 0; + font-weight: 600; + } + } + } + + #afterpayParentLink { + label { + > span { + &:first-of-type { + width: 100%; + } + + &:last-of-type { + width: 0; + } + } + } + } + + #creditCardParentDiv { + &.active { + margin-bottom: 32px; + border: 1px solid #0070D1; + border-radius: 10px; + + > .paymentSelection { + #creditCardParentLink { + border-width: 0 0 2px 0; + border-bottom-color: #0070D1; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + } + } + } + + .paymentSelection { + #creditCardImages { + width: 50%; + text-align: right; + + > img { + width: 20%; + } + } + } + + .creditCardSpecific { + padding: 0 16px; + + > .form-group { + width: 100%; + } + } + } + + .italicSmall { + margin-top: 10px; + } + + .disclaimerContainerv2 { + margin-bottom: 32px; + } + } + + @media only screen and (max-device-width: 767px) { + #applepay-and-paypal-container { + width: 100%; + } + + #other-payments-container { + > .form-group { + width: 100%; + } + } + } +} \ No newline at end of file diff --git a/public/scss/site-2020Styling.scss b/public/scss/site-2020Styling.scss index 3cd0839b..14cd2c28 100644 --- a/public/scss/site-2020Styling.scss +++ b/public/scss/site-2020Styling.scss @@ -116,3 +116,361 @@ .creditCardSpecific { display: none; } + +* { + box-sizing: border-box; +} + +*:before, +*:after { + box-sizing: border-box; +} + +.form-group.radio .list-group .list-group-item { + border-radius: 22px; + text-align: center; + box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2); +} +.form-group.radio .list-group .list-group-item .radio .list-group, +.form-group.radio .list-group .list-group-item .radio.list-group { + margin: 0 0 22px 0; +} +.form-group.radio .list-group .list-group-item > label { + padding: 10px 32px 10px 32px; +} +.form-group.radio .list-group .list-group-item .checkbox .list-group .list-group-item label, +.form-group.radio .list-group .list-group-item .radio .list-group .list-group-item label, +.form-group.radio .list-group .list-group-item .checkbox.list-group .list-group-item label, +.form-group.radio .list-group .list-group-item .radio.list-group .list-group-item label { + padding-left: 55px; +} +.list-group.radio .list-group-item { + border-radius: 22px; + text-align: center; + box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2); +} +.list-group.radio .list-group-item .radio .list-group, +.list-group.radio .list-group-item .radio.list-group { + margin: 0 0 22px 0; +} +.list-group.radio .list-group-item > label { + padding: 10px 32px 10px 32px; +} +@media (max-width: 992px) { + .list-group.radio .list-group-item > label { + padding: 12px 20px 12px 20px; + } +} +html .list-group .list-group-item .list-group.radio .list-group-item { + text-align: left; + border-radius: 0; +} +html .list-group .list-group-item .list-group.radio .list-group-item input[type="radio"] { + visibility: visible; +} +html .in-shop.vspacing .list-group.radio.vspacing .list-group-item { + border-radius: 48px; +} +.row > .form-group > .glyphicon { + right: 15px; +} + +.form-group { + margin-bottom: 10px; +} + +.form-group .control-label { + display: block; + margin-bottom: 2px; +} + +.form-group .form-control { + margin-bottom: 2px; + box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2); +} + +@media (min-width: 500px) { + .form-group { + width: 80%; + } +} +@media (min-width: 800px) { + .form-group { + width: 60%; + } +} + +.list-group { + margin-bottom: 20px; + padding-left: 0; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #ffffff; + border: 1px solid #dddddd; +} +.list-group-item:first-child { + border-top-right-radius: 5px; + border-top-left-radius: 5px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 5px; + border-bottom-left-radius: 5px; +} +a.list-group-item { + color: #555555; +} +a.list-group-item .list-group-item-heading { + color: #333333; +} +a.list-group-item:hover, +a.list-group-item:focus { + text-decoration: none; + color: #555555; + background-color: #f5f5f5; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + background-color: #f0f1f2; + color: #9aa1a3; + cursor: not-allowed; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #9aa1a3; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #ffffff; + background-color: #167cac; + border-color: #167cac; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #9cd7f2; +} +.list-group-item-success { + color: #cacbcc; + background-color: #e6f2ec; +} +a.list-group-item-success { + color: #cacbcc; +} +a.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +a.list-group-item-success:focus { + color: #cacbcc; + background-color: #d5e9df; +} +a.list-group-item-success.active, +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + color: #fff; + background-color: #cacbcc; + border-color: #cacbcc; +} +.list-group-item-info { + color: #125b7e; + background-color: #e7f1f6; +} +a.list-group-item-info { + color: #125b7e; +} +a.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +a.list-group-item-info:focus { + color: #125b7e; + background-color: #d4e6ef; +} +a.list-group-item-info.active, +a.list-group-item-info.active:hover, +a.list-group-item-info.active:focus { + color: #fff; + background-color: #125b7e; + border-color: #125b7e; +} +.list-group-item-warning { + color: #f8af1c; + background-color: #fef6e8; +} +a.list-group-item-warning { + color: #f8af1c; +} +a.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +a.list-group-item-warning:focus { + color: #f8af1c; + background-color: #fdecd0; +} +a.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + color: #fff; + background-color: #f8af1c; + border-color: #f8af1c; +} +.list-group-item-danger { + color: #da291c; + background-color: #fbe9e8; +} +a.list-group-item-danger { + color: #da291c; +} +a.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +a.list-group-item-danger:focus { + color: #da291c; + background-color: #f7d4d2; +} +a.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + color: #fff; + background-color: #da291c; + border-color: #da291c; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} + + +.radio .list-group.paymentSelection, .radio.list-group.paymentSelection { + margin-top: 0; + margin-bottom: 0; + + @media (max-width: 33.9em) { + label, a { + max-height: 52px; + } + } +} + +.radio, +.checkbox, +.form-group.checkbox .list-group, +.form-group.checkbox .list-group, +.form-group.radio .list-group, +.form-group.radio .list-group, +.checkbox.list-group, +.checkbox.list-group, +.radio.list-group, +.radio.list-group { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} + +.form-group.checkbox .list-group .list-group-item > label, +.form-group.radio .list-group .list-group-item > label, +.checkbox.list-group .list-group-item > label, +.radio.list-group .list-group-item > label { + margin-bottom: initial; + width: 100%; + font-weight: normal; + padding: 12px 27px 12px 33px; + color: #525656; +} + +.form-group.checkbox .list-group .list-group-item, +.form-group.radio .list-group .list-group-item, +.checkbox.list-group .list-group-item, +.radio.list-group .list-group-item { + margin-bottom: 12px; + border-width: 1px; + /* border-color: #cacbcc; */ + border-radius: 5px; + padding: 0; +} + +.form-group.checkbox .list-group .list-group-item.active, +.form-group.radio .list-group .list-group-item.active, +.checkbox.list-group .list-group-item.active, +.radio.list-group .list-group-item.active { + background-color: #e7f1f6; + color: #000000; +} + +.radio label, +.checkbox label { + min-height: 23px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; + color: #525656; +} + +img { + vertical-align: middle; +} + +#paypalParentLink label, +#afterpayParentLink label, +#creditCardParentLink label { + padding-top: 9px; + padding-bottom: 9px; +} + +#paypalParentLink label .paymentOptionText, +#creditCardParentLink label .paymentOptionText { + padding-left: 20px; + text-align: left; +} + +html #creditCardParentLink.list-group-item { + border-radius: 48px; + text-align: center; +} + +@media (max-width: 992px) { + .list-group.radio .list-group-item > label { + padding: 12px 20px 12px 20px; + } +} + +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: 500; + color: #000000; +} \ No newline at end of file diff --git a/src/constants/payment-method-constants.js b/src/constants/payment-method-constants.js index 48aa5008..1338bb08 100644 --- a/src/constants/payment-method-constants.js +++ b/src/constants/payment-method-constants.js @@ -1,15 +1,11 @@ -const hopPaymentMethods = Object.freeze({ - CREDIT_CARD: 'cc', - PAYPAL: 'pp', - AFTERPAY: 'ap' -}); - const paymentMethods = Object.freeze({ NONE: null, + PayNow: 'PayNow', // User selected the pay now and hasn't selected their payment method yet PAY_AT_TIME_OF_SERVICE: 'PayAtTimeOfService', CREDIT_CARD: 'CreditCard', PAYPAL: 'Paypal', - AFTERPAY: 'Afterpay' + AFTERPAY: 'Afterpay', + APPLEPAY: 'ApplePay' }); -export { hopPaymentMethods, paymentMethods }; +export { paymentMethods }; diff --git a/src/helpers/browser-helper.js b/src/helpers/browser-helper.js new file mode 100644 index 00000000..64c3a390 --- /dev/null +++ b/src/helpers/browser-helper.js @@ -0,0 +1,3 @@ +export function supportsApplePay() { + return !!(window.ApplePaySession && window.ApplePaySession.canMakePayments()); +} \ No newline at end of file diff --git a/src/layouts/order-confirmation/order-confirmation.spec.js b/src/layouts/order-confirmation/order-confirmation.spec.js index dfb9a45a..f57fac7a 100644 --- a/src/layouts/order-confirmation/order-confirmation.spec.js +++ b/src/layouts/order-confirmation/order-confirmation.spec.js @@ -13,6 +13,7 @@ import coverageStatuses from '@/constants/coverage-statuses'; import coverageType from '@/constants/coverage-type'; import { deepClone } from '@/helpers/object-helper'; import { AppointmentTypeStrings } from '@/constants/schedule-constants'; +import { paymentMethods } from "@/constants/payment-method-constants"; jest.mock('@/helpers/layout-helper.js', () => jest.fn()); @@ -80,7 +81,7 @@ const initialStore = { }, payment: { isInsurance: true, - isPayInAdvance: false + paymentMethod: paymentMethods.PAY_AT_TIME_OF_SERVICE }, contactInfo: { firstName: 'Test', diff --git a/src/layouts/order-confirmation/order-confirmation.vue b/src/layouts/order-confirmation/order-confirmation.vue index 4f649c88..c364ae05 100644 --- a/src/layouts/order-confirmation/order-confirmation.vue +++ b/src/layouts/order-confirmation/order-confirmation.vue @@ -147,7 +147,7 @@ export default { return { mainStore, submittedOrder }; }, data() { - var { + const { vehicle, serviceLocation, schedule, @@ -155,8 +155,9 @@ export default { payment, customerPortalLoginToken, damage, - referralNumber } = this.submittedOrder; - var { issConfig, hasRecalibrationPart } = this.mainStore; + referralNumber + } = this.submittedOrder; + const { issConfig, hasRecalibrationPart } = this.mainStore; return { vehicle, customerEmail: customer?.emailAddress, @@ -179,7 +180,7 @@ export default { mobile: 'MobileWordingWidget', dropOffAndInShop: 'DropOffAndInShopWordingWidget', siteFooter: 'SiteFooterWidget' - }, + } } }, computed: { @@ -383,8 +384,7 @@ export default { ); // Payment - const paymentMethodReqs = - useMainStore().order.payment.isPayInAdvance === false; + const paymentMethodReqs = useMainStore().order.payment.paymentMethod != null; return ( serviceLocationReqs diff --git a/src/layouts/payment-method/payment-method.spec.js b/src/layouts/payment-method/payment-method.spec.js index 3e60fce2..f791e600 100644 --- a/src/layouts/payment-method/payment-method.spec.js +++ b/src/layouts/payment-method/payment-method.spec.js @@ -72,8 +72,7 @@ describe('payment-method.vue', () => { const store = { order: { payment: { - isPayInAdvance: false, - payInAdvanceType: null + paymentMethod: null } } }; @@ -91,8 +90,7 @@ describe('payment-method.vue', () => { const store = { order: { payment: { - isPayInAdvance: true, - payInAdvanceType: payInAdvanceMethod + paymentMethod: payInAdvanceMethod }, insuranceCoverage: { coverageStatus: coverageStatuses.VERIFIED, @@ -115,8 +113,7 @@ describe('payment-method.vue', () => { const store = { order: { payment: { - isPayInAdvance: true, - payInAdvanceType: payInAdvanceMethod + paymentMethod: payInAdvanceMethod }, insuranceCoverage: { coverageStatus: coverageStatuses.VERIFIED, @@ -139,8 +136,7 @@ describe('payment-method.vue', () => { const store = { order: { payment: { - isPayInAdvance: true, - payInAdvanceType: payInAdvanceMethod + paymentMethod: payInAdvanceMethod }, insuranceCoverage: { coverageStatus: coverageStatuses.PENDING, @@ -173,8 +169,7 @@ describe('payment-method.vue', () => { const store = { order: { payment: { - isPayInAdvance: true, - payInAdvanceType: payInAdvanceMethod + paymentMethod: payInAdvanceMethod }, insuranceCoverage: { coverageStatus: coverageStatuses.VERIFIED, @@ -327,8 +322,7 @@ describe('payment-method.vue', () => { const store = { order: { payment: { - isPayInAdvance: false, - payInAdvanceType: null + paymentMethod: paymentMethods.PAY_AT_TIME_OF_SERVICE } } }; diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue index cd16dac3..b253f2e0 100644 --- a/src/layouts/payment-method/payment-method.vue +++ b/src/layouts/payment-method/payment-method.vue @@ -43,8 +43,8 @@ :isDismissible="false" /> { test('Returns false if pia options are not valid', () => { // Arrange const { wrapper } = getMountedComponent(defaultOrder); - useMainStore().order.payment.isPayInAdvance = null; - useMainStore().order.payment.payInAdvanceType = null; + useMainStore().order.payment.paymentMethod = null; // Act const result = wrapper.vm.arePagePrerequisitesValid(); @@ -252,8 +249,7 @@ describe('payment-page.vue', () => { test('Returns false if pay at time of service', () => { // Arrange const { wrapper } = getMountedComponent(defaultOrder); - useMainStore().order.payment.isPayInAdvance = false; - useMainStore().order.payment.payInAdvanceType = null; + useMainStore().order.payment.paymentMethod = paymentMethods.PAY_AT_TIME_OF_SERVICE; // Act const result = wrapper.vm.arePagePrerequisitesValid(); @@ -265,94 +261,6 @@ describe('payment-page.vue', () => { }); describe('payment type mapping', () => { - describe('getPaymentType', () => { - test('Maps AFTERPAY -> hopPaymentMethods.AFTERPAY', () => { - // Arrange - const { wrapper } = getMountedComponent(defaultOrder); - useMainStore().order.payment.payInAdvanceType = paymentMethods.AFTERPAY; - - // Act - const mapped = wrapper.vm.getPaymentType(); - - // Assert - expect(mapped).toBe(hopPaymentMethods.AFTERPAY); - }); - - test('Maps CREDIT_CARD -> hopPaymentMethods.CREDIT_CARD', () => { - // Arrange - const { wrapper } = getMountedComponent(defaultOrder); - useMainStore().order.payment.payInAdvanceType = paymentMethods.CREDIT_CARD; - - // Act - const mapped = wrapper.vm.getPaymentType(); - - // Assert - expect(mapped).toBe(hopPaymentMethods.CREDIT_CARD); - }); - - test('Maps PAYPAL -> hopPaymentMethods.PAYPAL', () => { - // Arrange - const { wrapper } = getMountedComponent(defaultOrder); - useMainStore().order.payment.payInAdvanceType = paymentMethods.PAYPAL; - - // Act - const mapped = wrapper.vm.getPaymentType(); - - // Assert - expect(mapped).toBe(hopPaymentMethods.PAYPAL); - }); - - test('Maps other values to self', () => { - // Arrange - const { wrapper } = getMountedComponent(defaultOrder); - useMainStore().order.payment.payInAdvanceType = 'SomeOtherText'; - - // Act - const mapped = wrapper.vm.getPaymentType(); - - // Assert - expect(mapped).toBe('SomeOtherText'); - }); - }); - - describe('cart-dropdown', () => { - test('Show cart dropdown if credit card', async () => { - const { wrapper } = getMountedComponent(defaultOrder); - wrapper.vm.paymentType = hopPaymentMethods.CREDIT_CARD; - - // Act - await wrapper.vm.$nextTick(); - const cartTable = wrapper.findComponent(CartDropdown); - - // Assert - expect(cartTable.exists()).toBeTruthy(); - }); - - test('show cart dropdown if afterpay', async () => { - const { wrapper } = getMountedComponent(defaultOrder); - wrapper.vm.paymentType = hopPaymentMethods.AFTERPAY; - - // Act - await wrapper.vm.$nextTick(); - const cartTable = wrapper.findComponent(CartDropdown); - - // Assert - expect(cartTable.exists()).toBeTruthy(); - }); - - test('Hide cart dropdown if paypal', async () => { - const { wrapper } = getMountedComponent(defaultOrder); - wrapper.vm.paymentType = hopPaymentMethods.PAYPAL; - - // Act - await wrapper.vm.$nextTick(); - const cartTable = wrapper.findComponent(CartDropdown); - - // Assert - expect(cartTable.exists()).toBeFalsy(); - }); - }); - describe('isPaypal', () => { test('Is responsive if initial data changes', async () => { // Arrange @@ -361,7 +269,7 @@ describe('payment-page.vue', () => { // Act const preVal = wrapper.vm.isPaypal; - wrapper.vm.paymentType = hopPaymentMethods.PAYPAL; + wrapper.vm.paymentType = paymentMethods.PAYPAL; await wrapper.vm.$nextTick(); const postVal = wrapper.vm.isPaypal; @@ -441,6 +349,7 @@ describe('payment-page.vue', () => { }; const { wrapper } = getMountedComponent(defaultOrder); + useMainStore().order.payment.paymentMethod = paymentMethods.PayNow; // Act wrapper.vm.handleIFrameContentWindowMessage(event); @@ -522,4 +431,26 @@ describe('payment-page.vue', () => { expect(afterPayErrorAlert.isVisible()).toBeTruthy(); }); }); + + describe.each([ + [paymentMethods.CREDIT_CARD, { data: 'creditCardSubmit' }], + [paymentMethods.AFTERPAY, { data: 'afterpayPaymentReceived' }], + [paymentMethods.APPLEPAY, { data: 'applepayOpened' }], + [paymentMethods.PAYPAL, { data: 'showLoaderForPaypal' }] + ])('handleIFrameContentWindowMessage', (expected, event) => { + test(`sets paymentMethod to ${getEnumName(paymentMethods, expected)} when data is ${event.data}`, () => { + // Arrange + const { wrapper } = getMountedComponent(defaultOrder); + useMainStore().order.payment.paymentMethod = paymentMethods.PayNow; + + useMainStore().savePaymentMethodChoice = jest.fn().mockImplementation((value) => {useMainStore().order.payment.paymentMethod = value}); + + // Act + wrapper.vm.handleIFrameContentWindowMessage(event); + const result = useMainStore().order.payment.paymentMethod; + + // Assert + expect(result).toBe(expected); + }); + }); }); diff --git a/src/layouts/payment-page/payment-page.vue b/src/layouts/payment-page/payment-page.vue index acf89e2f..052f2c24 100644 --- a/src/layouts/payment-page/payment-page.vue +++ b/src/layouts/payment-page/payment-page.vue @@ -33,12 +33,12 @@ class="hop-iframe payment-iframe" name="card-frame" seamless - scrolling="no"> + scrolling="no" + allow="payment *; microphone *; geolocation *;">

- + +