Skip to content

Commit

Permalink
Merge pull request #3214 from craftcms/feature/save-user-addressess-o…
Browse files Browse the repository at this point in the history
…n-checkout

Copy order addresses to credentialed user on order complete
  • Loading branch information
lukeholder committed Jul 17, 2023
2 parents 23d9308 + dac76c6 commit d386c0f
Show file tree
Hide file tree
Showing 22 changed files with 696 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ Outputs the checkout progress navigation using the request path and included `ch
label: 'Payment Method',
url: 'shop/checkout/payment-method'
},
{
label: 'Options',
url: 'shop/checkout/options'
},
{
label: 'Payment',
url: 'shop/checkout/payment'
Expand Down
11 changes: 11 additions & 0 deletions example-templates/dist/shop/_private/layouts/index.twig
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ Common, top-level layout template.
{% set flashNotice = craft.app.session.getFlash('notice') %}
{% set flashError = craft.app.session.getFlash('error') %}

{% macro docs(text, link) %}
<small class="">
{{ tag('a', {
text: 'ℹ︎ ' ~ text,
href: link,
class: 'text-gray-400 hover:text-gray-600 hover:underline',
target: '_blank',
}) }}
</small>
{% endmacro %}

<header>
<div class="bg-gray-900">
<div class="container mx-auto p-6 md:flex justify-content-between align-content-center">
Expand Down
108 changes: 108 additions & 0 deletions example-templates/dist/shop/checkout/options.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
{% extends 'shop/_private/layouts' %}

{# @var cart \craft\commerce\elements\Order #}

{% if cart is not defined %}
{% set cart = craft.commerce.carts.cart %}
{% endif %}

{#
We can skip the "options" step if the customer is a logged in user and
the addresses have come from the address book
#}
{% if currentUser and cart.sourceBillingAddressId and cart.sourceShippingAddressId %}
{% redirect 'shop/checkout/payment' %}
{% endif %}

{% if not cart.getCustomer() %}
{% redirect 'shop/checkout/email' %}
{% endif %}

{% if not cart.gateway %}
{% redirect 'shop/checkout/payment-method' %}
{% endif %}

{% block main %}
<div class="md:flex md:-mx-8" >
<div class="md:w-2/3 md:px-8">

<h1 class="font-bold text-xl">
{{- 'Options'|t -}}
</h1>

<form action="" method="post">
{{ csrfInput() }}
{{ actionInput('commerce/cart/update-cart') }}
{{ redirectInput(siteUrl('shop/checkout/payment')) }}
{{ successMessageInput('Options saved.') }}

{% set user = cart.email ? craft.users.email(cart.email).one() : null %}
{% if not user or not user.getIsCredentialed() %}
<div class="mt-3">
<label for="registerUserOnOrderComplete">
{{ hiddenInput('registerUserOnOrderComplete', false) }}
{{ input('checkbox', 'registerUserOnOrderComplete', 1, {
id: 'registerUserOnOrderComplete'
}) }}
{{ 'Create my account after ordering'|t }}
</label>
<div>
{{ _self.docs('Registering a user on order complete.', 'https://craftcms.com/docs/commerce/4.x/customers.html#registration-at-checkout') }}
</div>
</div>
{% endif %}

{% set saveAddressCheckboxesShown = false %}
{% if currentUser and cart.billingAddressId and not cart.sourceBillingAddressId %}
{% set saveAddressCheckboxesShown = true %}
<div class="mt-3">
<label for="saveBillingAddressOnOrderComplete">
{{ hiddenInput('saveBillingAddressOnOrderComplete', false) }}
{{ input('checkbox', 'saveBillingAddressOnOrderComplete', 1, {
id: 'saveBillingAddressOnOrderComplete',
checked: cart.saveBillingAddressOnOrderComplete,
}) }}
{{ 'Save billing address on order complete'|t }}
</label>
</div>
{% endif %}

{% if currentUser and cart.shippingAddressId and not cart.sourceShippingAddressId %}
<div class="mt-3">
{% set saveAddressCheckboxesShown = true %}
<label for="saveShippingAddressOnOrderComplete">
{{ hiddenInput('saveShippingAddressOnOrderComplete', false) }}
{{ input('checkbox', 'saveShippingAddressOnOrderComplete', 1, {
id: 'saveShippingAddressOnOrderComplete',
checked: cart.saveShippingAddressOnOrderComplete,
}) }}
{{ 'Save shipping address on order complete'|t }}
</label>
</div>
{% endif %}

{% if saveAddressCheckboxesShown %}
<div>
{{ _self.docs('Saving addresses on order complete.', '#') }}
</div>
{% endif %}

<div class="mt-6 flex justify-end">
{{ tag('button', {
type: 'submit',
name: 'submit',
class: 'cursor-pointer rounded px-4 py-2 inline-block bg-blue-500 hover:bg-blue-600 text-white hover:text-white',
text: 'Next'|t
}) }}
</div>
</form>
</div>

<div class="mt-8 md:w-1/3 md:px-8 md:mt-0">
{{ include('shop/checkout/_includes/order-summary', {
showShippingAddress: true,
showShippingMethod: true
}) }}
</div>
</div>
{% endblock %}
2 changes: 1 addition & 1 deletion example-templates/dist/shop/checkout/payment-method.twig
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<form method="post" action="" class="relative border-b-1 mb-4">
{{ csrfInput() }}
{{ actionInput('commerce/cart/update-cart') }}
{{ redirectInput(siteUrl('shop/checkout/payment')) }}
{{ redirectInput(siteUrl('shop/checkout/options')) }}
{{ successMessageInput('Payment options selected.') }}

<div class="mt-3">
Expand Down
13 changes: 0 additions & 13 deletions example-templates/dist/shop/checkout/payment.twig
Original file line number Diff line number Diff line change
Expand Up @@ -115,19 +115,6 @@
{{ cart.gateway.getPaymentConfirmationFormHtml({})|raw }}
{% endif %}

{% set user = cart.email ? craft.users.email(cart.email).one() : null %}
{% if not user or not user.getIsCredentialed() %}
<div class="mt-3">
<label for="registerUserOnOrderComplete">
{{ hiddenInput('registerUserOnOrderComplete', false) }}
{{ input('checkbox', 'registerUserOnOrderComplete', 1, {
id: 'registerUserOnOrderComplete'
}) }}
{{ 'Create an account'|t }}
</label>
</div>
{% endif %}

{{ include('shop/checkout/_includes/partial-payment') }}

{% if cart.paymentSourceId or cart.gateway.showPaymentFormSubmitButton() %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ Outputs the checkout progress navigation using the request path and included `ch
label: 'Payment Method',
url: '[[folderName]]/checkout/payment-method'
},
{
label: 'Options',
url: '[[folderName]]/checkout/options'
},
{
label: 'Payment',
url: '[[folderName]]/checkout/payment'
Expand Down
11 changes: 11 additions & 0 deletions example-templates/src/shop/_private/layouts/index.twig
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,17 @@ Common, top-level layout template.
{% set flashNotice = craft.app.session.getFlash('notice') %}
{% set flashError = craft.app.session.getFlash('error') %}

{% macro docs(text, link) %}
<small class="">
{{ tag('a', {
text: 'ℹ︎ ' ~ text,
href: link,
class: '[[classes.docs]]',
target: '_blank',
}) }}
</small>
{% endmacro %}

<header>
<div class="bg-gray-900">
<div class="container mx-auto p-6 md:flex justify-content-between align-content-center">
Expand Down
108 changes: 108 additions & 0 deletions example-templates/src/shop/checkout/options.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
{% extends '[[folderName]]/_private/layouts' %}

{# @var cart \craft\commerce\elements\Order #}

{% if cart is not defined %}
{% set cart = craft.commerce.carts.cart %}
{% endif %}

{#
We can skip the "options" step if the customer is a logged in user and
the addresses have come from the address book
#}
{% if currentUser and cart.sourceBillingAddressId and cart.sourceShippingAddressId %}
{% redirect '[[folderName]]/checkout/payment' %}
{% endif %}

{% if not cart.getCustomer() %}
{% redirect '[[folderName]]/checkout/email' %}
{% endif %}

{% if not cart.gateway %}
{% redirect '[[folderName]]/checkout/payment-method' %}
{% endif %}

{% block main %}
<div class="md:flex md:-mx-8" [[hx-disable]]>
<div class="md:w-2/3 md:px-8">

<h1 class="font-bold text-xl">
{{- 'Options'|t -}}
</h1>

<form action="" method="post">
{{ csrfInput() }}
{{ actionInput('commerce/cart/update-cart') }}
{{ redirectInput(siteUrl('shop/checkout/payment')) }}
{{ successMessageInput('Options saved.') }}

{% set user = cart.email ? craft.users.email(cart.email).one() : null %}
{% if not user or not user.getIsCredentialed() %}
<div class="mt-3">
<label for="registerUserOnOrderComplete">
{{ hiddenInput('registerUserOnOrderComplete', false) }}
{{ input('checkbox', 'registerUserOnOrderComplete', 1, {
id: 'registerUserOnOrderComplete'
}) }}
{{ 'Create my account after ordering'|t }}
</label>
<div>
{{ _self.docs('Registering a user on order complete.', 'https://craftcms.com/docs/commerce/4.x/customers.html#registration-at-checkout') }}
</div>
</div>
{% endif %}

{% set saveAddressCheckboxesShown = false %}
{% if currentUser and cart.billingAddressId and not cart.sourceBillingAddressId %}
{% set saveAddressCheckboxesShown = true %}
<div class="mt-3">
<label for="saveBillingAddressOnOrderComplete">
{{ hiddenInput('saveBillingAddressOnOrderComplete', false) }}
{{ input('checkbox', 'saveBillingAddressOnOrderComplete', 1, {
id: 'saveBillingAddressOnOrderComplete',
checked: cart.saveBillingAddressOnOrderComplete,
}) }}
{{ 'Save billing address on order complete'|t }}
</label>
</div>
{% endif %}

{% if currentUser and cart.shippingAddressId and not cart.sourceShippingAddressId %}
<div class="mt-3">
{% set saveAddressCheckboxesShown = true %}
<label for="saveShippingAddressOnOrderComplete">
{{ hiddenInput('saveShippingAddressOnOrderComplete', false) }}
{{ input('checkbox', 'saveShippingAddressOnOrderComplete', 1, {
id: 'saveShippingAddressOnOrderComplete',
checked: cart.saveShippingAddressOnOrderComplete,
}) }}
{{ 'Save shipping address on order complete'|t }}
</label>
</div>
{% endif %}

{% if saveAddressCheckboxesShown %}
<div>
{{ _self.docs('Saving addresses on order complete.', '#') }}
</div>
{% endif %}

<div class="mt-6 flex justify-end">
{{ tag('button', {
type: 'submit',
name: 'submit',
class: '[[classes.btn.base]] [[classes.btn.mainColor]]',
text: 'Next'|t
}) }}
</div>
</form>
</div>

<div class="mt-8 md:w-1/3 md:px-8 md:mt-0">
{{ include('[[folderName]]/checkout/_includes/order-summary', {
showShippingAddress: true,
showShippingMethod: true
}) }}
</div>
</div>
{% endblock %}
2 changes: 1 addition & 1 deletion example-templates/src/shop/checkout/payment-method.twig
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<form method="post" action="" class="relative border-b-1 mb-4">
{{ csrfInput() }}
{{ actionInput('commerce/cart/update-cart') }}
{{ redirectInput(siteUrl('[[folderName]]/checkout/payment')) }}
{{ redirectInput(siteUrl('[[folderName]]/checkout/options')) }}
{{ successMessageInput('Payment options selected.') }}

<div class="mt-3">
Expand Down
13 changes: 0 additions & 13 deletions example-templates/src/shop/checkout/payment.twig
Original file line number Diff line number Diff line change
Expand Up @@ -115,19 +115,6 @@
{{ cart.gateway.getPaymentConfirmationFormHtml({})|raw }}
{% endif %}

{% set user = cart.email ? craft.users.email(cart.email).one() : null %}
{% if not user or not user.getIsCredentialed() %}
<div class="mt-3">
<label for="registerUserOnOrderComplete">
{{ hiddenInput('registerUserOnOrderComplete', false) }}
{{ input('checkbox', 'registerUserOnOrderComplete', 1, {
id: 'registerUserOnOrderComplete'
}) }}
{{ 'Create an account'|t }}
</label>
</div>
{% endif %}

{{ include('[[folderName]]/checkout/_includes/partial-payment') }}

{% if cart.paymentSourceId or cart.gateway.showPaymentFormSubmitButton() %}
Expand Down
2 changes: 1 addition & 1 deletion src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ public static function editions(): array
/**
* @inheritDoc
*/
public string $schemaVersion = '4.2.4';
public string $schemaVersion = '4.2.5';

/**
* @inheritdoc
Expand Down
1 change: 1 addition & 0 deletions src/console/controllers/ExampleTemplatesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ private function _addCssClassesToReplacementData(): void
'[[classes.text.color]]' => "text-$mainColor-500",
'[[classes.text.dangerColor]]' => "text-$dangerColor-500",
'[[classes.a]]' => "text-$mainColor-500 hover:text-$mainColor-600",
'[[classes.docs]]' => "text-gray-400 hover:text-gray-600 hover:underline",
'[[classes.input]]' => "border border-gray-300 hover:border-gray-500 px-4 py-2 leading-tight rounded",
'[[classes.box.base]]' => "bg-gray-100 border-$mainColor-300 border-b-2 p-6",
'[[classes.box.selection]]' => "border-$mainColor-300 border-b-2 px-6 py-4 rounded-md shadow-md hover:shadow-lg",
Expand Down
21 changes: 17 additions & 4 deletions src/controllers/CartController.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,25 @@ public function actionUpdateCart(): ?Response
}

// Set if the customer should be registered on order completion
if ($this->request->getBodyParam('registerUserOnOrderComplete')) {
$this->_cart->registerUserOnOrderComplete = true;
$registerUserOnOrderComplete = $this->request->getBodyParam('registerUserOnOrderComplete');
if ($registerUserOnOrderComplete !== null) {
$this->_cart->registerUserOnOrderComplete = (bool)$registerUserOnOrderComplete;
}

if ($this->request->getBodyParam('registerUserOnOrderComplete') === 'false') {
$this->_cart->registerUserOnOrderComplete = false;
$saveBillingAddressOnOrderComplete = $this->request->getBodyParam('saveBillingAddressOnOrderComplete');
if ($saveBillingAddressOnOrderComplete !== null) {
$this->_cart->saveBillingAddressOnOrderComplete = (bool)$saveBillingAddressOnOrderComplete;
}

$saveShippingAddressOnOrderComplete = $this->request->getBodyParam('saveShippingAddressOnOrderComplete');
if ($saveShippingAddressOnOrderComplete !== null) {
$this->_cart->saveShippingAddressOnOrderComplete = (bool)$saveShippingAddressOnOrderComplete;
}

$saveAddressesOnOrderComplete = $this->request->getBodyParam('saveAddressesOnOrderComplete');
if ($saveAddressesOnOrderComplete !== null) {
$this->_cart->saveBillingAddressOnOrderComplete = (bool)$saveAddressesOnOrderComplete;
$this->_cart->saveShippingAddressOnOrderComplete = (bool)$saveAddressesOnOrderComplete;
}

// Set payment currency on cart
Expand Down
Loading

0 comments on commit d386c0f

Please sign in to comment.