12 Commits

Author SHA1 Message Date
d5d30616f0 Merge branch 'feature_old/standard-styling' into feature_old/isabelle-edits 2025-12-31 17:23:29 +01:00
1490fc6a1e feat(isabelle-edits): Adds spacing, heading, and border utilities
Adds utility classes for spacing, headings, and borders to provide more flexible styling options.

This commit introduces:
- Spacing utilities with responsive adjustments for different screen sizes.
- A heading selector for simplified styling of heading elements.
- A border utility for applying a consistent border style.
2025-12-24 13:51:58 +01:00
252b20bdc6 Add btn after mixin 2025-12-24 11:53:36 +01:00
c7cb507121 Merge branch 'feature/standard-styling' into feature/isabelle-edits 2025-12-24 11:53:03 +01:00
51bad8030e feat(standard-styling): Add button color map 2025-12-24 11:52:12 +01:00
1ccb71c8e0 feat(isabelle-edits): Modify index page layout
This new page structure for the home page makes it so you have more control over the index.tpl file. By default, if the index.tpl file is full width (meaning no side columns) the container becomes fluid and full-width.  For each section, you need to define a container, rows and columns.  This way you can easily have full-width background images for only certain sections.
2025-12-24 10:17:39 +01:00
00b79f12e2 feat(isabelle-edits): Clarify theme structure and add SVG icon support
Improves theme organization by adopting a 7-in-1 SCSS structure.

Introduces support for SVG icons within templates, enhancing visual flexibility.

Adds a checkmark SVG asset.
2025-12-24 09:33:55 +01:00
4ca5500e5f Merge branch 'feature/standard-styling' into feature/isabelle-edits 2025-12-23 09:35:48 +01:00
d5d1cd7874 Background and color utility classes & map 2025-12-22 12:02:19 +01:00
bae76ed030 Merge branch 'feature/standard-styling' into feature/isabelle-edits 2025-12-22 11:36:35 +01:00
871e42f4ba Add gap and font-size function classes 2025-12-22 11:35:05 +01:00
cf37d8a257 feat(isabelle-edits): Made grid & media queries more like bootstrap 5
This branch was made to save edits that would make my life easier but are optional. These edits stray further form the original theme than the edits in the standard styles feature branch do, so if you are not used to them you night not like them. That is why I separated the branch.
2025-12-22 10:49:47 +01:00
41 changed files with 553 additions and 746 deletions

View File

@@ -1,6 +1,6 @@
// Color system
$white: #fff;
$white: #fff;
$gray-100: #f8f9fa;
$gray-200: #e9ecef;
$gray-300: #dee2e6;
@@ -10,24 +10,33 @@ $gray-600: #6c757d;
$gray-700: #495057;
$gray-800: #343a40;
$gray-900: #212529;
$black: #000;
$black: #000;
$blue: #007bff;
$indigo: #6610f2;
$purple: #6f42c1;
$pink: #e83e8c;
$red: #dc3545;
$orange: #fd7e14;
$yellow: #ffc107;
$green: #28a745;
$teal: #20c997;
$cyan: #17a2b8;
$blue: #007bff;
$indigo: #6610f2;
$purple: #6f42c1;
$pink: #e83e8c;
$red: #dc3545;
$orange: #fd7e14;
$yellow: #ffc107;
$green: #28a745;
$teal: #20c997;
$cyan: #17a2b8;
$primary: $blue;
$secondary: $gray-600;
$success: $green;
$info: $cyan;
$warning: #ff9a52;
$danger: $red;
$light: $gray-100;
$dark: $gray-800;
$success: $green;
$info: $cyan;
$warning: #ff9a52;
$danger: $red;
$light: $gray-100;
$dark: $gray-800;
$primary: $blue;
$secondary: $gray-600;
// Map for utility classes
$theme-colors: (
"primary": $primary,
"secondary": $secondary,
//"tertiary": $tertiary,
//"quaternary": $quaternary,,
);

View File

@@ -1,12 +1,5 @@
$border-width: 1px;
$border-color: $gray-300;
$border-radius: 0.4rem;
$border-radius-lg: 0.4rem;
$border-radius-sm: 0.4rem;
$card-border-color: $border-color;
$table-border-color: $border-color;
$input-border-color: $border-color;
$input-focus-border-color: $border-color;
$form-check-input-border: $border-color;
$border-width: 1px;
$border-color: $gray-300;
$border-radius: .4rem;
$border-radius-lg: .4rem;
$border-radius-sm: .4rem;

View File

@@ -1,10 +1,8 @@
$input-btn-padding-y: rem-calc(8px);
$input-btn-padding-x: rem-calc(16px);
$input-btn-padding-y: rem-calc(8px);
$input-btn-padding-x: rem-calc(16px);
$input-btn-padding-y-sm: rem-calc(4px);
$input-btn-padding-x-sm: rem-calc(8px);
$input-btn-padding-y-sm: rem-calc(4px);
$input-btn-padding-x-sm: rem-calc(8px);
$input-btn-padding-y-lg: rem-calc(14px);
$input-btn-padding-x-lg: rem-calc(20px);
$input-height: rem-calc(50px);
$input-btn-padding-y-lg: rem-calc(14px);
$input-btn-padding-x-lg: rem-calc(20px);

View File

@@ -1,7 +1,8 @@
$font-family-sans-serif: "Plus Jakarta Sans", sans-serif;
$font-family-sans-serif: "Roboto", -apple-system, blinkmacsystemfont, "Segoe UI",
roboto, "Helvetica Neue", arial, "Noto Sans", "Liberation Sans", sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
$font-family-base: $font-family-sans-serif;
$headings-font-family: $font-family-sans-serif;
$font-weight-base: 400;
$font-size-base: rem-calc(14px);
$font-size-lg: $font-size-base * 1.125;

View File

@@ -5,4 +5,3 @@
@import "layout/index";
@import "components/index";
@import "custom/custom";

View File

@@ -10,15 +10,18 @@ Look up all available Bootstrap variables here: https://rstudio.github.io/bslib/
*/
//Abstracts: Things used throughout the site such as utility classes and generic overrides.
//@import "abstracts/base";
@import "abstracts/functions";
@import "abstracts/mixins";
@import "abstracts/utilities";
//@import "abstracts/base";
// Components: parts of the theme itself that are not associated with a module.
@import "components/buttons";
//@import "components/buttons";
@import "components/forms";
// Modules: Styling for specific modules.
//@import "modules/";
//Layouts: Parts of a page, such as the header, footer, etc.
//@import "layout/footer";
@import "layout/header";

View File

