Skip to content
  1. Extras
  2. MiniShop3
  3. Frontend interface
  4. Customer account
  5. Shipping addresses

Delivery addresses

Page for managing customer delivery addresses. Create, edit, delete addresses and set a default.

Page structure

ComponentChunkPurpose
Base layouttpl.msCustomer.baseWrapper with sidebar
Sidebartpl.msCustomer.sidebarAccount navigation
Address listtpl.msCustomer.addressesList container
Address rowtpl.msCustomer.address.rowSingle address row
Address formtpl.msCustomer.address.formCreate/edit form

Snippet call

fenom
{'!msCustomer' | snippet: [
    'service' => 'addresses'
]}

Parameters

ParameterDefaultDescription
serviceService type (addresses)
tpltpl.msCustomer.addressesAddress list chunk
addressTpltpl.msCustomer.address.rowAddress row chunk
formTpltpl.msCustomer.address.formForm chunk
unauthorizedTpltpl.msCustomer.unauthorizedChunk for guests
returntplFormat: tpl or data

Modes

The page has three modes via GET parameter mode:

URLModeDescription
/cabinet/addresses/listAddress list
/cabinet/addresses/?mode=createcreateCreate address
/cabinet/addresses/?mode=edit&id=5editEdit address #5

Placeholders

In tpl.msCustomer.addresses (list)

PlaceholderTypeDescription
{$addresses}stringRendered address rows (HTML)
{$addresses_count}intAddress count
{$customer}arrayCustomer data
{$success}stringSuccess message
{$error}stringError message

In tpl.msCustomer.address.row

PlaceholderTypeDescription
{$id}intAddress ID
{$name}stringAddress name
{$display_name}stringAuto-generated name
{$is_default}boolDefault address
{$index}stringPostal code
{$country}stringCountry
{$region}stringRegion
{$city}stringCity
{$street}stringStreet
{$building}stringBuilding
{$entrance}stringEntrance
{$floor}stringFloor
{$room}stringApartment/office
{$metro}stringMetro station
{$text_address}stringAddress comment

In tpl.msCustomer.address.form

PlaceholderTypeDescription
{$mode}stringMode: create or edit
{$address}arrayAddress data (when editing)
{$errors}arrayValidation errors
{$customer}arrayCustomer data

Address list chunk

fenom
{* tpl.msCustomer.addresses *}
{extends 'tpl.msCustomer.base'}

{block 'content'}
<script src="{'assets_url' | option}components/minishop3/js/web/modules/customer-addresses.js"></script>
<div class="ms3-customer-addresses">
    <div class="card shadow-sm">
        <div class="card-header bg-primary text-white d-flex justify-content-between align-items-center">
            <h5 class="mb-0">{'ms3_customer_addresses_title' | lexicon}</h5>
            <a href="?mode=create" class="btn btn-sm btn-light">
                {'ms3_customer_address_add' | lexicon}
            </a>
        </div>
        <div class="card-body">
            {if $success?}
            <div class="alert alert-success" role="alert">
                {$success}
            </div>
            {/if}

            {if $error?}
            <div class="alert alert-danger" role="alert">
                {$error}
            </div>
            {/if}

            {if $addresses_count > 0}
            <div class="list-group list-group-flush">
                {$addresses}
            </div>
            {else}
            <div class="alert alert-info" role="alert">
                {'ms3_customer_addresses_empty' | lexicon}
            </div>
            {/if}
        </div>
    </div>
</div>
<script>
new CustomerAddresses().init()
</script>
{/block}

Address row chunk

