first upload all files

This commit is contained in:
NW
2023-06-11 13:14:03 +01:00
parent f14dbc52b5
commit c08b36d1b6
1705 changed files with 106852 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
window.admin.removeSubmitButtonOffsetOn([
'#logo', '#footer', '#newsletter', '#product_page', '#slider_banners', '#three_column_full_width_banners',
'#brands', '#two_column_banners', '#three_column_banners', '#one_column_banner',
]);
$('#storefront_theme_color').on('change', (e) => {
if (e.currentTarget.value === 'custom_color') {
$('#custom-theme-color').removeClass('hide');
} else {
$('#custom-theme-color').addClass('hide');
}
});
$('#storefront_mail_theme_color').on('change', (e) => {
if (e.currentTarget.value === 'custom_color') {
$('#custom-mail-theme-color').removeClass('hide');
} else {
$('#custom-mail-theme-color').addClass('hide');
}
});
$('#storefront-settings-edit-form').on('click', '.panel-image', (e) => {
let picker = new MediaPicker({ type: 'image' });
picker.on('select', (file) => {
$(e.currentTarget).find('i').remove();
$(e.currentTarget).find('img').attr('src', file.path).removeClass('hide');
$(e.currentTarget).find('.banner-file-id').val(file.id);
});
});
$('.product-type').on('change', (e) => {
let categoryProducts = $(e.currentTarget).parents('.form-group').siblings('.category-products');
let productsLimit = $(e.currentTarget).parents('.form-group').siblings('.products-limit');
let customProducts = $(e.currentTarget).parents('.form-group').siblings('.custom-products');
categoryProducts.addClass('hide');
productsLimit.addClass('hide');
customProducts.addClass('hide');
if (e.currentTarget.value === 'category_products') {
categoryProducts.removeClass('hide');
}
if (e.currentTarget.value === 'latest_products' || e.currentTarget.value === 'recently_viewed_products' || e.currentTarget.value === 'category_products') {
productsLimit.removeClass('hide');
}
if (e.currentTarget.value === 'custom_products') {
customProducts.removeClass('hide');
}
});

View File

@@ -0,0 +1,4 @@
h4.section-title {
font-weight: 500;
margin-bottom: 10px;
}

View File

@@ -0,0 +1,117 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="570" height="466.011" viewBox="0 0 570 466.011">
<defs>
<linearGradient id="linear-gradient" x1="0.5" y1="0.98" x2="0.5" y2="0.034" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#fff" />
<stop offset="1" />
</linearGradient>
</defs>
<g id="Group_146" data-name="Group 146" transform="translate(-26.516 -57.452)">
<g id="Group_76" data-name="Group 76" transform="translate(29.78 115.484)">
<g id="Group_75" data-name="Group 75">
<path id="Path_12" data-name="Path 12" d="M560.936,393.058H110.3c-4.468,0-9.244.5-13.7,0-31.542-3.5-53.1-38.093-62.052-65.553a110.4,110.4,0,0,1-4.759-21.83C27.225,283.024,31.936,259.5,47.634,242.2,61.4,227.039,84.355,224.99,96.778,208.759c9.164-11.924,9.762-28.218,14.989-41.884,3.42-8.938,8.97-17.344,17.021-22.539,6.809-4.388,15-6.212,23.1-6.776a85.133,85.133,0,0,1,37.722,5.986,104.025,104.025,0,0,0,38.609,7.55c15.537.21,30.235-2.339,45.175-6.212,14.617-3.774,30.105-5.146,43.545-12.5,18.989-10.375,32.623-24.588,55.017-27.67,23.943-3.308,50.612,5,66.923,23.233,11,12.311,15.667,28.3,12.2,44.545-2.147,9.988-7.181,21.039.6,29.946,5.13,5.9,13.471,7.808,21.248,8.389,20.99,1.6,39.367,5.825,54.533,21.669,14.973,15.666,16.231,30.832,17.167,51.386a89.989,89.989,0,0,1-1.984,21.8c-.356,1.807-.759,3.615-1.178,5.422-.258,1.1-.517,2.178-.79,3.275-2.243,8.954-6.18,18.312-6.245,27.622-.112,16.681,14.973,25.169,21.781,38.656C556.79,381.8,560.872,393.058,560.936,393.058Z" transform="translate(-29.131 -104)" fill="#d9dffb" />
</g>
</g>
<path id="Path_13" data-name="Path 13" d="M542.641,305.676H29.79C27.225,283.024,31.936,259.5,47.634,242.2,61.4,227.039,84.355,224.99,96.778,208.759c9.164-11.924,9.762-28.218,14.989-41.884,3.42-8.938,8.97-17.344,17.021-22.539,6.809-4.388,15-6.212,23.1-6.776a85.133,85.133,0,0,1,37.722,5.986,104.025,104.025,0,0,0,38.609,7.55c15.537.21,30.235-2.339,45.175-6.212,14.617-3.774,30.105-5.146,43.545-12.5,18.989-10.375,32.623-24.588,55.017-27.67,23.943-3.308,50.612,5,66.923,23.233,11,12.311,15.667,28.3,12.2,44.545-2.147,9.988-7.181,21.039.6,29.946,5.13,5.9,13.471,7.808,21.248,8.389,20.99,1.6,39.367,5.825,54.533,21.669,14.973,15.666,16.231,30.832,17.167,51.386A89.989,89.989,0,0,1,542.641,305.676Z" transform="translate(0.649 11.484)" opacity="0.2" fill="url(#linear-gradient)" style="mix-blend-mode: screen;isolation: isolate" />
<path id="Path_14" data-name="Path 14" d="M199.28,301.828V198.441H154.589l-58.583,83.8L80.679,304.167v32.285h78.588v30.412H199.28V336.451h19.167V301.828Zm-37.2,0H122.789l12.956-19.587,26.331-39.818Z" transform="translate(13.44 34.919)" fill="#1b2c56" />
<path id="Path_15" data-name="Path 15" d="M214.178,328.719v11.424H112.516a9.6,9.6,0,0,1,7.49-7.777c4.9-.935,8.441,2.747,8.675,2.981.216-.754,2.354-7.7,9.286-10.165a14.728,14.728,0,0,1,9.573,0,6.841,6.841,0,0,1,8.389-8.982,13.526,13.526,0,0,1,24.535,4.185,6.8,6.8,0,0,1,12.286,1.8,12.545,12.545,0,0,1,21.428,6.538Z" transform="translate(21.341 62.6)" fill="#99a6d6" />
<path id="Path_16" data-name="Path 16" d="M266.185,158.292c-48.66,0-65.73,36.495-65.73,86.543,0,17.876,2.146,33.993,7.066,47.368,8.97,24.428,27.218,39.657,58.664,39.657,31.428,0,49.692-15.23,58.663-39.657,4.92-13.375,7.067-29.492,7.067-47.368C331.915,194.787,314.829,158.292,266.185,158.292Zm0,136.138a25.748,25.748,0,0,1-11.15-2.227c-13.439-6.292-15.295-25.281-15.295-47.368,0-26.186,2.807-49.112,26.445-49.112,23.62,0,26.427,22.926,26.427,49.112,0,22.087-1.856,41.06-15.279,47.368A25.793,25.793,0,0,1,266.185,294.43Z" transform="translate(43.162 24.956)" fill="#1b2c56" />
<g id="Group_78" data-name="Group 78" transform="translate(394.449 377.394)">
<g id="Group_77" data-name="Group 77">
<path id="Path_17" data-name="Path 17" d="M406.716,329.573v9.6H321.3a8.07,8.07,0,0,1,6.293-6.534c4.12-.785,7.093,2.309,7.289,2.505.181-.634,1.977-6.474,7.8-8.541a12.375,12.375,0,0,1,8.043,0,5.748,5.748,0,0,1,7.048-7.546,11.364,11.364,0,0,1,20.614,3.516,5.714,5.714,0,0,1,10.322,1.509,10.541,10.541,0,0,1,18,5.494Z" transform="translate(-321.299 -313.839)" fill="#99a6d6" />
<path id="Path_18" data-name="Path 18" d="M388.19,337.6h31.591a6.8,6.8,0,0,0-11.021-6.5,3.531,3.531,0,0,0-5.785-3.856,9.227,9.227,0,0,0-6.336-6.795c-4.1-1.1-8.806,1.165-10.835,5.6Q387,331.824,388.19,337.6Z" transform="translate(-305.292 -312.268)" fill="#537ec5" />
</g>
</g>
<path id="Path_19" data-name="Path 19" d="M435.638,301.828V198.441H390.964l-58.6,83.8-15.327,21.926v32.285h78.606v30.412h40V336.451h19.183V301.828Zm-37.189,0h-39.3L372.1,282.24l26.347-39.818Z" transform="translate(72.092 34.919)" fill="#1b2c56" />
<path id="Path_20" data-name="Path 20" d="M151.542,198.441h44.691v83.8H92.959Z" transform="translate(16.488 34.919)" opacity="0.2" fill="url(#linear-gradient)" style="mix-blend-mode: screen;isolation: isolate" />
<path id="Path_21" data-name="Path 21" d="M331.915,244.835c0,17.876-2.147,33.993-7.067,47.368H207.521c-4.92-13.375-7.066-29.492-7.066-47.368,0-50.048,17.07-86.543,65.73-86.543C314.829,158.292,331.915,194.787,331.915,244.835Z" transform="translate(43.162 24.956)" opacity="0.2" fill="url(#linear-gradient)" style="mix-blend-mode: screen;isolation: isolate" />
<path id="Path_22" data-name="Path 22" d="M432.591,198.441v83.8H329.318l58.6-83.8Z" transform="translate(75.139 34.919)" opacity="0.2" fill="url(#linear-gradient)" style="mix-blend-mode: screen;isolation: isolate" />
<g id="Group_81" data-name="Group 81" transform="translate(471.515 384.385)">
<g id="Group_80" data-name="Group 80">
<path id="Path_23" data-name="Path 23" d="M444.886,330.832v6.948H383.044a5.843,5.843,0,0,1,4.556-4.73,6.165,6.165,0,0,1,5.277,1.814,9.616,9.616,0,0,1,5.649-6.185,8.97,8.97,0,0,1,5.824,0,4.162,4.162,0,0,1,5.1-5.463,8.228,8.228,0,0,1,14.925,2.546,4.138,4.138,0,0,1,7.474,1.092,7.631,7.631,0,0,1,13.034,3.978Z" transform="translate(-383.044 -319.441)" fill="#99a6d6" />
<g id="Group_79" data-name="Group 79" transform="translate(58.291 5.721)">
<path id="Path_24" data-name="Path 24" d="M431.475,336.643h22.871a4.921,4.921,0,0,0-7.979-4.708,2.557,2.557,0,0,0-4.189-2.792,6.681,6.681,0,0,0-4.587-4.919,6.9,6.9,0,0,0-7.845,4.055Q430.609,332.461,431.475,336.643Z" transform="translate(-429.746 -324.024)" fill="#bdc9f4" />
</g>
</g>
</g>
<g id="Group_82" data-name="Group 82" transform="translate(307.779 356.78)">
<rect id="Rectangle_15" data-name="Rectangle 15" width="3.226" height="44.815" fill="#010038" />
</g>
<g id="Group_83" data-name="Group 83" transform="translate(243.354 374.838)">
<path id="Path_25" data-name="Path 25" d="M297.447,329.7v10.924h-97.2a9.182,9.182,0,0,1,7.161-7.437c4.689-.894,8.072,2.627,8.3,2.851.206-.721,2.25-7.368,8.879-9.721a14.094,14.094,0,0,1,9.154,0,6.54,6.54,0,0,1,8.019-8.587,12.933,12.933,0,0,1,23.46,4,6.5,6.5,0,0,1,11.746,1.717,11.994,11.994,0,0,1,20.488,6.251Z" transform="translate(-200.244 -311.792)" fill="#99a6d6" />
<path id="Path_26" data-name="Path 26" d="M276.366,338.833h35.949a7.733,7.733,0,0,0-12.541-7.4,4.02,4.02,0,0,0-6.584-4.39,10.5,10.5,0,0,0-7.209-7.732c-4.668-1.253-10.021,1.327-12.33,6.374Q275.007,332.258,276.366,338.833Z" transform="translate(-182.029 -310.004)" fill="#bdc9f4" />
</g>
<path id="Path_64" data-name="Path 64" d="M38.669,336.9c14.084,0,17.45,19.241,22.333,28.983,7.016,14,19.65,25.108,35.8,26.187,10.422.7,20.73-2.727,31.176-2.62,52.431.538,77.184,65.574,129.566,64.885,32.211-.423,60.007-19.16,87.59-33.958,14.17-7.6,28.935-14.552,44.807-17.691,20.091-3.974,40.1-.426,60.133,2.136,4.662.6,9.331,1.15,14.017,1.526,40.915,3.288,102.9-16.166,107.215-64.627q.124-1.386.157-2.777.034-1.329-.025-2.66Z" transform="translate(3.016 69.124)" fill="#1b2c56" />
<path id="Path_65" data-name="Path 65" d="M594.1,334.09H28.935a2.42,2.42,0,0,0,0,4.84H594.1a2.42,2.42,0,1,0,0-4.84Z" transform="translate(0 68.58)" fill="#1b2c56" />
<g id="Group_115" data-name="Group 115" transform="translate(82.42 324.638)">
<g id="Group_110" data-name="Group 110">
<path id="Path_93" data-name="Path 93" d="M71.306,293.216c7.056.422,9.451,7.42,10.029,9.6l7.813,7.815V285.547c-5.622-5.59-1.212-13.976-1.212-13.976,7.134,5.079,3.335,11.864,2.012,13.815v10.149l6.955-6.956c.62-7.886,9.824-9.981,9.824-9.981.768,8.728-6.867,10.239-9.206,10.5L90.009,296.6l-.061-.061V335.51h-.8V311.635l-.061.061-8.215-8.217C71.186,303.552,71.306,293.216,71.306,293.216Z" transform="translate(-71.306 -271.572)" fill="#ff502f" />
<path id="Rectangle_17" data-name="Rectangle 17" d="M3.272,0h9.968a3.272,3.272,0,0,1,3.272,3.272V16.688a0,0,0,0,1,0,0H0a0,0,0,0,1,0,0V3.272A3.272,3.272,0,0,1,3.272,0Z" transform="translate(26.764 78.431) rotate(180)" fill="#1b2c56" />
</g>
<g id="Group_114" data-name="Group 114" transform="translate(17.333 30.492)">
<g id="Group_113" data-name="Group 113">
<g id="Group_112" data-name="Group 112">
<g id="Group_111" data-name="Group 111">
<path id="Path_94" data-name="Path 94" d="M108.11,314.3l-4.141,3.757V314.04c3.14-1.561,10-7.036,6.415-18.038,0,0-12.47,4.777-8.013,18.044v5.8L98.929,316c-.454-2.982-3.281-10.468-13.736-10.234,0,0,.838,11.454,12.69,11.462l4.488,5.006v7.677h1.6v-9.7l5.165-4.686c10.519.716,12.077-9.431,12.077-9.431C111.847,305.146,108.751,311.63,108.11,314.3Z" transform="translate(-85.193 -296.002)" fill="#49beb7" />
</g>
</g>
</g>
<path id="Path_95" data-name="Path 95" d="M109.56,338.028H94.115l-3.2-17.842h21.837Z" transform="translate(-83.772 -290.001)" fill="#1b2c56" />
</g>
</g>
<g id="Group_121" data-name="Group 121" transform="translate(566.104 325.797)">
<g id="Group_120" data-name="Group 120">
<g id="Group_119" data-name="Group 119">
<g id="Group_116" data-name="Group 116" transform="translate(10.027)">
<path id="Path_96" data-name="Path 96" d="M473.088,284.676a71.491,71.491,0,0,1-1.787-11.518l-.026-.658-.457.473a8.051,8.051,0,0,0-2.051,5.195c0,.829.054,1.563.106,2.274a10.016,10.016,0,0,1-.645,5.356c-1.269,2.894-2.107,5.421-.423,9.375l.493,1.146c1.277,2.952,1.8,4.173,1.321,6.538a8.035,8.035,0,0,0,4.487,8.177c-.122,5.367-.277,9.833-.281,9.927l.563.021c.008-.2.711-20.433.292-26.71A71.278,71.278,0,0,0,473.088,284.676Z" transform="translate(-466.861 -272.5)" fill="#ff502f" />
</g>
<g id="Group_117" data-name="Group 117" transform="translate(0 13.549)">
<path id="Path_97" data-name="Path 97" d="M459.718,283.582l-.29-.227-.143.339a6.04,6.04,0,0,0,.7,5.825,7.642,7.642,0,0,1,1.258,4,11.2,11.2,0,0,0,1.94,5.707,13.249,13.249,0,0,0,3.425,3.088c1.286.875,2.214,1.508,2.434,3.082.04.282.072.548.1.8.315,2.49.489,3.872,4.115,5.1,1.051,4.089,1.539,6.94,1.553,7.026l.555-.094C475.325,317.974,470.938,292.372,459.718,283.582Z" transform="translate(-458.828 -283.355)" fill="#ff502f" />
</g>
<g id="Group_118" data-name="Group 118" transform="translate(18.052 20.487)">
<path id="Path_98" data-name="Path 98" d="M481,289.312l-.085-.4-.342.22c-8.631,5.549-7.229,26.607-7.166,27.5l.281-.021h0l.281-.02c0-.064-.134-2.007-.094-4.844.273-.417,1.326-2.023,2.121-3.266a2.889,2.889,0,0,0,.242-2.376,5.912,5.912,0,0,1-.06-2.6,4.742,4.742,0,0,1,1.2-2.423,7.614,7.614,0,0,0,1.309-2.069,6.792,6.792,0,0,0,.448-2.921,3.687,3.687,0,0,1,.741-2.785A4.857,4.857,0,0,0,481,289.312Z" transform="translate(-473.291 -288.914)" fill="#ff502f" />
</g>
</g>
</g>
<path id="Path_99" data-name="Path 99" d="M479.358,339.923h-9.982l-2.764-29.285h15.511Z" transform="translate(-456.896 -263.036)" fill="#1b2c56" />
</g>
<g id="Group_127" data-name="Group 127" transform="translate(57.242 57.722)">
<path id="Path_100" data-name="Path 100" d="M368.515,89.9a11.2,11.2,0,0,0-1.4-4.792l1.39-.775a12.886,12.886,0,0,0-2.685-3.346l-1.058,1.191a11.2,11.2,0,0,0-4.375-2.406l.433-1.524-.02-.005a12.769,12.769,0,0,0-3.495-.487c-.252,0-.5.006-.751.021l.094,1.589a11.22,11.22,0,0,0-4.793,1.4l-.774-1.39a12.835,12.835,0,0,0-3.349,2.682l1.191,1.058a11.187,11.187,0,0,0-2.41,4.374l-1.523-.434-.009.029a12.784,12.784,0,0,0-.487,3.5q0,.371.021.741l1.589-.094a11.221,11.221,0,0,0,1.394,4.794l-1.39.773a12.857,12.857,0,0,0,2.679,3.351l1.061-1.189a11.19,11.19,0,0,0,4.371,2.413l-.437,1.524.04.011a12.825,12.825,0,0,0,3.5.487q.388,0,.771-.024l-.1-1.588a11.225,11.225,0,0,0,4.79-1.407l.776,1.389a12.837,12.837,0,0,0,3.344-2.687l-1.191-1.057a11.2,11.2,0,0,0,2.4-4.377l1.524.432,0-.01a12.819,12.819,0,0,0,.487-3.495c0-.255-.008-.509-.022-.761Zm-13.989,10.509h0l.079-.277Zm9.317-7.988a6.782,6.782,0,1,1,.258-1.852A6.793,6.793,0,0,1,363.843,92.419Z" transform="translate(21.663 -52.751)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<path id="Path_101" data-name="Path 101" d="M338.515,173.9a11.2,11.2,0,0,0-1.4-4.792l1.39-.775a12.884,12.884,0,0,0-2.685-3.346l-1.058,1.191a11.2,11.2,0,0,0-4.375-2.406l.433-1.524-.02,0a12.767,12.767,0,0,0-3.495-.487c-.252,0-.5.006-.751.021l.094,1.589a11.22,11.22,0,0,0-4.793,1.4l-.774-1.39a12.834,12.834,0,0,0-3.349,2.682l1.191,1.058a11.187,11.187,0,0,0-2.41,4.374l-1.523-.434-.009.029a12.785,12.785,0,0,0-.487,3.5q0,.371.021.741l1.589-.094a11.22,11.22,0,0,0,1.394,4.794l-1.39.773a12.859,12.859,0,0,0,2.679,3.351l1.061-1.189a11.19,11.19,0,0,0,4.371,2.413l-.437,1.524.04.011a12.826,12.826,0,0,0,3.5.487q.388,0,.771-.024l-.1-1.588a11.226,11.226,0,0,0,4.79-1.407l.776,1.389a12.837,12.837,0,0,0,3.344-2.687l-1.191-1.057a11.2,11.2,0,0,0,2.4-4.377l1.524.432,0-.01a12.819,12.819,0,0,0,.487-3.495c0-.255-.007-.509-.022-.761Zm-13.989,10.509h0l.079-.277Zm9.317-7.988a6.782,6.782,0,1,1,.258-1.852A6.793,6.793,0,0,1,333.843,176.419Z" transform="translate(14.219 -31.907)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<path id="Path_102" data-name="Path 102" d="M120.262,107.332a6.662,6.662,0,0,0-.836-2.855l.829-.462a7.65,7.65,0,0,0-1.6-1.995l-.63.71a6.66,6.66,0,0,0-2.607-1.434l.258-.909-.011,0a7.612,7.612,0,0,0-2.083-.291c-.15,0-.3,0-.448.014l.056.946a6.687,6.687,0,0,0-2.856.834l-.461-.829a7.646,7.646,0,0,0-2,1.6l.709.63a6.673,6.673,0,0,0-1.435,2.606l-.909-.26,0,.019a7.643,7.643,0,0,0-.29,2.082c0,.149,0,.3.012.442l.947-.055a6.672,6.672,0,0,0,.831,2.857l-.83.461a7.662,7.662,0,0,0,1.6,2l.633-.708a6.662,6.662,0,0,0,2.6,1.437l-.261.909.024.006a7.661,7.661,0,0,0,2.083.291c.154,0,.307,0,.461-.014l-.057-.947a6.665,6.665,0,0,0,2.855-.839l.462.829a7.649,7.649,0,0,0,1.993-1.6l-.71-.63a6.667,6.667,0,0,0,1.432-2.609l.909.258v-.006a7.609,7.609,0,0,0,.29-2.082c0-.152,0-.3-.012-.454Zm-8.336,6.262h0l.047-.165Zm5.553-4.759a4.043,4.043,0,1,1,.154-1.1A4.049,4.049,0,0,1,117.479,108.835Z" transform="translate(-37.531 -47.207)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.322" />
<path id="Path_103" data-name="Path 103" d="M75.157,180.381a11.214,11.214,0,0,0-1.4-4.792l1.39-.775a12.885,12.885,0,0,0-2.685-3.346L71.4,172.659a11.2,11.2,0,0,0-4.375-2.406l.433-1.524-.02-.005a12.817,12.817,0,0,0-3.495-.487q-.378,0-.751.021l.094,1.589a11.216,11.216,0,0,0-4.793,1.4l-.774-1.39a12.86,12.86,0,0,0-3.349,2.682l1.189,1.058a11.2,11.2,0,0,0-2.409,4.373l-1.524-.434-.007.03a12.818,12.818,0,0,0-.488,3.495c0,.247.007.5.022.741l1.589-.094a11.208,11.208,0,0,0,1.394,4.8l-1.39.771a12.812,12.812,0,0,0,2.679,3.351l1.061-1.189a11.175,11.175,0,0,0,4.371,2.413l-.437,1.524.04.011a12.826,12.826,0,0,0,3.5.487c.257,0,.515-.008.771-.024l-.1-1.588a11.231,11.231,0,0,0,4.79-1.407l.776,1.389a12.836,12.836,0,0,0,3.344-2.687L72.352,188.5a11.2,11.2,0,0,0,2.4-4.377l1.523.432,0-.01a12.816,12.816,0,0,0,.487-3.495c0-.255-.007-.509-.022-.761ZM61.168,190.891h0l.077-.277Zm9.317-7.988a6.782,6.782,0,1,1,.258-1.852A6.793,6.793,0,0,1,70.486,182.9Z" transform="translate(-51.133 -30.298)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<path id="Path_104" data-name="Path 104" d="M296.644,88.572a5.747,5.747,0,0,0-.721-2.463l.715-.4a6.606,6.606,0,0,0-1.38-1.719l-.544.612a5.732,5.732,0,0,0-2.248-1.237l.222-.783-.01,0a6.618,6.618,0,0,0-1.8-.25c-.13,0-.258,0-.387.011l.049.816a5.755,5.755,0,0,0-2.463.719l-.4-.714a6.582,6.582,0,0,0-1.721,1.378l.612.544a5.75,5.75,0,0,0-1.238,2.248l-.783-.223-.005.015a6.572,6.572,0,0,0-.251,1.8c0,.127,0,.255.011.381l.818-.047a5.752,5.752,0,0,0,.716,2.464l-.715.4a6.59,6.59,0,0,0,1.377,1.722l.545-.61a5.748,5.748,0,0,0,2.247,1.239l-.225.784.021,0a6.571,6.571,0,0,0,1.8.251c.132,0,.265,0,.4-.012l-.05-.816a5.755,5.755,0,0,0,2.463-.723l.4.714a6.6,6.6,0,0,0,1.72-1.382l-.613-.543a5.738,5.738,0,0,0,1.234-2.25l.784.223V90.71a6.52,6.52,0,0,0,.25-1.8c0-.131,0-.261-.011-.391Zm-7.191,5.4h0l.041-.142Zm4.789-4.105a3.491,3.491,0,0,1-3.356,2.541,3.452,3.452,0,0,1-.952-.134,3.5,3.5,0,1,1,4.309-2.408Z" transform="translate(6.726 -51.616)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<path id="Path_105" data-name="Path 105" d="M171.331,99.773a5.776,5.776,0,0,0-.721-2.463l.714-.4a6.586,6.586,0,0,0-1.379-1.72l-.544.612a5.746,5.746,0,0,0-2.248-1.236l.222-.784-.01,0a6.572,6.572,0,0,0-1.8-.251c-.13,0-.258,0-.387.012l.049.816a5.755,5.755,0,0,0-2.464.719l-.4-.715a6.633,6.633,0,0,0-1.721,1.378l.612.545a5.738,5.738,0,0,0-1.238,2.247l-.784-.223,0,.016a6.571,6.571,0,0,0-.251,1.8c0,.127,0,.255.011.381l.816-.047a5.759,5.759,0,0,0,.718,2.464l-.715.4a6.608,6.608,0,0,0,1.377,1.722l.545-.612a5.766,5.766,0,0,0,2.247,1.241l-.225.783.021.006a6.57,6.57,0,0,0,1.8.25q.2,0,.4-.011l-.05-.816a5.773,5.773,0,0,0,2.463-.724l.4.714a6.585,6.585,0,0,0,1.719-1.38l-.612-.544a5.733,5.733,0,0,0,1.234-2.249l.784.222v0a6.619,6.619,0,0,0,.25-1.8c0-.131,0-.262-.011-.392Zm-7.191,5.4h0l.04-.142Zm4.789-4.105a3.491,3.491,0,0,1-6.85-.949,3.453,3.453,0,0,1,.134-.952,3.49,3.49,0,1,1,6.716,1.9Z" transform="translate(-24.37 -48.836)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<path id="Path_106" data-name="Path 106" d="M188.716,170.914a5.775,5.775,0,0,0-.721-2.464l.714-.4a6.628,6.628,0,0,0-1.379-1.72l-.544.613a5.747,5.747,0,0,0-2.249-1.237l.223-.784-.01,0a6.618,6.618,0,0,0-1.8-.25c-.13,0-.258,0-.387.011l.049.816a5.756,5.756,0,0,0-2.464.719l-.4-.715a6.593,6.593,0,0,0-1.721,1.379l.612.544a5.735,5.735,0,0,0-1.238,2.248l-.784-.223,0,.015a6.571,6.571,0,0,0-.251,1.8c0,.127,0,.255.011.381l.816-.047a5.754,5.754,0,0,0,.718,2.464l-.715.4a6.589,6.589,0,0,0,1.377,1.722l.545-.612a5.726,5.726,0,0,0,2.247,1.241l-.225.783.02.006a6.588,6.588,0,0,0,1.8.251c.132,0,.265,0,.4-.012l-.05-.816a5.784,5.784,0,0,0,2.461-.723l.4.714a6.636,6.636,0,0,0,1.719-1.382l-.613-.543a5.756,5.756,0,0,0,1.236-2.25l.783.223v-.006a6.571,6.571,0,0,0,.251-1.8c0-.131,0-.261-.011-.392Zm-7.191,5.4h0l.04-.142Zm4.789-4.105a3.488,3.488,0,1,1,.132-.952A3.492,3.492,0,0,1,186.314,172.21Z" transform="translate(-20.056 -31.183)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<path id="Path_107" data-name="Path 107" d="M399.44,161.581a4.749,4.749,0,0,0-.593-2.026l.587-.327a5.386,5.386,0,0,0-1.135-1.414l-.447.5A4.723,4.723,0,0,0,396,157.3l.183-.644-.009,0a5.445,5.445,0,0,0-1.477-.206c-.106,0-.212,0-.318.01l.04.672a4.752,4.752,0,0,0-2.026.59l-.327-.587a5.424,5.424,0,0,0-1.415,1.133l.5.447a4.725,4.725,0,0,0-1.017,1.849l-.644-.183,0,.012a5.4,5.4,0,0,0-.206,1.477c0,.1,0,.21.009.313l.671-.039a4.745,4.745,0,0,0,.589,2.026l-.588.327a5.435,5.435,0,0,0,1.133,1.417l.448-.5a4.716,4.716,0,0,0,1.847,1.02l-.185.644.017,0a5.445,5.445,0,0,0,1.477.206c.11,0,.218,0,.327-.01l-.041-.671a4.731,4.731,0,0,0,2.025-.6l.328.588a5.405,5.405,0,0,0,1.413-1.136l-.5-.447a4.726,4.726,0,0,0,1.015-1.85l.644.182v0a5.4,5.4,0,0,0,.206-1.478c0-.107,0-.215-.009-.322Zm-5.912,4.441h0l.032-.117Zm3.938-3.376a2.875,2.875,0,0,1-2.761,2.091,2.938,2.938,0,0,1-.783-.11,2.871,2.871,0,0,1,.78-5.633,2.841,2.841,0,0,1,.783.11,2.868,2.868,0,0,1,1.981,3.542Z" transform="translate(32.779 -33.224)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<path id="Path_108" data-name="Path 108" d="M477.106,196.914a4.737,4.737,0,0,0-.593-2.026l.588-.327a5.429,5.429,0,0,0-1.135-1.414l-.448.5a4.727,4.727,0,0,0-1.848-1.017l.183-.644-.009,0a5.444,5.444,0,0,0-1.477-.206c-.107,0-.212,0-.318.01l.04.672a4.731,4.731,0,0,0-2.026.592l-.327-.588a5.427,5.427,0,0,0-1.415,1.133l.5.448a4.729,4.729,0,0,0-1.018,1.849l-.644-.185,0,.012a5.444,5.444,0,0,0-.206,1.478c0,.1,0,.21.01.313l.671-.04a4.739,4.739,0,0,0,.589,2.027l-.588.326a5.429,5.429,0,0,0,1.132,1.417l.448-.5a4.73,4.73,0,0,0,1.849,1.02l-.185.644.016.005a5.4,5.4,0,0,0,1.478.206c.109,0,.217,0,.326-.01l-.04-.672a4.745,4.745,0,0,0,2.025-.594l.327.587a5.411,5.411,0,0,0,1.414-1.136l-.5-.447a4.7,4.7,0,0,0,1.016-1.85l.644.184v-.005a5.4,5.4,0,0,0,.206-1.477c0-.109,0-.216-.01-.322Zm-5.912,4.442h0l.034-.117Zm3.938-3.376a2.871,2.871,0,0,1-2.76,2.089,2.841,2.841,0,0,1-.783-.11,2.874,2.874,0,1,1,3.542-1.98Z" transform="translate(52.051 -24.456)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<path id="Path_109" data-name="Path 109" d="M368.188,213.479a7.05,7.05,0,0,0-.879-3l.87-.486a8.068,8.068,0,0,0-1.681-2.1l-.663.745a7.014,7.014,0,0,0-2.741-1.507l.272-.955-.012,0a8,8,0,0,0-2.189-.306c-.157,0-.315.005-.471.014l.059.995a7.047,7.047,0,0,0-3,.876l-.484-.87a8.068,8.068,0,0,0-2.1,1.679l.745.664a7.02,7.02,0,0,0-1.509,2.74l-.954-.273,0,.019a8,8,0,0,0-.306,2.189c0,.156,0,.311.014.464l.995-.059a7.032,7.032,0,0,0,.874,3l-.871.484a8.022,8.022,0,0,0,1.679,2.1l.664-.744a7,7,0,0,0,2.737,1.51l-.273.955.025.008a8.048,8.048,0,0,0,2.189.3c.162,0,.323,0,.484-.015l-.061-.995a7.007,7.007,0,0,0,3-.881l.487.87a8.039,8.039,0,0,0,2.094-1.683l-.746-.663a7.012,7.012,0,0,0,1.505-2.741l.954.271,0-.006a8.048,8.048,0,0,0,.3-2.189c0-.16,0-.318-.014-.477Zm-8.763,6.581h0l.05-.174Zm5.836-5a4.247,4.247,0,1,1,.162-1.161A4.257,4.257,0,0,1,365.261,215.058Z" transform="translate(23.809 -20.959)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.262" />
<path id="Path_110" data-name="Path 110" d="M232.641,121.423a5.4,5.4,0,1,1-5.4-5.4A5.4,5.4,0,0,1,232.641,121.423Z" transform="translate(-8.772 -43.255)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<path id="Path_111" data-name="Path 111" d="M323.119,61.1a3.374,3.374,0,1,1-3.375-3.375A3.375,3.375,0,0,1,323.119,61.1Z" transform="translate(14.685 -57.722)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<path id="Path_112" data-name="Path 112" d="M415.545,127.468a3.374,3.374,0,1,1-3.374-3.375A3.373,3.373,0,0,1,415.545,127.468Z" transform="translate(37.62 -41.252)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<path id="Path_113" data-name="Path 113" d="M428.545,189.134a3.374,3.374,0,1,1-3.374-3.374A3.375,3.375,0,0,1,428.545,189.134Z" transform="translate(40.846 -25.95)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<circle id="Ellipse_11" data-name="Ellipse 11" cx="3.374" cy="3.374" r="3.374" transform="translate(309.897 74.802)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<path id="Path_114" data-name="Path 114" d="M198.044,71.91a3.374,3.374,0,1,1-3.374-3.374A3.373,3.373,0,0,1,198.044,71.91Z" transform="translate(-16.352 -55.039)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<path id="Path_115" data-name="Path 115" d="M97,152.4a3.374,3.374,0,1,1-3.375-3.374A3.375,3.375,0,0,1,97,152.4Z" transform="translate(-41.426 -35.064)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<g id="Group_122" data-name="Group 122" transform="translate(256.261 6.861)">
<line id="Line_10" data-name="Line 10" y2="6.523" transform="translate(3.262)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<line id="Line_11" data-name="Line 11" x1="6.523" transform="translate(0 3.262)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
</g>
<g id="Group_123" data-name="Group 123" transform="translate(61.859 198.114)">
<line id="Line_12" data-name="Line 12" y2="6.523" transform="translate(3.262)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<line id="Line_13" data-name="Line 13" x1="6.523" transform="translate(0 3.262)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
</g>
<g id="Group_124" data-name="Group 124" transform="translate(170.765 67.213)">
<line id="Line_14" data-name="Line 14" y2="6.523" transform="translate(3.262)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<line id="Line_15" data-name="Line 15" x1="6.523" transform="translate(0 3.262)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
</g>
<g id="Group_125" data-name="Group 125" transform="translate(96.5 140.229)">
<line id="Line_16" data-name="Line 16" y2="6.523" transform="translate(3.262 0)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<line id="Line_17" data-name="Line 17" x1="6.523" transform="translate(0 3.262)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
</g>
<g id="Group_126" data-name="Group 126" transform="translate(24.654 73.378)">
<line id="Line_18" data-name="Line 18" y2="6.523" transform="translate(3.262)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
<line id="Line_19" data-name="Line 19" x1="6.523" transform="translate(0 3.262)" fill="none" stroke="#99a6d6" stroke-miterlimit="10" stroke-width="0.541" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,48 @@
import Vue from 'vue';
export default class {
constructor() {
this.errors = {};
}
record(errors) {
this.errors = errors;
}
any() {
return Object.keys(this.errors).length > 0;
}
has(key) {
return this.errors.hasOwnProperty(key);
}
get(key) {
if (this.errors[key]) {
return this.errors[key][0];
}
}
clear(key) {
if (key === undefined) {
return;
}
Vue.delete(this.errors, this.normalizeKey(key));
}
reset() {
this.errors = {};
}
normalizeKey(key) {
let keyParts = key.replace('[]', '').split('[');
// No need to normalize the key.
if (keyParts.length === 1) {
return key;
}
return keyParts.join('.').slice(0, -1);
}
}

