# View & Template Rendering

* Checkout structure basically consists of three pages.
  * If the user has not logged in, it first redirects to the `Login-Register-Guest` page.
  * If the user has logged in, it redirects to the `Checkout/Address-Payment` page.
  * If the order is successfully completed, it redirects to the `Success` page.

## <mark style="color:red;">Login-Register-Guest​</mark> <a href="#login-register-guest" id="login-register-guest"></a>

**HTML Path:** `templates/orders/index.html`

**Included File:** `templates/orders/login/index.html`

**Js Path:** `templates/orders/login/index.js`

* Optionally, each of the forms `Login`, `Register` and `Guest` or a combination of these can be used.
* When creating forms in page content, `Html(Jinja)` and `Javascript` should be used together.
* Form macros are imported on the top of the page.

  ```
  {# templates/orders/login/index.html #}
  {% from 'auth/_forms/loginForm.html' import LoginForm %}
  {% from 'auth/_forms/registerForm.html' import RegisterForm %}
  {% from 'auth/_forms/guestForm.html' import GuestForm %}
  ```
* Optionally, a `id` value that corresponds to the ID value of `<pz-form>` element as a parameter can be sent when using macros.

  For instance, if the same form is to be used twice in mobile and desktop viewing, then the forms need to be distinguished by ID.

  ```
  {# templates/orders/login/index.html #}
  ​
  {{ LoginForm() }}
  {# The default id value is "LoginForm". #}
  ​
  {{ LoginForm('checkout_login_form') }}
  {# It can also be used with the custom id value. #}
  ​
  {{ RegisterForm() }}
  {# The default id value is "RegisterForm". #}
  ​
  {{ RegisterForm('checkout_register_form') }}
  {# It can also be used with the custom id value. #}
  ​
  {{ GuestForm() }}
  {# The default id value is "GuestForm". #}
  ​
  {{ GuestForm('checkout_guest_form') }}
  {# It can also be used with the custom id value. #}
  ```
* `LoginForm`, `RegisterForm` and `GuestForm` JS classes are imported under `templates/orders/login/index.js`.

  ```
  /* templates/orders/login/index.js */
  import LoginForm from '../../auth/_forms/loginForm';
  import RegisterForm from '../../auth/_forms/RegisterForm';
  import GuestForm from '../../auth/_forms/guestForm';
  ```
* `LoginForm`, `RegisterForm` and `GuestForm` JS classes are called in the `constructor` method under `CheckoutAuth` class of `templates/orders/login/index.js`.

  Form element should be sent as a parameter to each class.

  ```
  /* templates/orders/login/index.js */
  constructor() {
    new LoginForm(document.getElementById('LoginForm'));
    new RegisterForm(document.getElementById('RegisterForm'));
    new GuestForm(document.getElementById('GuestForm'));
  }
  ```

## <mark style="color:red;">Checkout/Address-Payment​</mark> <a href="#checkoutaddress-payment" id="checkoutaddress-payment"></a>

**HTML Path:** `templates/orders/checkout.html`

**Included File:** `templates/orders/checkout/index.html`

**JS Path:** `templates/orders/checkout/index.js`​

* Checkout/Address-Payment page consists of three main components, which are `Address Tab`, `Checkout Tab` and `Order Summary`.
* When creating page content, `Html(Jinja)` and `Javascript` should be used together.
* There are tabs on top of the page. You can switch between tabs `Address` and `Checkout`.
* `Order Summary` field is fixed on the page.
* `Tab` there are certain functions to launch the structure.
  * The `js-tab` class should be used for the tab button and a `key` that matches `content` should be used in `data-tab` attribute.
  * The `js-tab-content` class should be used for tab content and a `key` matching `tab` should be used in `data-tab` attribute.​

```
{# templates/orders/checkout/index.html #}
​
{# Tab Buttons #}
<button class="js-tab" data-tab="address">Address</button>
<button class="js-tab" data-tab="payment">Checkout</button>
​
{# Tab Contents #}
<div class="js-tab-content" data-tab="address">
  {% include './address/index.html' %}
</div>
<div class="js-tab-content" data-tab="payment">
  {% include './payment/index.html' %}
</div>
​
{# Order Summary #}
{% include './summary/index.html' %}
```

* As seen in the code block above, the `./address/index.html` file for address tab content and the `./payment/index.html` file for the payment tab content are `include`.
* Also demonstrated in the above code block, the `./summary/index.html` file is `include` for the order summary content.
* `Tabs` and `Summary` JS classes are imported under `templates/orders/checkout/index.js`.

  ```
  /* templates/orders/checkout/index.js */
  import Tabs from './tabs';
  import Summary from './summary';
  ```
* `Tabs` and `Summary` JS classes are called in the `constructor` method under `Checkout` class of `templates/orders/checkout/index.js`.

  ```
  /* templates/orders/checkout/index.js */
  constructor() {
    // Runs the tab structure.
    new Tabs();
  ​
    // Runs the order summary fields.
    new Summary(document.querySelector('.js-checkout-page'));
  }
  ```

### <mark style="color:red;">Address (Address Tab)​</mark> <a href="#address-address-tab" id="address-address-tab"></a>

**HTML Path:** `templates/orders/checkout/address/index.html`

**JS Path:** `templates/orders/checkout/address/index.js`

* It is the page that contains the list of addresses and shipping companies.
* The address list field consists of the following components:
  * Information message,
  * List of delivery addresses,
  * List of invoice addresses and
  * Address add and edit form.​