fenom
{* tpl.msCustomer.address.row *}
<div class="list-group-item"
     data-confirm-set-default="{'ms3_customer_address_set_default_confirm' | lexicon}"
     data-confirm-delete="{'ms3_customer_address_delete_confirm' | lexicon}"
     data-error-unknown="{'ms3_err_unknown' | lexicon}">
    <div class="d-flex w-100 justify-content-between align-items-start">
        <div class="flex-grow-1">
            <h6 class="mb-1">
                {if $name}
                    {$name}
                {else}
                    {$display_name}
                {/if}
                {if $is_default}
                <span class="badge bg-success ms-2">
                    {'ms3_customer_address_default' | lexicon}
                </span>
                {/if}
            </h6>
            <p class="mb-1 text-muted small">
                {if $index}{$index}, {/if}
                {$city}{if $region}, {$region}{/if}{if $country}, {$country}{/if}
            </p>
            <p class="mb-1 small">
                {$street}{if $building}, {$building}{/if}
                {if $entrance}, {$entrance}{/if}
                {if $floor}, {$floor}{/if}
                {if $room}, {$room}{/if}
            </p>
            {if $metro}
            <p class="mb-1 small text-muted">{$metro}</p>
            {/if}
        </div>
        <div class="btn-group btn-group-sm ms-3" role="group">
            {if !$is_default}
            <button type="button"
                    class="btn btn-outline-secondary set-default-address"
                    data-address-id="{$id}"
                    title="{'ms3_customer_address_set_default' | lexicon}">

            </button>
            {/if}
            <a href="?mode=edit&id={$id}"
               class="btn btn-outline-primary"
               title="{'ms3_customer_address_edit' | lexicon}">

            </a>
            <button type="button"
                    class="btn btn-outline-danger delete-address"
                    data-address-id="{$id}"
                    title="{'ms3_customer_address_delete' | lexicon}">

            </button>
        </div>
    </div>
</div>

Address form chunk