View File

@@ -0,0 +1,98 @@
require("./storefront");
import Vue from "vue";
import store from "./store";
import { notify, trans, chunk } from "./functions";
import VueToast from "vue-toast-notification";
import vClickOutside from "v-click-outside";
import VPagination from "./components/VPagination.vue";
import HeaderSearch from "./components/layout/HeaderSearch.vue";
import SidebarCart from "./components/layout/SidebarCart";
import NewsletterPopup from "./components/layout/NewsletterPopup";
import NewsletterSubscription from "./components/layout/NewsletterSubscription";
import CookieBar from "./components/layout/CookieBar";
import LandscapeProducts from "./components/LandscapeProducts.vue";
import DynamicTab from "./components/home/DynamicTab";
import HomeFeatures from "./components/home/HomeFeatures.vue";
import FeaturedCategories from "./components/home/FeaturedCategories.vue";
import BannerThreeColumnFullWidth from "./components/home/BannerThreeColumnFullWidth.vue";
import ProductTabsOne from "./components/home/ProductTabsOne.vue";
import TopBrands from "./components/home/TopBrands.vue";
import FlashSaleAndVerticalProducts from "./components/home/FlashSaleAndVerticalProducts.vue";
import FlashSale from "./components/home/FlashSale.vue";
import BannerTwoColumn from "./components/home/BannerTwoColumn.vue";
import VerticalProducts from "./components/home/VerticalProducts.vue";
import ProductGrid from "./components/home/ProductGrid.vue";
import BannerThreeColumn from "./components/home/BannerThreeColumn.vue";
import ProductTabsTwo from "./components/home/ProductTabsTwo.vue";
import BannerOneColumn from "./components/home/BannerOneColumn.vue";
import ProductIndex from "./components/products/Index";
import ProductCardGridView from "./components/products/index/ProductCardGridView.vue";
import ProductCardListView from "./components/products/index/ProductCardListView.vue";
import ProductCardVertical from "./components/ProductCardVertical.vue";
import ProductShow from "./components/products/Show";
import CartIndex from "./components/cart/Index";
import CheckoutCreate from "./components/checkout/Create";
import CompareIndex from "./components/compare/Index";
import MyWishlist from "./components/account/wishlist/Index";
import MyAddresses from "./components/account/addresses/Index";
Vue.prototype.route = route;
Vue.prototype.$notify = notify;
Vue.prototype.$trans = trans;
Vue.prototype.$chunk = chunk;
Vue.use(VueToast);
Vue.use(vClickOutside);
Vue.component("v-pagination", VPagination);
Vue.component("header-search", HeaderSearch);
Vue.component("sidebar-cart", SidebarCart);
Vue.component("newsletter-popup", NewsletterPopup);
Vue.component("newsletter-subscription", NewsletterSubscription);
Vue.component("cookie-bar", CookieBar);
Vue.component("landscape-products", LandscapeProducts);
Vue.component("dynamic-tab", DynamicTab);
Vue.component("home-features", HomeFeatures);
Vue.component("featured-categories", FeaturedCategories);
Vue.component("banner-three-column-full-width", BannerThreeColumnFullWidth);
Vue.component("product-tabs-one", ProductTabsOne);
Vue.component("top-brands", TopBrands);
Vue.component("flash-sale-and-vertical-products", FlashSaleAndVerticalProducts);
Vue.component("flash-sale", FlashSale);
Vue.component("banner-two-column", BannerTwoColumn);
Vue.component("vertical-products", VerticalProducts);
Vue.component("product-grid", ProductGrid);
Vue.component("banner-three-column", BannerThreeColumn);
Vue.component("product-tabs-two", ProductTabsTwo);
Vue.component("banner-one-column", BannerOneColumn);
Vue.component("product-index", ProductIndex);
Vue.component("product-card-grid-view", ProductCardGridView);
Vue.component("product-card-list-view", ProductCardListView);
Vue.component("product-card-vertical", ProductCardVertical);
Vue.component("product-show", ProductShow);
Vue.component("cart-index", CartIndex);
Vue.component("checkout-create", CheckoutCreate);
Vue.component("compare-index", CompareIndex);
Vue.component("my-wishlist", MyWishlist);
Vue.component("my-addresses", MyAddresses);
new Vue({
el: "#app",
computed: {
cart() {
return store.state.cart;
},
wishlistCount() {
return store.wishlistCount();
},
},
});
$.ajaxSetup({
headers: {
"X-CSRF-TOKEN": FleetCart.csrfToken,
},
});

View File

@@ -0,0 +1,99 @@
<template>
<section class="landscape-products-wrap" v-if="hasAnyProduct">
<div class="container">
<div class="products-header">
<h5 class="section-title">{{ title }}</h5>
</div>
<div class="landscape-products" ref="productsPlaceholder">
<ProductCard v-for="(product, index) in products" :key="index" :product="product"></ProductCard>
</div>
</div>
</section>
</template>
<script>
import ProductCard from './ProductCard.vue';
import { slickPrevArrow, slickNextArrow } from '../functions';
export default {
components: { ProductCard },
props: ['title', 'products'],
computed: {
hasAnyProduct() {
return this.products.length !== 0;
},
},
mounted() {
$(this.$refs.productsPlaceholder).slick({
rows: 0,
dots: false,
arrows: true,
infinite: true,
slidesToShow: 6,
slidesToScroll: 6,
rtl: window.FleetCart.rtl,
prevArrow: slickPrevArrow(),
nextArrow: slickNextArrow(),
responsive: [
{
breakpoint: 1761,
settings: {
slidesToShow: 5,
slidesToScroll: 5,
},
},
{
breakpoint: 1301,
settings: {
slidesToShow: 4,
slidesToScroll: 4,
},
},
{
breakpoint: 1051,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
},
},
{
breakpoint: 992,
settings: {
slidesToShow: 4,
slidesToScroll: 4,
},
},
{
breakpoint: 881,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
},
},
{
breakpoint: 768,
settings: {
dots: true,
arrows: false,
slidesToShow: 3,
slidesToScroll: 3,
},
},
{
breakpoint: 641,
settings: {
dots: true,
arrows: false,
slidesToShow: 2,
slidesToScroll: 2,
},
},
],
});
},
};
</script>

View File

@@ -0,0 +1,92 @@
<template>
<div class="product-card">
<div class="product-card-top">
<a :href="productUrl" class="product-image">
<img :src="baseImage" :class="{ 'image-placeholder': ! hasBaseImage }" alt="product image">
</a>
<div class="product-card-actions">
<button
class="btn btn-wishlist"
:class="{ 'added': inWishlist }"
:title="$trans('storefront::product_card.wishlist')"
@click="syncWishlist"
>
<i class="la-heart" :class="inWishlist ? 'las' : 'lar'"></i>
</button>
<button
class="btn btn-compare"
:class="{ 'added': inCompareList }"
:title="$trans('storefront::product_card.compare')"
@click="syncCompareList"
>
<i class="las la-random"></i>
</button>
</div>
<ul class="list-inline product-badge">
<li class="badge badge-danger" v-if="product.is_out_of_stock">
{{ $trans('storefront::product_card.out_of_stock') }}
</li>
<li class="badge badge-primary" v-else-if="product.is_new">
{{ $trans('storefront::product_card.new') }}
</li>
<li class="badge badge-success" v-if="product.has_percentage_special_price">
-{{ product.special_price_percent }}%
</li>
</ul>
</div>
<div class="product-card-middle">
<ProductRating :ratingPercent="product.rating_percent" :reviewCount="product.reviews.length"/>
<a :href="productUrl" class="product-name">
<h6>{{ product.name }}</h6>
</a>
<div class="product-price product-price-clone" v-html="product.formatted_price"></div>
</div>
<div class="product-card-bottom">
<div class="product-price" v-html="product.formatted_price"></div>
<button
v-if="hasNoOption || product.is_out_of_stock"
class="btn btn-primary btn-add-to-cart"
:class="{ 'btn-loading': addingToCart }"
:disabled="product.is_out_of_stock"
@click="addToCart"
>
<i class="las la-cart-arrow-down"></i>
{{ $trans('storefront::product_card.add_to_cart') }}
</button>
<a
v-else
:href="productUrl"
class="btn btn-primary btn-add-to-cart"
>
<i class="las la-eye"></i>
{{ $trans('storefront::product_card.view_options') }}
</a>
</div>
</div>
</template>
<script>
import ProductRating from './ProductRating.vue';
import ProductCardMixin from '../mixins/ProductCardMixin';
export default {
components: { ProductRating },
mixins: [
ProductCardMixin,
],
props: ['product'],
};
</script>

View File

@@ -0,0 +1,32 @@
<template>
<div :href="productUrl" class="vertical-product-card">
<a :href="productUrl" class="product-image">
<img :src="baseImage" :class="{ 'image-placeholder': ! hasBaseImage }" alt="product-image">
</a>
<div class="product-info">
<a :href="productUrl" class="product-name">
<h6>{{ product.name }}</h6>
</a>
<div class="product-price" v-html="product.formatted_price"></div>
<ProductRating :ratingPercent="product.rating_percent" :reviewCount="product.reviews.length"/>
</div>
</div>
</template>
<script>
import ProductRating from './ProductRating.vue';
import ProductCardMixin from '../mixins/ProductCardMixin';
export default {
components: { ProductRating },
mixins: [
ProductCardMixin,
],
props: ['product'],
};
</script>

View File

@@ -0,0 +1,33 @@
<template>
<div class="product-rating">
<div class="back-stars">
<i class="las la-star"></i>
<i class="las la-star"></i>
<i class="las la-star"></i>
<i class="las la-star"></i>
<i class="las la-star"></i>
<div class="front-stars" :style="{ width: ratingPercent + '%' }">
<i class="las la-star"></i>
<i class="las la-star"></i>
<i class="las la-star"></i>
<i class="las la-star"></i>
<i class="las la-star"></i>
</div>
</div>
<span class="rating-count" v-if="hasReviewCount">({{ this.reviewCount }})</span>
</div>
</template>
<script>
export default {
props: ['ratingPercent', 'reviewCount'],
computed: {
hasReviewCount() {
return this.reviewCount !== undefined;
},
},
};
</script>

View File

@@ -0,0 +1,143 @@
<template>
<ul class="pagination">
<li class="page-item" :class="{ disabled: hasFirst }">
<button class="page-link" :disabled="hasFirst" @click="prev">
<i class="las la-angle-left"></i>
</button>
</li>
<li v-show="rangeFirstPage !== 1" class="page-item">
<button class="page-link" @click="goto(1)">
1
</button>
</li>
<li v-show="rangeFirstPage === 3" class="page-item">
<button class="page-link" @click="goto(2)">
2
</button>
</li>
<li
v-show="rangeFirstPage !== 1 && rangeFirstPage !== 2 && rangeFirstPage !== 3"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li
v-for="page in range"
:key="page"
class="page-item"
:class="{ active: hasActive(page) }"
>
<button class="page-link" @click="goto(page)">
{{ page }}
</button>
</li>
<li
v-show="rangeLastPage !== totalPage && rangeLastPage !== (totalPage - 1) && rangeLastPage !== (totalPage - 2)"
class="page-item disabled"
>
<span class="page-link">...</span>
</li>
<li v-show="rangeLastPage === (totalPage - 2)" class="page-item">
<button class="page-link" @click="goto(totalPage - 1)">
{{ totalPage - 1 }}
</button>
</li>
<li v-if="rangeLastPage !== totalPage" class="page-item">
<button class="page-link" @click="goto(totalPage)">
{{ totalPage }}
</button>
</li>
<li class="page-item" :class="{ disabled: hasLast }">
<button class="page-link" :class="{ disabled: hasLast }" @click="next">
<i class="las la-angle-right"></i>
</button>
</li>
</ul>
</template>
<script>
export default {
props: {
totalPage: Number,
currentPage: Number,
rangeMax: {
type: Number,
default: 3,
},
},
mounted() {
if (this.currentPage > this.totalPage) {
this.$emit('page-changed', this.totalPage);
}
},
computed: {
rangeFirstPage() {
if (this.currentPage === 1) {
return 1;
}
if (this.currentPage === this.totalPage) {
if ((this.totalPage - this.rangeMax) < 0) {
return 1;
}
return this.totalPage - this.rangeMax + 1;
}
return this.currentPage - 1;
},
rangeLastPage() {
return Math.min(this.rangeFirstPage + this.rangeMax - 1, this.totalPage);
},
range() {
let rangeList = [];
for (let page = this.rangeFirstPage; page <= this.rangeLastPage; page += 1) {
rangeList.push(page);
}
return rangeList;
},
hasFirst() {
return this.currentPage === 1;
},
hasLast() {
return this.currentPage === this.totalPage;
},
},
methods: {
prev() {
this.$emit('page-changed', this.currentPage - 1);
},
next() {
this.$emit('page-changed', this.currentPage + 1);
},
goto(page) {
if (this.currentPage !== page) {
this.$emit('page-changed', page);
}
},
hasActive(page) {
return page === this.currentPage;
},
},
};
</script>

View File

