Update checkout page - #548
Conversation
JuliaEvseeva
left a comment
There was a problem hiding this comment.
@Vladyslav-Kuksiuk, please see minor UI comments.
| window.setTimeout(() => { | ||
| const restoredState = formController.getBrowserRestoredCountryState(); | ||
|
|
||
| phoneCountryManuallySelected = Boolean( |
There was a problem hiding this comment.
This derivation misfires for the common case where the user never touched the phone country.
The phone field is initialised to us (initPhoneNumberField()), and syncPhoneCountryState() writes that into #checkout-phone-country. So a visitor who opens checkout, types their email, navigates away and presses Back restores phoneCountryCode: 'US' with billingCountryCode: '' — and 'US' !== '' sets phoneCountryManuallySelected = true.
From then on applyPhoneCountryFromBillingCountry() is a no-op, so selecting "Germany" as the billing country leaves the phone prefix at +1.
On a bfcache restore this is doubly wrong: the closure variable survived the navigation and already held the correct false, and this line overwrites it.
| {{ with site.Params.payment.standardsupportproductid }} | ||
| {{ $productId = . }} | ||
| {{ end }} |
There was a problem hiding this comment.
The override sits inside the range, so it replaces the product ID of every column rather than just the standard-support one.
services.json has two header_cols: "Standard Support Pack" (with paygate_product_id) and "Custom Support" (deliberately without one). With standardSupportProductId configured, the second column also gets data-paygate-product-id. It happens to be harmless today only because pricing.js reads the first match of $('[data-paygate-product-id]').
Scoping the override to columns that already declare a product ID keeps the intent:
| {{ with site.Params.payment.standardsupportproductid }} | |
| {{ $productId = . }} | |
| {{ end }} | |
| {{ if $productId }} | |
| {{ with site.Params.payment.standardsupportproductid }} | |
| {{ $productId = . }} | |
| {{ end }} | |
| {{ end }} |
| } | ||
|
|
||
| /** Shows the resolved order summary and billing form. */ | ||
| function showCheckoutView() { |
There was a problem hiding this comment.
showSummaryLoading, showSummaryError, showCheckoutView, showMissingOrderView and showNotFoundView are five copies of the same six-line block — toggle $loading / $summary / $form / $missingOrder / $notFound / $summaryError, differing only in which one stays visible plus the setResultPageMode flag.
completed.js already has the generic form of exactly this (showView(activeViewId) iterating the view IDs). A small map from panel name to {element, isResultPage} would drop ~30 lines here and make it impossible to forget a panel when a sixth one is added.
| const buildChargeRequest = (orderId, buyerCountryCode, vatId) => { | ||
| if (!orderId || !buyerCountryCode) return null; | ||
| return vatId | ||
| ? {orderId, buyerCountryCode, vatId} | ||
| : {orderId, buyerCountryCode}; | ||
| }; |
There was a problem hiding this comment.
buildChargeRequest is re-implemented here instead of being imported, and the copy is byte-for-byte the current charge-request.js body.
The real module is already loaded at the top of this file via importSource('../assets/js/pages/checkout/charge-request.js'), so the harness can inject that export. As written, a behaviour change in charge-request.js cannot fail any charge-controller test, and the two copies can drift silently.
| - name: Run checkout tests | ||
| if: steps.docs.outputs.present == 'true' | ||
| working-directory: ${{ steps.docs.outputs.work_dir }} | ||
| run: npm test |
There was a problem hiding this comment.
The JS unit suite is wired into the link-check workflow and gated on steps.docs.outputs.present == 'true', so it only runs when a docs preview is being built, and a unit-test failure is reported to contributors as a link-check failure.
These tests do not depend on the rendered site at all. A dedicated job (or an existing build workflow) would run them on every PR and report under their own name.
| countries.forEach(country => { | ||
| select.add(new Option(country.name, country.code)); | ||
| }); |
There was a problem hiding this comment.
This appends ~250 options one at a time, each mutating the live <select> during page load and immediately before Select2 re-reads it. Building into a DocumentFragment and appending once makes it a single mutation:
| countries.forEach(country => { | |
| select.add(new Option(country.name, country.code)); | |
| }); | |
| const options = document.createDocumentFragment(); | |
| countries.forEach(country => { | |
| options.append(new Option(country.name, country.code)); | |
| }); | |
| select.append(options); | |
| } |
| .form-select { | ||
| appearance: auto; | ||
| } |
There was a problem hiding this comment.
.form-select is dead under .checkout .form-section after this PR: #checkout-country changed from class="form-input form-select" to class="form-input country-select", and the phone country <select> was removed entirely. Nothing in the checkout markup carries the class any more.
This whole appearance: auto rule can go, and .form-select can be dropped from the .form-input, .form-select selector on line 247.
| return true; | ||
| } | ||
|
|
||
| if (field.type === 'tel') { |
There was a problem hiding this comment.
This returns true for any type="tel" field before the field.required check, so a required phone input would silently pass validateRequiredFields().
Today it is unreachable — #checkout-phone is not required, and bindEvents() routes the phone field to its own blur -> validatePhoneNumber handler rather than here. It reads like a guard but is dead code that would misbehave the moment it becomes live.
| phoneCountryManuallySelected = false; | ||
| formController.restoreCountryState({ | ||
| billingCountryCode: '', | ||
| phoneCountryCode: 'US' |
There was a problem hiding this comment.
'US' duplicates the default phone country from form-controller.js (initialCountry: normalizeCountryCode(dom.$phoneCountry.val()) || 'us'), in a different case.
Exporting a single default from the form controller would keep the reload reset and the initial render from drifting apart.
Oleg-Melnik
left a comment
There was a problem hiding this comment.
@Vladyslav-Kuksiuk LGTM with comments to address.
This PR updates the checkout page and checkout-completed page according to the latest changes from the Company-Site versions of those pages.
Checkout page
Order not found
Transaction in progress
Payment completed
Payment failed
Resolves this issue.