Showing order history as an accordion

The commerce.get_orders and commerce.get_order snippets were meant to be used with two separate resources, but the docs mentioned it’s also possible to use get_orders to create an accordion so it’s all in one page instead.

Thanks to Frederik Houwen (@sitsol), we now have an example for that.

On your orders resource, call commerce.get_orders uncached with the name of the twig template you’ll create next.

[[!commerce.get_orders? &tpl=`frontend/account/orders-accordion.twig`]]

Create a twig template at frontend/account/orders-accordion.twig, with this content:

{% if orders|length > 0 %}
<div class="accordian-wrap">
  {% for order in orders %}    
  <div class="item">
    <div class="title-wrap">
      <div class="title">
        <span class="pow">#{{ order.id }}</span>
        <span class="text">{{ order.created_on|date('d-m-Y') }} | {{ order.total_formatted }}</span>
      </div>
    </div>
    <div class="body-wrap">
      <div class="body">
             <h3>{{ lex('commerce.order') }} #{{ order.id }}</h3>

            <ul class="c-order-summary">
                <li>
                    <span class="c-order-summary-label">{{ lex('commerce.date') }}: </span>
                    <span class="c-order-summary-value">{{ order.created_on|date('d-m-Y H:i') }}</span>
                </li>
                <li>
                    <span class="c-order-summary-label">{{ lex('commerce.status') }}: </span>
                    <span class="c-order-summary-value">{{ order.status.name }}</span>
                </li>
                <li>
                    <span class="c-order-summary-label">{{ lex('commerce.total') }}: </span>
                    <span class="c-order-summary-value">{{ order.total_formatted }}</span>
                </li>
            </ul>

            <h3>{{ lex('commerce.order_summary') }}</h3>

            <div class="table-responsive">
            <table class="c-order-details-table c-order-items table">
                <thead>
                <tr>
                    <th>{{ lex('commerce.quantity') }}</th>
                    <th>{{ lex('commerce.product') }}</th>
                    <th>{{ lex('commerce.price') }}</th>
                    <th>{{ lex('commerce.total') }}</th>
                </tr>
                </thead>
                <tbody>
                {% for item in order.items %}
                    <tr>
                        <td class="c-order-item-quantity">{{ item.quantity }}</td>
                        <td class="c-order-item-name"><a href="{{ item.link }}">{{ item.name }}</a></td>
                        <td class="c-order-item-price">{{ item.price_formatted }}</td>
                        <td class="c-order-item-tax">{{ item.total_formatted }}</td>
                    </tr>
                {% endfor %}
                </tbody>
                <tfoot>
                <tr>
                    <td colspan="3">&nbsp;</td>
                    <th>{{ order.total_formatted }}</th>
                </tr>
                </tfoot>
            </table>
            </div>    

            <h3>{{ lex('commerce.transactions') }}</h3>

            <ul class="c-order-details-list c-order-transactions">
                {% for transaction in order.transactions %}
                    <li>
                        <span class="c-order-transaction-method">{{ transaction.method.name }} </span>
                        <span class="c-order-transaction-amount">{{ transaction.amount_formatted }}</span>
                    </li>
                {% endfor %}
            </ul>       
  
      </div>
    </div>
  </div>
  {% endfor %}    
</div>    
{% else %}
<div class="c-orders-none">
    <p>{{ lex('commerce.no_orders_yet') }}</p>
</div>
{% endif %}

Note that this example doesn’t show all the different order totals (like taxes), but those could be added back.

For the css, you’ll need to add this to your css files:

.accordian-wrap {
  padding: 1em;
  border-radius: 10px;
}
.accordian-wrap ul {
    list-style: none;
    padding: 0;
}
.accordian-wrap ul li {
    margin: 0;
    padding: 0;
}
.accordian-wrap .title-wrap {
  background-color: #fff;
  padding: 1em;
  border-radius: 5px;
  border: 1px solid #ddd;
  cursor: pointer;
}
.accordian-wrap .title-wrap .title {
  font-size: 1.1em;
  color: #1a1a1a;
  line-height: 1.3em;
}
.accordian-wrap .title-wrap .title .pow {
  font-size: 1.1em;
  position: relative;
  margin-right: .1em;
  color: #e56620;    
  font-weight: bold;
}
.accordian-wrap .body-wrap {
  padding: .5em;
  margin: 0 .3em;
  background-color: #efefef;
  border-top: 0;
}
.accordian-wrap .body-wrap .body {
  display: none;
  padding: .5em;
  font-size: 1.0em;
  color: #1a1a1a;
  font-weight: 100;
  line-height: 1.5em;
}
.accordian-wrap .body-wrap .body p:nth-last-child(1) {
  margin-bottom: 0 !important;
}
.accordian-wrap .body-wrap .body p:nth-child(1) {
  margin-top: 0 !important;
}
.accordian-wrap .body-wrap .body p:nth-last-child(1):nth-child(1) {
  margin: 0 !important;
}
.accordian-wrap .item.active .body {
  display: block;
}
.accordian-wrap .item.active .title-wrap {
  cursor: default;
}

And finally a tiny bit of javascript for the accordion behaviour.

<script>
        $('.accordian-wrap .item .title-wrap').click( function(){
          if(!$(this).parent().hasClass('active')){
            $parent = $(this).parent().parent();
            $('.item',$parent).removeClass('active');
            $(this).parent().addClass('active');
          }
        });            
</script>

Now your users will have a functional accordion for the previous order section :slight_smile:

2 Likes

And if you use it in combination with pdoPage you can have a nice pagination in Ajax-mode. (getPage is also possible, but there you have no buildin-ajax and I think pdoPage is a little bit faster).