@@ -0,0 +1,163 @@
import Errors from '../../../Errors';
export default {
props: ['initialAddresses', 'initialDefaultAddress', 'countries'],
data() {
return {
addresses: this.initialAddresses,
defaultAddress: this.initialDefaultAddress,
form: { state: '' },
states: {},
errors: new Errors(),
formOpen: false,
editing: false,
loading: false,
};
},
computed: {
firstCountry() {
return Object.keys(this.countries)[0];
},
hasAddress() {
return Object.keys(this.addresses).length !== 0;
},
hasNoStates() {
return Object.keys(this.states).length === 0;
},
},
created() {
this.changeCountry(this.firstCountry);
},
methods: {
changeDefaultAddress(address) {
this.$set(this.defaultAddress, 'address_id', address.id);
$.ajax({
method: 'POST',
url: route('account.change_default_address'),
data: { address_id: address.id },
}).then((message) => {
this.$notify(message);
}).catch((xhr) => {
this.$notify(xhr.responseJSON.message);
});
},
changeCountry(country) {
this.form.country = country;
this.form.state = '';
this.fetchStates(country);
},
fetchStates(country) {
$.ajax({
method: 'GET',
url: route('countries.states.index', { code: country }),
}).then((states) => {
this.$set(this, 'states', states);
});
},
edit(address) {
this.formOpen = true;
this.editing = true;
this.form = address;
this.fetchStates(address.country);
},
remove(address) {
if (! confirm(this.$trans('storefront::account.addresses.confirm'))) {
return;
}
$.ajax({
method: 'DELETE',
url: route('account.addresses.destroy', address.id),
}).then((response) => {
this.$delete(this.addresses, address.id);
this.$notify(response.message);
}).catch((xhr) => {
this.$notify(xhr.responseJSON.message);
});
},
cancel() {
this.editing = false;
this.formOpen = false;
this.errors.reset();
this.resetForm();
},
save() {
this.loading = true;
if (this.editing) {
this.update();
} else {
this.create();
}
},
update() {
$.ajax({
method: 'PUT',
url: route('account.addresses.update', { id: this.form.id }),
data: this.form,
}).then((response) => {
this.formOpen = false;
this.editing = false;
this.addresses[this.form.id] = response.address;
this.resetForm();
this.$notify(response.message);
}).catch((xhr) => {
if (xhr.status === 422) {
this.errors.record(xhr.responseJSON.errors);
}
this.$notify(xhr.responseJSON.message);
}).always(() => {
this.loading = false;
});
},
create() {
$.ajax({
method: 'POST',
url: route('account.addresses.store'),
data: this.form,
}).then((response) => {
this.formOpen = false;
let address = { [response.address.id]: response.address };
this.$set(this, 'addresses', { ...this.addresses, ...address });
this.resetForm();
this.$notify(response.message);
}).catch((xhr) => {
if (xhr.status === 422) {
this.errors.record(xhr.responseJSON.errors);
}
this.$notify(xhr.responseJSON.message);
}).always(() => {
this.loading = false;
});
},
resetForm() {
this.form = { state: '' };
},
},
};

View File

@@ -0,0 +1,59 @@
import store from '../../../store';
import VPagination from '../../VPagination.vue';
import ProductHelpersMixin from '../../../mixins/ProductHelpersMixin';
export default {
components: { VPagination },
mixins: [
ProductHelpersMixin,
],
data() {
return {
fetchingWishlist: false,
products: { data: [] },
currentPage: 1,
};
},
computed: {
wishlistIsEmpty() {
return this.products.data.length === 0;
},
totalPage() {
return Math.ceil(this.products.total / 20);
},
},
created() {
this.fetchWishlist();
},
methods: {
fetchWishlist() {
this.fetchingWishlist = true;
$.ajax({
method: 'GET',
url: route('wishlist.products.index', {
page: this.currentPage,
}),
}).then((products) => {
this.products = products;
}).catch((xhr) => {
this.$notify(xhr.responseJSON.message);
}).always(() => {
this.fetchingWishlist = false;
});
},
remove(product) {
this.products.data.splice(this.products.data.indexOf(product), 1);
this.products.total--;
store.removeFromWishlist(product.id);
},
},
};

View File

@@ -0,0 +1,130 @@
import store from '../../store';
import CartHelpersMixin from '../../mixins/CartHelpersMixin';
import ProductHelpersMixin from '../../mixins/ProductHelpersMixin';
export default {
mixins: [
CartHelpersMixin,
ProductHelpersMixin,
],
data() {
return {
shippingMethodName: null,
crossSellProducts: [],
};
},
computed: {
hasAnyCrossSellProduct() {
return this.crossSellProducts.length !== 0;
},
},
created() {
this.$nextTick(() => {
if (store.state.cart.shippingMethodName) {
this.changeShippingMethod(store.state.cart.shippingMethodName);
} else {
this.updateShippingMethod(this.firstShippingMethod);
}
this.fetchCrossSellProducts();
});
},
methods: {
optionValues(option) {
let values = [];
for (let value of option.values) {
values.push(value.label);
}
return values.join(', ');
},
updateQuantity(cartItem, qty) {
if (qty < 1 || this.exceedsMaxStock(cartItem, qty)) {
return;
}
if (isNaN(qty)) {
qty = 1;
}
this.loadingOrderSummary = true;
cartItem.qty = qty;
$.ajax({
method: 'PUT',
url: route('cart.items.update', { cartItemId: cartItem.id }),
data: { qty: qty || 1 },
}).then((cart) => {
store.updateCart(cart);
}).catch((xhr) => {
this.$notify(xhr.responseJSON.message);
}).always(() => {
this.loadingOrderSummary = false;
});
},
exceedsMaxStock(cartItem, qty) {
return cartItem.product.manage_stock && cartItem.product.qty < qty;
},
remove(cartItem) {
this.loadingOrderSummary = true;
store.removeCartItem(cartItem);
if (store.cartIsEmpty()) {
this.crossSellProducts = [];
}
$.ajax({
method: 'DELETE',
url: route('cart.items.destroy', { cartItemId: cartItem.id }),
}).then((cart) => {
store.updateCart(cart);
}).catch((xhr) => {
this.$notify(xhr.responseJSON.message);
}).always(() => {
this.loadingOrderSummary = false;
});
},
clearCart() {
store.clearCart();
if (store.cartIsEmpty()) {
this.crossSellProducts = [];
}
$.ajax({
method: 'POST',
url: route('cart.clear.store'),
}).then((cart) => {
store.updateCart(cart);
}).catch((xhr) => {
this.$notify(xhr.responseJSON.message);
});
},
changeShippingMethod(shippingMethodName) {
this.shippingMethodName = shippingMethodName;
},
fetchCrossSellProducts() {
$.ajax({
method: 'GET',
url: route('cart.cross_sell_products.index'),
}).then((crossSellProducts) => {
this.crossSellProducts = crossSellProducts;
}).catch((xhr) => {
this.$notify(xhr.responseJSON.message);
});
},
},
};

View File

@@ -0,0 +1,671 @@
/* eslint-disable */
import store from "../../store";
import Errors from "../../Errors";
import CartHelpersMixin from "../../mixins/CartHelpersMixin";
import ProductHelpersMixin from "../../mixins/ProductHelpersMixin";
export default {
mixins: [CartHelpersMixin, ProductHelpersMixin],
props: [
"customerEmail",
"customerPhone",
"gateways",
"defaultAddress",
"addresses",
"countries",
],
data() {
return {
form: {
customer_email: this.customerEmail,
customer_phone: this.customerPhone,
billing: {},
shipping: {},
billingAddressId: null,
shippingAddressId: null,
newBillingAddress: false,
newShippingAddress: false,
ship_to_a_different_address: false,
},
states: {
billing: {},
shipping: {},
},
placingOrder: false,
errors: new Errors(),
stripe: null,
stripeCardElement: null,
stripeError: null,
authorizeNetToken: null,
};
},
computed: {
hasAddress() {
return Object.keys(this.addresses).length !== 0;
},
firstCountry() {
return Object.keys(this.countries)[0];
},
hasBillingStates() {
return Object.keys(this.states.billing).length !== 0;
},
hasShippingStates() {
return Object.keys(this.states.shipping).length !== 0;
},
hasNoPaymentMethod() {
return Object.keys(this.gateways).length === 0;
},
firstPaymentMethod() {
return Object.keys(this.gateways)[0];
},
shouldShowPaymentInstructions() {
return ["bank_transfer", "check_payment"].includes(
this.form.payment_method
);
},
paymentInstructions() {
if (this.shouldShowPaymentInstructions) {
return this.gateways[this.form.payment_method].instructions;
}
},
},
watch: {
"form.billingAddressId": function () {
this.mergeSavedBillingAddress();
},
"form.shippingAddressId": function () {
this.mergeSavedShippingAddress();
},
"form.billing.city": function (newCity) {
if (newCity) {
this.addTaxes();
}
},
"form.shipping.city": function (newCity) {
if (newCity) {
this.addTaxes();
}
},
"form.billing.zip": function (newZip) {
if (newZip) {
this.addTaxes();
}
},
"form.shipping.zip": function (newZip) {
if (newZip) {
this.addTaxes();
}
},
"form.billing.state": function (newState) {
if (newState) {
this.addTaxes();
}
},
"form.shipping.state": function (newState) {
if (newState) {
this.addTaxes();
}
},
"form.ship_to_a_different_address": function (newValue) {
if (newValue && this.form.shippingAddressId) {
this.form.shipping =
this.addresses[this.form.shippingAddressId];
} else {
this.form.shipping = {};
this.resetAddressErrors("shipping");
}
this.addTaxes();
},
"form.terms_and_conditions": function () {
this.errors.clear("terms_and_conditions");
},
"form.payment_method": function (newPaymentMethod) {
if (newPaymentMethod === "paypal") {
this.$nextTick(this.renderPayPalButton);
}
if (newPaymentMethod !== "stripe") {
this.stripeError = "";
}
},
},
created() {
if (this.defaultAddress.address_id) {
this.form.billingAddressId = this.defaultAddress.address_id;
this.form.shippingAddressId = this.defaultAddress.address_id;
}
if (!this.hasAddress) {
this.form.newBillingAddress = true;
this.form.newShippingAddress = true;
}
this.$nextTick(() => {
this.changePaymentMethod(this.firstPaymentMethod);
if (store.state.cart.shippingMethodName) {
this.changeShippingMethod(store.state.cart.shippingMethodName);
} else {
this.updateShippingMethod(this.firstShippingMethod);
}
if (window.Stripe) {
this.stripe = window.Stripe(FleetCart.stripePublishableKey);
this.renderStripeElements();
}
});
},
methods: {
addNewBillingAddress() {
this.resetAddressErrors("billing");
this.form.billing = {};
this.form.newBillingAddress = !this.form.newBillingAddress;
if (!this.form.newBillingAddress) {
this.mergeSavedBillingAddress();
}
},
addNewShippingAddress() {
this.resetAddressErrors("shipping");
this.form.shipping = {};
this.form.newShippingAddress = !this.form.newShippingAddress;
if (!this.form.newShippingAddress) {
this.mergeSavedShippingAddress();
}
},
// reset address errors based on address type
resetAddressErrors(addressType) {
Object.keys(this.errors.errors).map((key) => {
key.indexOf(addressType) !== -1 && this.errors.clear(key);
});
},
mergeSavedBillingAddress() {
this.resetAddressErrors("billing");
if (!this.form.newBillingAddress && this.form.billingAddressId) {
this.form.billing = this.addresses[this.form.billingAddressId];
}
},
mergeSavedShippingAddress() {
this.resetAddressErrors("shipping");
if (
this.form.ship_to_a_different_address &&
!this.form.newShippingAddress &&
this.form.shippingAddressId
) {
this.form.shipping =
this.addresses[this.form.shippingAddressId];
}
},
changeBillingCity(city) {
this.$set(this.form.billing, "city", city);
},
changeShippingCity(city) {
this.$set(this.form.shipping, "city", city);
},
changeBillingZip(zip) {
this.$set(this.form.billing, "zip", zip);
},
changeShippingZip(zip) {
this.$set(this.form.shipping, "zip", zip);
},
changeBillingCountry(country) {
this.$set(this.form.billing, "country", country);
if (country === "") {
this.form.billing.state = "";
this.states.billing = {};
return;
}
this.fetchStates(country, (states) => {
this.$set(this.states, "billing", states);
this.$set(this.form.billing, "state", "");
});
},
changeShippingCountry(country) {
this.$set(this.form.shipping, "country", country);
if (country === "") {
this.form.shipping.state = "";
this.states.shipping = {};
return;
}
this.fetchStates(country, (states) => {
this.$set(this.states, "shipping", states);
this.$set(this.form.shipping, "state", "");
});
},
fetchStates(country, callback) {
$.ajax({
method: "GET",
url: route("countries.states.index", { code: country }),
}).then(callback);
},
changeBillingState(state) {
this.$set(this.form.billing, "state", state);
},
changeShippingState(state) {
this.$set(this.form.shipping, "state", state);
},
changePaymentMethod(paymentMethod) {
this.$set(this.form, "payment_method", paymentMethod);
},
changeShippingMethod(shippingMethodName) {
this.$set(this.form, "shipping_method", shippingMethodName);
},
addTaxes() {
this.loadingOrderSummary = true;
$.ajax({
method: "POST",
url: route("cart.taxes.store"),
data: this.form,
})
.then((cart) => {
store.updateCart(cart);
})
.catch((xhr) => {
this.$notify(xhr.responseJSON.message);
})
.always(() => {
this.loadingOrderSummary = false;
});
},
placeOrder() {
if (!this.form.terms_and_conditions || this.placingOrder) {
return;
}
this.placingOrder = true;
$.ajax({
method: "POST",
url: route("checkout.create"),
data: {
...this.form,
ship_to_a_different_address:
+this.form.ship_to_a_different_address,
},
})
.then((response) => {
if (response.redirectUrl) {
window.location.href = response.redirectUrl;
} else if (this.form.payment_method === "stripe") {
this.confirmStripePayment(response);
} else if (this.form.payment_method === "paytm") {
this.confirmPaytmPayment(response);
} else if (this.form.payment_method === "razorpay") {
this.confirmRazorpayPayment(response);
} else if (this.form.payment_method === "paystack") {
this.confirmPaystackPayment(response);
} else if (this.form.payment_method === "authorizenet") {
this.confirmAuthorizeNetPayment(response);
} else if (this.form.payment_method === "flutterwave") {
this.confirmFlutterWavePayment(response);
} else if (this.form.payment_method === "mercadopago") {
this.confirmMercadoPagoPayment(response);
} else {
this.confirmOrder(
response.orderId,
this.form.payment_method
);
}
})
.catch((xhr) => {
if (xhr.status === 422) {
this.errors.record(xhr.responseJSON.errors);
}
this.$notify(xhr.responseJSON.message);
this.placingOrder = false;
});
},
confirmOrder(orderId, paymentMethod, params = {}) {
$.ajax({
method: "GET",
url: route("checkout.complete.store", {
orderId,
paymentMethod,
...params,
}),
})
.then(() => {
window.location.href = route("checkout.complete.show");
})
.catch((xhr) => {
this.placingOrder = false;
this.loadingOrderSummary = false;
this.deleteOrder(orderId);
this.$notify(xhr.responseJSON.message);
});
},
deleteOrder(orderId) {
if (!orderId) {
return;
}
$.ajax({
method: "GET",
url: route("checkout.payment_canceled.store", { orderId }),
}).then((xhr) => {
this.$notify(xhr.message);
});
},
renderPayPalButton() {
let vm = this;
let response;
window.paypal
.Buttons({
async createOrder() {
try {
response = await $.ajax({
method: "POST",
url: route("checkout.create"),
data: vm.form,
});
return response.resourceId;
} catch (xhr) {
if (xhr.status === 422) {
vm.errors.record(xhr.responseJSON.errors);
} else {
vm.$notify(xhr.responseJSON.message);
}
}
},
onApprove() {
vm.loadingOrderSummary = true;
vm.confirmOrder(response.orderId, "paypal", response);
},
onError() {
vm.deleteOrder(response.orderId);
},
onCancel() {
vm.deleteOrder(response.orderId);
},
})
.render("#paypal-button-container");
},
renderStripeElements() {
this.stripeCardElement = this.stripe.elements().create("card", {
hidePostalCode: true,
});
this.stripeCardElement.mount("#stripe-card-element");
},
async confirmStripePayment({ orderId, clientSecret }) {
let result = await this.stripe.confirmCardPayment(clientSecret, {
payment_method: {
card: this.stripeCardElement,
billing_details: {
email: this.form.customer_email,
name: `${this.form.billing.first_name} ${this.form.billing.last_name}`,
address: {
city: this.form.billing.city,
country: this.form.billing.country,
line1: this.form.billing.address_1,
line2: this.form.billing.address_2,
postal_code: this.form.billing.zip,
state: this.form.billing.state,
},
},
},
});
if (result.error) {
this.placingOrder = false;
this.stripeError = result.error.message;
this.deleteOrder(orderId);
} else {
this.confirmOrder(orderId, "stripe", result);
}
},
confirmPaytmPayment({ orderId, amount, txnToken }) {
let config = {
root: "",
flow: "DEFAULT",
data: {
orderId: orderId,
token: txnToken,
tokenType: "TXN_TOKEN",
amount: amount,
},
merchant: {
name: FleetCart.storeName,
redirect: false,
},
handler: {
transactionStatus: (response) => {
if (response.STATUS === "TXN_SUCCESS") {
this.confirmOrder(orderId, "paytm", response);
} else if (response.STATUS === "TXN_FAILURE") {
this.placingOrder = false;
this.deleteOrder(orderId);
}
window.Paytm.CheckoutJS.close();
},
notifyMerchant: (eventName) => {
if (eventName === "APP_CLOSED") {
this.placingOrder = false;
this.deleteOrder(orderId);
}
},
},
};
window.Paytm.CheckoutJS.init(config)
.then(() => {
window.Paytm.CheckoutJS.invoke();
})
.catch(() => {
this.deleteOrder(orderId);
});
},
confirmRazorpayPayment(razorpayOrder) {
this.placingOrder = false;
let vm = this;
new window.Razorpay({
key: FleetCart.razorpayKeyId,
name: FleetCart.storeName,
description: `Payment for order #${razorpayOrder.receipt}`,
image: FleetCart.storeLogo,
order_id: razorpayOrder.id,
handler(response) {
vm.placingOrder = true;
vm.confirmOrder(
razorpayOrder.receipt,
"razorpay",
response
);
},
modal: {
ondismiss() {
vm.deleteOrder(razorpayOrder.receipt);
},
},
prefill: {
name: `${vm.form.billing.first_name} ${vm.form.billing.last_name}`,
email: vm.form.customer_email,
contact: vm.form.customer_phone,
},
}).open();
},
confirmPaystackPayment({
key,
email,
amount,
ref,
currency,
order_id,
}) {
let vm = this;
PaystackPop.setup({
key,
email,
amount,
ref,
currency,
onClose() {
vm.placingOrder = false;
vm.deleteOrder(order_id);
},
callback(response) {
vm.placingOrder = false;
vm.confirmOrder(order_id, "paystack", response);
},
onBankTransferConfirmationPending(response) {
vm.placingOrder = false;
vm.confirmOrder(order_id, "paystack", response);
},
}).openIframe();
},
confirmAuthorizeNetPayment(authorizeNetOrder) {
this.authorizeNetToken = authorizeNetOrder.token;
this.$nextTick(() => {
this.$refs.authorizeNetForm.submit();
this.authorizeNetToken = null;
});
},
confirmFlutterWavePayment({
public_key,
tx_ref,
order_id,
amount,
currency,
payment_options,
redirect_url,
}) {
let vm = this;
FlutterwaveCheckout({
public_key,
tx_ref,
amount,
currency,
payment_options: payment_options.join(", "),
redirect_url,
customer: {
email: this.form.customer_email,
phone_number: this.form.customer_phone,
name: this.form.billing.full_name,
},
customizations: {
title: FleetCart.storeName,
logo: FleetCart.storeLogo,
},
onclose(incomplete) {
vm.placingOrder = false;
if (incomplete) {
vm.deleteOrder(order_id);
}
},
});
},
confirmMercadoPagoPayment(mercadoPagoOrder) {
this.placingOrder = false;
const supportedLocales = {
en_US: "en-US",
es_AR: "es-AR",
es_CL: "es-CL",
es_CO: "es-CO",
es_MX: "es-MX",
es_VE: "es-VE",
es_UY: "es-UY",
es_PE: "es-PE",
pt_BR: "pt-BR",
};
const mercadoPago = new MercadoPago(mercadoPagoOrder.publicKey, {
locale:
supportedLocales[mercadoPagoOrder.currentLocale] || "en-US",
});
mercadoPago.checkout({
preference: {
id: mercadoPagoOrder.preferenceId,
},
autoOpen: true,
});
},
},
};

View File

@@ -0,0 +1,119 @@
import store from '../../store';
import ProductRating from '../ProductRating.vue';
import ProductHelpersMixin from '../../mixins/ProductHelpersMixin';
export default {
components: { ProductRating },
mixins: [
ProductHelpersMixin,
],
props: ['compare'],
data() {
return {
products: this.compare.products,
attributes: this.compare.attributes,
fetchingRelatedProducts: false,
relatedProducts: [],
};
},
computed: {
hasAnyProduct() {
return Object.keys(this.products).length !== 0;
},
hasAnyRelatedProduct() {
return this.relatedProducts.length !== 0;
},
},
created() {
if (this.hasAnyProduct) {
this.fetchRelatedProducts();
}
},
methods: {
badgeClass(product) {
if (product.is_in_stock) {
return 'badge-success';
}
return 'badge-danger';
},
hasAttribute(product, attribute) {
for (let productAttribute of product.attributes) {
if (productAttribute.name === attribute.name) {
return true;
}
}
},
attributeValues(product, attribute) {
for (let productAttribute of product.attributes) {
if (productAttribute.name === attribute.name) {
return productAttribute.values.map((productAttributeValue) => {
return productAttributeValue.value;
}).join(', ');
}
}
},
remove(product) {
this.$delete(this.products, product.id);
if (! this.hasAnyProduct) {
this.relatedProducts = [];
}
$.ajax({
method: 'DELETE',
url: route('compare.destroy', { id: product.id }),
});
},
inWishlist(product) {
return store.inWishlist(product.id);
},
syncWishlist(product) {
store.syncWishlist(product.id);
},
addToCart(product) {
if (product.options_count !== 0) {
return window.location.href = this.productUrl(product);
}
$.ajax({
method: 'POST',
url: route('cart.items.store', { product_id: product.id, qty: 1 }),
}).then((cart) => {
store.updateCart(cart);
$('.header-cart').trigger('click');
}).catch((xhr) => {
this.$notify(xhr.responseJSON.message);
});
},
fetchRelatedProducts() {
this.fetchingRelatedProducts = true;
$.ajax({
method: 'GET',
url: route('compare.related_products.index'),
}).then((relatedProducts) => {
this.relatedProducts = relatedProducts;
}).catch((xhr) => {
this.$notify(xhr.responseJSON.message);
}).always(() => {
this.fetchingRelatedProducts = false;
});
},
},
};

View File

@@ -0,0 +1,19 @@
<template>
<section class="banner-wrap one-column-banner">
<div class="container">
<a
:href="banner.call_to_action_url"
class="banner"
:target="banner.open_in_new_window ? '_blank' : '_self'"
>
<img :src="banner.image.path" alt="banner">
</a>
</div>
</section>
</template>
<script>
export default {
props: ['banner'],
};
</script>

View File

@@ -0,0 +1,43 @@
<template>
<section class="banner-wrap three-column-banner">
<div class="container">
<div class="row">
<div class="col-md-6">
<a
:href="data.banner_1.call_to_action_url"
class="banner"
:target="data.banner_1.open_in_new_window ? '_blank' : '_self'"
>
<img :src="data.banner_1.image.path" alt="banner">
</a>
</div>
<div class="col-md-6">
<a
:href="data.banner_2.call_to_action_url"
class="banner"
:target="data.banner_2.open_in_new_window ? '_blank' : '_self'"
>
<img :src="data.banner_2.image.path" alt="banner">
</a>
</div>
<div class="col-md-6">
<a
:href="data.banner_3.call_to_action_url"
class="banner"
:target="data.banner_3.open_in_new_window ? '_blank' : '_self'"
>
<img :src="data.banner_3.image.path" alt="banner">
</a>
</div>
</div>
</div>
</section>
</template>
<script>
export default {
props: ['data'],
};
</script>

View File

@@ -0,0 +1,46 @@
<template>
<section
class="banner-wrap three-column-full-width-banner padding-tb-75"
:style="'background-image: url(' + data['background'].image.path + ')'"
>
<div class="container">
<div class="row">
<div class="col-md-4">
<a
:href="data.banner_1.call_to_action_url"
class="banner"
:target="data.banner_1.open_in_new_window ? '_blank' : '_self'"
>
<img :src="data.banner_1.image.path" alt="banner">
</a>
</div>
<div class="col-md-10">
<a
:href="data.banner_2.call_to_action_url"
class="banner"
:target="data.banner_2.open_in_new_window ? '_blank' : '_self'"
>
<img :src="data.banner_2.image.path" alt="banner">
</a>
</div>
<div class="col-md-4">
<a
:href="data.banner_3.call_to_action_url"
class="banner"
:target="data.banner_3.open_in_new_window ? '_blank' : '_self'"
>
<img :src="data.banner_3.image.path" alt="banner">
</a>
</div>
</div>
</div>
</section>
</template>
<script>
export default {
props: ['data'],
};
</script>

View File

@@ -0,0 +1,33 @@
<template>
<section class="banner-wrap two-column-banner">
<div class="container">
<div class="row">
<div class="col-md-9">
<a
:href="data.banner_1.call_to_action_url"
class="banner"
:target="data.banner_1.open_in_new_window ? '_blank' : '_self'"
>
<img :src="data.banner_1.image.path" alt="banner">
</a>
</div>
<div class="col-md-9">
<a
:href="data.banner_2.call_to_action_url"
class="banner"
:target="data.banner_2.open_in_new_window ? '_blank' : '_self'"
>
<img :src="data.banner_2.image.path" alt="banner">
</a>
</div>
</div>
</div>
</section>
</template>
<script>
export default {
props: ['data'],
};
</script>

View File

@@ -0,0 +1,27 @@
export default {
name: "DynamicTab",
props: ["label", "initialLogo", "url"],
data() {
return {
isActive: false,
};
},
computed: {
hasLogo() {
return !Array.isArray(this.initialLogo);
},
logo() {
if (this.hasLogo) {
return this.initialLogo.path;
}
return `${window.FleetCart.baseUrl}/themes/storefront/public/images/image-placeholder.png`;
},
},
template: "<div></div>",
};