* The shipping company list field consists of the following components:
  * Information message and
  * List of shipping companies.
* The `templateRenderer` JS method is used when creating lists on top of the page.

{% hint style="info" %}
`templateRenderer` The description of the JS method is at the end of this document.
{% endhint %}

### <mark style="color:red;">Payment (Payment Tab)​</mark> <a href="#payment-payment-tab" id="payment-payment-tab"></a>

**HTML Path:** `templates/orders/checkout/payment/index.html`

**JS Path:** `templates/orders/checkout/payment/index.js`

* It is the page that contains payment methods, installment options based on payment method, and the complete order button.
* There are tabs on top of the page. You can switch between available payment options tabs.
* `Tab` there are certain functions to launch the structure.
  * The `js-payment-tab` class should be used for the tab button and a `key` that matches `content` should be used in `data-type` attribute.
  * The `js-payment-tab-content` class should be used for the tab content and a `key` that matches `tab` should be used in `data-type` attribute.

```
{# templates/orders/checkout/payment/index.html #}
​
{# Tab Buttons #}
<button class="js-payment-tab" data-type="credit_card">Credit Card</button>
<button class="js-payment-tab" data-type="funds_transfer">Funds Transfer</button>
​
{# Tab Contents #}
<div class="js-payment-tab-content" data-type="credit_card">
  {% include './credit-card/index.html' %}
</div>
<div class="js-payment-tab-content" data-type="funds_transfer">
  {% include './funds-transfer/index.html' %}
</div>
```

* As seen in the code block above, the `./credit-card/index.html` file for credit card payment option tab content and the `./funds-transfer/index.html` file for the bank transfer payment option tab content are `include`.

### <mark style="color:red;">Summary (Order Summary)​</mark> <a href="#summary-order-summary" id="summary-order-summary"></a>

**HTML Path:** `templates/orders/checkout/summary/index.html`

**JS Path:** `templates/orders/checkout/summary/index.js`

* It is the page that includes all items in the order and item details, as well as price and discount information.

### <mark style="color:red;">templateRenderer​</mark> <a href="#templaterenderer" id="templaterenderer"></a>

**JS Path:** `templates/utils/index.js`​

* The `key`s written in a certain format on HTML elements are matched with `RegExp` by JS, rendered and `render` by `templateRenderer` method.
* The `key`s in `%_keyName_%` format can be inserted in any field in the HTML elements to be used as `Template`.
* `Template` the content of the HTML element to be used for this purpose will be read and the action will be carried out there

  That means, the element we identified as `template` with the `id` or `class` definition will not be included in the outcome.

  ```
  <!-- The template element must have at least one of the unique id or unique class values. -->
  <div id="user-data-template">
    <div data-user-pk="%\_userPk\_%">
      <span>Welcome, %\_userName\_%<span>
      <span>Your location is %\_userLocation\_% and permission is %\_userPermission\_%<span>
    </div>
  </div>
  ​
  <!-- The template element must have at least one of the unique id or unique class values. -->
  <div class="js-user-data"></div>
  ```
* As for JS, the HTML element we identified as `template` is selected, the `key`s it contains are updated with `value`s and `render` into an element, for which an outcome is requested.

  ```
  // The element determined as template is read with the .html() method.
  const template = $('#user-data-template').html();
  ​
  // Determine the new element to render new content.
  const renderContainer = $('.js-user-data');
  ​
  // Sample data object. This object will come from API.
  const data = {
    userPk: 1,
    userName: 'Akinon',
    userLocation: 'Istanbul',
    userPermission: 'Administrator'
  };
  ​
  // The first parameter should be 'template' and the second parameter should be 'data to change'.
  const content = templateRenderer(template, data);
  ​
  // Write the content to renderContainer element.
  renderContainer.html(content);
  ```

The `key`s in the `data` object matched the `key`s in `template` as they have the same title. In the\
`data` object;

was searched and found as\
`%_userPk_%` --> `userPk`,\
`%_userName_%` --> `userName`,\
`%_userLocation_%` --> `userLocation`,\
`%_userPermission_%` --> `userPermission` and its value was received.​

```
const template = $('#user-data-template').html();
const renderContainer = $('.js-user-data');
const data = {
  pk: 1,
  user_name: 'Akinon',
  user_location: 'Istanbul',
  user_permission: 'Administrator'
};
const content = templateRenderer(template, {
  userPk: data.pk,
  userName: data.userName,
  userLocation: data.userLocation,
  userPermission: data.userPermission
});
renderContainer.html(content);
```

In the above example; the `key`s the `data` object do not have the same title as the `key`s in `template`. Therefore, a new object should be created for the second parameter of `templateRenderer` method and matches should be established. Otherwise, `content` constant will return an empty result.

* Finally, the outcome will be as follows.

  ```
  <!-- The structure of template element will not change. -->
  <div id="user-data-template">
    <div data-user-pk="%\_userPk\_%">
      <span>Welcome, %\_userName\_%<span>
      <span>Your location is %\_userLocation\_% and permission is %\_userPermission\_%<span>
    </div>
  </div>
  ​
  <!-- Content will be rendered into the element below. -->
  <div class="js-user-data">
    <div data-user-pk="1">
      <span>Welcome, Akinon<span>
      <span>Your location is Istanbul and permission is Administrator<span>
    </div>
  </div>
  ```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.akinon.com/technical-guides/project-zero/django/page-types/checkout/view-and-template-rendering.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
