--- url: /api.md --- # API ## Customer Addresses ```html
``` ```javascript document.querySelector('form.address').addEventListener('submit', function(event){ event.preventDefault(); var button = this.querySelector('[type="submit"]'); button.disabled = true; button.classList.add('is-loading'); api.user.address.add(new FormData(this)) .then(function(response){ window.location.reload(); }) .catch(function(error){ document.querySelector('.address-error').textContent = error.message; }) .finally(function(){ button.disabled = false; button.classList.remove('is-loading'); }); }); document.querySelector('form.address').addEventListener('submit', function(event){ event.preventDefault(); var button = this.querySelector('[type="submit"]'); button.disabled = true; button.classList.add('is-loading'); api.user.address.update(123456789, new FormData(this)) .then(function(response){ window.location.reload(); }) .catch(function(error){ document.querySelector('.address-error').textContent = error.message; }) .finally(function(){ button.disabled = false; button.classList.remove('is-loading'); }); }); document.querySelector('a.delete-address').addEventListener('click', function(event){ event.preventDefault(); var link = this; link.classList.add('is-loading'); api.user.address.delete(123456789) .then(function(response){ window.location.reload(); }) .catch(function(error){ document.querySelector('.address-error').textContent = error.message; }) .finally(function(){ link.classList.remove('is-loading'); }); }); api.user.address.get(123456789) .then(function(response){ document.querySelector('[name="firstName"]').value = response.firstName; document.querySelector('[name="lastName"]').value = response.lastName; // ... fill remaining fields }) .catch(function(error){ document.querySelector('.address-error').textContent = error.message; }); ``` ## Newsletter (logged-in customer) ### api.user.newsletter.unsubscribe ```javascript document.querySelector('a.customer-unsubscribe').addEventListener('click', function(event){ event.preventDefault(); var link = this; link.classList.add('is-loading'); api.user.newsletter.unsubscribe() .then(function(){ window.location.reload(); }) .catch(function(error){ document.querySelector('.newsletter-error').textContent = error.message; }) .finally(function(){ link.classList.remove('is-loading'); }); }); ``` ## Order ### api.order.delete ```javascript document.querySelector('a.delete-order').addEventListener('click', function(event){ event.preventDefault(); var link = this; link.classList.add('is-loading'); api.order.delete() .then(function(response){ window.location.reload(); }) .catch(function(error){ document.querySelector('.order-error').textContent = error.message; }) .finally(function(){ link.classList.remove('is-loading'); }); }); ``` ### api.order.voucher.add ```javascript document.querySelector('a.add-voucher').addEventListener('click', function(event){ event.preventDefault(); var link = this; link.classList.add('is-loading'); api.order.voucher.add('XYZ1234') .then(function(response){ window.location.reload(); }) .catch(function(error){ document.querySelector('.voucher-error').textContent = error.message; }) .finally(function(){ link.classList.remove('is-loading'); }); }); ``` ### api.order.voucher.delete ```javascript document.querySelector('a.delete-voucher').addEventListener('click', function(event){ event.preventDefault(); var link = this; link.classList.add('is-loading'); api.order.voucher.delete('XYZ1234') .then(function(response){ window.location.reload(); }) .catch(function(error){ document.querySelector('.voucher-error').textContent = error.message; }) .finally(function(){ link.classList.remove('is-loading'); }); }); ``` ### api.order.item.changeAmount ```javascript document.querySelector('a.remove-change-amount').addEventListener('click', function(event){ event.preventDefault(); var link = this; link.classList.add('is-loading'); api.order.item.changeAmount(/* item id*/ 123, 7 /* new amount (cannot be zero) */) .then(function(response){ window.location.reload(); }) .catch(function(error){ document.querySelector('.cart-error').textContent = error.message; // Currently one of stock, unavailable, min_amount, max_amount, amount_multiple // More can be added later - always fallback to error message console.log(error.code); // translated error message console.log(error.message); // item name (useful if rule was triggered by bundle part) console.log(error.item.name); // correct amount for current validation (may not be valid for next validation) // zero for unavailable items console.log(error.recommendedAmount); }) .finally(function(){ link.classList.remove('is-loading'); }); }); ``` ### api.order.item.remove ```javascript document.querySelector('a.remove-cart-item').addEventListener('click', function(event){ event.preventDefault(); var link = this; link.classList.add('is-loading'); api.order.item.delete(123) .then(function(response){ window.location.reload(); }) .catch(function(error){ document.querySelector('.cart-error').textContent = error.message; }) .finally(function(){ link.classList.remove('is-loading'); }); }); ``` ### api.order.status.lookup Look up order status using the order code and email. This method is protected by proof-of-work and rate limiting. ```javascript document.querySelector('form.order-lookup').addEventListener('submit', function(event){ event.preventDefault(); var button = this.querySelector('[type="submit"]'); button.disabled = true; button.classList.add('is-loading'); var orderCode = this.querySelector('[name="orderCode"]').value; var email = this.querySelector('[name="email"]').value; api.order.status.lookup(orderCode, email) .then(function(response){ // redirect to order status page window.location.href = response.url; }) .catch(function(error){ document.querySelector('.order-lookup-error').textContent = error.message; }) .finally(function(){ button.disabled = false; button.classList.remove('is-loading'); }); }); ``` ## Products ### api.product.compare.add ```javascript document.querySelector('a.compare-product').addEventListener('click', function(event){ event.preventDefault(); var link = this; link.classList.add('is-loading'); api.product.compare.add(123) .then(function(response){ response.count // number of products in comparison response.url // URL to the product comparison page }) .catch(function(error){ document.querySelector('.compare-error').textContent = error.message; }) .finally(function(){ link.classList.remove('is-loading'); }); }); ``` ### api.product.compare.remove ```javascript document.querySelector('a.compare-product').addEventListener('click', function(event){ event.preventDefault(); var link = this; link.classList.add('is-loading'); api.product.compare.remove(123) .then(function(response){ response.count // number of products in comparison response.url // URL to the product comparison page }) .catch(function(error){ document.querySelector('.compare-error').textContent = error.message; }) .finally(function(){ link.classList.remove('is-loading'); }); }); ``` ### api.product.compare.clear ```javascript document.querySelector('a.compare-product').addEventListener('click', function(event){ event.preventDefault(); var link = this; link.classList.add('is-loading'); api.product.compare.remove() .then(function(response){ }) .catch(function(error){ document.querySelector('.compare-error').textContent = error.message; }) .finally(function(){ link.classList.remove('is-loading'); }); }); ``` ### api.log.feature.used Feature usage logging is intended for tracking less frequently used features over a limited period -- for example, for A/B testing. The name can be arbitrary -- it is only used for debug reporting. ```javascript document.querySelector('a.compare-product').addEventListener('click', function(event){ event.preventDefault(); api.log.feature.used('product-added-to-compare'); }); ``` ### api.geo.suggest.location Returns a list of locations (addresses, cities, regions, ...) for the given phrase. Optionally, results can be filtered by country ("cz") or biased by coordinates. If the exact location is not known, it should always be used at least with GeoIP coordinates. ```javascript api.geo.suggest.location('Drtinova 10', 'cz', 50.0843, 14.4075); ``` --- --- url: /cart.md --- # Checkout Process ## Checkout Flow Architecture The checkout is a multi-step process controlled by the `sekce` (section) variable. The main template `kosik.tpl` acts as a router, including the appropriate step partial based on the current section: ```twig {# kosik.tpl — checkout router #} {% if kos %} {# nesouhlas = terms and conditions not accepted #} {% if nesouhlas %}No products found.
No products match your filter.
trans:No products found.
```
**Lazy-loaded lifestyle image variant**
```twig