View File

@@ -0,0 +1,120 @@
<template>
<section class="featured-categories-wrap">
<div class="container">
<div class="featured-categories-header">
<div class="featured-categories-text">
<h2 class="title">{{ data.title }}</h2>
<span class="excerpt">{{ data.subtitle }}</span>
</div>
<ul class="tabs featured-categories-tabs">
<li
v-for="(tab, index) in tabs"
:key="index"
:class="classes(tab)"
@click="change(tab)"
>
<div class="featured-category-image">
<img :src="tab.logo" :class="{ 'image-placeholder': ! tab.hasLogo }" alt="category logo">
</div>
<span class="featured-category-name">{{ tab.label }}</span>
</li>
</ul>
</div>
<div class="tab-content featured-category-products">
<ProductCard v-for="product in products" :key="product.id" :product="product"/>
</div>
</div>
<dynamic-tab
v-for="(category, index) in data.categories"
:key="index"
:label="category.name"
:initial-logo="category.logo"
:url="route('storefront.featured_category_products.index', { categoryNumber: index + 1 })"
>
</dynamic-tab>
</section>
</template>
<script>
import ProductCard from '../ProductCard.vue';
import DynamicTabsMixin from '../../mixins/DynamicTabsMixin';
import { slickPrevArrow, slickNextArrow } from '../../functions';
export default {
components: { ProductCard },
mixins: [
DynamicTabsMixin,
],
props: ['data'],
methods: {
selector() {
return $('.featured-category-products');
},
slickOptions() {
return {
rows: 0,
dots: true,
arrows: false,
infinite: true,
slidesToShow: 6,
slidesToScroll: 6,
rtl: window.FleetCart.rtl,
prevArrow: slickPrevArrow(),
nextArrow: slickNextArrow(),
responsive: [
{
breakpoint: 1761,
settings: {
slidesToShow: 5,
slidesToScroll: 5,
},
},
{
breakpoint: 1301,
settings: {
slidesToShow: 4,
slidesToScroll: 4,
},
},
{
breakpoint: 1051,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
},
},
{
breakpoint: 992,
settings: {
slidesToShow: 4,
slidesToScroll: 4,
},
},
{
breakpoint: 881,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
},
},
{
breakpoint: 641,
settings: {
slidesToShow: 2,
slidesToScroll: 2,
},
},
],
};
},
},
};
</script>

View File

@@ -0,0 +1,75 @@
<template>
<div class="col-xl-6 col-lg-18">
<div class="daily-deals-wrap">
<div class="daily-deals-header clearfix">
<h4 class="section-title" v-html="title"></h4>
</div>
<div class="daily-deals" ref="productsPlaceholder">
<FlashSaleProductCard v-for="product in products" :key="product.id" :product="product"/>
</div>
</div>
</div>
</template>
<script>
import FlashSaleProductCard from './FlashSaleProductCard.vue';
import { slickPrevArrow, slickNextArrow } from '../../functions';
export default {
components: { FlashSaleProductCard },
props: ['title', 'url'],
data() {
return {
products: [],
};
},
created() {
$.ajax({
method: 'GET',
url: this.url,
}).then((products) => {
this.products = products;
this.$nextTick(() => {
$(this.$refs.productsPlaceholder).slick(this.slickOptions());
});
});
},
methods: {
slickOptions() {
return {
rows: 0,
dots: false,
arrows: true,
infinite: true,
slidesToShow: 1,
slidesToScroll: 1,
rtl: window.FleetCart.rtl,
prevArrow: slickPrevArrow(),
nextArrow: slickNextArrow(),
responsive: [
{
breakpoint: 1200,
settings: {
slidesToShow: 2,
slidesToScroll: 2,
},
},
{
breakpoint: 768,
settings: {
slidesToShow: 1,
slidesToScroll: 1,
},
},
],
};
},
},
};
</script>

View File

@@ -0,0 +1,37 @@
<template>
<section class="vertical-products-wrap">
<div class="container">
<div class="row">
<flash-sale
:title="data.flash_sale_title"
:url="route('storefront.flash_sale_products.index')"
>
</flash-sale>
<vertical-products
:title="data.vertical_products_1_title"
:url="route('storefront.vertical_products.index', { columnNumber: 1 })"
>
</vertical-products>
<vertical-products
:title="data.vertical_products_2_title"
:url="route('storefront.vertical_products.index', { columnNumber: 2 })"
>
</vertical-products>
<vertical-products
:title="data.vertical_products_3_title"
:url="route('storefront.vertical_products.index', { columnNumber: 3 })"
>
</vertical-products>
</div>
</div>
</section>
</template>
<script>
export default {
props: ['data'],
};
</script>

View File

@@ -0,0 +1,76 @@
<template>
<div class="daily-deals-inner">
<div class="daily-deals-top">
<a :href="productUrl" class="product-image">
<img :src="baseImage" :class="{ 'image-placeholder': ! hasBaseImage }" alt="product-image">
</a>
</div>
<a :href="productUrl" class="product-name">
<h6>{{ product.name }}</h6>
</a>
<div class="product-info">
<div class="product-price" v-html="product.formatted_price"></div>
<ProductRating :ratingPercent="product.rating_percent" :reviewCount="product.reviews.length"/>
</div>
<div class="daily-deals-countdown clearfix"></div>
<div class="deal-progress">
<div class="deal-stock">
<div class="stock-available">
{{ $trans('storefront::product_card.available') }}
<span>{{ product.pivot.qty }}</span>
</div>
<div class="stock-sold">
{{ $trans('storefront::product_card.sold') }}
<span>{{ product.pivot.sold }}</span>
</div>
</div>
<div class="progress">
<div class="progress-bar" :style="{ width: progress }"></div>
</div>
</div>
</div>
</template>
<script>
import ProductRating from '../ProductRating.vue';
import ProductCardMixin from '../../mixins/ProductCardMixin';
export default {
components: { ProductRating },
mixins: [
ProductCardMixin,
],
props: ['product'],
computed: {
progress() {
return (this.product.pivot.sold / this.product.pivot.qty * 100) + '%';
},
},
mounted() {
$(this.$el).find('.daily-deals-countdown').countdown({
until: new Date(this.product.pivot.end_date),
format: 'DHMS',
labels: [
this.$trans('storefront::product_card.years'),
this.$trans('storefront::product_card.months'),
this.$trans('storefront::product_card.weeks'),
this.$trans('storefront::product_card.days'),
this.$trans('storefront::product_card.hours'),
this.$trans('storefront::product_card.minutes'),
this.$trans('storefront::product_card.seconds'),
],
});
},
};
</script>

View File

@@ -0,0 +1,26 @@
<template>
<section class="features-wrap">
<div class="container">
<div class="features">
<div class="feature-list">
<div class="single-feature" v-for="(feature, index) in features" :key="index">
<div class="feature-icon">
<i :class="feature.icon"></i>
</div>
<div class="feature-details">
<h6>{{ feature.title }}</h6>
<span>{{ feature.subtitle }}</span>
</div>
</div>
</div>
</div>
</div>
</section>
</template>
<script>
export default {
props: ['features'],
};
</script>

View File

@@ -0,0 +1,77 @@
<template>
<section class="grid-products-wrap clearfix">
<div class="container">
<div class="tab-products-header clearfix">
<ul class="tabs float-left">
<li
v-for="(tab, index) in tabs"
:key="index"
:class="classes(tab)"
@click="change(tab)"
>
{{ tab.label }}
</li>
</ul>
</div>
<div class="tab-content grid-products">
<div v-for="(productChunks, index) in $chunk(products, 12)" :key="index" class="grid-products-inner">
<ProductCard v-for="product in productChunks" :key="product.id" :product="product"/>
</div>
</div>
<dynamic-tab
v-for="(tabLabel, index) in data"
:key="index"
:label="tabLabel"
:url="route('storefront.product_grid.index', { tabNumber: index + 1 })"
>
</dynamic-tab>
</div>
</section>
</template>
<script>
import ProductCard from '../ProductCard.vue';
import DynamicTabsMixin from '../../mixins/DynamicTabsMixin';
import { slickPrevArrow, slickNextArrow } from '../../functions';
export default {
components: { ProductCard },
mixins: [
DynamicTabsMixin,
],
props: ['data'],
methods: {
selector() {
return $('.grid-products');
},
slickOptions() {
return {
rows: 0,
dots: false,
arrows: true,
infinite: true,
slidesToShow: 1,
slidesToScroll: 1,
rtl: window.FleetCart.rtl,
prevArrow: slickPrevArrow(),
nextArrow: slickNextArrow(),
responsive: [
{
breakpoint: 768,
settings: {
dots: true,
arrows: false,
},
},
],
};
},
},
};
</script>

View File

@@ -0,0 +1,128 @@
<template>
<section class="landscape-tab-products-wrap clearfix">
<div class="container">
<div class="tab-products-header clearfix">
<ul class="tabs float-left">
<li
v-for="(tab, index) in tabs"
:key="index"
:class="classes(tab)"
@click="change(tab)"
>
{{ tab.label }}
</li>
</ul>
</div>
<div class="tab-content landscape-left-tab-products">
<ProductCard
v-for="product in products"
:key="product.id"
:product="product"
/>
</div>
<dynamic-tab
v-for="(tabLabel, index) in data"
:key="index"
:label="tabLabel"
:url="
route('storefront.tab_products.index', {
sectionNumber: 1,
tabNumber: index + 1,
})
"
>
</dynamic-tab>
</div>
</section>
</template>
<script>
import ProductCard from "../ProductCard.vue";
import DynamicTabsMixin from "../../mixins/DynamicTabsMixin";
import { slickPrevArrow, slickNextArrow } from "../../functions";
export default {
components: { ProductCard },
mixins: [DynamicTabsMixin],
props: ["data"],
methods: {
selector() {
return $(".landscape-left-tab-products");
},
slickOptions() {
return {
rows: 0,
dots: false,
arrows: true,
infinite: true,
slidesToShow: 6,
slidesToScroll: 6,
rtl: window.FleetCart.rtl,
prevArrow: slickPrevArrow(),
nextArrow: slickNextArrow(),
responsive: [
{
breakpoint: 1761,
settings: {
slidesToShow: 5,
slidesToScroll: 5,
},
},
{
breakpoint: 1301,
settings: {
slidesToShow: 4,
slidesToScroll: 4,
},
},
{
breakpoint: 1051,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
},
},
{
breakpoint: 992,
settings: {
slidesToShow: 4,
slidesToScroll: 4,
},
},
{
breakpoint: 881,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
},
},
{
breakpoint: 661,
settings: {
dots: true,
arrows: false,
slidesToShow: 3,
slidesToScroll: 3,
},
},
{
breakpoint: 641,
settings: {
dots: true,
arrows: false,
slidesToShow: 2,
slidesToScroll: 2,
},
},
],
};
},
},
};
</script>

View File

@@ -0,0 +1,107 @@
<template>
<section class="landscape-tab-products-wrap clearfix">
<div class="container">
<div class="tab-products-header clearfix">
<h5 class="section-title float-left">{{ data.title }}</h5>
<ul class="tabs float-right">
<li
v-for="(tab, index) in tabs"
:key="index"
:class="classes(tab)"
@click="change(tab)"
>
{{ tab.label }}
</li>
</ul>
</div>
<div class="tab-content landscape-right-tab-products">
<ProductCard v-for="product in products" :key="product.id" :product="product"/>
</div>
</div>
<dynamic-tab
v-for="(tabLabel, index) in data.tabs"
:key="index"
:label="tabLabel"
:url="route('storefront.tab_products.index', {sectionNumber: 2, tabNumber: index + 1 })"
>
</dynamic-tab>
</section>
</template>
<script>
import ProductCard from '../ProductCard.vue';
import DynamicTabsMixin from '../../mixins/DynamicTabsMixin';
export default {
components: { ProductCard },
mixins: [DynamicTabsMixin],
props: ['data'],
methods: {
selector() {
return $('.landscape-right-tab-products');
},
slickOptions() {
return {
rows: 0,
dots: true,
arrows: false,
infinite: true,
slidesToShow: 6,
slidesToScroll: 6,
rtl: window.FleetCart.rtl,
responsive: [
{
breakpoint: 1761,
settings: {
slidesToShow: 5,
slidesToScroll: 5,
},
},
{
breakpoint: 1301,
settings: {
slidesToShow: 4,
slidesToScroll: 4,
},
},
{
breakpoint: 1051,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
},
},
{
breakpoint: 992,
settings: {
slidesToShow: 4,
slidesToScroll: 4,
},
},
{
breakpoint: 881,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
},
},
{
breakpoint: 641,
settings: {
slidesToShow: 2,
slidesToScroll: 2,
},
},
],
};
},
},
};
</script>

View File

@@ -0,0 +1,22 @@
<template>
<section class="top-brands-wrap clearfix">
<div class="container">
<div class="top-brands clearfix">
<a
v-for="(topBrand, index) in topBrands"
:key="index"
:href="topBrand.url"
class="top-brand-image"
>
<img :src="topBrand.logo.path" alt="brand logo">
</a>
</div>
</div>
</section>
</template>
<script>
export default {
props: ['topBrands'],
};
</script>

View File

@@ -0,0 +1,58 @@
<template>
<div class="col-xl-4 col-lg-6">
<div class="vertical-products">
<div class="vertical-products-header">
<h4 class="section-title">{{ title }}</h4>
</div>
<div class="vertical-products-slider" ref="productsPlaceholder">
<div v-for="(productChunks, index) in $chunk(products, 5)" :key="index" class="vertical-products-slide">
<ProductCardVertical v-for="product in productChunks" :key="product.id" :product="product"/>
</div>
</div>
</div>
</div>
</template>
<script>
import ProductCardVertical from '../ProductCardVertical.vue';
export default {
components: { ProductCardVertical },
props: ['title', 'url'],
data() {
return {
products: [],
};
},
created() {
$.ajax({
method: 'GET',
url: this.url,
}).then((products) => {
this.products = products;
this.$nextTick(() => {
$(this.$refs.productsPlaceholder).slick(this.slickOptions());
});
});
},
methods: {
slickOptions() {
return {
rows: 0,
dots: false,
arrows: true,
infinite: true,
slidesToShow: 1,
slidesToScroll: 1,
rtl: window.FleetCart.rtl,
};
},
},
};
</script>

View File

@@ -0,0 +1,24 @@
export default {
data() {
return {
show: false,
};
},
mounted() {
setTimeout(() => {
this.show = true;
});
},
methods: {
accept() {
this.show = false;
$.ajax({
method: 'DELETE',
url: route('storefront.cookie_bar.destroy'),
});
},
},
};

View File

@@ -0,0 +1,452 @@
<template>
<div class="header-search-wrap" v-click-outside="hideSuggestions">
<div class="header-search">
<form class="search-form" @submit.prevent="search">
<div class="header-search-lg">
<input
type="text"
name="query"
class="form-control search-input"
autocomplete="off"
v-model="form.query"
:placeholder="
$trans('storefront::layout.search_for_products')
"
@keydown.esc="hideSuggestions"
@keydown.down="nextSuggestion"
@keydown.up="prevSuggestion"
/>
<div class="header-search-right" @focusin="hideSuggestions">
<select
name="category"
class="header-search-select custom-select-option arrow-black"
@nice-select-updated="
changeCategory($event.target.value)
"
>
<option
value=""
:selected="initialCategoryIsNotInCategoryList"
>
{{
$trans("storefront::layout.all_categories")
}}
</option>
<option
v-for="category in categories"
:key="category.slug"
:value="category.slug"
:selected="category.slug === initialCategory"
>
{{ category.name }}
</option>
</select>
<button
type="submit"
class="btn btn-primary btn-search"
>
<i class="las la-search"></i>
</button>
</div>
</div>
<div class="header-search-sm">
<i class="las la-search"></i>
</div>
</form>
<div
v-if="
Boolean(isMostSearchedKeywordsEnabled) &&
mostSearchedKeywords.length !== 0
"
class="searched-keywords"
>
<label>
{{ $trans("storefront::layout.most_searched") }}
</label>
<ul class="list-inline searched-keywords-list">
<li
v-for="(
mostSearchedKeyword, index
) in mostSearchedKeywords"
:key="index"
>
<a
:href="
route('products.index', {
query: mostSearchedKeyword,
})
"
>
{{ mostSearchedKeyword }}
</a>
</li>
</ul>
</div>
</div>
<div class="header-search-sm-form">
<form class="search-form" @submit.prevent="search">
<div class="btn-close">
<i class="las la-arrow-left"></i>
</div>
<!-- Cannot use v-model due to a bug. See https://github.com/vuejs/vue/issues/8231 -->
<input
type="text"
name="query"
class="form-control search-input-sm"
autocomplete="off"
:placeholder="
$trans('storefront::layout.search_for_products')
"
:value="form.query"
@input="form.query = $event.target.value"
@keydown.esc="hideSuggestions"
@keydown.down="nextSuggestion"
@keydown.up="prevSuggestion"
/>
<button type="submit" class="btn btn-search">
<i class="las la-search"></i>
</button>
</form>
</div>
<div class="search-suggestions" v-if="shouldShowSuggestions">
<div
class="search-suggestions-inner custom-scrollbar"
ref="searchSuggestionsInner"
>
<div
class="category-suggestion"
v-if="suggestions.categories.length !== 0"
>
<h6 class="title">
{{ $trans("storefront::layout.category_suggestions") }}
</h6>
<ul class="list-inline category-suggestion-list">
<li
v-for="category in suggestions.categories"
:key="category.slug"
class="list-item"
:class="{ active: isActiveSuggestion(category) }"
:ref="category.slug"
@mouseover="changeActiveSuggestion(category)"
@mouseleave="clearActiveSuggestion"
>
<a
:href="category.url"
class="single-item"
v-text="category.name"
@click="hideSuggestions"
>
</a>
</li>
</ul>
</div>
<div class="product-suggestion">
<h6 class="title">
{{ $trans("storefront::layout.product_suggestions") }}
</h6>
<ul class="list-inline product-suggestion-list">
<li
v-for="product in suggestions.products"
:key="product.slug"
class="list-item"
:class="{ active: isActiveSuggestion(product) }"
:ref="product.slug"
@mouseover="changeActiveSuggestion(product)"
@mouseleave="clearActiveSuggestion"
>
<a
:href="product.url"
class="single-item"
@click="hideSuggestions"
>
<div class="product-image">
<img
:src="baseImage(product)"
:class="{
'image-placeholder':
!hasBaseImage(product),
}"
alt="product image"
/>
</div>
<div class="product-info">
<div class="product-info-top">
<h6
class="product-name"
v-html="product.name"
></h6>
<ul
class="list-inline product-badge"
v-if="product.is_out_of_stock"
>
<li class="badge badge-danger">
{{
$trans(
"storefront::product_card.out_of_stock"
)
}}
</li>
</ul>
</div>
<div
class="product-price"
v-html="product.formatted_price"
></div>
</div>
</a>
</li>
</ul>
<a
v-if="suggestions.remaining !== 0"
:href="moreResultsUrl"
@click="hideSuggestions"
class="more-results"
>
{{
$trans("storefront::layout.more_results", {
count: this.suggestions.remaining,
})
}}
</a>
</div>
</div>
</div>
</div>
</template>
<script>
import ProductHelpersMixin from "../../mixins/ProductHelpersMixin";
export default {
mixins: [ProductHelpersMixin],
props: [
"categories",
"mostSearchedKeywords",
"isMostSearchedKeywordsEnabled",
"initialQuery",
"initialCategory",
],
data() {
return {
activeSuggestion: null,
showSuggestions: false,
form: {
query: this.initialQuery,
category: this.initialCategory,
},
suggestions: {
categories: [],
products: [],
remaining: 0,
},
};
},
computed: {
initialCategoryIsNotInCategoryList() {
return !this.categories.includes(this.initialCategory);
},
shouldShowSuggestions() {
if (!this.showSuggestions) {
return false;
}
return this.hasAnySuggestion;
},
moreResultsUrl() {
if (this.form.category) {
return route("categories.products.index", this.form);
}
return route("products.index", { query: this.form.query });
},
hasAnySuggestion() {
return this.suggestions.products.length !== 0;
},
allSuggestions() {
return [
...this.suggestions.categories,
...this.suggestions.products,
];
},
firstSuggestion() {
return this.allSuggestions[0];
},
lastSuggestion() {
return this.allSuggestions[this.allSuggestions.length - 1];
},
},
watch: {
"form.query": function (newQuery) {
if (newQuery === "") {
this.clearSuggestions();
} else {
this.showSuggestions = true;
this.fetchSuggestions();
}
},
},
methods: {
changeCategory(category) {
this.form.category = category;
this.fetchSuggestions();
},
fetchSuggestions() {
$.ajax({
method: "GET",
url: route("suggestions.index", this.form),
}).then((suggestions) => {
this.suggestions.categories = suggestions.categories;
this.suggestions.products = suggestions.products;
this.suggestions.remaining = suggestions.remaining;
this.clearActiveSuggestion();
this.resetSuggestionScrollBar();
});
},
search() {
if (!this.form.query) {
return;
}
if (this.activeSuggestion) {
window.location.href = this.activeSuggestion.url;
this.hideSuggestions();
return;
}
if (this.form.category) {
window.location.href = route(
"categories.products.index",
this.form
);
return;
}
window.location.href = route("products.index", {
query: this.form.query,
});
},
clearSuggestions() {
this.suggestions.categories = [];
this.suggestions.products = [];
},
hideSuggestions(e) {
this.showSuggestions = false;
this.clearActiveSuggestion();
},
isActiveSuggestion(suggestion) {
if (!this.activeSuggestion) {
return false;
}
return this.activeSuggestion.slug === suggestion.slug;
},
changeActiveSuggestion(suggestion) {
this.activeSuggestion = suggestion;
},
clearActiveSuggestion() {
this.activeSuggestion = null;
},
nextSuggestion() {
if (!this.hasAnySuggestion) {
return;
}
this.activeSuggestion =
this.allSuggestions[this.nextSuggestionIndex()];
if (!this.activeSuggestion) {
this.activeSuggestion = this.firstSuggestion;
}
this.adjustSuggestionScrollBar();
},
prevSuggestion() {
if (!this.hasAnySuggestion) {
return;
}
if (this.prevSuggestionIndex() === -1) {
this.clearActiveSuggestion();
return;
}
this.activeSuggestion =
this.allSuggestions[this.prevSuggestionIndex()];
if (!this.activeSuggestion) {
this.activeSuggestion = this.lastSuggestion;
}
this.adjustSuggestionScrollBar();
},
nextSuggestionIndex() {
return this.currentSuggestionIndex() + 1;
},
prevSuggestionIndex() {
return this.currentSuggestionIndex() - 1;
},
currentSuggestionIndex() {
return this.allSuggestions.indexOf(this.activeSuggestion);
},
adjustSuggestionScrollBar() {
this.$refs.searchSuggestionsInner.scrollTop =
this.$refs[this.activeSuggestion.slug][0].offsetTop - 200;
},
resetSuggestionScrollBar() {
if (this.$refs.searchSuggestionsInner !== undefined) {
this.$refs.searchSuggestionsInner.scrollTop = 0;
}
},
},
};
</script>

View File

@@ -0,0 +1,72 @@
export default {
data() {
return {
email: '',
subscribed: false,
subscribing: false,
error: '',
disable_popup: false,
};
},
watch: {
email() {
this.error = '';
},
disable_popup(bool) {
if (bool) {
this.disableNewsletterPopup();
} else {
this.enableNewsletterPopup();
}
},
},
mounted() {
setTimeout(() => {
$('.newsletter-wrap').modal('show');
}, 1000);
},
methods: {
enableNewsletterPopup() {
$.ajax({
method: 'POST',
url: route('storefront.newsletter_popup.store'),
});
},
disableNewsletterPopup() {
$.ajax({
method: 'DELETE',
url: route('storefront.newsletter_popup.destroy'),
});
},
subscribe() {
if (! this.email || this.subscribed) {
return;
}
this.subscribing = true;
$.ajax({
method: 'POST',
url: route('subscribers.store'),
data: { email: this.email },
}).then(() => {
this.email = '';
this.subscribed = true;
}).catch((response) => {
if (response.status === 422) {
this.error = response.responseJSON.errors.email[0];
} else {
this.error = response.responseJSON.message;
}
}).always(() => {
this.subscribing = false;
});
},
},
};

View File

@@ -0,0 +1,36 @@
export default {
data() {
return {
email: '',
subscribed: false,
subscribing: false,
};
},
methods: {
subscribe() {
if (! this.email || this.subscribed) {
return;
}
this.subscribing = true;
$.ajax({
method: 'POST',
url: route('subscribers.store'),
data: { email: this.email },
}).then(() => {
this.email = '';
this.subscribed = true;
}).catch((response) => {
if (response.status === 422) {
this.$notify(response.responseJSON.errors.email[0]);
} else {
this.$notify(response.responseJSON.message);
}
}).always(() => {
this.subscribing = false;
});
},
},
};

View File

@@ -0,0 +1,20 @@
import store from '../../store';
import SidebarCartItem from './SidebarCartItem.vue';
export default {
components: { SidebarCartItem },
computed: {
cart() {
return store.state.cart;
},
cartIsEmpty() {
return store.cartIsEmpty();
},
cartIsNotEmpty() {
return ! store.cartIsEmpty();
},
},
};

View File

@@ -0,0 +1,69 @@
<template>
<div class="sidebar-cart-item">
<a :href="productUrl(cartItem.product)" class="product-image">
<img
:src="baseImage(cartItem.product)"
:class="{ 'image-placeholder': ! hasBaseImage(cartItem.product) }"
alt="product image"
>
</a>
<div class="product-info">
<a :href="productUrl(cartItem.product)" class="product-name" :title="cartItem.product.name">
{{ cartItem.product.name }}
</a>
<ul class="list-inline product-options">
<li v-for="option in cartItem.options" :key="option.id">
<label>{{ option.name }}:</label> {{ optionValues(option) }}
</li>
</ul>
<div class="product-quantity">
{{ cartItem.qty }} x <span v-html="cartItem.unitPrice.inCurrentCurrency.formatted"></span>
</div>
</div>
<div class="remove-cart-item">
<button class="btn-remove" @click="remove">
<i class="las la-times"></i>
</button>
</div>
</div>
</template>
<script>
import store from '../../store';
import ProductHelpersMixin from '../../mixins/ProductHelpersMixin';
export default {
mixins: [
ProductHelpersMixin,
],
props: ['cartItem'],
methods: {
optionValues(option) {
let values = [];
for (let value of option.values) {
values.push(value.label);
}
return values.join(', ');
},
remove() {
store.removeCartItem(this.cartItem);
$.ajax({
method: 'DELETE',
url: route('cart.items.destroy', { cartItemId: this.cartItem.id }),
}).then((cart) => {
store.updateCart(cart);
});
},
},
};
</script>

View File

@@ -0,0 +1,188 @@
import noUiSlider from "nouislider";
import { trans } from "../../functions";
import { collapseFilters } from "./index/helpers";
export default {
props: [
"initialQuery",
"initialBrandName",
"initialBrandBanner",
"initialBrandSlug",
"initialCategoryName",
"initialCategoryBanner",
"initialCategorySlug",
"initialTagName",
"initialTagSlug",
"initialAttribute",
"maxPrice",
"initialSort",
"initialPerPage",
"initialPage",
"initialViewMode"
],
data() {
return {
fetchingProducts: false,
products: { data: [] },
attributeFilters: [],
brandBanner: this.initialBrandBanner,
categoryName: this.initialCategoryName,
categoryBanner: this.initialCategoryBanner,
viewMode: this.initialViewMode,
queryParams: {
query: this.initialQuery,
brand: this.initialBrandSlug,
category: this.initialCategorySlug,
tag: this.initialTagSlug,
attribute: this.initialAttribute,
fromPrice: 0,
toPrice: this.maxPrice,
sort: this.initialSort,
perPage: this.initialPerPage,
page: this.initialPage
}
};
},
computed: {
emptyProducts() {
return this.products.data.length === 0;
},
totalPage() {
return Math.ceil(this.products.total / this.queryParams.perPage);
},
showingResults() {
if (this.emptyProducts) {
return;
}
return trans("storefront::products.showing_results", {
from: this.products.from,
to: this.products.to,
total: this.products.total
});
}
},
mounted() {
this.addEventListeners();
this.initPriceFilter();
this.fetchProducts();
},
methods: {
addEventListeners() {
$(this.$refs.sortSelect).on("change", e => {
this.queryParams.sort = e.currentTarget.value;
this.fetchProducts();
});
$(this.$refs.perPageSelect).on("change", e => {
this.queryParams.perPage = e.currentTarget.value;
this.fetchProducts();
});
},
initPriceFilter() {
noUiSlider.create(this.$refs.priceRange, {
connect: true,
direction: window.FleetCart.rtl ? "rtl" : "ltr",
start: [0, this.maxPrice],
range: {
min: [0],
max: [this.maxPrice]
}
});
this.$refs.priceRange.noUiSlider.on("update", (values, handle) => {
let value = Math.round(values[handle]);
if (handle === 0) {
this.queryParams.fromPrice = value;
} else {
this.queryParams.toPrice = value;
}
});
this.$refs.priceRange.noUiSlider.on("change", this.fetchProducts);
},
updatePriceRange(fromPrice, toPrice) {
this.$refs.priceRange.noUiSlider.set([fromPrice, toPrice]);
this.fetchProducts();
},
toggleAttributeFilter(slug, value) {
if (!this.queryParams.attribute.hasOwnProperty(slug)) {
this.queryParams.attribute[slug] = [];
}
if (this.queryParams.attribute[slug].includes(value)) {
this.queryParams.attribute[slug].splice(
this.queryParams.attribute[slug].indexOf(value),
1
);
} else {
this.queryParams.attribute[slug].push(value);
}
this.fetchProducts({ updateAttributeFilters: false });
},
isFilteredByAttribute(slug, value) {
if (!this.queryParams.attribute.hasOwnProperty(slug)) {
return false;
}
return this.queryParams.attribute[slug].includes(value);
},
changeCategory(category) {
this.categoryName = category.name;
this.categoryBanner = category.banner.path;
this.queryParams.query = null;
this.queryParams.category = category.slug;
this.queryParams.attribute = {};
this.queryParams.page = 1;
this.fetchProducts();
},
changePage(page) {
this.queryParams.page = page;
this.fetchProducts();
},
fetchProducts(options = { updateAttributeFilters: true }) {
this.fetchingProducts = true;
$.ajax({
url: route("products.index", this.queryParams)
})
.then(response => {
this.products = response.products;
if (options.updateAttributeFilters) {
this.attributeFilters = response.attributes;
}
this.$nextTick(() => {
collapseFilters();
});
})
.catch(xhr => {
this.$notify(xhr.responseJSON.message);
})
.always(() => {
this.fetchingProducts = false;
});
}
}
};

View File

@@ -0,0 +1,234 @@
import store from '../../store';
import Errors from '../../Errors';
import ProductRating from '../ProductRating.vue';
import ProductCardMixin from '../../mixins/ProductCardMixin';
import RelatedProducts from './show/RelatedProducts.vue';
export default {
components: { ProductRating, RelatedProducts },
mixins: [
ProductCardMixin,
],
props: ['product', 'reviewCount', 'avgRating'],
data() {
return {
price: this.product.formatted_price,
activeTab: 'description',
currentReviewPage: 1,
fetchingReviews: false,
reviews: {},
addingNewReview: false,
reviewForm: {},
cartItemForm: {
product_id: this.product.id,
qty: 1,
options: {},
},
errors: new Errors(),
};
},
computed: {
totalReviews() {
if (! this.reviews.total) {
return this.reviewCount;
}
return this.reviews.total;
},
ratingPercent() {
return (this.avgRating / 5) * 100;
},
emptyReviews() {
return this.totalReviews === 0;
},
totalReviewPage() {
return Math.ceil(this.reviews.total / 4);
},
},
created() {
this.fetchReviews();
},
mounted() {
$(this.$refs.upSellProducts).slick({
rows: 0,
dots: false,
arrows: true,
infinite: true,
slidesToShow: 1,
slidesToScroll: 1,
rtl: window.FleetCart.rtl,
});
},
methods: {
updateQuantity(qty) {
if (qty < 1 || this.exceedsMaxStock(qty)) {
return;
}
if (isNaN(qty)) {
qty = 1;
}
this.cartItemForm.qty = qty;
},
exceedsMaxStock(qty) {
return this.product.manage_stock && this.product.qty < qty;
},
changeReviewPage(page) {
this.currentReviewPage = page;
this.fetchReviews();
},
updatePrice() {
this.$nextTick(() => {
$.ajax({
method: 'POST',
url: route('products.price.show', { id: this.product.id }),
data: { options: this.cartItemForm.options },
}).then((price) => {
this.price = price;
}).catch((xhr) => {
this.$notify(xhr.responseJSON.message);
});
});
},
updateSelectTypeOptionValue(optionId, e) {
this.$set(this.cartItemForm.options, optionId, $(e.target).val());
this.errors.clear(`options.${optionId}`);
},
updateCheckboxTypeOptionValue(optionId, e) {
let values = $(e.target)
.parents('.variant-check')
.find('input[type="checkbox"]:checked')
.map((_, el) => {
return el.value;
});
this.$set(this.cartItemForm.options, optionId, values.get());
},
customRadioTypeOptionValueIsActive(optionId, valueId) {
if (! this.cartItemForm.options.hasOwnProperty(optionId)) {
return false;
}
return this.cartItemForm.options[optionId] === valueId;
},
syncCustomRadioTypeOptionValue(optionId, valueId) {
if (this.customRadioTypeOptionValueIsActive(optionId, valueId)) {
this.$delete(this.cartItemForm.options, optionId);
} else {
this.$set(this.cartItemForm.options, optionId, valueId);
this.errors.clear(`options.${optionId}`);
}
this.updatePrice();
},
customCheckboxTypeOptionValueIsActive(optionId, valueId) {
if (! this.cartItemForm.options.hasOwnProperty(optionId)) {
this.$set(this.cartItemForm.options, optionId, []);
return false;
}
return this.cartItemForm.options[optionId].includes(valueId);
},
syncCustomCheckboxTypeOptionValue(optionId, valueId) {
if (this.customCheckboxTypeOptionValueIsActive(optionId, valueId)) {
this.cartItemForm.options[optionId].splice(
this.cartItemForm.options[optionId].indexOf(valueId),
1
);
} else {
this.cartItemForm.options[optionId].push(valueId);
this.errors.clear(`options.${optionId}`);
}
this.updatePrice();
},
fetchReviews() {
this.fetchingReviews = true;
$.ajax({
method: 'GET',
url: route('products.reviews.index', {
productId: this.product.id,
page: this.currentReviewPage,
}),
}).then((reviews) => {
this.reviews = reviews;
}).catch((xhr) => {
this.$notify(xhr.responseJSON.message);
}).always(() => {
this.fetchingReviews = false;
});
},
addNewReview() {
this.addingNewReview = true;
$.ajax({
method: 'POST',
url: route('products.reviews.store', { productId: this.product.id }),
data: this.reviewForm,
}).then((review) => {
this.reviewForm = {};
this.reviews.total++;
this.reviews.data.unshift(review);
$('.captcha-input').prev('img').trigger('click');
}).catch((xhr) => {
if (xhr.status === 422) {
this.errors.record(xhr.responseJSON.errors);
} else {
this.$notify(xhr.responseJSON.message);
}
}).always(() => {
this.addingNewReview = false;
});
},
addToCart() {
this.addingToCart = true;
$.ajax({
method: 'POST',
url: route('cart.items.store', this.cartItemForm),
}).then((cart) => {
store.updateCart(cart);
$('.header-cart').trigger('click');
}).catch((xhr) => {
if (xhr.status === 422) {
this.errors.record(xhr.responseJSON.errors);
} else {
this.$notify(xhr.responseJSON.message);
}
}).always(() => {
this.addingToCart = false;
});
},
},
};

View File

@@ -0,0 +1,15 @@
<template>
<div class="col">
<ProductCard :product="product"/>
</div>
</template>
<script>
import ProductCard from './../../ProductCard.vue';
export default {
components: { ProductCard },
props: ['product'],
};
</script>

View File

@@ -0,0 +1,92 @@
<template>
<div class="list-product-card">
<div class="list-product-card-inner">
<div class="product-card-left">
<a :href="productUrl" class="product-image">
<img :src="baseImage" :class="{ 'image-placeholder': ! hasBaseImage }" alt="product-image">
<ul class="list-inline product-badge">
<li class="badge badge-danger" v-if="product.is_out_of_stock">
{{ $trans('storefront::product_card.out_of_stock') }}
</li>
<li class="badge badge-primary" v-else-if="product.is_new">
{{ $trans('storefront::product_card.new') }}
</li>
<li class="badge badge-success" v-if="product.has_percentage_special_price">
-{{ product.special_price_percent }}%
</li>
</ul>
</a>
</div>
<div class="product-card-right">
<a :href="productUrl" class="product-name">
<h6>{{ product.name }}</h6>
</a>
<div class="clearfix"></div>
<ProductRating :ratingPercent="product.rating_percent" :reviewCount="product.reviews.length"/>
<div class="product-price" v-html="product.formatted_price"></div>
<button
v-if="hasNoOption || product.is_out_of_stock"
class="btn btn-default btn-add-to-cart"
:class="{ 'btn-loading': addingToCart }"
:disabled="product.is_out_of_stock"
@click="addToCart"
>
<i class="las la-cart-arrow-down"></i>
{{ $trans('storefront::product_card.add_to_cart') }}
</button>
<a
v-else
:href="productUrl"
class="btn btn-default btn-add-to-cart"
>
<i class="las la-eye"></i>
{{ $trans('storefront::product_card.view_options') }}
</a>
<div class="product-card-actions">
<button
class="btn btn-wishlist"
:class="{ 'added': inWishlist }"
@click="syncWishlist"
>
<i class="la-heart" :class="inWishlist ? 'las' : 'lar'"></i>
{{ $trans('storefront::product_card.wishlist') }}
</button>
<button
class="btn btn-compare"
:class="{ 'added': inCompareList }"
@click="syncCompareList"
>
<i class="las la-random"></i>
{{ $trans('storefront::product_card.compare') }}
</button>
</div>
</div>
</div>
</div>
</template>
<script>
import ProductRating from './../../ProductRating.vue';
import ProductCardMixin from '../../../mixins/ProductCardMixin';
export default {
components: { ProductRating },
mixins: [
ProductCardMixin,
],
props: ['product'],
};
</script>

View File

@@ -0,0 +1,25 @@
import { trans } from '../../../functions';
export function collapseFilters() {
$('.filter-checkbox').each(function () {
let self = $(this);
let filterCollapseCheckbox = self.children().eq(4).nextAll('.form-check');
filterCollapseCheckbox.hide();
self.next().remove();
if (self.children().length > 5) {
self.after(`<span class="btn-show-more">${trans('storefront::products.show_more')}</span>`);
self.next().on('click', (e) => {
let target = $(e.currentTarget);
let showMoreText = trans('storefront::products.show_more');
let showLessText = trans('storefront::products.show_less');
target.text(target.text() === showMoreText ? showLessText : showMoreText);
filterCollapseCheckbox.slideToggle(200);
});
}
});
}

View File

@@ -0,0 +1,97 @@
<template>
<section class="landscape-products-wrap" v-if="hasAnyProduct">
<div class="products-header">
<h5 class="section-title">{{ $trans('storefront::product.related_products') }}</h5>
</div>
<div class="landscape-products" ref="productsPlaceholder">
<ProductCard v-for="(product, index) in products" :key="index" :product="product"></ProductCard>
</div>
</section>
</template>
<script>
import ProductCard from './../../ProductCard.vue';
import { slickPrevArrow, slickNextArrow } from '../../../functions';
export default {
components: { ProductCard },
props: ['products'],
computed: {
hasAnyProduct() {
return this.products.length !== 0;
},
},
mounted() {
$(this.$refs.productsPlaceholder).slick({
rows: 0,
dots: false,
arrows: true,
infinite: true,
slidesToShow: 5,
slidesToScroll: 5,
rtl: window.FleetCart.rtl,
prevArrow: slickPrevArrow(),
nextArrow: slickNextArrow(),
responsive: [
{
breakpoint: 1761,
settings: {
slidesToShow: 4,
slidesToScroll: 4,
},
},
{
breakpoint: 1341,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
},
},
{
breakpoint: 1081,
settings: {
slidesToShow: 2,
slidesToScroll: 2,
},
},
{
breakpoint: 992,
settings: {
slidesToShow: 4,
slidesToScroll: 4,
},
},
{
breakpoint: 881,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
},
},
{
breakpoint: 661,
settings: {
dots: true,
arrows: false,
slidesToShow: 3,
slidesToScroll: 3,
},
},
{
breakpoint: 641,
settings: {
dots: true,
arrows: false,
slidesToShow: 2,
slidesToScroll: 2,
},
},
],
});
},
};
</script>

View File

@@ -0,0 +1,61 @@
import Vue from 'vue';
export function notify(message, options = {}) {
Vue.$toast.open({
message,
type: 'default',
duration: 3000,
position: (screen.width < 992) ? 'bottom' : 'bottom-right',
...options,
});
}
export function trans(langKey, replace = {}) {
let line = window.FleetCart.langs[langKey];
for (let key in replace) {
line = line.replace(`:${key}`, replace[key]);
}
return line;
}
export function isEmpty(value) {
return $.isEmptyObject(value);
}
export function chunk(array, size) {
let chunkedArray = [];
let index = 0;
while (index < array.length) {
chunkedArray.push(array.slice(index, size + index));
index += size;
}
return chunkedArray;
}
export function slickPrevArrow() {
if (window.FleetCart.rtl) {
return `<div class="arrow-prev">
<i class="las la-angle-right"></i> ${trans('storefront::layout.prev')}
</div>`;
}
return `<div class="arrow-prev">
<i class="las la-angle-left"></i> ${trans('storefront::layout.prev')}
</div>`;
}
export function slickNextArrow() {
if (window.FleetCart.rtl) {
return `<div class="arrow-next">
${trans('storefront::layout.next')} <i class="las la-angle-left"></i>
</div>`;
}
return `<div class="arrow-next">
${trans('storefront::layout.next')} <i class="las la-angle-right"></i>
</div>`;
}

View File

@@ -0,0 +1,100 @@
import store from '../store';
export default {
data() {
return {
loadingOrderSummary: false,
shippingMethodName: null,
applyingCoupon: false,
couponCode: null,
couponError: null,
};
},
computed: {
cart() {
return store.state.cart;
},
cartIsEmpty() {
return store.cartIsEmpty();
},
cartIsNotEmpty() {
return ! store.cartIsEmpty();
},
hasShippingMethod() {
return store.hasShippingMethod();
},
firstShippingMethod() {
return Object.keys(store.state.cart.availableShippingMethods)[0];
},
hasCoupon() {
return store.state.cart.coupon.code !== undefined;
},
},
methods: {
applyCoupon() {
if (! this.couponCode) {
return;
}
this.loadingOrderSummary = true;
this.applyingCoupon = true;
$.ajax({
method: 'POST',
url: route('cart.coupon.store', { coupon: this.couponCode }),
}).then((cart) => {
this.couponCode = null;
store.updateCart(cart);
}).catch((xhr) => {
this.couponError = xhr.responseJSON.message;
}).always(() => {
this.loadingOrderSummary = false;
this.applyingCoupon = false;
});
},
removeCoupon() {
this.loadingOrderSummary = true;
$.ajax({
method: 'DELETE',
url: route('cart.coupon.destroy'),
}).then((cart) => {
store.updateCart(cart);
}).catch((xhr) => {
this.$notify(xhr.responseJSON.message);
}).always(() => {
this.loadingOrderSummary = false;
});
},
updateShippingMethod(shippingMethodName) {
if (! shippingMethodName) {
return;
}
this.loadingOrderSummary = true;
this.changeShippingMethod(shippingMethodName);
$.ajax({
method: 'POST',
url: route('cart.shipping_method.store', { shipping_method: shippingMethodName }),
}).then((cart) => {
store.updateCart(cart);
}).catch((xhr) => {
this.$notify(xhr.responseJSON.message);
}).always(() => {
this.loadingOrderSummary = false;
});
},
},
};

View File

@@ -0,0 +1,54 @@
export default {
data() {
return {
tabs: [],
activeTab: null,
loading: false,
products: [],
};
},
mounted() {
this.tabs = this.$children.filter((component) => {
return component.$options.name === "DynamicTab";
});
// Show the first tab by default on page load.
this.change(this.tabs[0]);
},
methods: {
classes(tab) {
return {
"tab-item": true,
loading: this.activeTab === tab && this.loading,
active: this.activeTab === tab && !this.loading,
};
},
change(activeTab) {
if (this.activeTab === activeTab || activeTab === undefined) {
return;
}
this.loading = true;
this.activeTab = activeTab;
$.ajax({
method: "GET",
url: activeTab.url,
}).then((products) => {
if (this.selector().hasClass("slick-initialized")) {
this.selector().slick("unslick");
}
this.products = products;
this.loading = false;
this.$nextTick(() => {
this.selector().slick(this.slickOptions());
});
});
},
},
};

View File

@@ -0,0 +1,78 @@
import store from "../store";
export default {
data() {
return {
addingToCart: false,
};
},
computed: {
productUrl() {
return route("products.show", this.product.slug);
},
hasAnyOption() {
return this.product.options_count > 0;
},
hasNoOption() {
return !this.hasAnyOption;
},
hasBaseImage() {
return this.product.base_image.length !== 0;
},
baseImage() {
if (this.hasBaseImage) {
return this.product.base_image.path;
}
return `${window.FleetCart.baseUrl}/themes/storefront/public/images/image-placeholder.png`;
},
inWishlist() {
return store.inWishlist(this.product.id);
},
inCompareList() {
return store.inCompareList(this.product.id);
},
},
methods: {
syncWishlist() {
store.syncWishlist(this.product.id);
},
syncCompareList() {
store.syncCompareList(this.product.id);
},
addToCart() {
this.addingToCart = true;
$.ajax({
method: "POST",
url: route("cart.items.store", {
product_id: this.product.id,
qty: 1,
}),
})
.then((cart) => {
store.updateCart(cart);
if (document.location.href !== route("cart.index")) {
$(".header-cart").trigger("click");
}
})
.catch((xhr) => {
this.$notify(xhr.responseJSON.message);
})
.always(() => {
this.addingToCart = false;
});
},
},
};

View File

@@ -0,0 +1,19 @@
export default {
methods: {
productUrl(product) {
return route('products.show', product.slug);
},
hasBaseImage(product) {
return product.base_image.length !== 0;
},
baseImage(product) {
if (this.hasBaseImage(product)) {
return product.base_image.path;
}
return `${window.FleetCart.baseUrl}/themes/storefront/public/images/image-placeholder.png`;
},
},
};

View File

@@ -0,0 +1,105 @@
import Vue from "vue";
import { isEmpty } from "./functions";
export default {
state: Vue.observable({
cart: FleetCart.cart,
wishlist: FleetCart.wishlist,
compareList: FleetCart.compareList,
}),
cartIsEmpty() {
return isEmpty(this.state.cart.items);
},
updateCart(cart) {
this.state.cart = cart;
},
removeCartItem(cartItem) {
Vue.delete(this.state.cart.items, cartItem.id);
},
clearCart() {
this.state.cart.items = {};
},
hasShippingMethod() {
return (
Object.keys(this.state.cart.availableShippingMethods).length !== 0
);
},
wishlistCount() {
return this.state.wishlist.length;
},
inWishlist(productId) {
return this.state.wishlist.includes(productId);
},
syncWishlist(productId) {
if (this.inWishlist(productId)) {
this.removeFromWishlist(productId);
} else {
this.addToWishlist(productId);
}
},
addToWishlist(productId) {
if (FleetCart.loggedIn) {
this.state.wishlist.push(productId);
} else {
return (window.location.href = route("login"));
}
$.ajax({
method: "POST",
url: route("wishlist.store"),
data: { productId },
});
},
removeFromWishlist(productId) {
this.state.wishlist.splice(this.state.wishlist.indexOf(productId), 1);
$.ajax({
method: "DELETE",
url: route("wishlist.destroy", { productId }),
});
},
inCompareList(productId) {
return this.state.compareList.includes(productId);
},
syncCompareList(productId) {
if (this.inCompareList(productId)) {
this.removeFromCompareList(productId);
} else {
this.addToCompareList(productId);
}
},
addToCompareList(productId) {
this.state.compareList.push(productId);
$.ajax({
method: "POST",
url: route("compare.store"),
data: { productId },
});
},
removeFromCompareList(productId) {
this.state.compareList.splice(
this.state.compareList.indexOf(productId),
1
);
$.ajax({
method: "DELETE",
url: route("compare.destroy", { productId }),
});
},
};

View File

@@ -0,0 +1,531 @@
require('./vendors/vendors');
$(() => {
/* variables
/*----------------------------------------*/
let _window = $(window),
body = $('body');
/* button loading
/*----------------------------------------*/
$('[data-loading]').on('click', (e) => {
e.currentTarget.classList.add('btn-loading');
});
/* select option
/*----------------------------------------*/
let select = $('.custom-select-option');
select.niceSelect();
select.on('change', (e) => {
e.target.dispatchEvent(new Event('nice-select-updated', { bubbles: true }));
});
/* overlay
/*----------------------------------------*/
let overlay = $('.overlay');
/* sidebar cart
/*----------------------------------------*/
let headerCart = $('.header-column-right .header-cart'),
sidebarCart = $('.sidebar-cart-wrap'),
sidebarCartClose = $('.sidebar-cart-close');
headerCart.on('click', (e) => {
e.stopPropagation();
overlay.addClass('active');
sidebarCart.addClass('active');
});
sidebarCartClose.on('click', () => {
overlay.removeClass('active');
sidebarCart.removeClass('active');
});
sidebarCart.on('click', (e) => {
e.stopPropagation();
});
/* header
/*----------------------------------------*/
let headerWrap = $('.header-wrap'),
headerWrapInner = $('.header-wrap-inner'),
headerWrapInnerHeight = headerWrapInner.outerHeight(),
headerSearchSm = $('.header-search-sm'),
searchInputSm = $('.search-input-sm'),
headerSearchSmClose = $('.header-search-sm-form .btn-close');
headerSearchSm.on('click', (e) => {
let target = $(e.currentTarget);
target.parents('.header-search').next().toggleClass('active');
searchInputSm.focus();
});
headerSearchSmClose.on('click', (e) => {
let target = $(e.currentTarget);
target.parents('.header-search-sm-form').removeClass('active');
});
_window.on('resize', () => {
headerWrapInnerHeight = headerWrapInner.outerHeight();
});
_window.on('load scroll resize', () => {
let headerWrapHeight = headerWrap.outerHeight(),
headerWrapOffsetTop = headerWrap.offset().top + headerWrapHeight;
function stickyHeader() {
let scrollTop = _window.scrollTop();
if (scrollTop > headerWrapOffsetTop) {
headerWrap.css('padding-top', `${headerWrapInnerHeight}px`);
headerWrapInner.addClass('sticky');
setTimeout(() => {
headerWrapInner.addClass('show');
});
return;
}
headerWrap.css('padding-top', 0);
headerWrapInner.removeClass('sticky show');
}
stickyHeader();
});
/* menu dropdown arrow
/*----------------------------------------*/
let megaMenuItem = $('.mega-menu > li'),
subMenuDropdown = $('.sub-menu > .dropdown'),
sidebarMenuSubMenu = $('.sidebar-menu .sub-menu');
function menuDropdownArrow(parentSelector, childSelector) {
parentSelector.each(function () {
let self = $(this);
if (self.children().length > 1) {
if (window.FleetCart.rtl) {
self.children(`${childSelector}`).append('<i class="las la-angle-left"></i>');
return;
}
self.children(`${childSelector}`).append('<i class="las la-angle-right"></i>');
}
});
}
menuDropdownArrow(subMenuDropdown, 'a');
menuDropdownArrow(megaMenuItem, '.menu-item');
/* navigation
/*----------------------------------------*/
let moreCategories = $('.more-categories'),
categoryDropdown = $('.category-dropdown'),
categoryNavInner = $('.category-nav-inner'),
categoryDropdownWrap = $('.category-dropdown-wrap'),
verticalMegaMenuList = $('.vertical-megamenu > li');
categoryNavInner.on('click', () => {
categoryDropdownWrap.toggleClass('show');
});
_window.on('load resize', () => {
let verticalMegaMenuListHeight = 0,
homeSliderHeight = homeSlider.height(),
categoryDropdownHeight = homeSliderHeight;
categoryDropdown.css('height', `${categoryDropdownHeight}px`);
verticalMegaMenuList.each(function () {
let self = $(this);
verticalMegaMenuListHeight += self.height();
if (verticalMegaMenuListHeight + 78 > categoryDropdownHeight) {
self.addClass('hide');
moreCategories.removeClass('hide');
return;
}
self.removeClass('hide');
moreCategories.addClass('hide');
});
});
/* sidebar menu
/*----------------------------------------*/
let sidebarMenuIcon = $('.sidebar-menu-icon'),
sidebarMenuWrap = $('.sidebar-menu-wrap'),
sidebarMenuClose = $('.sidebar-menu-close'),
sidebarMenuTab = $('.sidebar-menu-tab a'),
sidebarMenuList = $('.sidebar-menu li'),
sidebarMenuLink = $('.sidebar-menu > li > a'),
sidebarMenuListUl = $('.sidebar-menu > li > ul'),
sidebarMenuDropdown = $('.sidebar-menu > .dropdown'),
sidebarMenuSubMenuUl = $('.sidebar-menu .sub-menu ul'),
sidebarMenuSubMenuLink = $('.sidebar-menu .sub-menu > a');
sidebarMenuIcon.on('click', (e) => {
e.stopPropagation();
overlay.addClass('active');
sidebarMenuWrap.addClass('active');
});
sidebarMenuClose.on('click', (e) => {
overlay.removeClass('active');
sidebarMenuWrap.removeClass('active');
});
sidebarMenuWrap.on('click', (e) => {
e.stopPropagation();
});
sidebarMenuTab.on('click', (e) => {
let target = $(e.currentTarget);
e.preventDefault();
target.tab('show');
});
sidebarMenuList.each(function () {
let self = $(this);
if (self.children().length > 1) {
if (window.FleetCart.rtl) {
self.children('a').after('<i class="las la-angle-left"></i>');
return;
}
self.children('a').after('<i class="las la-angle-right"></i>');
}
});
sidebarMenuDropdown.on('click', (e) => {
let target = $(e.currentTarget);
if (! target.hasClass('active')) {
$('.sidebar-menu > li').removeClass('active');
target.addClass('active');
} else {
$('.sidebar-menu > li').removeClass('active');
}
if (! target.children('ul').hasClass('open')) {
$('.sidebar-menu .open').removeClass('open').slideUp(300);
target.children('ul').addClass('open').slideDown(300);
return;
}
$('.sidebar-menu .open').removeClass('open').slideUp(300);
});
sidebarMenuLink.on('click', (e) => {
e.stopPropagation();
});
sidebarMenuListUl.on('click', (e) => {
e.stopPropagation();
});
sidebarMenuSubMenu.on('click', (e) => {
let target = $(e.currentTarget);
if (! target.hasClass('active')) {
target.addClass('active');
} else {
target.removeClass('active');
}
target.children('ul').slideToggle(300);
});
sidebarMenuSubMenuUl.on('click', function (e) {
e.stopPropagation();
});
sidebarMenuSubMenuLink.on('click', (e) => {
e.stopPropagation();
});
/* slider
/*----------------------------------------*/
let homeSlider = $('.home-slider');
if (homeSlider.length !== 0) {
homeSlider.slick({
rows: 0,
rtl: window.FleetCart.rtl,
cssEase: 'ease',
speed: Number(homeSlider.data('speed')),
fade: !! JSON.parse(homeSlider.data('fade')),
dots: !! JSON.parse(homeSlider.data('dots')),
arrows: !! JSON.parse(homeSlider.data('arrows')),
autoplay: !! JSON.parse(homeSlider.data('autoplay')),
autoplaySpeed: Number(homeSlider.data('autoplay-speed')),
responsive: [
{
breakpoint: 768,
settings: {
dots: false,
},
},
],
}).slickAnimation();
}
/* tooltip
/*----------------------------------------*/
$('[data-toggle="tooltip"]').tooltip({
trigger: 'hover',
selector: '[data-toggle="tooltip"]',
});
/* top brands
/*----------------------------------------*/
let topBrands = $('.top-brands');
topBrands.slick({
rows: 0,
dots: false,
arrows: true,
infinite: true,
slidesToShow: 7,
slidesToScroll: 7,
rtl: window.FleetCart.rtl,
responsive: [
{
breakpoint: 1200,
settings: {
slidesToShow: 6,
slidesToScroll: 6,
},
},
{
breakpoint: 1050,
settings: {
slidesToShow: 5,
slidesToScroll: 5,
},
},
{
breakpoint: 900,
settings: {
slidesToShow: 4,
slidesToScroll: 4,
},
},
{
breakpoint: 750,
settings: {
slidesToShow: 3,
slidesToScroll: 3,
},
},
{
breakpoint: 600,
settings: {
slidesToShow: 2,
slidesToScroll: 2,
},
},
],
});
/* sidebar filter
/*----------------------------------------*/
let mobileViewFilter = $('.mobile-view-filter');
let filterSectionWrap = $('.filter-section-wrap');
let sidebarFilterClose = $('.sidebar-filter-close');
mobileViewFilter.on('click', (e) => {
e.stopPropagation();
filterSectionWrap.addClass('active');
overlay.addClass('active');
});
sidebarFilterClose.on('click', () => {
filterSectionWrap.removeClass('active');
overlay.removeClass('active');
});
filterSectionWrap.on('click', (e) => {
e.stopPropagation();
});
body.on('click', () => {
overlay.removeClass('active');
sidebarCart.removeClass('active');
sidebarMenuWrap.removeClass('active');
filterSectionWrap.removeClass('active');
});
/* browse categories
/*----------------------------------------*/
$('.browse-categories li').each((i, li) => {
if ($(li).children('ul').length > 0) {
$(li).addClass('parent');
}
});
let filterCategoriesLink = $('.browse-categories li.parent > a');
let parentUls = $('.browse-categories li.active').parentsUntil('.browse-categories', 'ul');
if (window.FleetCart.rtl) {
filterCategoriesLink.before('<i class="las la-angle-left"></i>');
} else {
filterCategoriesLink.before('<i class="las la-angle-right"></i>');
}
parentUls.show().siblings('i').addClass('open');
$('.browse-categories li i').on('click', (e) => {
$(e.currentTarget).toggleClass('open').siblings('ul').slideToggle(300);
});
/* image gallery
/*----------------------------------------*/
let baseImage = $('.base-image');
$('.additional-image-wrap').slick({
rows: 0,
dots: false,
arrows: true,
vertical: true,
infinite: false,
slidesToShow: 4,
slideToScroll: 1,
asNavFor: baseImage,
focusOnSelect: true,
adaptiveHeight: true,
verticalSwiping: true,
responsive: [
{
breakpoint: 577,
settings: {
vertical: false,
variableWidth: true,
verticalSwiping: false,
rtl: window.FleetCart.rtl,
},
},
],
});
baseImage.slick({
rows: 0,
fade: true,
dots: false,
swipe: false,
arrows: false,
infinite: false,
draggable: false,
slidesToShow: 1,
slidesToScroll: 1,
rtl: window.FleetCart.rtl,
});
baseImage.slickLightbox({
src: 'data-image',
itemSelector: '.base-image-slide',
slick: {
fade: true,
infinite: false,
rtl: window.FleetCart.rtl,
},
});
$('.base-image-slide').zoom({
magnify: 1.2,
touch: false,
});
/* number picker
/*----------------------------------------*/
$('.btn-number').on('click', function (e) {
e.preventDefault();
let type = $(this).attr('data-type');
let input = $(this).closest('.input-group-quantity').find('input.input-quantity');
let minValue = input.attr('min');
let maxValue = input.attr('max');
let currentValue = parseInt(input.val());
if (! $.isNumeric(currentValue)) {
input.val(minValue);
input[0].dispatchEvent(new Event('input'), { bubbles: true });
}
if (type === 'minus') {
if (currentValue > minValue) {
input.val(currentValue - 1);
input[0].dispatchEvent(new Event('input'), { bubbles: true });
$('.btn-number.btn-plus').removeAttr('disabled');
}
if (input.val() === minValue) {
$(this).attr('disabled', true);
}
} else if (type === 'plus') {
if (! maxValue || currentValue < maxValue) {
input.val(currentValue + 1);
input[0].dispatchEvent(new Event('input'), { bubbles: true });
$('.btn-number.btn-minus').removeAttr('disabled');
}
if (input.val() === maxValue) {
$(this).attr('disabled', true);
}
}
});
$('.input-number').on('input', function () {
let self = $(this);
let minValue = parseInt(self.attr('min'));
let maxValue = parseInt(self.attr('max'));
let currentValue = parseInt(self.val());
if (! $.isNumeric(self.val())) {
self.val(minValue);
$('.btn-number.btn-minus').attr('disabled', true);
}
if (currentValue < minValue) {
self.val(minValue);
$('.btn-number.btn-minus').attr('disabled', true);
}
if (maxValue && currentValue > maxValue) {
self.val(maxValue);
$('.btn-number.btn-plus').attr('disabled', true);
}
});
});

View File

@@ -0,0 +1,10 @@
require('flatpickr');
for (let el of $('.datetime-picker')) {
$(el).flatpickr({
mode: el.hasAttribute('data-range') ? 'range' : 'single',
enableTime: el.hasAttribute('data-time'),
noCalendar: el.hasAttribute('data-no-calender'),
altInput: true,
});
}

View File

@@ -0,0 +1,230 @@
/*
slick-animation.js
Version: 0.3.3 Beta
Author: Marvin Hübner
Docs: https://github.com/marvinhuebner/slick-animation
Repo: https://github.com/marvinhuebner/slick-animation
*/
(function ($) {
$.fn.slickAnimation = function () {
var currentSlickSlider = $(this);
var slickItems = currentSlickSlider.find('.slick-list .slick-track > div');
var firstSlickItem = currentSlickSlider.find('[data-slick-index="0"]');
var animatedClass = 'animated';
var visible = {opacity: '1'};
var hidden = {opacity: '0'};
/**
* function for setting animationIn and animationOut class
* @param obj
* @param type
* @param animationIn
* @param animatedClass
* @param visibility
*/
function slickSetAnimationDefault(obj, type, animationIn, animatedClass, visibility) {
visibility = typeof visibility !== 'undefined' ? visibility : false;
slickRemoveAnimation(obj, 'delay');
slickRemoveAnimation(obj, 'duration');
if (type['opacity'] == 1) {
obj.addClass(animationIn);
obj.addClass(animatedClass);
} else {
obj.removeClass(animationIn);
obj.removeClass(animatedClass);
}
if (visibility) obj.css(type);
}
/**
* get timeout when delay, duration, delay and duration is set
* @param delayIn
* @param durationIn
* @returns {number}
*/
function getTimeout(delayIn, durationIn) {
if (delayIn) {
return delayIn * 1000 + 1000;
} else if (durationIn) {
return durationIn * 1000;
} else if ((delayIn) || (durationIn)) {
return (delayIn * 1000) + (durationIn * 1000);
}
return 1000;
}
/**
* add css animations for delay and duration
* @param obj
* @param animation
* @param value
*/
function slickAddAnimation(obj, animation, value) {
var delayInAttr = [
'animation-' + animation,
'-webkit-animation-' + animation,
'-moz-animation-' + animation,
'-o-animation-' + animation,
'-ms-animation-' + animation
];
var delayInAttributes = {};
delayInAttr.forEach(function (entry) {
delayInAttributes[entry] = value + 's';
});
obj.css(delayInAttributes);
}
/**
* remove css animations for delay and duration
* @param obj
* @param animation
*/
function slickRemoveAnimation(obj, animation) {
var delayInAttr = [
'animation-' + animation,
'-webkit-animation-' + animation,
'-moz-animation-' + animation,
'-o-animation-' + animation,
'-ms-animation-' + animation
];
var delayInAttributes = {};
delayInAttr.forEach(function (entry) {
delayInAttributes[entry] = '';
});
obj.css(delayInAttributes);
}
slickItems.each(function () {
var slickItem = $(this);
slickItem.find('[data-animation-in]').each(function () {
var self = $(this);
self.css(hidden);
var animationIn = self.attr('data-animation-in');
var animationOut = self.attr('data-animation-out');
var delayIn = self.attr('data-delay-in');
var durationIn = self.attr('data-duration-in');
var delayOut = self.attr('data-delay-out');
var durationOut = self.attr('data-duration-out');
if (animationOut) {
if (firstSlickItem.length > 0) {
if (slickItem.hasClass('slick-current')) {
slickSetAnimationDefault(self, visible, animationIn, animatedClass, true);
if (delayIn) {
slickAddAnimation(self, 'delay', delayIn);
}
if (durationIn) {
slickAddAnimation(self, 'duration', durationIn);
}
setTimeout(function () {
slickSetAnimationDefault(self, hidden, animationIn, animatedClass);
slickSetAnimationDefault(self, visible, animationOut, animatedClass);
if (delayOut) {
slickAddAnimation(self, 'delay', delayOut);
}
if (durationOut) {
slickAddAnimation(self, 'duration', durationOut);
}
setTimeout(function() {
slickRemoveAnimation(self, 'delay');
slickRemoveAnimation(self, 'duration');
}, getTimeout(delayOut, durationOut));
}, getTimeout(delayIn, durationIn));
}
}
currentSlickSlider.on('afterChange', function (event, slick, currentSlider) {
if (slickItem.hasClass('slick-current')) {
slickSetAnimationDefault(self, visible, animationIn, animatedClass, true);
if (delayIn) {
slickAddAnimation(self, 'delay', delayIn);
}
if (durationIn) {
slickAddAnimation(self, 'duration', durationIn);
}
setTimeout(function () {
slickSetAnimationDefault(self, hidden, animationIn, animatedClass);
slickSetAnimationDefault(self, visible, animationOut, animatedClass);
if (delayOut) {
slickAddAnimation(self, 'delay', delayOut);
}
if (durationOut) {
slickAddAnimation(self, 'duration', durationOut);
}
setTimeout(function() {
slickRemoveAnimation(self, 'delay');
slickRemoveAnimation(self, 'duration');
}, getTimeout(delayOut, durationOut));
}, getTimeout(delayIn, durationIn));
}
});
currentSlickSlider.on('beforeChange', function (event, slick, currentSlider) {
slickSetAnimationDefault(self, hidden, animationOut, animatedClass, true);
});
} else {
if (firstSlickItem.length > 0) {
if (slickItem.hasClass('slick-current')) {
slickSetAnimationDefault(self, visible, animationIn, animatedClass, true);
if (delayIn) {
slickAddAnimation(self, 'delay', delayIn);
}
if (durationIn) {
slickAddAnimation(self, 'duration', durationIn);
}
}
}
currentSlickSlider.on('afterChange', function (event, slick, currentSlider) {
if (slickItem.hasClass('slick-current')) {
slickSetAnimationDefault(self, visible, animationIn, animatedClass, true);
if (delayIn) {
slickAddAnimation(self, 'delay', delayIn);
}
if (durationIn) {
slickAddAnimation(self, 'duration', durationIn);
}
}
});
currentSlickSlider.on('beforeChange', function (event, slick, currentSlider) {
slickSetAnimationDefault(self, hidden, animationIn, animatedClass, true);
});
}
});
});
return this;
}
})(jQuery);

View File

@@ -0,0 +1,11 @@
window.$ = window.jQuery = require('jquery');
require('popper.js');
require('bootstrap');
require('jquery-nice-select');
require('jquery-zoom');
require('slick-carousel');
require('slick-lightbox');
require('./slick-animation.js');
require('../../../../../node_modules/kbw-countdown/dist/js/jquery.plugin.js');
require('../../../../../node_modules/kbw-countdown/src/js/jquery.countdown.js');

View File

@@ -0,0 +1,77 @@
$grid-columns: 18;
@import
'~bootstrap/scss/bootstrap',
'~line-awesome/dist/line-awesome/scss/line-awesome',
'~jquery-nice-select/scss/nice-select',
'~animate.css/animate',
'~slick-carousel/slick/slick',
'~slick-carousel/slick/slick-theme',
'~slick-lightbox/src/styles/slick-lightbox',
'~kbw-countdown/src/css/jquery.countdown',
'~nouislider/distribute/nouislider',
'~flatpickr/dist/flatpickr';
@import
'utils/_variables',
'utils/_utilities',
'utils/_common';
@import
'base/_reset',
'base/_typography',
'base/_carousel';
@import
'components/_custom-select',
'components/_mega-menu',
'components/_tabs',
'components/_buttons',
'components/_scrollbar',
'components/_countdown',
'components/_breadcrumb',
'components/_form',
'components/_alert',
'components/_table',
'components/_badge',
'components/_panel',
'components/_pagination',
'components/_loader',
'components/_modal',
'components/_toast';
@import
'layout/_top-nav',
'layout/_header',
'layout/_sidebar-menu',
'layout/_sidebar-cart',
'layout/_navigation',
'layout/_landscape-products',
'layout/_steps',
'layout/_order-summary',
'layout/_subscribe',
'layout/_newsletter',
'layout/_cookie-bar',
'layout/_footer';
@import
'pages/_home',
'pages/_login',
'pages/_register',
'pages/_account',
'pages/_contact',
'pages/_compare',
'pages/_product-search',
'pages/_product-details',
'pages/_cart',
'pages/_checkout',
'pages/_order-complete',
'pages/_all-brands',
'pages/_all-categories',
'pages/_order-details',
'pages/_404',
'pages/_custom-page';
[v-cloak] {
display: none !important;
}

View File

@@ -0,0 +1,150 @@
.slick-list {
.slick-track {
float: left;
}
}
.slick-dotted {
&.slick-slider {
margin-bottom: 0;
}
}
.slick-prev,
.slick-next {
z-index: 1;
&:before {
font-family: 'Line Awesome Free';
font-size: 14px;
font-weight: 900;
color: $color-gray-dark;
opacity: 1;
transition: $transition-default;
}
&:hover {
&:before {
color: $color-default;
color: var(--color-primary);
}
}
}
.slick-prev:before {
content: '\f104';
}
.slick-next:before {
content: '\f105';
}
.rtl {
.slick-prev:before {
content: '\f105';
}
.slick-next:before {
content: '\f104';
}
}
.slick-lightbox {
.slick-prev,
.slick-next {
&:before {
font-size: 24px;
}
}
.slick-lightbox-close {
right: 13px;
&:before {
font-family: 'Line Awesome Free';
font-weight: 900;
font-size: 20px;
content: '\f00d';
transition: $transition-default;
}
&:hover {
&:before {
color: $color-default;
color: var(--color-primary);
}
}
}
}
.slick-dots {
bottom: 0;
display: flex;
flex-wrap: wrap;
justify-content: center;
margin-bottom: -12px;
li {
height: 10px;
width: 10px;
margin: 0 8px 12px;
transition: $transition-primary;
button {
height: 10px;
width: 10px;
padding: 0;
transition: $transition-primary;
&:before {
content: '';
font-size: 14px;
height: 10px;
width: 10px;
background: $color-default;
background: var(--color-primary);
border-radius: 5px;
transition: $transition-primary;
}
}
&.slick-active {
width: 30px;
button {
width: 30px;
&:before {
width: 30px;
opacity: 1;
}
}
}
}
}
.arrow-prev.slick-arrow,
.arrow-next.slick-arrow {
position: absolute;
font-size: 14px;
padding: 4px 0;
color: $color-gray-dark;
z-index: 1;
cursor: pointer;
transition: none;
&:hover {
font-weight: 500;
color: $color-default;
color: var(--color-primary);
}
}
.arrow-prev {
right: 69px;
}
.arrow-next {
right: -3px;
}

View File

@@ -0,0 +1,93 @@
html {
font-family: $primary-font;
}
body {
direction: ltr;
font-family: $primary-font;
font-size: 15px;
font-weight: 400;
font-style: normal;
min-width: 320px;
color: $color-black;
overflow-x: hidden;
}
h1, h2, h3, h4, h5, h6 {
color: $color-black;
}
h1, h2, h3, h4, h5, h6,
ul, ol, li, address, p {
margin: 0;
padding: 0;
}
div, a, button {
&:active, &:focus, &:visited {
outline: 0;
}
}
a {
transition: $transition-default;
&:hover {
text-decoration: none;
}
}
b, strong {
font-weight: 500;
}
.tooltip {
pointer-events: none;
> .tooltip-inner {
font-size: 12px;
padding: 4px 8px;
border-radius: $radius-default;
}
}
.container {
padding-left: 4.5%;
padding-right: 4.5%;
}
@media screen and (min-width: 1920px) {
.container {
max-width: 1770px;
padding-left: 15px;
padding-right: 15px;
}
}
@media screen and (min-width: 2200px) {
.container {
max-width: 1920px;
}
}
@media screen and (max-width: 1920px) {
.container {
max-width: 100%;
padding-left: 4%;
padding-right: 4%;
}
}
@media screen and (max-width: 1500px) {
.container {
padding-left: 1.5%;
padding-right: 1.5%;
}
}
@media screen and (max-width: $lg) {
.container {
padding-left: 15px;
padding-right: 15px;
}
}

View File

@@ -0,0 +1,38 @@
h1, h2, h3, h4, h5, h6, p, span {
font-family: $primary-font;
}
h1 {
font-size: 36px;
line-height: 44px;
}
h2 {
font-size: 28px;
line-height: 36px;
}
h3 {
font-size: 24px;
line-height: 30px;
}
h4 {
font-size: 20px;
line-height: 28px;
}
h5 {
font-size: 18px;
line-height: 24px;
}
h6 {
font-size: 15px;
line-height: 18px;
}
p {
font-size: 15px;
line-height: 22px;
}

View File

@@ -0,0 +1,62 @@
.alert {
font-size: 16px;
position: fixed;
right: 15px;
bottom: 15px;
display: flex;
margin: 0 0 0 15px;
padding: 20px 64px 20px 28px;
align-items: center;
border: none;
border-left: 3px solid;
border-radius: $radius-default;
> i {
font-size: 20px;
margin-right: 16px;
}
.close {
font-size: 16px;
top: 50%;
right: 17px;
padding: 10px;
opacity: 1;
transform: translateY(-50%);
&:hover {
> i {
color: $color-default;
color: var(--color-primary);
}
}
> i {
color: $color-gray-dark;
}
}
}
.alert-success {
color: $color-green;
background: #e8f7f3;
border-color: $color-green;
}
.alert-danger {
color: $color-red;
background: #fbebea;
border-color: $color-red;
}
.alert-info {
color: $color-info;
background: #e2ecf7;
border-color: $color-info;
}
.alert-warning {
color: $color-yellow;
background: #fef5ea;
border-color: $color-yellow;
}

View File

@@ -0,0 +1,29 @@
.badge {
font-size: 14px;
font-weight: 400;
min-width: 120px;
display: inline-block;
padding: 10px 15px;
text-align: center;
border-radius: 20px;
}
.badge-success {
color: $color-green;
background: #edf9f6;
}
.badge-danger {
color: $color-red;
background: #fdf0ed;
}
.badge-info {
color: $color-info;
background: #eef5fb;
}
.badge-warning {
color: $color-yellow;
background: #fff9ef;
}

View File

@@ -0,0 +1,51 @@
.breadcrumb {
margin: 23px 0 0;
padding: 0;
background: $color-white;
ul {
margin-left: -11px;
> li {
font-size: 15px;
line-height: 26px;
position: relative;
display: inline-block;
padding: 0 10px;
&:after {
position: absolute;
content: '\f105';
font-family: 'Line Awesome Free';
font-weight: 900;
font-size: 12px;
right: -7px;
top: 1px;
color: $color-black;
}
&:last-child {
&:after {
content: '';
}
}
&.active {
color: $color-gray-dark;
&:after {
color: $color-gray-dark;
}
}
> a {
color: $color-black;
&:hover {
color: $color-default;
color: var(--color-primary);
}
}
}
}
}

View File

@@ -0,0 +1,123 @@
.btn {
font-family: $primary-font;
font-size: 15px;
line-height: 26px;
position: relative;
border: none;
padding: 7px 24px;
border-radius: $radius-default;
transition: $transition-default;
&:focus {
box-shadow: none !important;
outline: 0;
}
}
.btn-primary {
font-weight: 500;
color: $color-white;
background: $color-default;
background: var(--color-primary);
&:focus {
background: $color-default;
background: var(--color-primary);
}
&:active,
&:hover,
&:active:focus {
background: $color-default-hover;
background: var(--color-primary-hover);
}
&:not(:disabled):not(.disabled):active,
&:not(:disabled):not(.disabled).active {
background: $color-default-hover;
background: var(--color-primary-hover);
}
&:disabled,
&.disabled,
&[disabled] {
background: $color-default;
background: var(--color-primary);
&:active,
&:hover,
&:focus,
&:hover:focus {
background: $color-default;
background: var(--color-primary);
}
}
}
.btn-default {
font-weight: 500;
padding: 6px 24px;
background: transparent;
border: 1px solid $color-default;
border: 1px solid var(--color-primary);
&:active,
&:hover,
&:active:focus {
color: $color-white;
background: $color-default;
background: var(--color-primary);
}
&.disabled,
&[disabled] {
&:active,
&:hover,
&:focus,
&:hover:focus {
color: $color-black;
background: transparent !important;
&.btn-loading {
&:after {
border-color: $color-default;
border-color: var(--color-primary);
}
}
}
}
&.btn-loading {
&:after {
border-color: $color-default;
border-color: var(--color-primary);
}
&:active,
&:hover,
&:focus,
&:hover:focus {
&:after {
border-color: $color-white;
}
}
}
}
.btn-lg {
margin-top: 5px;
padding: 12px 50px;
}
.btn-remove {
font-size: 15px;
color: $color-black;
background: transparent;
border: none;
transition: $transition-default;
&:hover {
color: $color-default;
color: var(--color-primary);
}
}

View File

@@ -0,0 +1,40 @@
.is-countdown {
border: none;
background: transparent;
.countdown-row {
display: flex;
padding: 0;
justify-content: center;
}
.countdown-show4 {
.countdown-section {
width: auto;
}
}
.countdown-section {
position: relative;
float: none;
}
.countdown-amount {
font-size: 16px;
line-height: 22px;
display: flex;
margin: 0 auto 26px;
align-items: center;
justify-content: center;
}
.countdown-period {
position: absolute;
font-size: 12px;
line-height: 22px;
left: 50%;
bottom: 0;
color: $color-gray;
transform: translateX(-50%);
}
}

View File

@@ -0,0 +1,60 @@
.nice-select {
height: auto;
display: inline-block;
float: none;
border: none;
&:after {
border: none;
}
&.form-control {
color: $color-black;
padding: 12px 30px 12px 20px;
border: 1px solid $color-gray-lite;
&.arrow-black {
background-position: right 10px center;
}
}
&.right {
float: none;
}
.list {
min-width: 190px;
margin-top: 1px;
padding: 19px 0 16px;
border-radius: $radius-default;
box-shadow: 0 0 3px rgba(0, 0, 0, 0.15);
transform: scale(0.8);
z-index: 9;
transition: all $transition-default cubic-bezier(0.5, 0, 0, 1.25);
}
.option {
line-height: 36px;
padding: 0 30px;
&:hover {
color: $color-default;
color: var(--color-primary);
background: $color-white;
}
&.focus {
background: $color-white;
}
&.selected {
font-weight: 400;
color: $color-default;
color: var(--color-primary);
&.focus {
background: $color-white;
}
}
}
}

View File

@@ -0,0 +1,214 @@
.form-group {
margin-bottom: 20px;
label {
font-weight: 500;
margin-bottom: 9px;
> span {
margin-left: 4px;
color: $color-red;
}
}
}
.form-control {
font-size: 14px;
height: 45px;
padding: 10px 15px;
border-color: $color-gray-lite;
border-radius: $radius-default;
transition: $transition-default;
&:focus {
border-color: $color-default;
border-color: var(--color-primary);
box-shadow: none;
}
}
select {
border: none;
&.arrow-black {
background-position: right 10px center;
}
}
textarea {
&.form-control {
transition: border $transition-default, resize 0ms;
}
}
.form-check {
padding: 0;
label {
font-weight: 400;
color: $color-gray;
}
input[type="checkbox"] {
position: absolute;
left: 0;
margin: 0;
display: none;
&:checked + label,
&:not(:checked) + label {
position: relative;
padding-left: 28px;
cursor: pointer;
display: inline-block;
text-align: left;
}
&:checked + label:before,
&:not(:checked) + label:before {
content: '';
position: absolute;
left: 0;
top: 1px;
width: 18px;
height: 17px;
border: 1px solid $border-color;
border-radius: $radius-default;
transition: $transition-default;
}
&:checked + label:after,
&:not(:checked) + label:after {
position: absolute;
content: '';
top: 5px;
left: 4px;
height: 6px;
width: 10px;
border: 2px solid;
border-color: $color-default;
border-color: var(--color-primary);
/*rtl:begin:ignore*/
border-top: none;
border-right: none;
transform: rotate(-45deg) scale(0);
/*rtl:end:ignore*/
transition: $transition-default;
}
&:not(:checked) + label:after {
opacity: 0;
transform: rotate(-45deg) scale(0) #{'/*rtl:ignore*/'};
}
&:checked + label:after {
opacity: 1;
transform: rotate(-45deg) scale(1) #{'/*rtl:ignore*/'};
}
}
}
.form-radio {
padding: 0;
label {
font-weight: 400;
color: $color-gray;
}
input[type="radio"] {
position: absolute;
left: 0;
margin: 0;
display: none;
&:checked + label,
&:not(:checked) + label {
position: relative;
padding-left: 28px;
cursor: pointer;
display: inline-block;
text-align: left;
}
&:checked + label:before,
&:not(:checked) + label:before {
content: '';
position: absolute;
left: 0;
top: 2px;
width: 17px;
height: 17px;
border: 1px solid $border-color;
border-radius: 50%;
transition: $transition-default;
}
&:checked + label:after,
&:not(:checked) + label:after {
position: absolute;
content: '';
top: 7px;
left: 5px;
height: 7px;
width: 7px;
background: $color-default;
background: var(--color-primary);
border-radius: 50%;
transform: scale(0);
transition: $transition-default;
}
&:not(:checked) + label:after {
opacity: 0;
transform: scale(0);
}
&:checked + label:after {
opacity: 1;
transform: scale(1);
}
}
}
.form-check-label {
> a {
color: $color-default;
color: var(--color-primary);
&:hover {
color: $color-default-hover;
color: var(--color-primary-hover);
}
}
}
.has-error {
.form-control {
border-color: $color-red;
&:focus {
border-color: $color-red;
}
}
}
.error-message {
line-height: 20px;
display: block;
margin: 4px 0 -5px;
color: $color-red;
}
::placeholder {
color: $color-gray-dark !important;
opacity: 1;
}
:-ms-input-placeholder {
color: $color-gray-dark !important;
}
::-ms-input-placeholder {
color: $color-gray-dark !important;
}

View File

@@ -0,0 +1,74 @@
.loading {
position: relative;
&:before {
position: absolute;
content: '';
left: 0;
top: 0;
right: 0;
bottom: 0;
background: $color-white-transparent;
border-radius: $radius-default;
z-index: 2;
}
&:after {
position: absolute;
content: '';
left: 50%;
top: 50%;
height: 30px;
width: 30px;
border-radius: 50%;
border: 3px solid $color-default;
border: 3px solid var(--color-primary);
border-top-color: transparent !important;
z-index: 3;
animation: loader-spin 800ms infinite linear;
}
}
.btn-loading {
color: transparent !important;
&:after {
position: absolute;
content: '';
left: 50%;
top: 50%;
height: 16px;
width: 16px;
border: 2px solid $color-white;
border-radius: 50%;
border-top-color: transparent !important;
animation: loader-spin 800ms infinite linear;
}
}
@keyframes loader-spin {
0% {
transform: translate(-50%, -50%) rotate(0deg);
}
100% {
transform: translate(-50%, -50%) rotate(360deg);
}
}
@keyframes tab-loader {
0% {
left: 0;
width: 20px;
}
50% {
left: calc(100% - 20px);
width: 20px;
}
100% {
left: 0;
width: 20px;
}
}

View File

@@ -0,0 +1,176 @@
.mega-menu {
> .multi-level {
.sub-menu {
> li {
&:hover {
> a {
color: $color-default;
color: var(--color-primary);
}
}
}
}
}
.dropdown {
position: relative;
&:hover {
> .sub-menu {
opacity: 1;
visibility: visible;
}
}
> .sub-menu {
position: absolute;
width: 175px;
padding: 12px 0 10px;
background: $color-white;
border-radius: $radius-default;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.12);
opacity: 0;
visibility: hidden;
z-index: 1;
transition: $transition-default;
> li {
> a {
font-size: 14px;
line-height: 29px;
position: relative;
display: block;
padding: 0 36px 0 19px;
color: $color-gray;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
> i {
font-size: 12px;
position: absolute;
right: 18px;
top: 50%;
transform: translateY(-50%);
}
}
}
}
}
> .fluid-menu {
position: relative;
&:hover {
> .fluid-menu-wrap {
opacity: 1;
visibility: visible;
}
}
> .fluid-menu-wrap {
position: absolute;
width: 720px;
background: $color-white;
background-size: contain;
background-repeat: no-repeat;
background-position: right bottom;
border-radius: $radius-default;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.12);
opacity: 0;
visibility: hidden;
z-index: 1;
transition: $transition-default;
}
}
.fluid-menu-content {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
padding: 20px 10px 0;
.fluid-menu-list {
flex: 0 0 33.33333333333333%;
width: 33.33333333333333%;
margin-bottom: 15px;
padding: 0 15px;
}
.fluid-menu-title {
font-size: 15px;
line-height: 22px;
margin-bottom: 7px;
> a {
color: $color-black;
&:hover {
color: $color-default;
color: var(--color-primary);
}
}
}
.fluid-sub-menu-list {
li {
a {
font-size: 13px;
line-height: 29px;
max-width: 100%;
display: inline-block;
color: $color-gray;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: middle;
&:hover {
color: $color-default;
color: var(--color-primary);
}
}
}
}
}
}
@keyframes menu-in-top {
0% {
transform: translateY(-15px);
}
100% {
transform: translateY(0);
}
}
@keyframes menu-in-right {
0% {
transform: translateX(0);
}
100% {
transform: translateX(15px);
}
}
@keyframes menu-in-bottom {
0% {
transform: translateY(0);
}
100% {
transform: translateY(15px);
}
}
@keyframes menu-in-left {
0% {
transform: translateX(-15px);
}
100% {
transform: translateX(0);
}
}

View File

@@ -0,0 +1,17 @@
.modal {
padding-right: 0 !important;
}
.modal-dialog {
margin: 15px auto;
}
.modal-content {
padding: 0;
border: none;
border-radius: $radius-default;
}
.modal-body {
padding: 0;
}

View File

@@ -0,0 +1,73 @@
.pagination {
margin-right: -13px;
justify-content: flex-end;
.page-item {
&.active {
.page-link {
color: $color-default;
color: var(--color-primary);
}
}
&.disabled {
.page-link {
opacity: 0.5;
}
}
&:first-child,
&:last-child {
.page-link {
padding: 8px 10px;
> i {
font-size: 14px;
}
}
}
.page-link {
font-weight: 500;
line-height: 23px;
margin: 0;
padding: 8px 14px;
color: $color-gray-dark;
background: transparent;
border: none;
border-radius: $radius-default;
&:hover {
color: $color-default;
color: var(--color-primary);
background: transparent;
}
&:focus {
box-shadow: none;
}
}
}
}
.rtl {
.pagination {
.page-item {
&:first-child,
&:last-child {
.page-link {
> i {
transform: rotateY(180deg) #{'/*rtl:ignore*/'};
}
}
}
}
}
}
@media screen and (max-width: $lg) {
.pagination {
margin-right: 0;
justify-content: center;
}
}

View File

@@ -0,0 +1,33 @@
.panel {
margin-bottom: 50px;
border-radius: $radius-default;
&:last-child {
margin-bottom: 0;
}
.panel-header {
display: flex;
padding: 20px 30px;
background: $color-white-lite;
align-items: center;
justify-content: space-between;
border: 1px solid $color-gray-lite;
border-radius: $radius-default $radius-default 0 0;
> a {
color: $color-gray-dark;
&:hover {
color: $color-default;
color: var(--color-primary);
}
}
}
.panel-body {
border: 1px solid $color-gray-lite;
border-top: none;
border-radius: 0 0 $radius-default $radius-default;
}
}

View File

@@ -0,0 +1,24 @@
.custom-scrollbar {
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: $color-gray-lite transparent;
&::-webkit-scrollbar {
width: 8px;
}
&::-webkit-scrollbar-track,
&::-webkit-scrollbar-track-piece {
background: transparent;
}
&::-webkit-scrollbar-thumb,
&::-webkit-scrollbar-thumb:vertical {
border-radius: $radius-default;
background: $color-gray-lite;
&:hover {
background: $border-color;
}
}
}

View File

@@ -0,0 +1,34 @@
.table-bordered {
td {
border-color: $color-gray-lite;
}
}
.table {
thead {
th {
border-bottom: 1px solid $color-gray-lite;
}
}
tbody {
tr {
&:first-child {
td {
padding-top: 30px;
}
}
}
}
th {
font-weight: 500;
padding: 15px 30px;
border-top: none;
}
td {
padding: 20px 30px;
border-color: $color-gray-lite;
}
}

View File

@@ -0,0 +1,131 @@
%nav-link {
font-size: 15px;
line-height: 26px;
position: relative;
padding: 13px 3px;
color: $color-gray-dark;
border: none;
border-radius: 0;
transition: $transition-default;
&:before {
position: absolute;
content: '';
left: 50%;
bottom: 0;
height: 1px;
width: 0;
background: $color-default;
background: var(--color-primary);
transform: translateX(-50%);
transition: 150ms ease-in-out;
}
&:after {
position: absolute;
content: '';
left: 50%;
bottom: -7px;
height: 8px;
width: 15px;
background: $color-default;
background: var(--color-primary);
border-bottom-left-radius: 12px;
border-bottom-right-radius: 12px;
opacity: 0;
transform: translateX(-50%);
transition: 150ms ease-in-out;
z-index: 1;
}
&:hover {
&:before {
width: 40px;
}
}
&.active {
font-weight: 500;
color: $color-default;
color: var(--color-primary);
&:before {
width: 100%;
}
&:after {
opacity: 1;
}
}
&.loading {
pointer-events: none;
&:before {
left: 0;
top: auto;
transform: none;
animation: tab-loader 1.2s ease infinite;
}
&:after {
content: none;
}
}
}
.nav-tabs {
border: none;
.nav-link {
@extend %nav-link;
}
}
.tabs:not(.featured-categories-tabs) {
list-style: none;
margin-bottom: -1px;
.tab-item {
@extend %nav-link;
float: left;
margin-left: 30px;
cursor: pointer;
transition: none;
&:first-child {
margin-left: 0;
}
&.active {
cursor: default;
}
}
}
.tab-content {
.slick-list {
margin: 0 -15px -50px;
padding: 30px 0 50px;
.slick-track {
display: flex;
align-items: stretch;
}
}
.slick-dots {
position: relative;
bottom: auto;
margin-top: 30px;
}
}
@media screen and (max-width: $lg) {
.tab-content {
.slick-list {
margin: 0 -8px -50px;
}
}
}

View File

@@ -0,0 +1,9 @@
@import "~vue-toast-notification/dist/theme-default";
.notices {
.toast {
max-width: 768px;
opacity: 1;
min-height: 3.5em;
}
}

View File

@@ -0,0 +1,54 @@
.cookie-bar-wrap {
position: fixed;
left: 0;
right: 0;
bottom: -200px;
background: #3b4045;
box-shadow: 0 -1px 3px rgba(0, 0, 0, 0.1);
opacity: 0;
visibility: hidden;
transform: translateY(0);
z-index: 50;
transition: 600ms ease;
&.show {
opacity: 1;
visibility: visible;
transform: translateY(-200px);
}
}
.cookie-bar {
display: flex;
flex-wrap: nowrap;
justify-content: center;
align-items: center;
padding: 15px 0;
.cookie-bar-text {
font-size: 14px;
margin-right: 100px;
color: $color-white-dark;
}
.cookie-bar-action {
display: flex;
white-space: nowrap;
.btn-accept {
padding: 5px 24px;
}
}
}
@media screen and (max-width: $lg) {
.cookie-bar {
flex-direction: column;
padding: 16px 0 20px;
.cookie-bar-text {
margin: 0 0 14px 0;
text-align: center;
}
}
}

View File

@@ -0,0 +1,6 @@
@import 'footer/_footer-top',
'footer/_footer-bottom';
.footer {
padding-top: 70px;
}

View File

@@ -0,0 +1,22 @@
@import 'header/_header-left',
'header/_header-search',
'header/_searched-keywords',
'header/_search-suggestion',
'header/_header-right',
'header/_sticky-header';
.header-wrap {
position: relative;
z-index: 8;
}
.header-wrap-inner {
padding: 40px 0;
}
@media screen and (max-width: $lg) {
.header-wrap-inner {
padding: 15px 0;
border-bottom: 1px solid $border-color;
}
}

View File

@@ -0,0 +1,42 @@
.landscape-products-wrap {
margin-top: 45px;
.products-header {
border-bottom: 1px solid $border-color-lite;
}
.section-title {
padding-bottom: 14px;
}
}
.landscape-products {
.arrow-prev.slick-arrow,
.arrow-next.slick-arrow {
top: -40px;
}
.slick-list {
margin: 0 -15px -50px;
padding: 30px 0 50px;
.slick-track {
display: flex;
align-items: stretch;
}
}
.slick-dots {
position: relative;
bottom: auto;
margin-top: 30px;
}
}
@media screen and (max-width: $lg) {
.landscape-products {
.slick-list {
margin: 0 -8px -50px;
}
}
}

View File

@@ -0,0 +1,409 @@
.navigation-inner {
display: flex;
align-items: center;
border: 1px solid $border-color;
border-radius: $radius-default;
.navbar {
padding: 0;
z-index: 2;
.navbar-nav {
margin: 0 30px;
}
}
.navigation-text {
margin-left: auto;
margin-right: 25px;
color: $color-yellow;
}
}
.category-nav {
position: relative;
width: 262px;
min-width: 262px;
display: flex;
padding: 4px 0 4px 4px;
align-items: center;
align-self: stretch;
&.show {
.category-nav-inner {
cursor: default;
}
.category-dropdown-wrap {
display: block;
}
}
.category-nav-inner {
font-weight: 500;
line-height: 24px;
width: 100%;
display: flex;
padding: 14px 35px 13px 30px;
color: $color-white;
flex-grow: 1;
align-items: center;
justify-content: space-between;
background: $color-default;
background: var(--color-primary);
border-radius: $radius-default 0 0 $radius-default;
cursor: pointer;
&:after {
display: none;
}
> i {
font-size: 16px;
}
}
.category-dropdown-wrap {
position: absolute;
left: -1px;
top: calc(100% + 31px);
display: none;
width: 263px;
background: $color-white;
border: 1px solid $border-color;
border-top: none;
border-bottom: none;
border-radius: $radius-default;
z-index: 4;
&:before,
&:after {
position: absolute;
content: '';
left: 0;
height: 1px;
width: 100%;
background: $border-color;
}
&:before {
top: 0;
}
&:after {
bottom: 0;
}
&.show {
display: block;
}
.category-dropdown {
&:before,
&:after {
position: absolute;
content: '';
left: 50%;
border-style: solid;
transform: translateX(-50%);
z-index: 1;
}
&:before {
top: -25px;
border-width: 13px 15px;
border-color: transparent;
border-bottom-color: $border-color;
}
&:after {
top: -23px;
border-width: 12px 14px;
border-color: transparent;
border-bottom-color: $color-white;
}
}
}
}
.vertical-megamenu {
position: static;
padding: 15px 0;
> li {
&.hide {
display: none;
}
&.more-categories {
> .menu-item {
font-weight: 500;
}
}
&:hover {
> .menu-item {
font-weight: 500;
color: $color-default;
color: var(--color-primary);
&:after {
opacity: 1;
visibility: visible;
}
> .menu-item-icon {
color: $color-default;
color: var(--color-primary);
}
> i {
color: $color-default;
color: var(--color-primary);
}
}
}
> .menu-item {
position: relative;
line-height: 46px;
display: block;
padding: 0 50px 0 24px;
color: $color-black;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
transition: none;
&:after {
position: absolute;
content: '';
left: 0;
top: 15px;
height: 15px;
width: 7px;
background: $color-default;
background: var(--color-primary);
opacity: 0;
visibility: hidden;
border-top-right-radius: 12px;
border-bottom-right-radius: 12px;
transition: $transition-default;
}
> .menu-item-icon {
font-size: 16px;
display: inline-flex;
margin: 15px 10px 0 0;
color: $color-gray;
vertical-align: top;
transition: $transition-default;
}
> i {
font-size: 12px;
position: absolute;
top: 17px;
right: 25px;
color: $color-gray;
transition: $transition-default;
}
}
}
&.mega-menu {
.dropdown {
&:hover {
> .sub-menu {
animation: menu-in-left 250ms ease;
}
}
> .sub-menu {
right: -175px;
top: 0;
animation: menu-in-right 250ms ease;
}
}
> .fluid-menu {
&:hover {
> .fluid-menu-wrap {
animation: menu-in-left 250ms ease;
}
}
> .fluid-menu-wrap {
top: 0;
right: -720px;
animation: menu-in-right 250ms ease;
}
}
}
}
.horizontal-megamenu {
position: relative;
flex-wrap: wrap;
&.mega-menu {
> .fluid-menu {
position: relative;
}
}
> .nav-item {
&:hover {
> .nav-link {
font-weight: 500;
color: $color-default;
color: var(--color-primary);
> i {
right: 12px;
color: $color-default;
color: var(--color-primary);
}
}
}
&.multi-level,
&.fluid-menu {
> .nav-link {
padding-right: 35px;
}
}
> .nav-link {
line-height: 36px;
position: relative;
margin-bottom: -1px;
padding: 12px 15px 12px;
color: $color-black;
white-space: nowrap;
transition: none;
&:after {
content: attr(data-text);
font-weight: 500;
display: block;
height: 0;
overflow: hidden;
visibility: hidden;
}
> i {
position: absolute;
top: 50%;
right: 15px;
color: $color-gray;
transform: translateY(-50%) rotate(90deg);
}
}
}
&.mega-menu {
> .dropdown.multi-level {
> .sub-menu {
left: 0;
top: 59px;
}
}
.dropdown {
&:hover {
> .sub-menu {
animation: menu-in-top 250ms ease;
}
}
> .sub-menu {
left: 100%;
top: 0;
animation: menu-in-bottom 250ms ease;
}
}
> .fluid-menu {
&:hover {
> .fluid-menu-wrap {
animation: menu-in-top 250ms ease;
}
}
> .fluid-menu-wrap {
top: 59px;
left: 0;
animation: menu-in-bottom 250ms ease;
}
}
}
}
.rtl {
.horizontal-megamenu {
> .nav-item {
&:hover {
> .nav-link {
> i {
left: 15px #{'/*rtl:ignore*/'};
}
}
}
}
}
}
@media screen and (max-width: 1400px) {
.category-nav {
width: 245px;
min-width: 245px;
.category-dropdown-wrap {
width: 246px;
}
}
}
@media screen and (max-width: 1300px) {
.navigation-inner {
.navigation-text {
display: none;
}
}
}
@media screen and (max-width: 1047px) {
.vertical-megamenu {
&.mega-menu {
> .fluid-menu {
> .fluid-menu-wrap {
right: -696px;
width: 696px;
}
}
}
}
}
@media screen and (max-width: $lg) {
.navigation-wrap {
display: none;
}
.navigation-inner {
.navbar {
.navbar-nav {
margin-left: 0;
}
}
}
.category-nav {
display: none;
.category-dropdown-wrap {
display: none;
}
}
}

View File

@@ -0,0 +1,160 @@
.newsletter-wrap {
.modal-dialog {
width: 850px;
max-width: none;
}
}
.newsletter-inner {
position: relative;
display: flex;
.close {
font-size: 20px;
position: absolute;
top: 16px;
right: 15px;
transition: $transition-default;
&:hover {
color: $color-default;
color: var(--color-primary);
}
}
}
.newsletter-left {
width: 63%;
padding: 41px 50px 37px;
.title {
font-weight: 400;
margin-bottom: 16px;
}
.sub-title {
font-size: 18px;
font-weight: 300;
margin-bottom: 45px;
color: $color-gray;
}
.newsletter-form {
margin-bottom: 26px;
.form-group {
display: flex;
margin-bottom: 0;
.error-message {
display: none;
text-align: left;
}
}
> .error-message {
text-align: left;
}
}
.btn-subscribe {
font-weight: 400;
margin-left: 10px;
padding: 7px 30px;
white-space: nowrap;
> i {
margin-right: 4px;
}
}
.info-text {
font-size: 14px;
margin-bottom: 18px;
color: $color-gray-dark;
a {
color: $color-default;
color: var(--color-primary);
&:hover {
color: $color-default-hover;
color: var(--color-primary-hover);
}
}
}
.newsletter-checkbox {
margin-bottom: 0;
}
}
.newsletter-right {
width: 37%;
background-size: contain;
background-repeat: no-repeat;
background-position: center center;
}
@media screen and (max-width: $lg) {
.newsletter-wrap {
.modal-dialog {
width: 550px;
}
}
.newsletter-left {
width: 100%;
padding: 33px 40px 27px;
text-align: center;
.title {
font-size: 28px;
line-height: 36px;
}
.sub-title {
font-size: 17px;
}
}
.newsletter-right {
display: none;
}
}
@media screen and (max-width: 600px) {
.newsletter-wrap {
.modal-dialog {
width: calc(100% - 30px);
}
}
}
@media screen and (max-width: 500px) {
.newsletter-left {
padding: 28px 30px 22px;
.sub-title {
margin-bottom: 35px;
}
.newsletter-form {
.form-group {
flex-direction: column;
.error-message {
display: block;
}
}
> .error-message {
display: none;
}
}
.btn-subscribe {
margin: 15px 0 0 0;
}
}
}

View File

@@ -0,0 +1,28 @@
@import 'order-summary/_order-summary-top',
'order-summary/_order-summary-middle',
'order-summary/_order-summary-bottom';
.order-summary-wrap {
width: 380px;
min-width: 380px;
padding-left: 15px;
}
.order-summary {
padding: 24px 30px 30px;
background: $color-white-dark;
border-radius: $radius-default;
.price-amount {
font-weight: 500;
}
}
@media screen and (max-width: $lg) {
.order-summary-wrap {
width: 100%;
min-width: 0;
margin-top: 50px;
padding-left: 0;
}
}

View File

@@ -0,0 +1,78 @@
@import 'sidebar-cart/_sidebar-cart-top',
'sidebar-cart/_sidebar-cart-middle',
'sidebar-cart/_sidebar-cart-bottom';
.sidebar-cart-wrap {
position: fixed;
top: 0;
right: -200px;
bottom: 0;
height: 100%;
width: 400px;
background: $color-white;
box-shadow: 2.5px 4.33px 40px 5px rgba(12, 31, 46, 0.1);
opacity: 0;
visibility: hidden;
z-index: 200;
transition: $transition-primary;
&.active {
right: 0;
opacity: 1;
visibility: visible;
}
.empty-message {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
display: flex;
padding: 40px 0;
justify-content: center;
align-items: center;
flex-direction: column;
text-align: center;
svg {
height: 100px;
width: 100px;
margin-bottom: 22px;
g {
fill: $color-default;
fill: var(--color-primary);
}
}
}
}
@media screen and (max-width: 420px) {
.sidebar-cart-wrap {
right: -180px;
width: 360px;
}
}
@media screen and (max-width: 380px) {
.sidebar-cart-wrap {
right: -165px;
width: 330px;
}
}
@media screen and (max-width: 350px) {
.sidebar-cart-wrap {
right: -150px;
width: 300px;
.sidebar-cart-actions {
flex-direction: column;
.btn-view-cart {
margin-bottom: 10px;
}
}
}
}

View File

@@ -0,0 +1,228 @@
.sidebar-menu-wrap {
position: fixed;
left: -150px;
top: 0;
bottom: 0;
width: 270px;
background: $color-white;
box-shadow: 2.5px 4.33px 40px 5px rgba(12, 31, 46, 0.1);
opacity: 0;
visibility: hidden;
z-index: 200;
transition: $transition-primary;
&.active {
left: 0;
opacity: 1;
visibility: visible;
}
.sidebar-menu-header {
display: flex;
padding: 15px 26px;
align-items: center;
justify-content: space-between;
background: $color-default;
background: var(--color-primary);
> h4 {
font-weight: 400;
color: $color-white;
}
.sidebar-menu-close {
display: flex;
cursor: pointer;
opacity: 0.8;
transition: $transition-default;
&:hover {
opacity: 1;
}
> i {
font-size: 18px;
color: $color-white;
}
}
}
.sidebar-menu-tab {
border-bottom: none;
.nav-item {
width: 50%;
}
&.nav-tabs {
.nav-link {
padding: 8px;
color: $color-gray-dark;
text-align: center;
background: $color-white-lite;
border: none;
border-radius: 0;
&.active {
font-weight: 400;
color: $color-black;
background: $color-white;
cursor: default;
}
&:after {
content: none;
}
}
}
}
> .tab-content {
position: absolute;
left: 0;
top: 100px;
right: 0;
bottom: 0;
}
}
.sidebar-menu {
margin: 15px 0;
> li {
cursor: pointer;
&:hover {
> .menu-item {
color: $color-default;
color: var(--color-primary);
> .menu-item-icon {
color: $color-default;
color: var(--color-primary);
}
}
> i {
color: $color-default;
color: var(--color-primary);
}
}
&.active {
.menu-item {
color: $color-default;
color: var(--color-primary);
&:after {
opacity: 1;
visibility: visible;
}
> .menu-item-icon {
color: $color-default;
color: var(--color-primary);
}
}
> i {
transform: rotate(90deg);
}
}
> .menu-item {
&:after {
position: absolute;
content: '';
left: 0;
top: 16px;
height: 15px;
width: 7px;
background: $color-default;
background: var(--color-primary);
opacity: 0;
visibility: hidden;
border-top-right-radius: 12px;
border-bottom-right-radius: 12px;
transition: $transition-default;
}
> .menu-item-icon {
font-size: 16px;
color: $color-gray;
margin: 1px 10px 0 0;
transition: $transition-default;
}
}
> ul {
> li {
> a {
max-width: 160px;
}
> ul {
> li {
> a {
max-width: 155px;
}
}
}
}
}
}
li {
&:hover {
> a,
> i {
color: $color-default;
color: var(--color-primary);
}
}
a {
line-height: 45px;
max-width: 170px;
display: inline-block;
margin-left: 24px;
color: $color-black;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: middle;
}
> i {
font-size: 12px;
position: absolute;
top: 18px;
right: 30px;
color: $color-gray;
float: right;
transition: $transition-default;
}
ul {
display: none;
margin-left: 10px;
}
}
.dropdown {
position: relative;
&.active {
> a {
color: $color-default;
color: var(--color-primary);
}
> i {
color: $color-default;
color: var(--color-primary);
transform: rotate(90deg);
}
}
}
}

View File

@@ -0,0 +1,103 @@
.steps-wrap {
margin-bottom: 40px;
}
.step-tabs {
display: flex;
justify-content: center;
.step-tab {
font-size: 18px;
font-weight: 500;
height: 60px;
width: 350px;
display: flex;
margin: 0 15px;
justify-content: center;
align-items: center;
color: $color-black;
text-align: center;
background: $color-white;
border: 1px solid $color-gray-lite;
border-radius: $radius-default;
white-space: nowrap;
cursor: default;
&.active {
color: $color-white;
background: $color-default;
background: var(--color-primary);
border-color: $color-default;
border-color: var(--color-primary);
.step-tab-text {
.bg-text {
color: $color-white;
}
}
}
}
.step-tab-link {
display: flex;
width: 100%;
color: $color-black;
justify-content: center;
align-self: stretch;
align-items: center;
}
.step-tab-text {
position: relative;
.bg-text {
font-size: 45px;
position: absolute;
top: 50%;
right: -35px;
width: 50px;
color: $color-black;
opacity: 0.15;
transform: translateY(-50%);
}
}
}
@media screen and (max-width: $lg) {
.steps-wrap {
display: none;
}
.step-tabs {
.step-tab {
font-size: 16px;
height: 50px;
width: 250px;
}
.step-tab-text {
.bg-text {
font-size: 36px;
}
}
}
}
@media screen and (max-width: 886px) {
.step-tabs {
align-items: center;
flex-direction: column;
.step-tab {
margin: 8px 15px;
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
}
}
}

View File

@@ -0,0 +1,115 @@
.subscribe-wrap {
margin-top: 50px;
background: $color-default;
background: var(--color-primary);
}
.subscribe {
display: flex;
justify-content: center;
padding: 30px 0 25px;
> .row {
width: 100%;
}
.subscribe-text {
.title,
.sub-title {
display: block;
color: $color-white;
}
.title {
font-size: 30px;
font-weight: 500;
line-height: 30px;
}
.sub-title {
line-height: 24px;
margin-top: 10px;
}
}
.subscribe-field {
display: flex;
align-items: center;
justify-content: flex-end;
.form-group {
position: relative;
margin-bottom: 0;
> input {
height: 50px;
width: 450px;
border: none;
padding: 12px 147px 10px 20px;
}
> .btn-subscribe {
font-weight: 400;
position: absolute;
top: 5px;
right: 5px;
border-radius: 0 $radius-default $radius-default 0;
}
}
}
}
@media screen and (max-width: 1300px) {
.subscribe {
.subscribe-field {
.form-group {
> input {
width: 400px;
}
}
}
}
}
@media screen and (max-width: $xl) {
.subscribe {
.subscribe-field {
.form-group {
> input {
width: 450px;
}
}
}
}
}
@media screen and (max-width: $lg) {
.subscribe {
padding-bottom: 34px;
.subscribe-text {
text-align: center;
}
.subscribe-field {
margin-top: 25px;
justify-content: center;
}
}
}
@media screen and (max-width: 500px) {
.subscribe {
.subscribe-field {
> form {
width: 100%;
}
.form-group {
> input {
width: 100%;
}
}
}
}
}

View File

@@ -0,0 +1,84 @@
.top-nav-wrap {
border-bottom: 1px solid $border-color;
}
.top-nav {
padding: 10px 15px;
.top-nav-left {
> span {
display: block;
}
}
.top-nav-right-list {
display: flex;
justify-content: center;
flex-wrap: wrap;
> li {
border-right: 1px solid $border-color-lite;
display: inline-block;
padding: 0 20px;
&:first-child {
padding-left: 0;
}
&:last-child {
padding-right: 0;
border-right: none;
}
> a {
display: block;
color: $color-black;
&:hover {
color: $color-default;
color: var(--color-primary);
}
> i {
margin-right: 5px;
color: $color-default;
color: var(--color-primary);
}
}
> i {
margin-right: 5px;
color: $color-default;
color: var(--color-primary);
}
}
.nice-select {
padding: 0 20px 0 0;
.list {
left: -22px;
min-width: 150px;
margin-top: 11px;
padding: 14px 0 11px;
}
.option {
padding: 0 20px;
}
}
}
}
@media screen and (max-width: $lg) {
.top-nav {
> .row {
flex-direction: column;
}
.top-nav-left {
margin-bottom: 10px;
text-align: center;
}
}
}

View File

@@ -0,0 +1,47 @@
.footer-bottom {
margin-top: 60px;
padding: 20px 0;
border-top: 1px solid $border-color-lite;
}
.footer-text {
line-height: 26px;
color: $color-gray;
a {
font-weight: 500;
color: $color-default;
color: var(--color-primary);
&:hover {
color: $color-default-hover;
color: var(--color-primary-hover);
}
}
}
.footer-payment {
display: flex;
justify-content: flex-end;
> img {
max-height: 30px;
max-width: 100%;
}
}
@media screen and (max-width: $md) {
.footer-bottom {
margin-top: 50px;
padding-top: 13px;
}
.footer-text {
text-align: center;
}
.footer-payment {
margin-top: 15px;
justify-content: center;
}
}

View File

@@ -0,0 +1,107 @@
.footer-top {
.title {
margin-bottom: 23px;
}
.social-links {
margin: 37px 0 0 -8px;
}
}
.footer-links:not(.footer-tags) {
.list-inline {
li {
display: block;
margin-bottom: 14px;
&:last-child {
margin-bottom: 0;
}
a {
display: inline-block;
max-width: 100%;
color: $color-gray;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: top;
transition: $transition-default;
&:hover {
color: $color-default;
color: var(--color-primary);
}
}
}
}
}
.footer-tags {
.title {
margin-bottom: 28px;
}
.list-inline {
margin-bottom: -7px;
li {
display: inline-block;
max-width: 100%;
margin: 0 4px 7px 0;
&:last-child {
margin-right: 0;
}
a {
line-height: 33px;
display: block;
color: $color-gray;
border: 1px solid $color-gray-lite;
border-radius: $radius-default;
padding: 0 10px;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: top;
&:hover {
color: $color-default;
color: var(--color-primary);
border-color: $color-default-transparent;
border-color: var(--color-primary-transparent);
}
}
}
}
}
@media screen and (max-width: $lg) {
.footer-top {
> .row {
> div:nth-child(4) {
.footer-links {
margin-top: 38px;
}
}
}
}
.footer-tags {
margin-top: 38px;
}
}
@media screen and (max-width: $md) {
.footer-top {
.social-links {
margin: 19px 0 -3px -8px;
}
}
.footer-links {
margin-top: 38px;
}
}

View File

@@ -0,0 +1,110 @@
.header-column-left {
display: flex;
align-self: flex-start;
}
.sidebar-menu-icon-wrap {
display: flex;
height: 60px;
padding-left: 15px;
align-items: center;
justify-content: center;
.sidebar-menu-icon {
display: flex;
height: 30px;
width: 35px;
align-items: flex-start;
justify-content: center;
flex-direction: column;
cursor: pointer;
&:hover {
> span {
width: 20px;
background: $color-default;
background: var(--color-primary);
&:last-child {
width: 20px;
}
}
}
> span {
height: 2px;
width: 16px;
margin-bottom: 4px;
background: $color-black;
transition: $transition-primary;
&:nth-child(2) {
width: 20px;
}
&:last-child {
width: 12px;
margin-bottom: 0;
}
}
}
}
.header-logo {
display: flex;
height: 60px;
width: 266px;
padding: 0 15px;
align-items: center;
overflow: hidden;
img {
max-height: 100%;
max-width: 100%;
}
h3 {
color: $color-default;
color: var(--color-primary);
}
svg {
direction: ltr #{'/*rtl:ignore*/'};
height: 60px;
width: 245px;
#logo_f_bg,
#logo_f_text,
#logo_f_text_inner {
fill: $color-default;
fill: var(--color-primary);
}
}
}
@media screen and (max-width: $xl) {
.header-logo {
width: 200px;
}
}
@media screen and (min-width: 992px) {
.sidebar-menu-icon-wrap {
display: none;
}
}
@media screen and (max-width: $lg) {
.header-logo {
h1 {
font-size: 28px;
}
}
}
@media screen and (max-width: 391px) {
.header-logo {
width: 160px;
padding-left: 5px;
}
}

View File

@@ -0,0 +1,99 @@
.header-column-right {
height: 60px;
padding: 0 15px;
.header-wishlist,
.header-cart {
display: flex;
align-items: center;
> span {
line-height: 28px;
color: $color-black;
white-space: nowrap;
transition: $transition-default;
}
}
.header-wishlist {
&:hover {
> span,
.icon-wrap > i {
color: $color-default;
color: var(--color-primary);
}
}
}
.header-cart {
margin-left: 35px;
cursor: pointer;
&:hover {
> span,
.icon-wrap > i {
color: $color-default;
color: var(--color-primary);
}
}
}
.icon-wrap {
position: relative;
margin-right: 10px;
> i {
font-size: 34px;
line-height: 36px;
color: $color-black;
transition: $transition-default;
}
> .count {
position: absolute;
font-size: 10px;
line-height: 20px;
top: 1px;
right: -6px;
height: 18px;
width: 18px;
color: $color-white;
background: $color-red;
text-align: center;
border-radius: 50%;
}
}
}
@media screen and (max-width: $xl) {
.header-column-right {
.icon-wrap {
margin-right: 6px;
}
.header-wishlist,
.header-cart {
> span {
display: none;
}
}
}
}
@media screen and (max-width: $lg) {
.header-column-right {
.header-wishlist {
display: none;
}
.header-cart {
margin-left: 0;
}
}
}
@media screen and (max-width: 391px) {
.header-column-right {
padding-left: 10px;
}
}

View File

@@ -0,0 +1,175 @@
.header-search-wrap {
position: relative;
min-width: 0;
flex-grow: 1;
padding: 0 40px;
}
.header-search {
position: relative;
.header-search-lg {
position: relative;
display: flex;
border: 1px solid $border-color;
border-radius: $radius-default;
.search-input {
height: 58px;
padding-left: 30px;
border: none;
}
.header-search-right {
display: flex;
align-items: center;
margin-right: 4px;
}
.btn-search {
display: flex;
height: 50px;
width: 50px;
margin-left: 40px;
padding: 0;
align-items: center;
justify-content: center;
border-radius: 0 $radius-default $radius-default 0;
> i {
font-size: 18px;
line-height: 36px;
}
}
}
.nice-select {
display: flex;
align-items: center;
.list {
margin-top: 19px;
}
}
}
.header-search-sm-form {
position: absolute;
left: 15px;
right: 15px;
top: 0;
height: 100%;
background: $color-white;
opacity: 0;
z-index: -1;
transform: scale(0.96);
pointer-events: none;
transition: $transition-default;
&.active {
opacity: 1;
transform: scale(1);
z-index: 1;
pointer-events: auto;
}
> form {
position: relative;
display: flex;
width: 100%;
align-items: center;
> input {
height: 60px;
padding: 10px 50px;
border: none;
}
.btn-close,
.btn-search {
position: absolute;
top: 50%;
display: flex;
height: 50px;
width: 50px;
padding: 15px;
align-items: center;
justify-content: center;
cursor: pointer;
transform: translateY(-50%);
&:hover {
> i {
color: $color-default;
color: var(--color-primary);
}
}
> i {
font-size: 24px;
color: $color-gray;
transition: $transition-default;
}
}
.btn-close {
left: 0;
}
.btn-search {
right: 0;
}
}
}
@media screen and (min-width: 992px) {
.header-search {
.header-search-sm {
display: none;
}
}
.header-search-sm-form {
display: none;
}
}
@media screen and (max-width: $lg) {
.header-search-wrap {
position: static;
display: flex;
flex-grow: 0;
margin-left: auto;
padding: 0 15px;
align-items: center;
}
.header-search {
.header-search-lg {
display: none;
}
.header-search-sm {
&:hover {
> i {
color: $color-default;
color: var(--color-primary);
}
}
> i {
font-size: 34px;
line-height: 36px;
color: $color-black;
cursor: pointer;
transition: $transition-default;
}
}
}
}
@media screen and (max-width: 391px) {
.header-search-wrap {
padding: 0 10px;
}
}

View File

@@ -0,0 +1,191 @@
.search-suggestions {
position: absolute;
left: 41px;
top: 60px;
right: 41px;
background: $color-white;
border-bottom: 2px solid $color-default;
border-bottom: 2px solid var(--color-primary);
border-radius: 0 0 $radius-default $radius-default;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);
.search-suggestions-inner {
max-height: 425px;
background: $color-white;
padding-bottom: 11px;
}
.title {
font-size: 13px;
font-weight: 400;
position: relative;
padding: 6px 20px;
color: $color-gray-dark;
background: $color-white-dark;
&:after {
position: absolute;
content: '';
left: 0;
top: 7px;
height: 15px;
width: 7px;
background: $color-default;
background: var(--color-primary);
border-top-right-radius: 12px;
border-bottom-right-radius: 12px;
}
}
.list-item {
transition: $transition-default;
&.active {
background: #f7f9fa;
}
}
}
.category-suggestion {
.title {
margin-bottom: 14px;
}
& + .product-suggestion {
margin-top: 11px;
}
}
.category-suggestion-list {
.single-item {
font-size: 14px;
line-height: 26px;
display: block;
max-width: 100%;
padding: 0 20px;
color: $color-gray;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: top;
}
}
.product-suggestion {
padding-bottom: 3px;
.title {
margin-bottom: 14px;
}
.more-results {
font-size: 14px;
display: block;
margin: 14px 0 -14px;
padding: 6px 0;
color: $color-gray-dark;
background: $color-white-dark;
text-align: center;
border-top: 1px solid $color-gray-lite;
&:hover {
color: $color-default;
color: var(--color-primary);
}
}
}
.product-suggestion-list {
.list-item {
margin-bottom: 4px;
&:last-child {
margin-bottom: 0;
}
}
.single-item {
position: relative;
display: flex;
padding: 6px 20px;
}
.product-image {
height: 50px;
width: 50px;
min-width: 50px;
border-radius: $radius-default;
overflow: hidden;
.image-placeholder {
height: 35px;
width: 35px;
}
}
.product-info {
min-width: 0;
margin-left: 20px;
flex-grow: 1;
}
.product-info-top {
display: flex;
justify-content: space-between;
}
.product-name {
font-size: 14px;
display: inline-block;
max-width: 100%;
margin-bottom: 3px;
color: $color-gray;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: top;
}
.product-badge {
position: relative;
top: auto;
right: auto;
margin: -2px 0 -1px 15px;
}
em {
font-weight: 500;
font-style: inherit;
color: $color-default;
color: var(--color-primary);
}
}
@media screen and (max-width: $lg) {
.search-suggestions {
top: 76px;
left: 15px;
right: 15px;
display: none;
.search-suggestions-inner {
max-height: 359px;
}
}
.header-wrap-inner {
&.sticky {
.search-suggestions {
top: 71px;
}
}
}
.header-search-sm-form {
&.active {
+ .search-suggestions {
display: block;
}
}
}
}

View File

@@ -0,0 +1,62 @@
.header-search {
.searched-keywords {
display: flex;
width: 95%;
margin: 14px auto -9px;
justify-content: center;
> label {
font-size: 14px;
line-height: 26px;
margin-bottom: 0;
color: $color-default;
color: var(--color-primary);
white-space: nowrap;
}
}
.searched-keywords-list {
height: 26px;
overflow: hidden;
li {
font-size: 14px;
line-height: 26px;
position: relative;
display: inline-block;
padding: 0 15px;
&:after {
position: absolute;
content: '';
left: -1px;
top: 4px;
height: 16px;
width: 1px;
background: $color-gray-dark;
}
&:first-child:after {
height: 0;
width: 0;
}
a {
color: $color-gray-dark;
&:hover {
color: $color-default;
color: var(--color-primary);
}
}
}
}
}
@media screen and (max-width: $lg) {
.header-search {
.searched-keywords {
display: none;
}
}
}

View File

@@ -0,0 +1,36 @@
.header-wrap-inner {
&.sticky {
position: fixed;
left: 0;
top: -200px;
right: 0;
min-width: 320px;
padding: 10px 0;
background: $color-white;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
z-index: 150;
.row {
&.flex-nowrap {
align-items: center;
}
}
.header-logo {
height: 55px;
svg {
height: 55px;
}
}
.searched-keywords {
display: none;
}
}
&.show {
top: 0;
transition: 600ms ease;
}
}

View File

@@ -0,0 +1,25 @@
.order-summary-bottom {
.checkout-terms-and-conditions {
margin: -1px 0 0;
padding-bottom: 17px;
text-align: center;
.error-message {
margin: -2px 0 8px;
}
}
.btn {
width: 100%;
}
}
#paypal-button-container {
.paypal-buttons {
vertical-align: top;
iframe.component-frame {
z-index: 0;
}
}
}

View File

@@ -0,0 +1,39 @@
.order-summary-middle {
padding: 25px 0 8px;
&.loading {
&:before {
left: -15px;
top: 15px;
right: -15px;
bottom: 15px;
}
}
.shipping-methods {
margin: 21px 0 -6px;
> h6 {
margin-bottom: 17px;
}
.error-message {
margin: 0;
padding-bottom: 10px;
}
.form-group {
margin: -1px 0 0;
}
.form-radio {
display: flex;
justify-content: space-between;
label {
padding-right: 20px;
color: $color-black;
}
}
}
}

View File

@@ -0,0 +1,39 @@
.order-summary-top {
.section-title {
padding-bottom: 18px;
border-bottom: 1px solid $border-color-lite;
}
.cart-item {
padding: 25px 0 24px;
border-bottom: 1px solid $color-gray-lite;
li {
display: flex;
margin-bottom: 9px;
justify-content: space-between;
&:last-child {
margin-bottom: 0;
}
}
label {
margin-bottom: 0;
padding-right: 20px;
}
.product-name {
color: $color-black;
&:hover {
color: $color-default;
color: var(--color-primary);
}
}
.product-quantity {
font-weight: 500;
}
}
}

View File

@@ -0,0 +1,28 @@
.sidebar-cart-bottom {
position: absolute;
left: 0;
bottom: 0;
right: 0;
background: $color-white;
.sidebar-cart-subtotal {
display: flex;
margin: 0 30px;
padding: 25px 0;
justify-content: space-between;
border-top: 1px solid $border-color-lite;
> span {
font-weight: 500;
color: $color-default;
color: var(--color-primary);
}
}
.sidebar-cart-actions {
display: flex;
padding: 20px 30px;
background: $color-white-lite;
justify-content: space-between;
}
}

View File

@@ -0,0 +1,84 @@
.sidebar-cart-middle {
position: absolute;
left: 0;
right: 0;
top: 60px;
bottom: 155px;
padding: 0 30px;
&.empty {
bottom: 0;
overflow: visible;
}
}
.sidebar-cart-items-wrap {
padding: 5px 0;
background: $color-white;
}
.sidebar-cart-item {
position: relative;
display: flex;
padding: 25px 0 21px;
border-bottom: 1px solid $color-white-lite;
&:last-child {
border-bottom: none;
}
.product-image {
height: 46px;
width: 46px;
min-width: 46px;
border-radius: $radius-default;
overflow: hidden;
.image-placeholder {
height: 25px;
width: 25px;
}
}
.product-info {
margin: 0 30px 0 20px;
min-width: 0;
.product-name {
font-size: 15px;
font-weight: 400;
line-height: 24px;
display: block;
color: $color-black;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&:hover {
color: $color-default;
color: var(--color-primary);
}
}
.product-quantity {
font-size: 13px;
line-height: 26px;
color: #666666;
}
}
.remove-cart-item {
position: absolute;
top: 16px;
right: -8px;
.btn-remove {
font-size: 14px;
opacity: 0.6;
&:hover {
opacity: 1;
}
}
}
}

View File

@@ -0,0 +1,29 @@
.sidebar-cart-top {
display: flex;
padding: 15px 30px;
align-items: center;
justify-content: space-between;
background: $color-default;
background: var(--color-primary);
.title {
font-weight: 400;
color: $color-white;
}
.sidebar-cart-close {
display: flex;
cursor: pointer;
opacity: 0.8;
transition: $transition-default;
&:hover {
opacity: 1;
}
> i {
font-size: 18px;
color: $color-white;
}
}
}

Some files were not shown because too many files have changed in this diff Show More