@@ -8,34 +8,10 @@
}
}
// Font weight utility classes generator
// Generates utility classes like .fw-100, .fw-200, etc.
@for $i from 100 through 900 {
@if $i % 100 == 0 {
.fw-#{$i} {
font-weight: #{$i} !important;
}
}
}
// gap size utility classes generator
// Generates utility classes like .gap-4, .gap-col-4, .gap-row-4
// Generates utility classes like .gap-4
@for $i from 1 through 35 {
.gap-#{$i} {
gap: rem-calc($i * 1px) !important;
}
.gap-col-#{$i} {
column-gap: rem-calc($i * 1px) !important;
}
.gap-row-#{$i} {
row-gap: rem-calc($i * 1px) !important;
}
}
// hex to rgba function
@function hex-to-rgba($hex, $alpha) {
$r: red($hex);
$g: green($hex);
$b: blue($hex);
@return rgba($r, $g, $b, $alpha);
}

View File

@@ -46,7 +46,7 @@
// Mixin to add an after pseudo-element with a mask image to customize button colors
/* Example:
.btn-arrow-right{
.btn{
&::after {
@include btn-after("../img/arrow-right.svg");
}

View File

@@ -1,43 +1,30 @@
// Header selector for interpolation
// Example usage: #{$headers} { ... }
$headers: "h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6";
// All text selector for interpolation
$text: "#{$headers}, p, span, a, li";
// Section Spacers. Just set the two variables below and it is fully responsive!
// $section-spacer-small applies on breakpoints lg and below, OR always if specified in the class with --small (ex. section-spacer--small).
// Spacers
$section-spacer: rem-calc(50px);
$section-spacer-small: rem-calc(25px);
.section-spacer-both {
margin-top: $section-spacer-small;
margin-bottom: $section-spacer-small;
.section-spacer {
margin-top: $section-spacer;
@include bs5-media-breakpoint-up(lg) {
margin-top: $section-spacer;
margin-bottom: $section-spacer;
margin-top: calc($section-spacer * 1.5);
}
&--small {
margin-top: $section-spacer-small;
margin-bottom: $section-spacer-small;
@include bs5-media-breakpoint-up(lg) {
margin-top: $section-spacer-small;
margin-bottom: $section-spacer-small;
margin-top: calc($section-spacer-small * 1.5);
}
}
}
.section-spacer {
@extend .section-spacer-both;
margin-bottom: unset;
&--small {
margin-bottom: unset;
}
// Header selector for interpolation
// Example usage: #{$headings} { ... }
$headings: "h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6";
// Background
.bg__block {
// background: url(../img/bg.svg) repeat center center, $tertiary;
}
.section-spacer-bottom {
@extend .section-spacer-both;
margin-top: unset;
&--small {
margin-top: unset;
}
// Border
.bordered {
border: 1px solid $border-color !important;
}

View File

@@ -1,5 +1,4 @@
// To customize text colors per button, use this map and below function
// To customize text colors per button, use this map
$btn-color: (
"primary": $white,
"secondary": $white,
@@ -7,51 +6,21 @@ $btn-color: (
"dark": $white,
);
// Generate button color overrides from the map
@each $name, $color in $btn-color {
.btn-#{$name},
.btn-lg-#{$name},
.btn-sm-#{$name} {
color: $color !important;
}
}
// Configure btn-outline text color on hover per button. (Same thing as above but for btn-outline and only on hover)
$btn-outline-hover: (
"primary": $white,
"secondary": $white,
);
@each $name, $bg in $btn-outline-hover {
$text-color: if(
map-has-key($btn-color, $name),
map-get($btn-color, $name),
$white
);
.btn-outline-#{$name}:hover,
.btn-outline-#{$name}:focus,
.btn-outline-#{$name}:active,
.btn-outline-#{$name}.active,
.show > .btn-outline-#{$name}.dropdown-toggle {
color: $text-color !important;
}
}
// Bootstrap touchspin
.bootstrap-touchspin {
flex-wrap: nowrap;
.input-touchspin {
height: rem-calc(50px);
min-width: rem-calc(75px);
border-left: 0px;
}
.input-group-btn-vertical {
display: flex;
flex-direction: column;
button {
border-radius: 0px;
.btn-outline-#{$name},
.btn-lg-outline-#{$name},
.btn-sm-outline-#{$name} {
color: $color;
&:hover,
&:focus,
&:active {
color: $color !important;
}
}
}

View File

@@ -1,10 +1,12 @@
.input-group.js-parent-focus {
.field-password-policy .input-group.js-parent-focus {
> * {
max-height: rem-calc(39px);
}
.form-control {
height: unset;
}
.input-group-append .btn {
border-top-right-radius: $border-radius !important;
border-bottom-right-radius: $border-radius !important;
}
}
.input-group.js-parent-focus {
height: $input-height;
}

View File

@@ -10,8 +10,4 @@
margin: 0;
}
}
.header-top__badge {
right: -0.9em;
}
}

View File

@@ -1,6 +1,6 @@
import $ from "jquery";
import prestashop from "prestashop";
import debounce from "@js/theme/utils/debounce";
import $ from 'jquery';
import prestashop from 'prestashop';
import debounce from '@js/theme/utils/debounce';
prestashop.cart = prestashop.cart || {};
@@ -9,395 +9,358 @@ prestashop.cart.active_inputs = null;
const spinnerSelector = 'input[name="product-quantity-spin"]';
let hasError = false;
let isUpdateOperation = false;
let errorMsg = "";
let errorMsg = '';
const CheckUpdateQuantityOperations = {
switchErrorStat: () => {
/**
* if errorMsg is not empty or if notifications are shown, we have error to display
* if hasError is true, quantity was not updated : we don't disable checkout button
*/
const $checkoutBtn = $(prestashop.themeSelectors.checkout.btn);
switchErrorStat: () => {
/**
* if errorMsg is not empty or if notifications are shown, we have error to display
* if hasError is true, quantity was not updated : we don't disable checkout button
*/
const $checkoutBtn = $(prestashop.themeSelectors.checkout.btn);
if (
$(prestashop.themeSelectors.notifications.dangerAlert).length ||
(errorMsg !== "" && !hasError)
) {
$checkoutBtn.addClass("disabled");
}
if ($(prestashop.themeSelectors.notifications.dangerAlert).length || (errorMsg !== '' && !hasError)) {
$checkoutBtn.addClass('disabled');
}
if (errorMsg !== "") {
const strError = `
if (errorMsg !== '') {
const strError = `
<article class="alert alert-danger" role="alert" data-alert="danger">
<ul class="mb-0">
<li>${errorMsg}</li>
</ul>
</article>
`;
$(prestashop.themeSelectors.notifications.container).html(strError);
errorMsg = "";
isUpdateOperation = false;
if (hasError) {
// if hasError is true, quantity was not updated : allow checkout
$checkoutBtn.removeClass("disabled");
}
} else if (!hasError && isUpdateOperation) {
hasError = false;
isUpdateOperation = false;
$(prestashop.themeSelectors.notifications.container).html("");
$checkoutBtn.removeClass("disabled");
}
},
checkUpdateOperation: (resp) => {
/**
* resp.hasError can be not defined but resp.errors not empty: quantity is updated but order cannot be placed
* when resp.hasError=true, quantity is not updated
*/
const { hasError: hasErrorOccurred, errors: errorData } = resp;
hasError = hasErrorOccurred ?? false;
const errors = errorData ?? "";
$(prestashop.themeSelectors.notifications.container).html(strError);
errorMsg = '';
isUpdateOperation = false;
if (hasError) {
// if hasError is true, quantity was not updated : allow checkout
$checkoutBtn.removeClass('disabled');
}
} else if (!hasError && isUpdateOperation) {
hasError = false;
isUpdateOperation = false;
$(prestashop.themeSelectors.notifications.container).html('');
$checkoutBtn.removeClass('disabled');
}
},
checkUpdateOperation: (resp) => {
/**
* resp.hasError can be not defined but resp.errors not empty: quantity is updated but order cannot be placed
* when resp.hasError=true, quantity is not updated
*/
const { hasError: hasErrorOccurred, errors: errorData } = resp;
hasError = hasErrorOccurred ?? false;
const errors = errorData ?? '';
// 1.7.2.x returns errors as string, 1.7.3.x returns array
if (errors instanceof Array) {
errorMsg = errors.join(" ");
} else {
errorMsg = errors;
}
// 1.7.2.x returns errors as string, 1.7.3.x returns array
if (errors instanceof Array) {
errorMsg = errors.join(' ');
} else {
errorMsg = errors;
}
isUpdateOperation = true;
},
isUpdateOperation = true;
},
};
/**
* Attach Bootstrap TouchSpin event handlers
*/
function createSpin() {
$.each($(spinnerSelector), (index, spinner) => {
$(spinner).TouchSpin({
verticalupclass: "",
verticaldownclass: "",
buttondown_class:
"btn btn-primary btn-touchspin js-touchspin js-increase-product-quantity",
buttonup_class:
"btn btn-primary btn-touchspin js-touchspin js-decrease-product-quantity",
min: parseInt($(spinner).attr("min"), 10),
max: 1000000,
verticalup:
'<img src="/themes/falcon/_dev/img/chevron_up.svg" alt="Up" />',
verticaldown:
'<img src="/themes/falcon/_dev/img/chevron_down.svg" alt="Down" />',
});
$.each($(spinnerSelector), (index, spinner) => {
$(spinner).TouchSpin({
verticalupclass: 'material-icons touchspin-up',
verticaldownclass: 'material-icons touchspin-down',
buttondown_class: 'btn btn-touchspin js-touchspin js-increase-product-quantity',
buttonup_class: 'btn btn-touchspin js-touchspin js-decrease-product-quantity',
min: parseInt($(spinner).attr('min'), 10),
max: 1000000,
});
});
CheckUpdateQuantityOperations.switchErrorStat();
CheckUpdateQuantityOperations.switchErrorStat();
}
const preventCustomModalOpen = (event) => {
if (window.shouldPreventModal) {
event.preventDefault();
if (window.shouldPreventModal) {
event.preventDefault();
return false;
}
return false;
}
return true;
return true;
};
$(() => {
const productLineInCartSelector =
prestashop.themeSelectors.cart.productLineQty;
const promises = [];
const productLineInCartSelector = prestashop.themeSelectors.cart.productLineQty;
const promises = [];
prestashop.on("updateCart", () => {
$(prestashop.themeSelectors.cart.quickview).modal("hide");
$("body").addClass("cart-loading");
});
prestashop.on('updateCart', () => {
$(prestashop.themeSelectors.cart.quickview).modal('hide');
$('body').addClass('cart-loading');
});
prestashop.on("updatedCart", () => {
window.shouldPreventModal = false;
prestashop.on('updatedCart', () => {
window.shouldPreventModal = false;
$(prestashop.themeSelectors.product.customizationModal).on(
"show.bs.modal",
(modalEvent) => {
preventCustomModalOpen(modalEvent);
},
);
createSpin();
$("body").removeClass("cart-loading");
$(prestashop.themeSelectors.product.customizationModal).on('show.bs.modal', (modalEvent) => {
preventCustomModalOpen(modalEvent);
});
createSpin();
$('body').removeClass('cart-loading');
});
const $body = $("body");
createSpin();
function isTouchSpin(namespace) {
return (
namespace === "on.startupspin" || namespace === "on.startdownspin"
);
const $body = $('body');
function isTouchSpin(namespace) {
return namespace === 'on.startupspin' || namespace === 'on.startdownspin';
}
function shouldIncreaseProductQuantity(namespace) {
return namespace === 'on.startupspin';
}
function findCartLineProductQuantityInput($target) {
const $input = $target.parents(prestashop.themeSelectors.cart.touchspin).find(productLineInCartSelector);
if ($input.is(':focus')) {
return null;
}
function shouldIncreaseProductQuantity(namespace) {
return namespace === "on.startupspin";
return $input;
}
function camelize(subject) {
const actionTypeParts = subject.split('-');
let i;
let part;
let camelizedSubject = '';
for (i = 0; i < actionTypeParts.length; i += 1) {
part = actionTypeParts[i];
if (i !== 0) {
part = part.substring(0, 1).toUpperCase() + part.substring(1);
}
camelizedSubject += part;
}
function findCartLineProductQuantityInput($target) {
const $input = $target
.parents(prestashop.themeSelectors.cart.touchspin)
.find(productLineInCartSelector);
return camelizedSubject;
}
if ($input.is(":focus")) {
return null;
}
return $input;
function parseCartAction($target, namespace) {
if (!isTouchSpin(namespace)) {
return {
url: $target.attr('href'),
type: camelize($target.data('link-action')),
};
}
function camelize(subject) {
const actionTypeParts = subject.split("-");
let i;
let part;
let camelizedSubject = "";
const $input = findCartLineProductQuantityInput($target);
for (i = 0; i < actionTypeParts.length; i += 1) {
part = actionTypeParts[i];
let cartAction = {};
if (i !== 0) {
part = part.substring(0, 1).toUpperCase() + part.substring(1);
}
camelizedSubject += part;
}
return camelizedSubject;
if ($input) {
if (shouldIncreaseProductQuantity(namespace)) {
cartAction = {
url: $input.data('up-url'),
type: 'increaseProductQuantity',
};
} else {
cartAction = {
url: $input.data('down-url'),
type: 'decreaseProductQuantity',
};
}
}
function parseCartAction($target, namespace) {
if (!isTouchSpin(namespace)) {
return {
url: $target.attr("href"),
type: camelize($target.data("link-action")),
};
}
return cartAction;
}
const $input = findCartLineProductQuantityInput($target);
let cartAction = {};
if ($input) {
if (shouldIncreaseProductQuantity(namespace)) {
cartAction = {
url: $input.data("up-url"),
type: "increaseProductQuantity",
};
} else {
cartAction = {
url: $input.data("down-url"),
type: "decreaseProductQuantity",
};
}
}
return cartAction;
const abortPreviousRequests = () => {
let promise;
while (promises.length > 0) {
promise = promises.pop();
promise.abort();
}
};
const abortPreviousRequests = () => {
let promise;
while (promises.length > 0) {
promise = promises.pop();
promise.abort();
}
const getTouchSpinInput = ($button) => $($button.parents(prestashop.themeSelectors.cart.touchspin).find('input'));
$(prestashop.themeSelectors.product.customizationModal).on('show.bs.modal', (modalEvent) => {
preventCustomModalOpen(modalEvent);
});
const handleCartAction = (event) => {
event.preventDefault();
window.shouldPreventModal = true;
const $target = $(event.currentTarget);
const { dataset } = event.currentTarget;
const cartAction = parseCartAction($target, event.namespace);
const requestData = {
ajax: '1',
action: 'update',
};
const getTouchSpinInput = ($button) =>
$(
$button
.parents(prestashop.themeSelectors.cart.touchspin)
.find("input"),
);
if (typeof cartAction === 'undefined') {
return;
}
$(prestashop.themeSelectors.product.customizationModal).on(
"show.bs.modal",
(modalEvent) => {
preventCustomModalOpen(modalEvent);
},
);
$.ajax({
url: cartAction.url,
method: 'POST',
data: requestData,
dataType: 'json',
beforeSend: (jqXHR) => {
promises.push(jqXHR);
},
})
.then((resp) => {
const $quantityInput = getTouchSpinInput($target);
CheckUpdateQuantityOperations.checkUpdateOperation(resp);
$quantityInput.val(resp.quantity);
const handleCartAction = (event) => {
event.preventDefault();
window.shouldPreventModal = true;
// Refresh cart preview
prestashop.emit('updateCart', {
reason: dataset,
resp,
});
})
.fail((resp) => {
prestashop.emit('handleError', {
eventType: 'updateProductInCart',
resp,
cartAction: cartAction.type,
});
});
};
const $target = $(event.currentTarget);
const { dataset } = event.currentTarget;
$body.on('click', prestashop.themeSelectors.cart.actions, handleCartAction);
const cartAction = parseCartAction($target, event.namespace);
const requestData = {
ajax: "1",
action: "update",
};
function sendUpdateQuantityInCartRequest(updateQuantityInCartUrl, requestData, $target) {
abortPreviousRequests();
window.shouldPreventModal = true;
if (typeof cartAction === "undefined") {
return;
}
return $.ajax({
url: updateQuantityInCartUrl,
method: 'POST',
data: requestData,
dataType: 'json',
beforeSend: (jqXHR) => {
promises.push(jqXHR);
},
})
.then((resp) => {
CheckUpdateQuantityOperations.checkUpdateOperation(resp);
$.ajax({
url: cartAction.url,
method: "POST",
data: requestData,
dataType: "json",
beforeSend: (jqXHR) => {
promises.push(jqXHR);
},
})
.then((resp) => {
const $quantityInput = getTouchSpinInput($target);
CheckUpdateQuantityOperations.checkUpdateOperation(resp);
$quantityInput.val(resp.quantity);
$target.val(resp.quantity);
const dataset = ($target && $target.dataset) ? $target.dataset : resp;
// Refresh cart preview
prestashop.emit("updateCart", {
reason: dataset,
resp,
});
})
.fail((resp) => {
prestashop.emit("handleError", {
eventType: "updateProductInCart",
resp,
cartAction: cartAction.type,
});
});
// Refresh cart preview
prestashop.emit('updateCart', {
reason: dataset,
resp,
});
})
.fail((resp) => {
prestashop.emit('handleError', {
eventType: 'updateProductQuantityInCart',
resp,
});
});
}
function getQuantityChangeType($quantity) {
return $quantity > 0 ? 'up' : 'down';
}
function getRequestData(quantity) {
return {
ajax: '1',
qty: Math.abs(quantity),
action: 'update',
op: getQuantityChangeType(quantity),
};
}
$body.on("click", prestashop.themeSelectors.cart.actions, handleCartAction);
function updateProductQuantityInCart(event) {
const $target = $(event.currentTarget);
const updateQuantityInCartUrl = $target.data('update-url');
const baseValue = $target.attr('value');
function sendUpdateQuantityInCartRequest(
updateQuantityInCartUrl,
requestData,
$target,
) {
abortPreviousRequests();
window.shouldPreventModal = true;
// There should be a valid product quantity in cart
const targetValue = $target.val();
return $.ajax({
url: updateQuantityInCartUrl,
method: "POST",
data: requestData,
dataType: "json",
beforeSend: (jqXHR) => {
promises.push(jqXHR);
},
})
.then((resp) => {
CheckUpdateQuantityOperations.checkUpdateOperation(resp);
/* eslint-disable */
if (targetValue != parseInt(targetValue, 10) || targetValue < 0 || Number.isNaN(targetValue)) {
window.shouldPreventModal = false;
$target.val(baseValue);
return;
}
/* eslint-enable */
$target.val(resp.quantity);
const dataset =
$target && $target.dataset ? $target.dataset : resp;
// There should be a new product quantity in cart
const qty = targetValue - baseValue;
// Refresh cart preview
prestashop.emit("updateCart", {
reason: dataset,
resp,
});
})
.fail((resp) => {
prestashop.emit("handleError", {
eventType: "updateProductQuantityInCart",
resp,
});
});
if (qty === 0) {
return;
}
function getQuantityChangeType($quantity) {
return $quantity > 0 ? "up" : "down";
if (targetValue === '0') {
$target.closest('.product-line-actions').find('[data-link-action="delete-from-cart"]').click();
} else {
$target.attr('value', targetValue);
sendUpdateQuantityInCartRequest(updateQuantityInCartUrl, getRequestData(qty), $target);
}
}
function getRequestData(quantity) {
return {
ajax: "1",
qty: Math.abs(quantity),
action: "update",
op: getQuantityChangeType(quantity),
};
}
$body.on('touchspin.on.stopspin', spinnerSelector, debounce(updateProductQuantityInCart));
function updateProductQuantityInCart(event) {
const $target = $(event.currentTarget);
const updateQuantityInCartUrl = $target.data("update-url");
const baseValue = $target.attr("value");
// There should be a valid product quantity in cart
const targetValue = $target.val();
/* eslint-disable */
if (
targetValue != parseInt(targetValue, 10) ||
targetValue < 0 ||
Number.isNaN(targetValue)
) {
window.shouldPreventModal = false;
$target.val(baseValue);
return;
}
/* eslint-enable */
// There should be a new product quantity in cart
const qty = targetValue - baseValue;
if (qty === 0) {
return;
}
if (targetValue === "0") {
$target
.closest(".product-line-actions")
.find('[data-link-action="delete-from-cart"]')
.click();
} else {
$target.attr("value", targetValue);
sendUpdateQuantityInCartRequest(
updateQuantityInCartUrl,
getRequestData(qty),
$target,
);
}
}
$body.on(
"touchspin.on.stopspin",
spinnerSelector,
debounce(updateProductQuantityInCart),
);
$body.on("focusout keyup", productLineInCartSelector, (event) => {
if (event.type === "keyup") {
if (event.keyCode === 13) {
isUpdateOperation = true;
updateProductQuantityInCart(event);
}
return false;
}
if (!isUpdateOperation) {
updateProductQuantityInCart(event);
$body.on(
'focusout keyup',
productLineInCartSelector,
(event) => {
if (event.type === 'keyup') {
if (event.keyCode === 13) {
isUpdateOperation = true;
updateProductQuantityInCart(event);
}
return false;
});
}
$body.on("click", prestashop.themeSelectors.cart.discountCode, (event) => {
event.stopPropagation();
event.preventDefault();
if (!isUpdateOperation) {
updateProductQuantityInCart(event);
}
const $code = $(event.currentTarget);
const $discountInput = $("[name=discount_name]");
const $discountForm = $discountInput.closest("form");
return false;
},
);
$discountInput.val($code.text());
// Show promo code field
$discountForm.trigger("submit");
$body.on(
'click',
prestashop.themeSelectors.cart.discountCode,
(event) => {
event.stopPropagation();
event.preventDefault();
return false;
});
const $code = $(event.currentTarget);
const $discountInput = $('[name=discount_name]');
const $discountForm = $discountInput.closest('form');
$discountInput.val($code.text());
// Show promo code field
$discountForm.trigger('submit');
return false;
},
);
});

View File

@@ -66,22 +66,6 @@ function initStickyHeader() {
}
}
// Sync product thumbs height with main images height
function syncThumbsHeight() {
const mainImages = document.querySelector(".product-main-images");
const thumbs = document.querySelector(".product-thumbs.swiper");
// Only apply if Swiper is vertical
if (mainImages && thumbs && thumbs.classList.contains("swiper-vertical")) {
thumbs.style.maxHeight = mainImages.offsetHeight + "px";
thumbs.style.height = mainImages.offsetHeight + "px";
} else {
return;
}
}
window.addEventListener("load", syncThumbsHeight);
window.addEventListener("resize", syncThumbsHeight);
$(() => {
initStickyHeader();
accLinksTriggerActive();
@@ -95,19 +79,4 @@ $(() => {
$(".js-select-link").on("change", ({ target }) => {
window.location.href = $(target).val();
});
// Postcode input formatting
const $postCodeInput = $("input[name='postcode']");
$postCodeInput.on("input", function () {
let value = $(this).val();
// Match 4 digits followed by 2 letters (e.g., 1234AB)
const match = value.match(/^(\d{4})([a-zA-Z]{2})$/);
if (match) {
// Add space between numbers and letters
const formatted = `${match[1]} ${match[2]}`;
$(this).val(formatted);
}
});
});

View File

@@ -1,5 +1,5 @@
<div class="col-auto">
<div class="col-auto mt-2 px-1">
<a
class="product-page__action-btn btn btn-light shadow rounded-circle favorite-btn p-2"
href="#"
@@ -18,7 +18,7 @@
{/if}
</div>
<div class="favorite-btn__content favorite-btn__content--add">
{capture name="svg_output"}{svg_icon file='heart.svg' width="22"}{/capture}
{capture name="svg_output"}{svg_icon file='heart.svg'}{/capture}
{if $smarty.capture.svg_output}
{$smarty.capture.svg_output nofilter}
{else}

View File

@@ -17,7 +17,7 @@
{/if}
</div>
<div class="favorite-btn__content favorite-btn__content--add">
{capture name="svg_output"}{svg_icon file='heart.svg' width="22"}{/capture}
{capture name="svg_output"}{svg_icon file='heart.svg'}{/capture}
{if $smarty.capture.svg_output}
{$smarty.capture.svg_output nofilter}
{else}

View File

@@ -28,13 +28,7 @@
<div class="d-flex align-items-center mb-3 justify-content-between position-relative">
<span class="h4 mb-0">{l s='Store information' d='Shop.Theme.Global'}</span>
<a href="#footer_contact_list" class="icon-collapse stretched-link text-reset d-block d-md-none" data-toggle="collapse">
{capture name="svg_output"}{svg_icon file='chevron_down.svg'}{/capture}
{if $smarty.capture.svg_output}
<span style="margin-bottom: 3px;">
{$smarty.capture.svg_output nofilter}
{else}
<i class="material-icons d-block"></i>
{/if}
<i class="material-icons d-block"></i>
</a>
</div>

View File

@@ -28,13 +28,7 @@
<div class="d-flex align-items-center mb-3 justify-content-between position-relative">
<span class="h4 mb-0">{l s='Your account' d='Shop.Theme.Customeraccount'}</span>
<a href="#footer_account_list" class="icon-collapse stretched-link text-reset d-block d-md-none" data-toggle="collapse">
{capture name="svg_output"}{svg_icon file='chevron_down.svg'}{/capture}
{if $smarty.capture.svg_output}
<span style="margin-bottom: 3px;">
{$smarty.capture.svg_output nofilter}
{else}
<i class="material-icons d-block"></i>
{/if}
<i class="material-icons d-block"></i>
</a>
</div>

View File

@@ -33,24 +33,8 @@
title="{l s='Log in to your customer account' d='Shop.Theme.Customeraccount'}"
{/if}
>
<span class="d-none d-xl-block text-secondary">
{if $logged}
{if $customer.firstname}
{$customer.firstname|escape:'html':'UTF-8'}
{else}
{l s='Log out' d='Shop.Theme.Actions'}
{/if}
{else}
{l s='Log in' d='Shop.Theme.Actions'}
{/if}
</span>
<div class="header-top__icon-container">
{capture name="svg_output"}{svg_icon file='person.svg'}{/capture}
{if $smarty.capture.svg_output}
{$smarty.capture.svg_output nofilter}
{else}
<span class="header-top__icon material-icons">person</span>
{/if}
<span class="header-top__icon material-icons">person</span>
</div>
</a>
</div>

View File

@@ -4,13 +4,7 @@
<div class="d-flex align-items-center mb-3 justify-content-between position-relative">
<span class="h4 mb-0">{$linkBlock.title}</span>
<a href="#footer_sub_menu_{$_expand_id}" class="icon-collapse stretched-link text-reset d-block d-md-none" data-toggle="collapse">
{capture name="svg_output"}{svg_icon file='chevron_down.svg'}{/capture}
{if $smarty.capture.svg_output}
<span style="margin-bottom: 3px;">
{$smarty.capture.svg_output nofilter}
{else}
<i class="material-icons d-block"></i>
{/if}
<i class="material-icons d-block"></i>
</a>
</div>
<div id="footer_sub_menu_{$_expand_id}" class="collapse d-md-block">

View File

@@ -23,38 +23,13 @@
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*}
{* Simple display without titles for the header and footer *}
{if $hookName == "displayFooterPrivacy"}
{foreach $linkBlocks as $linkBlock}
{foreach $linkBlock.links as $link}
<p class="links-list__elem mb-0">
<a
id="{$link.id}-{$linkBlock.id}"
class="{$link.class} links-list__link"
href="{$link.url}"
title="{$link.description}"
{if !empty($link.target)} target="{$link.target}" {/if}
>
{$link.title}
</a>
</p>
{/foreach}
{/foreach}
{else}
{* Regular display *}
{foreach $linkBlocks as $linkBlock}
<div class="col-12 col-md-3">
<div class="col-md-3 col-12 mb-lg-4">
{assign var=_expand_id value=10|mt_rand:100000}
<div class="d-flex align-items-center mb-3 justify-content-between position-relative">
<span class="h4 mb-0">{$linkBlock.title}</span>
<a href="#footer_sub_menu_{$_expand_id}" class="icon-collapse stretched-link text-reset d-block d-md-none" data-toggle="collapse">
{capture name="svg_output"}{svg_icon file='chevron_down.svg'}{/capture}
{if $smarty.capture.svg_output}
<span style="margin-bottom: 3px;">
{$smarty.capture.svg_output nofilter}
{else}
<i class="material-icons d-block"></i>
{/if}
<i class="material-icons d-block"></i>
</a>
</div>
<div id="footer_sub_menu_{$_expand_id}" class="collapse d-md-block">
@@ -76,4 +51,3 @@
</div>
</div>
{/foreach}
{/if}

View File

@@ -21,14 +21,9 @@
>
<span class="align-self-center">{$node.label}</span>
{if $node.children|count}
{capture name="svg_output"}{svg_icon file='chevron_down.svg'}{/capture}
{if $smarty.capture.svg_output}
<span class="d-none d-md-block pl-1" style="margin-bottom: 3px;">
{$smarty.capture.svg_output nofilter}
{svg_icon file='chevron_down.svg' }
</span>
{else}
<i class="material-icons d-block"></i>
{/if}
{/if}
</a>
{if $node.children|count}

View File

@@ -1,22 +1,25 @@
<div class="footer-bottom py-1 py-lg-3">
<div class="container">
<div class="row d-flex flex-column flex-lg-row justify-content-between align-items-center">
<div class="copyright">
<span class="text-white fw-400">
{l
s='Copyright © %year% %shop%'
sprintf=['%year%' => $smarty.now|date_format:"%Y", '%shop%' => $shop.name|capitalize]
d='Shop.Theme.Footer'
}
</span>
</div>
<a href="https://dewebsmid.nl/prestashop/" class="text-white fw-400" rel="noopener" target="_blank">
{l s='PrestaShop' d='Shop.Theme.Footer'}
<div class="footer-bottom py-3">
<div class="container d-flex justify-content-between align-items-center">
<div class="copyright">
<span>
{l
s='Copyright © %year% %shop%'
sprintf=['%year%' => $smarty.now|date_format:"%Y", '%shop%' => $shop.name|capitalize]
d='Shop.Theme.Footer'
}
</span>
</div>
<a href="https://dewebsmid.nl/prestashop/" rel="noopener" target="_blank">
{l s='PrestaShop' d='Shop.Theme.Footer'}
</a>
<div class="privacy">
<a href="content/3-gebruiks-voorwaarden">
{l s='Terms & Conditions' d='Shop.Theme.Footer'}
</a>
<span class="mx-2"> | </span>
<a href="content/1-levering">
{l s='Privacy policy' d='Shop.Theme.Footer'}
</a>
<div class="privacy d-flex gap-20">
{* Need to create this hook in the db. Use ps_linklist with it- see modules/ps_linklist/views/templates/hook/linkblock.tpl *}
{hook h='displayFooterPrivacy'}
</div>
</div>
</div>
</div>

View File

@@ -29,7 +29,7 @@
{/block}
</div>
</div>
<div class="footer-container pb-0 mt-0">
<div class="footer-container pb-0">
<div class="container">
<div class="row">
{block name='hook_footer'}

View File

@@ -74,13 +74,9 @@
{/block}
{block name='stylesheets'}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&display=swap" rel="stylesheet">
{include file="_partials/stylesheets.tpl" stylesheets=$stylesheets}
{/block}
{block name='javascript_head'}
{include file="_partials/javascript.tpl" javascript=$javascript.head vars=$js_custom_vars}
{/block}

View File

@@ -33,6 +33,20 @@
{/block}
{block name='header_top'}
{* Optional: Add USP bar at the top of the header
Uncomment the code below to enable it
Use the uspanywhere module and hook to "displayHeaderTopUsps" *}
{*
<div class="header-cta d-none d-lg-block py-2 py-lg-3 bg-primary">
<div class="container">
<div class="row d-flex gap-20">
{hook h='displayHeaderTopUsps'}
</div>
</div>
</div>
*}
<div class="js-header-top-wrapper">
<div class="header-top js-header-top">
<div class="header-top__content pb-md-0 py-2">

View File

@@ -26,43 +26,38 @@
{block name='pagination_page_list'}
{if $pagination.should_be_displayed}
<div class="d-flex justify-content-between align-items-center">
<div class="results__block">
{l s='%curr_numer% van %total_items% resultaten' sprintf=['%curr_numer%' => $pagination.items_shown_to,'%total_items%' => $pagination.total_items] d='Shop.Theme.Actions'}
</div>
<nav>
<ul class="pagination justify-content-center m-0">
{foreach from=$pagination.pages item="page"}
<li class="page-item{if $page.current} active{/if} {if $page.type === 'spacer'}disabled{/if}">
{if $page.type === 'spacer'}
<span
rel="{if $page.type === 'previous'}prev{elseif $page.type === 'next'}next{else}nofollow{/if}"
href="#"
class="page-link"
>
&hellip;
</span>
{else}
<a
rel="{if $page.type === 'previous'}prev{elseif $page.type === 'next'}next{else}nofollow{/if}"
href="{$page.url}"
class="page-link {['disabled' => !$page.clickable, 'js-search-link' => true]|classnames}"
>
{if $page.type === 'previous'}
<span class="material-icons font-reset align-middle">keyboard_arrow_left</span>
<span class="sr-only">{l s='Previous' d='Shop.Theme.Actions'}</span>
{elseif $page.type === 'next'}
<span class="material-icons font-reset align-middle">keyboard_arrow_right</span>
<span class="sr-only">{l s='Next' d='Shop.Theme.Actions'}</span>
{else}
{$page.page}
{/if}
</a>
{/if}
</li>
{/foreach}
</ul>
</nav>
</div>
<nav>
<ul class="pagination justify-content-center mt-4 mb-2">
{foreach from=$pagination.pages item="page"}
<li class="page-item{if $page.current} active{/if} {if $page.type === 'spacer'}disabled{/if}">
{if $page.type === 'spacer'}
<span
rel="{if $page.type === 'previous'}prev{elseif $page.type === 'next'}next{else}nofollow{/if}"
href="#"
class="page-link"
>
&hellip;
</span>
{else}
<a
rel="{if $page.type === 'previous'}prev{elseif $page.type === 'next'}next{else}nofollow{/if}"
href="{$page.url}"
class="page-link {['disabled' => !$page.clickable, 'js-search-link' => true]|classnames}"
>
{if $page.type === 'previous'}
<span class="material-icons font-reset align-middle">keyboard_arrow_left</span>
<span class="sr-only">{l s='Previous' d='Shop.Theme.Actions'}</span>
{elseif $page.type === 'next'}
<span class="material-icons font-reset align-middle">keyboard_arrow_right</span>
<span class="sr-only">{l s='Next' d='Shop.Theme.Actions'}</span>
{else}
{$page.page}
{/if}
</a>
{/if}
</li>
{/foreach}
</ul>
</nav>
{/if}
{/block}

View File

@@ -1,15 +1,7 @@
{* Defensive: Handles LazyArray objects for category *}
{if is_object($category)}
{$category = $category|json_encode|json_decode:true}
{if isset($category.category)}
{$category = $category.category}
{/if}
{/if}
<div id="js-product-list-footer">
{if isset($category.additional_description) && $category.additional_description && $listing.pagination.items_shown_from == 1}
{if $category.additional_description && $listing.pagination.items_shown_from == 1}
<div id="category-description-2" class="cms-content my-3">
{$category.additional_description nofilter}
</div>
{/if}
</div>
</div>

View File

@@ -23,19 +23,24 @@
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*}
{block name='brand_miniature_item'}
<li class="col-12 col-sm-6 col-lg-4 col-xl-3 mb-3">
<li class="col-lg-3 col-sm-4 col-6 mb-3">
<div class="card h-100">
{$brand_url = $brand.image.bySize.home_default.url}
{$sizes = Image::getSize('home_default')}
<img
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='{$sizes.width}' height='{$sizes.height}' viewBox='0 0 1 1'%3E%3C/svg%3E"
data-src="{$brand_url}"
data-src="{$brand.image|replace:'small_default':'home_default'}"
alt="{$brand.name}"
class="card-img-top lazyload"
width="{$sizes.width}"
height="{$sizes.height}"
>
<div class="card-footer text-center">
<div class="card-body">
<p class="h6 mb-0">
<a class="text-reset stretched-link" href="{$brand.url}">{$brand.name}</a>
</p>
</div>
<div class="card-footer text-center">
<span class="btn btn-link p-0">{$brand.nb_products}</span>
</div>
</div>
</li>

View File

@@ -26,7 +26,7 @@
{$listingType = $type|default:'listing'}
<div
{if $listingType === 'listing'}
class="products-list__block col col-sm-6 col-lg-4 col-xl-3"
class="products-list__block products-list__block--grid"
{elseif $listingType === 'slider'}
class="swiper-slide product-slider__item col-6 col-md-4 col-lg-3"
{/if}

View File

@@ -26,8 +26,8 @@
{if !$configuration.is_catalog}
{block name='product_quantity'}
<div class="product-quantity row mb-1 align-items-center">
<div class="qty col-auto px-1">
<div class="product-quantity row mb-1 mx-n1 mt-n2 align-items-center">
<div class="qty col-12 col-sm-auto mx-auto mt-2 px-1">
<input
type="number"
name="qty"
@@ -46,7 +46,7 @@
>
</div>
<div class="add col">
<div class="add col mt-2 px-1">
<button
class="btn btn-primary add-to-cart btn-block"
data-button-action="add-to-cart"

View File

@@ -130,7 +130,6 @@
value="{$product.quantity}"
name="product-quantity-spin"
min="{$product.minimal_quantity}"
data-verticalbuttons="true"
aria-label="{l s='%productName% product quantity field' sprintf=['%productName%' => $product.name] d='Shop.Theme.Checkout'}"
/>
</div>

View File

@@ -38,11 +38,6 @@
<span class="label">{$cart.totals.total.label}&nbsp;{if $configuration.display_taxes_label && $configuration.taxes_enabled}{$cart.labels.tax_short}{/if}</span>
<span class="value">{$cart.totals.total.value}</span>
</div>
{if !$cart.has_delivery_address}
<p class="no_delivery_address_yet_message">
{l s='Shipping costs will be calculated in the next step, before you checkout. Shipping costs depend on the country the order is shipped to. For the Netherlands, orders with a value of € 125.00 will be shipped free of charge. You can view the shippingcosts <a href="https://www.nijssenbulbs.com/content/16-verzendkosten"><u>here</u></a>' d='Shop.Checkout.Total'}
</p>
{/if}
{/if}
{/block}

View File

@@ -72,7 +72,7 @@
{/if}
<div class="add-address mt-2 mb-3">
<a class="btn btn-primary btn-sm" href="{$new_address_delivery_url}">{l s='add new address' d='Shop.Theme.Actions'}</a>
<a class="btn btn-outline-primary btn-sm" href="{$new_address_delivery_url}">{l s='add new address' d='Shop.Theme.Actions'}</a>
</div>
{if $use_same_address && !$cart.is_virtual}
@@ -116,7 +116,7 @@
{/if}
<div class="add-address mt-2 mb-3">
<a class="btn btn-primary btn-sm" href="{$new_address_invoice_url}">{l s='add new address' d='Shop.Theme.Actions'}</a>
<a class="btn btn-outline-primary btn-sm" href="{$new_address_invoice_url}">{l s='add new address' d='Shop.Theme.Actions'}</a>
</div>
{/if}

View File

@@ -44,7 +44,7 @@
{block name='continue_shopping'}
<div class="my-3">
<a class="btn btn-primary" href="{$urls.pages.index}">
<a class="btn btn-outline-primary" href="{$urls.pages.index}">
<span class="material-icons btn-icon mr-1">keyboard_arrow_left</span>
{l s='Continue shopping' d='Shop.Theme.Actions'}
</a>

View File

@@ -73,7 +73,7 @@
</div>
<div class="text-center customer-links__footer">
<a href="{$link->getPageLink('index', true, null, 'mylogout')}" class="customer-links__logout btn btn-secondary mt-2">
<a href="{$link->getPageLink('index', true, null, 'mylogout')}" class="customer-links__logout">
{l s='Sign out' d='Shop.Theme.Actions'}
</a>
</div>

View File

@@ -66,7 +66,7 @@
{if $order.details.reorder_url}
<div class="mt-2 text-right">
<a href="{$order.details.reorder_url}" class="btn btn-primary">{l s='Reorder' d='Shop.Theme.Actions'}</a>
<a href="{$order.details.reorder_url}" class="btn btn-outline-primary">{l s='Reorder' d='Shop.Theme.Actions'}</a>
</div>
{/if}

View File

@@ -24,8 +24,31 @@
*}
{extends file='page.tpl'}
{block name='page_content_container'}
<section id="content" class="page-home">
{* {include file='pages/index/hero.tpl'} *}
</section>
{/block}
{block name='page_content_container'}
<section id="content" class="page-home">
{block name='page_content_top'}{/block}
{block name='page_content'}
{* Define containers, rows and columns here for each section *}
{* Example:
<section id="home_hero" class="mt-0">
<div class="container">
<div class="row">
<div class="col-6 displayCustomhtml1">
{hook h='displayCustomhtml1'}
</div>
<div class="col-6 displayHomeBanner1">
{hook h='displayHomeBanner1'}
</div>
</div>
</div>
</section>
*}
{block name='hook_home'}
{$HOOK_HOME nofilter}
{/block}
{/block}
</section>
{/block}

View File

@@ -25,101 +25,96 @@
<!doctype html>
<html lang="{$language.locale}">
<head>
<head>
{block name='head'}
{include file='_partials/head.tpl'}
{include file='_partials/head.tpl'}
{/block}
</head>
</head>
<body id="{$page.page_name}" class="{$page.body_classes|classnames}">
<body id="{$page.page_name}" class="{$page.body_classes|classnames}">
{block name='hook_after_body_opening_tag'}
{hook h='displayAfterBodyOpeningTag'}
{hook h='displayAfterBodyOpeningTag'}
{/block}
<main class="l-main">
{block name='product_activation'}
{include file='catalog/_partials/product-activation.tpl'}
{/block}
<header id="header" class="l-header mb-0">
{block name='header'}
{include file='_partials/header.tpl'}
{/block}
</header>
<section id="wrapper">
{block name='notifications'}
{include file='_partials/notifications.tpl'}
{block name='product_activation'}
{include file='catalog/_partials/product-activation.tpl'}
{/block}
{hook h="displayWrapperTop"}
<div class="{if $page.page_name == 'index' } container-fluid p-0 overflow-hidden {else}container{/if}">
{block name='breadcrumb'}
{include file='_partials/breadcrumb.tpl'}
{/block}
<div {if $page.page_name != 'index' || !isset($page.body_classes['layout-full-width'])}class="row"{/if}>
{block name="left_column"}
<div id="left-column" class="col-12 col-md-4 col-lg-3">
{if $page.page_name == 'product'}
{hook h='displayLeftColumnProduct' product=$product category=$category}
{else}
{hook h="displayLeftColumn"}
{/if}
</div>
<header id="header" class="l-header">
{block name='header'}
{include file='_partials/header.tpl'}
{/block}
</header>
{block name="content_wrapper"}
<div id="content-wrapper" class="js-content-wrapper left-column right-column col-md-4 col-lg-6">
{hook h="displayContentWrapperTop"}
{block name="content"}
<p>Hello world! This is HTML5 Boilerplate.</p>
<section id="wrapper">
{block name='notifications'}
{include file='_partials/notifications.tpl'}
{/block}
{hook h="displayWrapperTop"}
<div class="{if $page.page_name == 'index' }container-fluid p-0 overflow-hidden{else} container {/if}">
{block name='breadcrumb'}
{include file='_partials/breadcrumb.tpl'}
{/block}
{hook h="displayContentWrapperBottom"}
</div>
{/block}
<div {if $page.page_name != 'index' || !isset($page.body_classes['layout-full-width'])}class="row"{/if}>
{block name="left_column"}
<div id="left-column" class="col-12 col-md-4 col-lg-3">
{if $page.page_name == 'product'}
{hook h='displayLeftColumnProduct' product=$product category=$category}
{else}
{hook h="displayLeftColumn"}
{/if}
</div>
{/block}
{block name="content_wrapper"}
<div id="content-wrapper" class="js-content-wrapper left-column right-column col-md-4 col-lg-6">
{hook h="displayContentWrapperTop"}
{block name="content"}
<p>Hello world! This is HTML5 Boilerplate.</p>
{/block}
{hook h="displayContentWrapperBottom"}
</div>
{/block}
{block name="right_column"}
<div id="right-column" class="col-12 col-md-4 col-lg-3">
{if $page.page_name == 'product'}
{hook h='displayRightColumnProduct'}
{else}
{hook h="displayRightColumn"}
{/if}
</div>
{/block}
</div>
</div>
{hook h="displayWrapperBottom"}
</section>
{block name="right_column"}
<div id="right-column" class="col-12 col-md-4 col-lg-3">
{if $page.page_name == 'product'}
{hook h='displayRightColumnProduct'}
{else}
{hook h="displayRightColumn"}
{/if}
</div>
<footer id="footer" class="l-footer js-footer">
{block name="footer"}
{include file="_partials/footer.tpl"}
{/block}
</div>
</div>
{hook h="displayWrapperBottom"}
</section>
<footer id="footer" class="l-footer js-footer mt-0">
{block name="footer"}
{include file="_partials/footer.tpl"}
{/block}
</footer>
</footer>
</main>
{block name='javascript_bottom'}
{include file="_partials/password-policy-template.tpl"}
{include file="_partials/javascript.tpl" javascript=$javascript.bottom}
{include file="_partials/password-policy-template.tpl"}
{include file="_partials/javascript.tpl" javascript=$javascript.bottom}
{/block}
{block name='hook_before_body_closing_tag'}
{hook h='displayBeforeBodyClosingTag'}
{hook h='displayBeforeBodyClosingTag'}
{/block}
{block name='mobile-modals'}
{include file="_partials/mobile-modals.tpl"}
{include file="_partials/mobile-modals.tpl"}
{/block}
{block name='page-loader'}
{include file="_partials/page-loader.tpl"}
{include file="_partials/page-loader.tpl"}
{/block}
</body>
</body>
</html>

View File

@@ -28,7 +28,7 @@
{block name='right_column'}{/block}
{block name='content_wrapper'}
<div id="content-wrapper" class="{if $page.page_name != 'index' || !isset($page.body_classes['layout-full-width'])}col-12 {/if}js-content-wrapper">
<div id="content-wrapper" class="{if $page.page_name != 'index' || !isset($page.body_classes['layout-full-width'])}col-12 {/if}js-content-wrapper">
{hook h="displayContentWrapperTop"}
{block name='content'}
<p>Hello world! This is HTML5 Boilerplate.</p>

View File

@@ -1,10 +0,0 @@
{* hero section on home page *}
<section id="home_hero" class="section-spacer-both">
<div class="container">
<div class="row">
<div class="col-12 col-md-8 col-xl-6">
</div>
</div>
</div>
</section>