fenom
{* tpl.msCustomer.address.form *}
<div class="ms3-customer-address-form">
    <div class="card shadow-sm">
        <div class="card-header bg-primary text-white">
            <h5 class="mb-0">
                {if $mode == 'edit'}
                    {'ms3_customer_address_edit' | lexicon}
                {else}
                    {'ms3_customer_address_add' | lexicon}
                {/if}
            </h5>
        </div>
        <div class="card-body">
            <form class="ms3_form ms3-address-form" method="post" action="">
                <input type="hidden" name="ms3_action"
                       value="customer/{if $mode == 'edit'}address-update{else}address-create{/if}">
                {if $mode == 'edit'}
                <input type="hidden" name="id" value="{$address.id}">
                {/if}

                {* Address name *}
                <div class="mb-3">
                    <label for="name" class="form-label">
                        {'ms3_customer_address_name' | lexicon}
                    </label>
                    <input type="text" class="form-control" id="name" name="name"
                           value="{$address.name}"
                           placeholder="{'ms3_customer_address_name_placeholder' | lexicon}">
                    <div class="form-text">
                        {'ms3_customer_address_name_help' | lexicon}
                    </div>
                </div>

                <div class="row">
                    {* Postal code *}
                    <div class="col-md-4 mb-3">
                        <label for="index" class="form-label">
                            {'ms3_customer_index' | lexicon}
                        </label>
                        <input type="text" class="form-control" id="index" name="index"
                               value="{$address.index}">
                    </div>

                    {* Country *}
                    <div class="col-md-8 mb-3">
                        <label for="country" class="form-label">
                            {'ms3_customer_country' | lexicon}
                        </label>
                        <input type="text" class="form-control" id="country" name="country"
                               value="{$address.country}">
                    </div>
                </div>

                <div class="row">
                    {* Region *}
                    <div class="col-md-6 mb-3">
                        <label for="region" class="form-label">
                            {'ms3_customer_region' | lexicon}
                        </label>
                        <input type="text" class="form-control" id="region" name="region"
                               value="{$address.region}">
                    </div>

                    {* City *}
                    <div class="col-md-6 mb-3">
                        <label for="city" class="form-label">
                            {'ms3_customer_city' | lexicon} <span class="text-danger">*</span>
                        </label>
                        <input type="text" class="form-control" id="city" name="city"
                               value="{$address.city}" required>
                    </div>
                </div>

                {* Street *}
                <div class="mb-3">
                    <label for="street" class="form-label">
                        {'ms3_customer_street' | lexicon} <span class="text-danger">*</span>
                    </label>
                    <input type="text" class="form-control" id="street" name="street"
                           value="{$address.street}" required>
                </div>

                <div class="row">
                    {* Building *}
                    <div class="col-md-3 mb-3">
                        <label for="building" class="form-label">
                            {'ms3_customer_building' | lexicon} <span class="text-danger">*</span>
                        </label>
                        <input type="text" class="form-control" id="building" name="building"
                               value="{$address.building}" required>
                    </div>

                    {* Entrance *}
                    <div class="col-md-3 mb-3">
                        <label for="entrance" class="form-label">
                            {'ms3_customer_entrance' | lexicon}
                        </label>
                        <input type="text" class="form-control" id="entrance" name="entrance"
                               value="{$address.entrance}">
                    </div>

                    {* Floor *}
                    <div class="col-md-3 mb-3">
                        <label for="floor" class="form-label">
                            {'ms3_customer_floor' | lexicon}
                        </label>
                        <input type="text" class="form-control" id="floor" name="floor"
                               value="{$address.floor}">
                    </div>

                    {* Room *}
                    <div class="col-md-3 mb-3">
                        <label for="room" class="form-label">
                            {'ms3_customer_room' | lexicon}
                        </label>
                        <input type="text" class="form-control" id="room" name="room"
                               value="{$address.room}">
                    </div>
                </div>

                {* Metro *}
                <div class="mb-3">
                    <label for="metro" class="form-label">
                        {'ms3_customer_metro' | lexicon}
                    </label>
                    <input type="text" class="form-control" id="metro" name="metro"
                           value="{$address.metro}">
                </div>

                {* Comment *}
                <div class="mb-3">
                    <label for="text_address" class="form-label">
                        {'ms3_customer_comment' | lexicon}
                    </label>
                    <textarea class="form-control" id="text_address" name="text_address"
                              rows="2">{$address.text_address}</textarea>
                </div>

                {* Buttons *}
                <div class="d-flex justify-content-between gap-2 mt-4">
                    <a href="?" class="btn btn-secondary">
                        {'ms3_customer_cancel' | lexicon}
                    </a>
                    <button type="submit" class="btn btn-primary ms3_link">
                        {if $mode == 'edit'}
                            {'ms3_customer_save' | lexicon}
                        {else}
                            {'ms3_customer_address_add' | lexicon}
                        {/if}
                    </button>
                </div>
            </form>
        </div>
    </div>
</div>

JavaScript API

The page uses the CustomerAddresses class for AJAX:

javascript
// Init
new CustomerAddresses().init()

// API endpoints
POST /api/v1/customer/address/set-default  // Set default
POST /api/v1/customer/address/delete       // Delete address

Action buttons

html
<!-- Set default -->
<button class="set-default-address" data-address-id="5">★</button>

<!-- Delete -->
<button class="delete-address" data-address-id="5">✕</button>

Form handling

Actionms3_actionDescription
Createcustomer/address-createCreate address
Editcustomer/address-updateUpdate address

Address fields

FieldRequiredDescription
nameNoAddress name (Home, Office)
indexNoPostal code
countryNoCountry
regionNoRegion/state
cityYesCity
streetYesStreet
buildingYesBuilding
entranceNoEntrance
floorNoFloor
roomNoApartment/office
metroNoMetro station
text_addressNoAddress comment

System settings

SettingDescription
ms3_customer_addresses_page_idAddresses page ID

CSS classes

ClassElement
.ms3-customer-addressesAddress list container
.ms3-customer-address-formForm container
.ms3-address-formAddress form
.set-default-addressSet default button
.delete-addressDelete button