Instantly share code, notes, and snippets.

Embed
What would you like to do?
Booking Form allowing units, and updating qty with number of units * days
{% comment %}
Instructions:
1. Add a hidden quantity field for BTA products in the booking-form.liquid snippet:
<input type="hidden" id="quantity" name="quantity" value="1" />
2. Make sure the normal quantity input is not rendered for BTA products (e.g. in sections/product-template.liquid).
For example, this is how it should look on the Debut theme:
{% if section.settings.show_quantity_selector %}
{% unless product.metafields.bookthatapp.config %}
<div class="product-form__item product-form__item--quantity">
<label for="Quantity">{{ 'products.product.quantity' | t }}</label>
<input type="number" id="Quantity" name="quantity" value="1" min="1" class="product-form__input" pattern="[0-9]*">
</div>
{% endunless %}
{% endif %}
3. Add the input for units:
<input type="number" id="units" name="properties[Units]" value="1" min="1" pattern="[0-9]*" />
Note: this is just a regular line item property with the name 'Units'.
It should go just after <div class="booking-form">
You will probably need to copy the markup/CSS classes so that it looks nice. Here is how it should look for Debut:
<input type="hidden" id="quantity" name="quantity" value="1" />
<div class="product-form__item product-form__item--quantity">
<label for="Quantity">{{ 'products.product.quantity' | t }}</label>
<input type="number" id="units" name="properties[Units]" value="1" min="1" class="product-form__input" pattern="[0-9]*" />
</div>
4. Copy the ProductRental Javascript from below to the booking form snippet.
5. Update cart.liquid as per the cart template section below
6. If the theme shows a count of items in the cart header update it per the cart count section below
{% endcomment %}
{% if product.metafields.bookthatapp.config %}
<div class="booking-form">
<div>
{% capture attribute %}booking-start{% endcapture %}
<label for="{{ attribute }}-{{ product.handle }}">From:</label>
<input id="{{ attribute }}-{{ product.handle }}" type="text" name="properties[From]" size="12" class="datepicker bta required bta-load-enable bta-dp-start" disabled="disabled"
data-handle="{{ product.handle }}" data-variant="{{ product.selected_or_first_available_variant.id }}"
data-bta-product-config="{{ product.metafields.bookthatapp.config }}"
data-bta-variant-config="{% for variant in product.variants %}{{ variant.id }}:{{ variant.metafields.bookthatapp.config }}{% unless forloop.last %},{% endunless %}{% endfor %}"
data-bta-range-partner-id="#booking-finish-{{ product.handle }}"
data-bta-range-days-max="0" data-bta-range-days-min="0" />
</div>
<div>
{% capture attribute %}booking-finish{% endcapture %}
<label for="{{ attribute }}-{{ product.handle }}">To:</label>
<input id="{{ attribute }}-{{ product.handle }}" type="text" name="properties[To]" size="12" class="datepicker bta required bta-load-enable bta-dp-finish" disabled="disabled"
data-bta-range-partner-id="#booking-start-{{ product.handle }}" />
</div>
<div class="quantity">
<label for="quantity">Quantity:</label>
{% comment %}
<div class="rental-summary">
Days: <span class="rental-days"></span><br>
Total: <span class="rental-total"></span>
</div>
{% endcomment %}
<input type="number" id="units" name="properties[Units]" value="1" min="1" pattern="[0-9]*" />
</div>
<div class="bta-validation-messages" style="display:none">
<p class="bta-validation-date-missing">Please select a date</p>
</div>
<input type="hidden" id="quantity" name="quantity" value="1" />
</div>
<script>
// rental product behaviour
var ProductRental = function() {
_this = this;
this.configs = {};
this.durations = [];
this.init = function() {
'{{ product.metafields.bookthatapp.config }}'.replace(new RegExp("([^?=&]+)(=([^&]*))?", "g"), function($0, $1, $2, $3) {_this.configs[$1] = $3;});
_this.durations = JSON.parse(unescape(_this.configs.durations)).sort(function(a, b) {
return a.position - b.position;
});
_this.hideDurationOptionSelect();
_this.initFormListeners();
};
this.initFormListeners = function() {
var form = $('form[action="/cart/add"]');
form.on('bta.dataLoaded, bta.datetimeChange', function(event, form) {
_this.updateQuantity();
});
form.on('click', '.js-qty__adjust', function() {
_this.updateQuantity();
});
$('#units').change(function() {
_this.updateQuantity();
});
};
this.updateQuantity = function() {
var form = $('form[action="/cart/add"]').data('bta.bookingForm'),
start = form.getStartDateTime(),
finish = form.getFinishDateTime();
$('.rental-summary .rental-total').text('-');
$('.rental-summary .rental-days').text('-');
if (start && finish) {
var days = form.rangeCount();
// total rent = number of units * number of days * variant.price
var variantId = bta.findSelectedVariantId(),
units = parseInt($('#units').val(), 10),
variant = _this.findVariant(variantId),
total = variant.price * units * days;
$('#quantity').val(units * days);
$('.rental-summary .rental-days').text(days);
$('.rental-summary .rental-total').text(_this.formatMoney(total));
}
};
this.findVariant = function(id) {
for (var i = 0; i < _this.product.variants.length; i++) {
if (_this.product.variants[i].id == id) {
return _this.product.variants[i];
}
}
};
this.hideDurationOptionSelect = function() {
// hide option for duration (bypass .selector-wrapper inside booking form)
$('.selector-wrapper:nth-child(' + _this.configs['duration_option_position'] + ')').filter(function(index) {
return $(this).parents('.booking-form').length == 0;
}).hide();
};
this.formatMoney = function(total) {
return Shopify.formatMoney(total, '{{ shop.money_format }}')
};
this.product = {{ product | json }};
}
document.addEventListener("DOMContentLoaded", function(event) {
new ProductRental().init();
});
var bta = {
productId: {{ product.id }}
}
</script>
{% endif %}
// ============ Cart Template =============
1. Display line item property dates:
{% if item.product.metafields.bookthatapp.config %}
<p>{{ item.properties.From }} - {{ item.properties.To }}</p>
{% else %}
// ususal guff
{% endif %}
2. Show units for quantity
{% if item.product.metafields.bookthatapp.config %}
{{ item.quantity | divided_by: item.properties.Units }} days x {{ item.properties.Units }}
<input type="hidden" name="updates[]" id="Updates_{{ item.id }}" value="{{ item.quantity }}" data-line="{{ forloop.index }}">
<a href="/cart/change?line={{ forloop.index }}&quantity=0">Remove</a>
{% else %}
<input type="number" name="updates[]" id="updates_{{ item.id }}" value="{{ item.quantity }}" min="0" data-line="{{ forloop.index }}">
{% endif %}
// ============ Cart Count (Header) =============
{% assign cart_count = 0 %}
{% for item in cart.items %}
{% if item.product.metafields.bookthatapp.config %}
{% assign cart_count = cart_count | plus: item.properties.Units %}
{% else %}
{% assign cart_count = item.quantity %}
{% endif %}
{% endfor %}
<span class="icon-cart"></span> {{ 'layout.general.cart' | t }} (<span class="cart_count">{{ cart_count }}</span>)
// ============ CSS ============
/* BookThatApp */
.booking-form {
display: -ms-flex;
display: -webkit-flex;
display: flex;
> div {
padding: 10px 0;
margin-right: 20px;
}
> div:last-child {
margin-right: 0px;
}
#units {min-width: 50px}
}
@gterrill

This comment has been minimized.

Copy link
Owner Author

gterrill commented Feb 2, 2019

Please contact us at support@zetya.com if you need help with this or would like a quote to have us install it for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment