diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..3cefc3c --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,4 @@ +include README.rst +include LICENSE + +recursive-include shuup_megastore_theme *.ico *.png *.jinja *.js *.css diff --git a/README.md b/README.md new file mode 100644 index 0000000..ac7e74e --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +Shuup Megastore Theme +===================== + +This is Megastore Theme for Shuup. + +Getting started +--------------- + +For Bash-based shells, this should do: + +```bash +pip install -r requirements.txt +(cd shuup_megastore_theme && npm run build) +cd .. +python -m shuup_workbench migrate +python -m shuup_workbench createsuperuser +python -m shuup_workbench runserver 0.0.0.0:8000 +``` + +For mock data, run + +```bash +python -m shuup_workbench shuup_populate_mock +``` diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b17df5b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +#https://github.com/shuupio/shoop/releases/download/v3.0.0/shuup-3.0.0-py2.py3-none-any.whl +#-e . +#PyYAML==3.11 +#beautifulsoup4==4.4.1 +#https://github.com/shoopio/shoop-carousel/archive/v1.0.1.zip#egg=shuup-carousel==1.0.1 diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..87d92ae --- /dev/null +++ b/setup.cfg @@ -0,0 +1,7 @@ +[bdist_wheel] +universal = 1 + +[flake8] +exclude = .tox,migrations,doc/* +max-line-length = 120 +max-complexity = 10 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..700502b --- /dev/null +++ b/setup.py @@ -0,0 +1,22 @@ +import setuptools + + +try: + import shoop_setup_utils +except ImportError: + shoop_setup_utils = None + + +if __name__ == '__main__': + setuptools.setup( + name="shuup_megastore_theme", + version="1.0.0", + description="Shuup Megastore Theme", + packages=setuptools.find_packages(), + include_package_data=True, + entry_points={"shoop.addon": "shuup_megastore_theme=shuup_megastore_theme"}, + cmdclass=(shoop_setup_utils.COMMANDS if shoop_setup_utils else {}), + install_requires=[ + 'shoop>=3.0,<5', + ], + ) diff --git a/shuup_megastore_theme/.gitignore b/shuup_megastore_theme/.gitignore new file mode 100644 index 0000000..fbdbaa0 --- /dev/null +++ b/shuup_megastore_theme/.gitignore @@ -0,0 +1,3 @@ +node_modules +bower_components +static/shuup_megastore_theme/fonts/ diff --git a/shuup_megastore_theme/VENDOR-LICENSES.md b/shuup_megastore_theme/VENDOR-LICENSES.md new file mode 100644 index 0000000..bac6e68 --- /dev/null +++ b/shuup_megastore_theme/VENDOR-LICENSES.md @@ -0,0 +1,12 @@ +Licenses for Vendored Software +============================== + +Image Lightbox, Responsive and Touch-friendly +--------------------------------------------- + +* Copyright: Osvaldas Valutis, www.osvaldas.info +* License: MIT License +* URL: http://osvaldas.info/image-lightbox-responsive-touch-friendly + +* static_src/less/vendor/imagelightbox.less +* static_src/js/vendor/imagelightbox.js diff --git a/shuup_megastore_theme/__init__.py b/shuup_megastore_theme/__init__.py new file mode 100644 index 0000000..b5bbf14 --- /dev/null +++ b/shuup_megastore_theme/__init__.py @@ -0,0 +1,41 @@ +from django.conf import settings +from django.utils.encoding import force_text +from django.utils.translation import ugettext_lazy as _ + +from shoop.apps import AppConfig +from shoop.xtheme import Theme + + +class ShuupMegastoreTheme(Theme): + identifier = __name__ + name = _("Shuup Megastore Theme") + author = "Yuki Miyagi" + template_dir = "shuup_megastore_theme/" + + def get_view(self, view_name): + from . import views + return getattr(views, view_name, None) + + def _format_cms_links(self, **query_kwargs): + if "shuup.simple_cms" not in settings.INSTALLED_APPS: + return + from shoop.simple_cms.models import Page + for page in Page.objects.visible().filter(**query_kwargs): + yield {"url": "/%s" % page.url, "text": force_text(page)} + + def get_cms_navigation_links(self): + return self._format_cms_links(visible_in_menu=True) + + +class ShuupMegastoreThemeAppConfig(AppConfig): + name = __name__ + verbose_name = ShuupMegastoreTheme.name + label = __name__ + provides = { + "xtheme": __name__ + ":ShuupMegastoreTheme", + "xtheme_plugin": [ + "shuup_megastore_theme.plugins:ProductHighlightPlugin", + ] + } + +default_app_config = __name__ + ".ShuupMegastoreThemeAppConfig" diff --git a/shuup_megastore_theme/bower.json b/shuup_megastore_theme/bower.json new file mode 100644 index 0000000..a729cfc --- /dev/null +++ b/shuup_megastore_theme/bower.json @@ -0,0 +1,27 @@ +{ + "name": "shuup-megastore-theme", + "version": "1.0.0", + "homepage": "-", + "authors": [ + "Yuki Miyagi ", + "Janne Tammi " + ], + "description": "Shuup Megastore Theme", + "license": "-", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ], + "dependencies": { + "jquery": "~2.1.4", + "owl.carousel": "~2.0.0-beta.3", + "bootstrap-select": "~1.7.5", + "jquery-easing": "*", + "jquery-touchswipe": "~1.6.12", + "bootstrap": "~3.3.5", + "font-awesome": "~4.5.0" + } +} diff --git a/shuup_megastore_theme/gulpfile.js b/shuup_megastore_theme/gulpfile.js new file mode 100644 index 0000000..39a9d63 --- /dev/null +++ b/shuup_megastore_theme/gulpfile.js @@ -0,0 +1,60 @@ +var gulp = require("gulp"); +var less = require("gulp-less"); +var concat = require("gulp-concat"); +var uglify = require("gulp-uglify"); +var plumber = require("gulp-plumber"); +var minifycss = require("gulp-cssnano"); +var gutil = require("gulp-util"); +var PRODUCTION = gutil.env.production || process.env.NODE_ENV == "production"; + +gulp.task("less", function() { + return gulp.src([ + "bower_components/owl.carousel/dist/assets/owl.carousel.min.css", + "static_src/less/style.less" + ]) + .pipe(plumber({})) + .pipe(less().on("error", function(err) { + console.log(err.message); + this.emit("end"); + })) + .pipe(concat("style.css")) + .pipe((PRODUCTION ? minifycss() : gutil.noop())) + .pipe(gulp.dest("static/shuup_megastore_theme/css/")); +}); + +gulp.task("less:watch", ["less"], function() { + gulp.watch(["static_src/less/**/*.less"], ["less"]); +}); + +gulp.task("js", function() { + return gulp.src([ + "bower_components/jquery/dist/jquery.min.js", + "bower_components/bootstrap/dist/js/bootstrap.js", + "bower_components/bootstrap-select/dist/js/bootstrap-select.min.js", + "bower_components/jquery-easing/jquery.easing.min.js", + "bower_components/owl.carousel/dist/owl.carousel.min.js", + "bower_components/jquery-touchswipe/jquery.touchSwipe.min.js", + "static_src/js/vendor/image-lightbox.js", + "static_src/js/custom/custom.js", + "static_src/js/custom/checkout.js" + ]) + .pipe(plumber({})) + .pipe(concat("shuup_megastore_theme.js")) + .pipe((PRODUCTION ? uglify() : gutil.noop())) + .pipe(gulp.dest("static/shuup_megastore_theme/js/")); +}); + +gulp.task("js:watch", ["js"], function() { + gulp.watch(["static_src/js/**/*.js"], ["js"]); +}); + +gulp.task("copy_fonts", function() { + return gulp.src([ + "bower_components/bootstrap/fonts/*", + "bower_components/font-awesome/fonts/*" + ]).pipe(gulp.dest("static/shuup_megastore_theme/fonts/")); +}); + +gulp.task("default", ["js", "less", "copy_fonts"]); + +gulp.task("watch", ["js:watch", "less:watch"]); diff --git a/shuup_megastore_theme/package.json b/shuup_megastore_theme/package.json new file mode 100644 index 0000000..67846f7 --- /dev/null +++ b/shuup_megastore_theme/package.json @@ -0,0 +1,23 @@ +{ + "name": "shuup-megastore-theme", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "build": "npm i && bower --config.interactive=false i && gulp" + }, + "author": "", + "license": "Proprietary", + "private": true, + "dependencies": { + "bower": "^1.6.5", + "gulp": "^3.9.0", + "gulp-autoprefixer": "^3.0.1", + "gulp-concat": "^2.6.0", + "gulp-cssnano": "^2.0.0", + "gulp-less": "^3.0.3", + "gulp-plumber": "^1.0.1", + "gulp-uglify": "^1.4.0", + "gulp-util": "^3.0.6" + } +} diff --git a/shuup_megastore_theme/plugins.py b/shuup_megastore_theme/plugins.py new file mode 100644 index 0000000..a298229 --- /dev/null +++ b/shuup_megastore_theme/plugins.py @@ -0,0 +1,37 @@ +from django import forms +from shoop.front.template_helpers.general import get_newest_products, get_best_selling_products, get_random_products +from shoop.xtheme.plugins._base import TemplatedPlugin # TODO: FIX THIS. +from django.utils.translation import ugettext_lazy as _ + + +class ProductHighlightPlugin(TemplatedPlugin): + identifier = "shuup_megastore_theme.product_highlight" + name = _("Shuup Megastore Theme Product Highlights") + template_name = "shuup_megastore_theme/highlight_plugin.jinja" + fields = [ + ("title", forms.CharField(required=False, initial="")), + ("type", forms.ChoiceField(choices=[ + ("newest", "Newest"), + ("best_selling", "Best Selling"), + ("random", "Random"), + ], initial="newest")), + ("count", forms.IntegerField(min_value=1, initial=8)) + ] + + def get_context_data(self, context): + type = self.config.get("type", "newest") + count = self.config.get("count", 8) + if type == "newest": + products = get_newest_products(context, count) + elif type == "best_selling": + products = get_best_selling_products(context, count) + elif type == "random": + products = get_random_products(context, count) + else: + products = [] + + return { + "request": context["request"], + "title": self.config.get("title"), + "products": products + } diff --git a/shuup_megastore_theme/static/.gitignore b/shuup_megastore_theme/static/.gitignore new file mode 100644 index 0000000..36db336 --- /dev/null +++ b/shuup_megastore_theme/static/.gitignore @@ -0,0 +1,2 @@ +*.css +*.js diff --git a/shuup_megastore_theme/static_src/js/custom/checkout.js b/shuup_megastore_theme/static_src/js/custom/checkout.js new file mode 100644 index 0000000..4542c1e --- /dev/null +++ b/shuup_megastore_theme/static_src/js/custom/checkout.js @@ -0,0 +1,41 @@ +window.activateCheckoutAddressCopy = function(){ + var shouldCopyFields = false; + + var toggleFieldDisability = function($field) { + $field.toggleClass("disabled", shouldCopyFields); + }; + + var toggleCopyFields = function() { + shouldCopyFields = $("#same_as_billing").is(":checked"); + $("#shipping :input").each(function(){ + $(this).attr("readonly", shouldCopyFields); + toggleFieldDisability($(this)); + }); + + $("#id_shipping-country").attr("readonly", shouldCopyFields); + + $target = $("#id_shipping-country").next(".btn-group").children("button"); + toggleFieldDisability($target); + if(shouldCopyFields) { + $("#billing :input").change(); + } + }; + + var copyFieldValue = function() { + if(!shouldCopyFields) + return; + var targetName = $(this).attr("id").split("-")[1]; + var $target = $("#id_shipping-"+targetName); + $target.val($(this).val()); + }; + + var copySelectValue = function() { + $("#id_shipping-country").selectpicker("val", $(this).val()); + }; + + $("#id_shipping-country").attr("readonly", true); + toggleCopyFields(); + $(document).on("input change", "#billing :input", copyFieldValue); + $("#same_as_billing").on("change", toggleCopyFields); + $("#id_billing-country").on("change", copySelectValue); +}; diff --git a/shuup_megastore_theme/static_src/js/custom/custom.js b/shuup_megastore_theme/static_src/js/custom/custom.js new file mode 100644 index 0000000..7e3dac3 --- /dev/null +++ b/shuup_megastore_theme/static_src/js/custom/custom.js @@ -0,0 +1,238 @@ +window.showPreview = function showPreview(productId) { + var modalSelector = "#product-" + productId + "-modal"; + var $productModal = $(modalSelector); + if ($productModal.length) { + $productModal.modal("show"); + return; + } + + // make sure modals disappear and are not "cached" + $(document).on("hidden.bs.modal", modalSelector, function() { + $(modalSelector).remove(); + }); + + $.ajax({ + url: "/xtheme/product_preview", + method: "GET", + data: { + id: productId + }, + success: function(data) { + $("body").append(data); + $(modalSelector).modal("show"); + updatePrice(); + $(".selectpicker").selectpicker(); + } + }); +}; + +function updatePrice() { + var $quantity = $("#product-quantity"); + if ($quantity.length === 0 || !$quantity.is(":valid")) { + return; + } + + var data = { + id: $("input[name=product_id]").val(), + quantity: $quantity.val() + }; + var $simpleVariationSelect = $("#product-variations"); + if ($simpleVariationSelect.length > 0) { + // Smells like a simple variation; use the selected child's ID instead. + data.id = $simpleVariationSelect.val(); + } else { + // See if we have variable variation select boxes; if we do, add those. + $("select.variable-variation").serializeArray().forEach(function(obj) { + data[obj.name] = obj.value; + }); + } + jQuery.ajax({url: "/xtheme/product_price", dataType: "html", data: data}).done(function(responseText) { + var $content = jQuery("
").append(jQuery.parseHTML(responseText)).find("#product-price-div"); + jQuery("#product-price-div").replaceWith($content); + if ($content.find("#no-price").length > 0) { + $("#add-to-cart-button").prop("disabled", true); + } else { + $("#add-to-cart-button").not(".not-orderable").prop("disabled", false); + } + }); +}; + +window.moveToPage = function moveToPage(pageNumber) { + var pager = $("ul.pager"); + + // Prevent double clicking when ajax is loading + if (pager.prop("disabled")) { + return false; + } + pager.prop("disabled", true); + + if (typeof (pageNumber) !== "number") { + pageNumber = parseInt(pageNumber); + if (isNaN(pageNumber)) { + return; + } + } + window.PAGE_NUMBER = pageNumber; + + reloadProducts(); +}; + +var reloadProducts = function() { + var filterString = "?sort=" + $("#id_sort").val() + "&page=" + window.PAGE_NUMBER; + $("#ajax_content").load(location.pathname + filterString); + $("html, body").animate({scrollTop: $("#ajax_content").offset().top-50}, "slow"); +}; + +var slowScrollToTop = function() { + $("html, body").animate({ scrollTop: 0 }, "slow"); +}; + +$(function() { + + $(document).on("change", ".variable-variation, #product-variations, #product-quantity", updatePrice); + + updatePrice(); + + $("#scroll_top").click(function(e) { + e.preventDefault(); + slowScrollToTop(); + }); + + $('.support-nav .dropdown-menu').click(function(e) { + e.stopPropagation(); + }); + + // Set up frontpage carusel + $('.frontpage-carousel').carousel({ + interval: 6000, + cycle: true, + pause: false + }); + + // Set up owl carousel for product list with 5 items + $(".owl-carousel.five").owlCarousel({ + margin: 30, + nav: true, + navText: [ + '', + '' + ], + responsiveClass: true, + responsive: { + 0: { // breakpoint from 0 up + items : 2, + }, + 640: { // breakpoint from 640 up + items : 3, + }, + 992: { // breakpoint from 992 up + items : 5, + } + } + }); + + // Set up owl carousel for product list with 3 items + $(".owl-carousel.four").owlCarousel({ + margin: 30, + nav: true, + navText: [ + '', + '' + ], + responsiveClass: true, + responsive: { + 0: { // breakpoint from 0 up + items : 2, + }, + 640: { // breakpoint from 640 up + items : 2, + }, + 992: { // breakpoint from 992 up + items : 4, + } + } + }); + + //add tooltip triggers to data-attribute html with data-toggle=tooltip + $('[data-toggle="tooltip"]').tooltip({ + delay: { "show": 750, "hide": 100 } + }); + + // Add slideDown animation to all bootstrap dropdowns + $('.dropdown').on('show.bs.dropdown', function() { + $(this).find('.dropdown-menu').first().stop(true, true).slideDown(200, "easeInSine"); + }); + + // Add slideUp animation to all bootstrap dropdowns + $('.dropdown').on('hide.bs.dropdown', function() { + $(this).find('.dropdown-menu').first().stop(true, true).slideUp(300, "easeOutSine"); + }); + + $('.selectpicker select').selectpicker(); + + //Enable carousel slide change by swiping + $(".carousel-inner").swipe({ + // Swipe handler for swiping left + swipeLeft: function() { + $('.frontpage-carousel').carousel('next'); + }, + // Swipe handler for swiping left + swipeRight: function() { + $('.frontpage-carousel').carousel('prev'); + }, + fallbackToMouseEvents: false, + }); + + $(window).scroll(function() { + if ($(window).scrollTop() > 400) { + $("#scroll_top").addClass('visible'); + } else { + $("#scroll_top").removeClass('visible'); + } + }); + + $(".category-link").hover(toggleMegaMenu); + + // Adds a toggle icon to offcanvas nav's each element that have child elements + $(".offcanvas-nav > ul li").each(function addOffcanvasToggler() { + if ($(this).find("ul").length) { + $(this).children("a").after(""); + } + }); + + // Toggle navigation items when toggle icon is clicked + $(".offcanvas-nav ul li .toggle-icon").on("click", function toggleNavItems(e) { + e.stopPropagation(); + $(this).parent().toggleClass("open"); + }); + + /* Close offcanvas navigation if user clicks outside the nav element + when the navigation is open */ + $(document).on("click", function(e) { + if (isOffcanvasNavOpen() && !$(e.target).closest(".offcanvas-nav").length) { + setOffcanvasNavState(false); + } + }); + + // Toggle the visibility of offcanvas navigation when the menu icon is clicked + $("#nav-toggler").click(function(e) { + e.stopPropagation(); + setOffcanvasNavState(!isOffcanvasNavOpen()); + }); + +}); + +function toggleMegaMenu() { + var elem = $(this).find("div.mega-menu-container"); + const posY = $(this).position().top - 70; + elem.css("top", posY); + elem.toggleClass("open"); +} + +function isOffcanvasNavOpen() { + return document.body.classList.contains("offcanvas-open"); +} + +function setOffcanvasNavState(flag) { + document.body.classList.toggle("offcanvas-open", !!flag); +} diff --git a/shuup_megastore_theme/static_src/js/vendor/image-lightbox.js b/shuup_megastore_theme/static_src/js/vendor/image-lightbox.js new file mode 100644 index 0000000..ba1a677 --- /dev/null +++ b/shuup_megastore_theme/static_src/js/vendor/image-lightbox.js @@ -0,0 +1,380 @@ +/* + By Osvaldas Valutis, www.osvaldas.info + Available for use under the MIT License +*/ + +;( function( $, window, document, undefined ) +{ + 'use strict'; + + var cssTransitionSupport = function() + { + var s = document.body || document.documentElement, s = s.style; + if( s.WebkitTransition == '' ) return '-webkit-'; + if( s.MozTransition == '' ) return '-moz-'; + if( s.OTransition == '' ) return '-o-'; + if( s.transition == '' ) return ''; + return false; + }, + + isCssTransitionSupport = cssTransitionSupport() === false ? false : true, + + cssTransitionTranslateX = function( element, positionX, speed ) + { + var options = {}, prefix = cssTransitionSupport(); + options[ prefix + 'transform' ] = 'translateX(' + positionX + ')'; + options[ prefix + 'transition' ] = prefix + 'transform ' + speed + 's linear'; + element.css( options ); + }, + + hasTouch = ( 'ontouchstart' in window ), + hasPointers = window.navigator.pointerEnabled || window.navigator.msPointerEnabled, + wasTouched = function( event ) + { + if( hasTouch ) + return true; + + if( !hasPointers || typeof event === 'undefined' || typeof event.pointerType === 'undefined' ) + return false; + + if( typeof event.MSPOINTER_TYPE_MOUSE !== 'undefined' ) + { + if( event.MSPOINTER_TYPE_MOUSE != event.pointerType ) + return true; + } + else + if( event.pointerType != 'mouse' ) + return true; + + return false; + }; + + $.fn.imageLightbox = function( options ) + { + var options = $.extend( + { + selector: 'id="imagelightbox"', + allowedTypes: 'png|jpg|jpeg|gif', + animationSpeed: 250, + preloadNext: true, + enableKeyboard: true, + quitOnEnd: false, + quitOnImgClick: false, + quitOnDocClick: true, + onStart: false, + onEnd: false, + onLoadStart: false, + onLoadEnd: false + }, + options ), + + targets = $([]), + target = $(), + image = $(), + imageWidth = 0, + imageHeight = 0, + swipeDiff = 0, + inProgress = false, + + isTargetValid = function( element ) + { + return $( element ).prop( 'tagName' ).toLowerCase() == 'a' && ( new RegExp( '\.(' + options.allowedTypes + ')$', 'i' ) ).test( $( element ).attr( 'href' ) ); + }, + + setImage = function() + { + if( !image.length ) return true; + + var screenWidth = $( window ).width() * 0.8, + screenHeight = $( window ).height() * 0.9, + tmpImage = new Image(); + + tmpImage.src = image.attr( 'src' ); + tmpImage.onload = function() + { + imageWidth = tmpImage.width; + imageHeight = tmpImage.height; + + if( imageWidth > screenWidth || imageHeight > screenHeight ) + { + var ratio = imageWidth / imageHeight > screenWidth / screenHeight ? imageWidth / screenWidth : imageHeight / screenHeight; + imageWidth /= ratio; + imageHeight /= ratio; + } + + image.css( + { + 'width': imageWidth + 'px', + 'height': imageHeight + 'px', + 'top': ( $( window ).height() - imageHeight ) / 2 + 'px', + 'left': ( $( window ).width() - imageWidth ) / 2 + 'px' + }); + }; + }, + + loadImage = function( direction ) + { + if( inProgress ) return false; + + direction = typeof direction === 'undefined' ? false : direction == 'left' ? 1 : -1; + + if( image.length ) + { + if( direction !== false && ( targets.length < 2 || ( options.quitOnEnd === true && ( ( direction === -1 && targets.index( target ) == 0 ) || ( direction === 1 && targets.index( target ) == targets.length - 1 ) ) ) ) ) + { + quitLightbox(); + return false; + } + var params = { 'opacity': 0 }; + if( isCssTransitionSupport ) cssTransitionTranslateX( image, ( 100 * direction ) - swipeDiff + 'px', options.animationSpeed / 1000 ); + else params.left = parseInt( image.css( 'left' ) ) + 100 * direction + 'px'; + image.animate( params, options.animationSpeed, function(){ removeImage(); }); + swipeDiff = 0; + } + + inProgress = true; + if( options.onLoadStart !== false ) options.onLoadStart(); + + setTimeout( function() + { + image = $( '' ) + .attr( 'src', target.attr( 'href' ) ) + .load( function() + { + image.appendTo( 'body' ); + setImage(); + + var params = { 'opacity': 1 }; + + image.css( 'opacity', 0 ); + if( isCssTransitionSupport ) + { + cssTransitionTranslateX( image, -100 * direction + 'px', 0 ); + setTimeout( function(){ cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 ) }, 50 ); + } + else + { + var imagePosLeft = parseInt( image.css( 'left' ) ); + params.left = imagePosLeft + 'px'; + image.css( 'left', imagePosLeft - 100 * direction + 'px' ); + } + + image.animate( params, options.animationSpeed, function() + { + inProgress = false; + if( options.onLoadEnd !== false ) options.onLoadEnd(); + }); + if( options.preloadNext ) + { + var nextTarget = targets.eq( targets.index( target ) + 1 ); + if( !nextTarget.length ) nextTarget = targets.eq( 0 ); + $( '' ).attr( 'src', nextTarget.attr( 'href' ) ).load(); + } + }) + .error( function() + { + if( options.onLoadEnd !== false ) options.onLoadEnd(); + }) + + var swipeStart = 0, + swipeEnd = 0, + imagePosLeft = 0; + + image.on( hasPointers ? 'pointerup MSPointerUp' : 'click', function( e ) + { + e.preventDefault(); + if( options.quitOnImgClick ) + { + quitLightbox(); + return false; + } + if( wasTouched( e.originalEvent ) ) return true; + var posX = ( e.pageX || e.originalEvent.pageX ) - e.target.offsetLeft; + target = targets.eq( targets.index( target ) - ( imageWidth / 2 > posX ? 1 : -1 ) ); + if( !target.length ) target = targets.eq( imageWidth / 2 > posX ? targets.length : 0 ); + loadImage( imageWidth / 2 > posX ? 'left' : 'right' ); + }) + .on( 'touchstart pointerdown MSPointerDown', function( e ) + { + if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true; + if( isCssTransitionSupport ) imagePosLeft = parseInt( image.css( 'left' ) ); + swipeStart = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX; + }) + .on( 'touchmove pointermove MSPointerMove', function( e ) + { + if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true; + e.preventDefault(); + swipeEnd = e.originalEvent.pageX || e.originalEvent.touches[ 0 ].pageX; + swipeDiff = swipeStart - swipeEnd; + if( isCssTransitionSupport ) cssTransitionTranslateX( image, -swipeDiff + 'px', 0 ); + else image.css( 'left', imagePosLeft - swipeDiff + 'px' ); + }) + .on( 'touchend touchcancel pointerup pointercancel MSPointerUp MSPointerCancel', function( e ) + { + if( !wasTouched( e.originalEvent ) || options.quitOnImgClick ) return true; + if( Math.abs( swipeDiff ) > 50 ) + { + target = targets.eq( targets.index( target ) - ( swipeDiff < 0 ? 1 : -1 ) ); + if( !target.length ) target = targets.eq( swipeDiff < 0 ? targets.length : 0 ); + loadImage( swipeDiff > 0 ? 'right' : 'left' ); + } + else + { + if( isCssTransitionSupport ) cssTransitionTranslateX( image, 0 + 'px', options.animationSpeed / 1000 ); + else image.animate({ 'left': imagePosLeft + 'px' }, options.animationSpeed / 2 ); + } + }); + + }, options.animationSpeed + 100 ); + }, + + removeImage = function() + { + if( !image.length ) return false; + image.remove(); + image = $(); + }, + + quitLightbox = function() + { + if( !image.length ) return false; + image.animate({ 'opacity': 0 }, options.animationSpeed, function() + { + removeImage(); + inProgress = false; + if( options.onEnd !== false ) options.onEnd(); + }); + }; + + $( window ).on( 'resize', setImage ); + + if( options.quitOnDocClick ) + { + $( document ).on( hasTouch ? 'touchend' : 'click', function( e ) + { + if( image.length && !$( e.target ).is( image ) ) quitLightbox(); + }) + } + + if( options.enableKeyboard ) + { + $( document ).on( 'keyup', function( e ) + { + if( !image.length ) return true; + e.preventDefault(); + if( e.keyCode == 27 ) quitLightbox(); + if( e.keyCode == 37 || e.keyCode == 39 ) + { + target = targets.eq( targets.index( target ) - ( e.keyCode == 37 ? 1 : -1 ) ); + if( !target.length ) target = targets.eq( e.keyCode == 37 ? targets.length : 0 ); + loadImage( e.keyCode == 37 ? 'left' : 'right' ); + } + }); + } + + $( document ).on( 'click', this.selector, function( e ) + { + if( !isTargetValid( this ) ) return true; + e.preventDefault(); + if( inProgress ) return false; + inProgress = false; + if( options.onStart !== false ) options.onStart(); + target = $( this ); + loadImage(); + }); + + this.each( function() + { + if( !isTargetValid( this ) ) return true; + targets = targets.add( $( this ) ); + }); + + this.switchImageLightbox = function( index ) + { + var tmpTarget = targets.eq( index ); + if( tmpTarget.length ) + { + var currentIndex = targets.index( target ); + target = tmpTarget; + loadImage( index < currentIndex ? 'left' : 'right' ); + } + return this; + }; + + this.quitImageLightbox = function() + { + quitLightbox(); + return this; + }; + + return this; + }; +})( jQuery, window, document ); + +// ACTIVITY INDICATOR +var activityIndicatorOn = function() +{ + $( '
' ).appendTo( 'body' ); +}, +activityIndicatorOff = function() +{ + $( '#imagelightbox-loading' ).remove(); +}, + +// OVERLAY +overlayOn = function() +{ + $( '
' ).appendTo( 'body' ); +}, +overlayOff = function() +{ + $( '#imagelightbox-overlay' ).remove(); +}, + + +// CLOSE BUTTON +closeButtonOn = function( instance ) +{ + $( '' ).appendTo( 'body' ).on( 'click touchend', function(){ $( this ).remove(); instance.quitImageLightbox(); return false; }); +}, +closeButtonOff = function() +{ + $( '#imagelightbox-close' ).remove(); +}, + +// ARROWS +arrowsOn = function( instance, selector ) +{ + var $arrows = $( '' ); + + $arrows.appendTo( 'body' ); + + $arrows.on( 'click touchend', function( e ) + { + e.preventDefault(); + + var $this = $( this ), + $target = $( selector + '[href="' + $( '#imagelightbox' ).attr( 'src' ) + '"]' ), + index = $target.index( selector ); + + if( $this.hasClass( 'imagelightbox-arrow-left' ) ) + { + index = index - 1; + if( !$( selector ).eq( index ).length ) + index = $( selector ).length; + } + else + { + index = index + 1; + if( !$( selector ).eq( index ).length ) + index = 0; + } + + instance.switchImageLightbox( index ); + return false; + }); +}, +arrowsOff = function() +{ + $( '.imagelightbox-arrow' ).remove(); +}; diff --git a/shuup_megastore_theme/static_src/less/shuup_megastore_theme/add-to-cart-indicator.less b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/add-to-cart-indicator.less new file mode 100644 index 0000000..5b75616 --- /dev/null +++ b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/add-to-cart-indicator.less @@ -0,0 +1,75 @@ +// Popup indication for products being added to basket +.cart-indicator { + color: #fff; + position: fixed; + text-align: center; + display: block; + width: auto; + padding: 30px; + width: 290px; + top: 50px; + right: 50px; + opacity: 0; + visibility: hidden; + z-index: -1; + border-radius: 2px; + + // Hide this for now + + // &:before { + // opacity: 0; + // visibility: hidden; + // content: ""; + // position: absolute; + // top: -10px; + // right: 10px; + // border-bottom: 10px solid transparent; + // border-left: 10px solid transparent; + // border-right: 10px solid transparent; + // } + + .success-msg, .error-msg { + opacity: 0; + .scale(0.5); + .transition(all 0.2s); + i { + font-size: 3em; + } + p { + font-size: 1.2em; + font-weight: 400; + } + } + + &.in { + z-index: 3000; + opacity: 1; + visibility: visible; + .transition(all 0.3s); + &:before { + .transition(all 0.3s); + opacity: 1; + visibility: visible; + } + &.success { + background-color: fade(@brand-primary, 80%); + &:before { border-bottom-color: fade(@brand-success, 80%); } + .success-msg { + display: block; + .scale(1); + opacity: 1; + } + .error-msg { display: none; } + } + &.error { + background-color: fade(@brand-danger, 80%); + &:before { border-bottom-color: fade(@brand-danger, 80%); } + .error-msg { + display: block; + .scale(1); + opacity: 1; + } + .success-msg { display: none; } + } + } +} diff --git a/shuup_megastore_theme/static_src/less/shuup_megastore_theme/base.less b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/base.less new file mode 100644 index 0000000..4ff8667 --- /dev/null +++ b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/base.less @@ -0,0 +1,292 @@ +body { + @media (max-width: @screen-sm-max) { + overflow-x: hidden; + + &.offcanvas-open { + overflow-y: hidden; + } + } +} + +.content-wrap { + transition: transform .4s; + position: relative; + body.index & { + padding-bottom: 0; + } + + @media (max-width: (@mobile-nav-breakpoint - 1)) { + body.offcanvas-open & { + transform: translate3d(-@mobile-nav-width, 0, 0); + } + } +} + + +.page-content { + padding-top: 20px; + padding-bottom: 60px; + main.index & { + padding-top: 0; + } +} + +.page-header { + border: 0; + text-transform: uppercase; +} + +.btn { + font-family: @font-headline; + text-transform: uppercase; +} + +.bootstrap-select { + .btn { + font-family: @font-primary; + text-transform: none; + } +} + +.panel, .well { + hr { + border-color: @border-color; + } +} + +.scroll-top-btn { + position: fixed; + bottom: 15px; + right: 15px; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + background: rgba(0,0,0,0.3); + color: #fff; + visibility: hidden; + opacity: 0; + transition: all 0.3s; + + &.visible { + visibility: visible; + opacity: 1; + } +} + +.title-bar { + width: 100%; + text-transform: uppercase; + margin-top: 15px; + margin-bottom: 25px; + + &.light { + padding: 0px 15px; + text-align: center; + position: relative; + &:before { + content: ""; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: @brand-light; + z-index: 0; + } + h1, h2, h3, h4 { + position: relative; + display: inline-block; + z-index: 1; + padding: 2px 15px; + margin: 0; + background: #fff; + vertical-align: middle; + } + } + + &.dark { + padding: 10px 15px; + background: @brand-dark; + color: #fff; + h1, h2, h3, h4 { + margin: 0; + } + } +} + +.frontpage-carousel { + margin-bottom: 50px; +} + +section.image-banner { + background: @brand-primary; + padding: 10px 0px; + text-align: center; + background-position: 50%; + background-repeat: no-repeat; + background-size: cover; + + h1 { + margin: 0 20px; + text-transform: uppercase; + color: #fff; + text-align: left; + + @media (min-width: @screen-md-min) { + font-size: 4rem; + } + } +} + +.breadcrumb { + padding: 0; + margin-top: 15px; + margin-bottom: 20px; + list-style: none; + color: @text-muted; + .small(); + + > li { + display: inline-block; + + a { + color: @text-muted; + } + + + li:before { + content: "@{breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space + padding: 0 5px; + } + } +} + +.panel { + box-shadow: none; + border: 0; + &.panel-white-bg { + background: #fff; + } + .panel-heading { + text-transform: uppercase; + } + .panel-title { + font-size: @font-size-h3; + } +} + +.message-wrapper { + position: fixed; + bottom: 10px; + left: 0; + right: 0; +} + +.main-menu { + background-color: @brand-light; + border-bottom: 4px solid @brand-primary; + padding: 15px 10px 15px 25px; + a { + font-size: 20px; + color:#000; + text-transform: uppercase; + font-weight:bold; + } +} +#main-menu { + background-color: @brand-light; + ul { + padding:0; + margin: 0; + list-style-type: none; + + } + > ul { + li { + a { + padding: 10px 0 10px 25px; + font-size: 14px; + color: #000; + display: block; + &:hover { + background-color: @brand-primary; + text-decoration: none; + color: #fff; + } + } + &.category-link { + .mega-menu-container { + + position: absolute; + left: 95%; + top: 0; + background: #fff; + visibility: hidden; + //overflow: hidden; + overflow-y: auto; + opacity: 0; + border: 1px solid #ddd; + box-shadow: 0px 0px 7px rgba(0, 0, 0, 0.1); + transition: all .3s; + padding: 0px; + margin-bottom: 15px; + max-height: 80vh; + + width: 800px; + + z-index: 1000; + &.open { + visibility: visible; + opacity: 1; + } + ul { + .make-sm-column(4); + .make-md-column(3); + } + a { + padding-left:0; + color: @brand-dark; + &:hover { + background-color: transparent; + text-decoration: underline; + } + &.megamenu-main-link { + color: @brand-primary; + padding: 10px 0 10px 15px; + background-color: @brand-lighter; + border-bottom: 1px solid @brand-primary; + text-transform: uppercase; + font-size: 16px; + font-weight: bold; + + //&:hover { + // background-color: transparent; + //} + } + } + } + } + } + } +} + +.table.table-prices { + width: 50%; + tr { + td { + white-space: nowrap; + border: none; + .original-price { + font-size: 13px; + text-decoration: line-through; + } + .discounted-price { + font-size: 17px; + } + } + } +} + +.discount-color { + color: @discount-color; +} diff --git a/shuup_megastore_theme/static_src/less/shuup_megastore_theme/carousels.less b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/carousels.less new file mode 100644 index 0000000..356d33f --- /dev/null +++ b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/carousels.less @@ -0,0 +1,79 @@ +.carousel { + + .carousel-control { + background-image: none !important; + background-repeat: no-repeat !important; + position: absolute; + top: 50%; + margin-top: -18px; + text-align: center; + width: 36px; + height: 36px; + line-height: 36px; + color: @gray-dark; + text-shadow: none; + opacity: 0.6; + + @media (max-width: @screen-xs-max) { + display: none; + } + + &.left { + left: 15px; + } + &.right { + right: 15px; + } + span { + font-size: 2rem; + line-height: 36px; + margin-top: 0; + top: 0; + } + } +} + +.carousel-section { + margin-top: 30px; + margin-bottom: 15px; + padding: 0px 30px; + + .carousel-section { + margin-top: 50px; + } + .owl-stage-outer { + z-index: 2; + } + .owl-nav { + position: absolute; + top: 50%; + left: 0; + right: 0; + transform: translate(0, -50%); + font-size: 4rem; + color: @text-muted; + + .owl-prev, .owl-next { + &.disabled { + cursor: default; + cursor: not-allowed; + opacity: 0.5; + } + } + + .owl-prev { + margin-left: -30px; + float: left; + } + .owl-next { + float: right; + margin-right: -30px; + } + } + .owl-dots { + display: none; + } +} + +.carousel-indicators { + bottom: 0 !important; +} diff --git a/shuup_megastore_theme/static_src/less/shuup_megastore_theme/category.less b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/category.less new file mode 100644 index 0000000..8643bd1 --- /dev/null +++ b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/category.less @@ -0,0 +1,17 @@ +.product-list { + .category-header { + margin-bottom: 40px; + } + .products { + margin-bottom: 40px; + } + .pager { + margin-top: -20px; + margin-bottom: 60px; + .page-counter { + display: inline-block; + padding-top: 5px; + margin: 0px 15px; + } + } +} diff --git a/shuup_megastore_theme/static_src/less/shuup_megastore_theme/checkout.less b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/checkout.less new file mode 100644 index 0000000..9e77977 --- /dev/null +++ b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/checkout.less @@ -0,0 +1,102 @@ +.checkout-provider-wrap { + position: relative; + min-height: 80px; + padding: 15px 0; + + & + .checkout-provider-wrap { + border-top: 1px solid @border-color; + padding-top: 30px; + margin-top: 15px; + + @media (min-width: @screen-sm-min) { + .checkout-service-provider { + top: 30px; + } + } + } +} + +.checkout-service-provider { + margin-bottom: 25px; + + @media (min-width: @screen-sm-min) { + position: absolute; + left: 15px; + top: 15px; + width: 200px; + margin: 0; + } + + h3 { + margin: 0; + font-size: @font-size-base; + font-weight: bold; + text-transform: uppercase; + color: @text-muted; + } + + img { + max-height: 50px; + max-width: 200px; + width: auto; + height: auto; + } +} + +.checkout-method-radio { + margin: 0; + + @media (min-width: @screen-sm-min) { + padding-left: 250px; + } + + & + .checkout-method-radio { + margin-top: 20px; + } + + label { + padding-left: 30px; + display: table; + width: 100%; + + input { + margin-left: -30px !important; + } + + .logo { + display: table-cell; + padding-right: 15px; + vertical-align: top; + width: 75px; + + img { + max-height: 30px; + max-width: 60px; + height: auto; + width: auto; + } + } + + .label-text { + display: table-cell; + vertical-align: top; + font-size: 1.6rem; + + .price { + font-weight: bold; + color: @brand-primary; + + &:before { + content: " - "; + color: @text-color; + font-weight: normal; + } + } + + .description { + font-size: 1.3rem; + color: @text-muted; + } + } + } +} diff --git a/shuup_megastore_theme/static_src/less/shuup_megastore_theme/footer.less b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/footer.less new file mode 100644 index 0000000..f0b22aa --- /dev/null +++ b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/footer.less @@ -0,0 +1,56 @@ +footer { + h2 { + text-transform: uppercase; + font-size: 18px; + } + ul { + padding: 0; + list-style: none; + .small(); + } + + @media (max-width: 480px) { + .col-xxs-12 { + width: 100%; + } + } + + .footer-top { + padding: 30px 0px; + background: @footer-bg; + + a { + color: @text-color; + &:hover, &:focus { + text-decoration: underline; + color: @brand-primary; + } + } + + h4 { + text-transform: uppercase; + margin-top: 20px; + margin-bottom: 8px; + border-bottom: 1px solid lighten(@gray, 40%); + padding-bottom: 5px; + } + + img { + height: 191px; + max-width: 210px; + } + } + + .footer-bottom { + padding: 15px 0px; + background: @brand-dark; + text-align: center; + + ul { + margin: 0; + li { + color: rgba(255,255,255,0.75); + } + } + } +} diff --git a/shuup_megastore_theme/static_src/less/shuup_megastore_theme/inputs.less b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/inputs.less new file mode 100644 index 0000000..4de829f --- /dev/null +++ b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/inputs.less @@ -0,0 +1,162 @@ +.form-group { + position: relative; + + &.required, + &.required-field { + label.control-label:after { + content: "*"; + color: @brand-danger; + font-weight: bold; + margin-left: 3px; + } + } +} + +.custom-checkbox { + margin-bottom: 10px; + + &.required.has-error { + input[type="checkbox"] + label:before { + border: 1px solid @brand-danger; + } + } + + input[type="checkbox"] { + display: none; + } + + input[type="checkbox"] + label { + position: relative; + cursor: pointer; + font-weight: normal; + margin: 0; + // Disable text select on label + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + &:hover { + &:before { + background-color: fade(@brand-primary, 15%); + border-color: fade(@brand-primary, 70%); + } + } + + &:before { + content: ""; + display: inline-block; + background: #fff; + width: 17px; + height: 17px; + border: 1px solid darken(@border-color, 10%); + vertical-align: top; + margin-right: 7px; + border-radius: 2px; + .transition(all 0.1s); + } + + &:after { + opacity: 0; + content: "\f00c"; + font-family: FontAwesome; + display: block; + color: #fff; + position: absolute; + left: 2px; + top: -1px; + font-size: 1.4rem; + .scale(0.4); + .transition(all 0.25s cubic-bezier(0.75,0.1,0.1,0.5)) + } + } + + input[type="checkbox"]:checked + label { + + &:before { + background: @brand-primary; + border-color: @brand-primary !important; + } + + &:after { + opacity: 1; + .scale(1); + } + } +} + +.custom-radio { + margin-bottom: 10px; + + &.required.has-error { + input[type="radio"] + label:before { + border: 1px solid @brand-danger; + } + } + + input[type="radio"] { + display: none; + } + + input[type="radio"] + label { + position: relative; + cursor: pointer; + font-weight: normal; + margin: 0; + // Disable text select on label + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + &:hover { + &:before { + background-color: fade(@brand-primary, 15%); + border-color: fade(@brand-primary, 70%); + } + } + + &:before { + content: ""; + display: inline-block; + background: #fff; + width: 17px; + height: 17px; + border: 1px solid darken(@border-color, 10%); + vertical-align: top; + margin-right: 7px; + border-radius: 50%; + .transition(all 0.1s); + } + + &:after { + opacity: 0; + content: ""; + display: block; + width: 9px; + height: 9px; + border-radius: 50%; + background-color: @brand-primary; + position: absolute; + left: 4px; + top: 4px; + .scale(0.4); + .transition(all 0.25s cubic-bezier(0.75,0.1,0.1,0.5)) + } + } + + input[type="radio"]:checked + label { + &:before { + border-color: @brand-primary !important; + background: #fff; + } + &:after { + opacity: 1; + .scale(1); + } + } +} diff --git a/shuup_megastore_theme/static_src/less/shuup_megastore_theme/modals.less b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/modals.less new file mode 100644 index 0000000..d7ad47e --- /dev/null +++ b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/modals.less @@ -0,0 +1,78 @@ +button.close-modal { + position: absolute; + top: -15px; + right: 10px; + background: @brand-dark; + color: #fff; + height: 40px; + width: 40px; + line-height: 40px; + text-align: center; + display: block; + z-index: 2; + border-radius: 50%; + border: 0; +} + +.modal-dialog { + margin: 30px auto; + width: @modal-sm; + padding: 0px 25px; + @media (min-width: @screen-md-min) { + width: @modal-md; + margin: 50px auto; + } +} + +.modal-content { + box-shadow: none; +} + +.product-preview-modal { + .modal-body { + padding: 45px 30px; + } + img { + width: 100%; + height: auto; + } + .preview-image { + .make-sm-column(5); + .make-md-column(6); + @media (min-width: @screen-sm-min) { + padding-right: 30px; + } + } + .labels { + position: absolute; + z-index: 2; + left: 15px; + top: 0; + .sale-badge { + display: inline-block; + width: 65px; + height: 65px; + line-height: 65px; + margin-right: 7px; + background: @brand-danger; + border-radius: 50%; + color: #fff; + text-align: center; + font-size: 2.1rem; + font-family: @font-headline; + } + } + .preview-details { + .make-sm-column(7); + .make-md-column(6); + @media (min-width: @screen-sm-min) { + padding-left: 30px; + } + .amount .input-group { + width: 1%; + input { + width: 130px; + } + } + } +} diff --git a/shuup_megastore_theme/static_src/less/shuup_megastore_theme/navigation.less b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/navigation.less new file mode 100644 index 0000000..5a0f87c --- /dev/null +++ b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/navigation.less @@ -0,0 +1,686 @@ +.nav-toggler { + display: inline-block; + position: relative; + height: @top-nav-height; + width: @top-nav-height; + border: 0; + padding: 0; + background: @mobile-nav-toggler-bg; + outline: 0; + + @media (min-width: @mobile-nav-breakpoint) { + display: none; + } + + &:hover { + .hamburger, + .hamburger:before, + .hamburger:after { + background: @mobile-nav-toggler-active-color; + } + } + + body.offcanvas-open & { + background: @mobile-nav-toggler-active-bg; + } + + body.offcanvas-open & .hamburger { + background-color: transparent; + + &:before, &:after { + top: 0; + background: @mobile-nav-toggler-active-color; + } + + &:before { + transform: rotate(-45deg); + } + + &:after { + transform: rotate(45deg); + } + } + + .hamburger, + .hamburger:before, + .hamburger:after { + background: @mobile-nav-toggler-color; + border-radius: 1px; + width: 22px; + height: 3px; + position: absolute; + display: block; + content: ""; + cursor: pointer; + transition: all .4s; + left: 50%; + top: 50%; + margin-top: -2px; + margin-left: -11px; + } + + .hamburger:before { + top: -6px; + margin-top: 0; + } + + .hamburger:after { + top: 6px; + margin-top: 0; + } +} +.site-nav { + margin-bottom: 0; + border: 0; + .top-nav { + .clearfix; + background: @brand-primary; + display: block; + + ul { + margin: 0; + padding: 0; + } + + .nav-left { + margin-left: -15px; + float: left; + } + + .nav-right { + margin-right: -15px; + float: right; + } + + .container > ul > li { + display: inline-block; + list-style: none; + position: relative; + > a, + > button { + border: 0; + background: none; + padding: 8px 15px; + display: inline-block; + color: #fff; + transition: color 0.1s, background 0.1s; + font-size: 1.2rem; + text-transform: uppercase; + &:hover, + &:focus { + color: @brand-primary; + text-decoration: none; + i.menu-icon { + color: @brand-primary; + } + } + } + } + + i.menu-icon { + font-size: 1.4rem; + margin-right: 5px; + color: #fff; + } + + i.dropdown-icon { + margin-left: 5px; + } + + .dropdown-menu { + left: auto; + right: 0; + margin-top: 7px; + padding: 8px 0; + box-shadow: 0 2px 4px 0 rgba(0,0,0,0.10); + min-width: 200px; + &.login { + min-width: 250px; + form { + padding: 5px 15px; + } + } + &:before, + &:after { + content: ""; + position: absolute; + bottom: 100%; + display: block; + left: auto; + right: 12px; + } + &:before { + border-bottom: 6px solid #fff; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + z-index: 2; + } + &:after { + border-bottom: 7px solid @border-color; + border-left: 7px solid transparent; + border-right: 7px solid transparent; + margin-left: 0; + margin-right: -1px; + z-index: 1; + } + li { + font-size: 1.3rem; + a { + padding: 8px 15px; + } + i { + font-size: 1.4rem; + margin-right: 5px; + } + } + } + + .cart { + .dropdown-menu { + left: auto; + right: 0; + padding: 15px; + @media (min-width: @screen-sm-min) { + white-space: nowrap; + } + &:before, + &:after { + left: auto; + right: 12px; + } + &:after { + margin-left: 0; + margin-right: -1px; + } + td { + font-size: 1.3rem; + } + } + .btn-view-cart { + padding: 10px 15px; + text-transform: uppercase; + i { + margin-left: 5px; + } + } + .empty-cart { + font-size: 1.6rem; + display: block; + padding: 5px; + i { + margin-right: 5px; + font-size: 1.8rem; + } + } + } + } + + .support-nav { + + .toggle-main-nav { + margin-left: -15px; + width: 60px; + height: 60px; + background: none; + float: left; + border: none; + position: relative; + + @media (min-width: @screen-sm-min) { + display: none; + } + &:hover { + .icon-bars:after, + .icon-bars:before { + background: @brand-primary; + } + + &.collapsed { + .icon-bars, + .icon-bars:after, + .icon-bars:before { + background: @brand-primary; + } + } + } + + .icon-bars, + .icon-bars:after, + .icon-bars:before { + display: block; + position: absolute; + width: 24px; + height: 3px; + border-radius: 0; + left: 50%; + margin-left: -12px; + background: @text-color; + .transition(all 0.15s); + } + + &.collapsed { + .icon-bars { + background-color: @text-color; + &:before { + top: -6px; + .rotate(0deg); + } + &:after { + top: 6px; + .rotate(0deg); + } + } + } + + .icon-bars { + background-color: transparent; + &:before { + content: ""; + top: 0; + .rotate(45deg); + + } + &:after { + content: ""; + top: 0; + .rotate(-45deg); + } + } + } + + .logo { + display: inline-block; + + a { + display: block; + padding: 15px 0px; + } + + img { + height: 25px; + width: auto; + @media (min-width: @screen-sm-min) { + height: 46px; + } + } + } + + ul.navbar-right { + float: right; + margin: 0; + + @media (max-width: @screen-xs-max) { + > li { + float: left; + position: static; + } + .dropdown-menu { + position: absolute; + left: 0; + width: 100%; + min-width: none; + } + } + + li .dropdown-toggle { + padding: 20px 15px; + border: 0; + background: 0; + position: relative; + &:hover { + color: @brand-primary; + &:before { + height: 5px; + } + i { + color: @brand-primary; + } + } + i { + margin-right: 5px; + font-size: 1.7rem; + .transition(color 0.25s); + @media (max-width: @screen-xs-max) { + margin: 0 5px; + } + } + } + + .open { + .dropdown-toggle { + background: @brand-light; + &:before { + height: 5px; + } + i { + color: @brand-primary; + } + } + } + + .search-form { + padding: 20px 0px 16px 0px; + width: 100%; + + @media (min-width: @screen-sm-min) { + width: 220px; + } + @media (min-width: @screen-md-min) { + width: 300px; + } + + .form-group { + margin: 0; + } + + .form-control { + background: none; + border: 1px solid transparent; + border-bottom: 2px solid @brand-light; + margin-right: -5px; + .box-shadow(none); + color: @brand-dark; + .transition(all 0.25s); + &:focus, + &:active { + border-bottom-color: @brand-primary; + } + } + + .btn { + color: @brand-dark; + font-size: 1.7rem; + background: none; + border: 1px solid transparent; + padding: 4px 12px 3px; + position: absolute; + top: 0; + right: 0; + outline: 0; + .transition(color 0.25s); + &:hover, &:focus { + color: @brand-primary; + } + &:active { + .box-shadow(none); + background: none; + } + } + + } + } + + .dropdown-menu { + border-radius: 0; + border: 2px; + background-color: #ffffff; + padding: 15px 0; + .box-shadow(1px 1px 1px 1px rgba(0,0,0,0.1)); + + &.cart, + &.wishlist, + &.login { + min-width: 300px; + padding: 15px; + } + + &.login { + i { + margin: 0 5px; + } + a { + display: block; + text-align: center; + padding: 15px 0 0; + } + } + + .text-warning { + padding: 10px 0; + display: block; + text-align: center; + } + } + + } + + .main-nav { + background: @brand-light; + font-family: @font-headline; + + @media (min-width: @screen-sm-min) { + .navbar-nav { + margin: 0 auto; + display: flex; + width: 100%; + } + + .navbar-nav > li { + flex: 1 auto; + float: none; + } + + .navbar-nav > li > a { + text-align: left; + } + } + + ul.navbar-nav > li > a { + padding: 7px 15px; + color: @brand-dark; + .transition(background-color 0.25s); + &:hover { + background: darken(@brand-light, 10%); + } + &:focus { + background: @brand-light; + } + } + + ul.navbar-nav > li.open > a { + background: darken(@brand-light, 10%); + &:focus { + background: darken(@brand-light, 10%); + } + } + + ul.navbar-nav > li .dropdown-menu { + background: @brand-light; + border: none; + border-radius: 0; + .box-shadow(none); + + > li { + > a { + font-size: 1.2rem; + color: @text-color; + padding: 5px 0 5px 10px; + &:hover, + &:focus, + &:active { + text-decoration: none; + background: darken(@brand-light, 20%); + z-index: 100; + } + } + } + } + + ul.navbar-right { + @media (max-width: @screen-xs-max) { + border-top: 1px solid rgba(255,255,255, 0.2); + padding-top: 10px; + } + } + + } +} + +.offcanvas-nav { + display: none; + position: fixed; + top: 0; + bottom: 0; + right: 0; + z-index: @zindex-navbar; + width: @mobile-nav-width; + background: @mobile-nav-bg; + overflow-y: auto; + transition: transform .4s; + transform: translate3d(100%, 0, 0); + + @media (max-width: (@mobile-nav-breakpoint - 1)) { + display: block; + } + + body.offcanvas-open & { + transform: translate3d(0, 0, 0); + } + + ul { + padding: 0; + margin: 0; + list-style: none; + display: none; + } + + > ul { + margin-bottom: 15px; + display: block; + } + + li { + display: block; + background: @mobile-nav-link-level-1-bg; + position: relative; + + &.mega-menu-title { + display: none; + } + + &.level-2 { + background: @mobile-nav-link-level-2-bg; + + > .toggle-icon { + background: @mobile-nav-link-level-2-bg; + + &:after { + background: @mobile-nav-link-level-3-bg; + } + } + } + + &.level-3 { + background: @mobile-nav-link-level-3-bg; + } + + &.is-parent { + > a { + padding-right: 44px; + } + } + + &.open { + > ul { + display: block; + } + + > .toggle-icon:before { + content: "\2014"; //em dash + } + } + + a { + display: block; + padding: 12px 15px; + color: @mobile-nav-link-color; + transition: all .15s; + font-size: 1.4rem; + + &.current { + color: @mobile-nav-link-active-color; + background-color: @mobile-nav-link-active-bg; + } + } + + .toggle-icon { + position: absolute; + top: 0; + right: 0; + width: 44px; + height: 44px; + line-height: 44px; + text-align: center; + background: @mobile-nav-link-level-1-bg; + cursor: pointer; + z-index: 2; + display: block; + + &:before { + content: "+"; + font-family: FontAwesome; + z-index: 2; + color: @mobile-nav-link-color; + position: relative; + display: block; + } + + &:after { + content: ""; + position: absolute; + left: 7px; + top: 7px; + bottom: 7px; + right: 7px; + border-radius: @border-radius-base; + background: @mobile-nav-link-level-2-bg; + z-index: 1; + } + } + } + + ul li > ul li a { + padding-left: (15px + 15); + } + + ul ul li > ul li a { + padding-left: (15px + 30); + } +} + +.offcanvas-search { + padding: 15px 15px 20px 15px; + margin-bottom: 15px; + + &-wrap { + position: relative; + } + + &-input { + width: 100%; + background: transparent; + color: @mobile-search-text-color; + border: 0; + border-bottom: 2px solid @mobile-search-border-color; + padding: 6px 30px 6px 6px; + font-size: 1.4rem; + transition: border-color .2s; + + &:focus, &:active { + border-bottom-color: @mobile-search-border-focus-color; + } + } + + &-submit { + position: absolute; + right: 5px; + top: 5px; + background: transparent; + color: @mobile-search-icon-color; + padding: 0; + + &:hover, &:focus { + color: @mobile-search-icon-hover-color; + } + } +} diff --git a/shuup_megastore_theme/static_src/less/shuup_megastore_theme/product-card.less b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/product-card.less new file mode 100644 index 0000000..6280897 --- /dev/null +++ b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/product-card.less @@ -0,0 +1,111 @@ +.product-card { + text-align: center; + position: relative; + + &:hover, &:focus { + .overlay { + @media (min-width: @screen-sm-min) { + display: block; + } + } + } + + &.category-view, + &.search-view { + margin-bottom: 40px; + .make-xs-column(6); + .make-sm-column(4); + .make-md-column(3); + @media (max-width: @screen-xs-max) { + &:nth-child(2n+1) { + clear: both; + } + } + @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) { + &:nth-child(3n+1) { + clear: both; + } + } + @media (min-width: @screen-md-min) and (max-width: @screen-md-max) { + &:nth-child(4n+1) { + clear: both; + } + } + @media (min-width: @screen-lg-min) { + width: 20%; + padding: 0px 15px; + float: left; + &:nth-child(5n+1) { + clear: both; + } + } + } + + .overlay { + z-index: 2; + display: none; + position: absolute; + top: 125px; + left: 15px; + right: 15px; + text-align: center; + .btn-preview { + background: @brand-dark; + color: #fff; + text-transform: uppercase; + font-size: 1.2rem; + font-weight: bold; + font-family: @font-primary; + i { + margin-right: 3px; + font-size: 1.4rem; + } + &:hover, &:focus { + background: lighten(@brand-dark, 7%); + color: #fff; + } + } + } + + a { + display: block; + color: @text-color; + &:hover, &:focus { + color: @brand-primary; + } + } + + .labels { + position: absolute; + z-index: 2; + left: 15px; + top: 0; + .sale-badge { + display: inline-block; + width: 40px; + height: 40px; + line-height: 40px; + margin-right: 7px; + background: @brand-danger; + border-radius: 50%; + color: #fff; + text-align: center; + font-size: 1.2rem; + font-family: @font-headline; + } + } + + .product-image { + padding: 0px 15px; + position: relative; + img { + width: 100%; + height: auto; + } + } + + .detail-wrap { + padding: 7px 15px; + font-size: 1.3rem; + } +} diff --git a/shuup_megastore_theme/static_src/less/shuup_megastore_theme/product-page.less b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/product-page.less new file mode 100644 index 0000000..741a88c --- /dev/null +++ b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/product-page.less @@ -0,0 +1,73 @@ +.product-page { + .product-image { + margin-bottom: 25px; + @media (min-width: @screen-md-min) { + padding-right: 30px; + } + } + .product-info { + margin-bottom: 25px; + @media (min-width: @screen-md-min) { + padding-left: 30px; + } + .boxes { + list-style: none; + padding: 0; + li { + background: @brand-light; + padding: 10px; + display: inline-table; + margin: 0px 5px 5px 0px; + i, span { + display: table-cell; + vertical-align: middle; + } + i { + font-size: 1.6em; + padding-right: 15px; + color: @gray-light; + } + } + } + .icons { + font-size: 1.3em; + i { + color: @gray-light; + &:hover { + color: @brand-primary; + } + } + i.fa-circle { + color: @brand-light; + } + } + } + .product-tabs { + margin-top: 30px; + i { + margin-right: 5px; + } + .tab-content { + padding-top: 25px; + } + } +} + +#product-price-section { + .amount .input-group { + width: 1%; + input { + width: 130px; + } + } + .price h2 { + margin-bottom: 0; + } + .btn-add-to-cart { + margin-top: 15px; + } +} + +form.add-to-basket { + margin-bottom: 15px; +} diff --git a/shuup_megastore_theme/static_src/less/shuup_megastore_theme/social-media-links.less b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/social-media-links.less new file mode 100644 index 0000000..d2bdc3b --- /dev/null +++ b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/social-media-links.less @@ -0,0 +1,16 @@ +section.social-media-lift { + padding: 40px 0px; + background: @brand-lightblue; + ul { + list-style: none; + } + li { + margin: 10px; + display: inline-block; + + } + + a { + color: @text-color; + } +} diff --git a/shuup_megastore_theme/static_src/less/shuup_megastore_theme/variables.less b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/variables.less new file mode 100644 index 0000000..6da7dbd --- /dev/null +++ b/shuup_megastore_theme/static_src/less/shuup_megastore_theme/variables.less @@ -0,0 +1,910 @@ + +// When screen size is smaller than this, enable mobile navigation +@mobile-nav-breakpoint: @screen-md; + +@font-headline: 'Oswald', sans-serif; +@font-primary: 'Open Sans', sans-serif; +@font-serif: Georgia, "Times New Roman", Times, serif; + +// Brand colors +@brand-light: #e6e7e8; +@brand-lighter: #f1f2f2; +@brand-dark: #58595b; +@brand-lightblue: #24dfff; + +@border-color: #cdcdcd; + +@footer-bg: #D9D9D9; +@top-nav-bg: #222; +@top-nav-height: 32px; +// +// Bootstrap variables customized for Shuup Megastore Theme +// -------------------------------------------------- + + +//== Colors +// +//## Gray and brand colors for use across Bootstrap. + +@gray-base: #000; +@gray-darker: lighten(@gray-base, 13.5%); // #222 +@gray-dark: lighten(@gray-base, 20%); // #333 +@gray: lighten(@gray-base, 33.5%); // #555 +@gray-light: lighten(@gray-base, 46.7%); // #777 +@gray-lighter: lighten(@gray-base, 93.5%); // #eee + +@discount-color: #b12704; + +@brand-primary: #21bffd; // beauty pink +@brand-success: #51A825; // bs original #5cb85c +@brand-info: #5254F6; // bs original #5bc0de +@brand-warning: #FEAA61; // bs original #f0ad4e +@brand-danger: #F76057; // bs original #d9534f + + +@mobile-nav-width: 270px; +@mobile-nav-bg: @top-nav-bg; +@mobile-nav-link-color: rgba(255,255,255,0.75); +@mobile-nav-link-level-1-bg: @mobile-nav-bg; +@mobile-nav-link-level-2-bg: lighten(@mobile-nav-link-level-1-bg, 5%); +@mobile-nav-link-level-3-bg: lighten(@mobile-nav-link-level-2-bg, 6%); +@mobile-nav-link-active-color: @link-color; +@mobile-nav-link-active-bg: transparent; + +@mobile-nav-toggler-color: #fff; +@mobile-nav-toggler-bg: transparent; +@mobile-nav-toggler-active-color: @link-color; +@mobile-nav-toggler-active-bg: transparent; + +@mobile-search-border-color: rgba(255, 255, 255, 0.7); +@mobile-search-border-focus-color: @brand-primary; +@mobile-search-text-color: #fff; +@mobile-search-icon-color: #fff; +@mobile-search-icon-hover-color: @brand-primary; + +//== Scaffolding +// +//## Settings for some of the most global styles. + +//** Background color for ``. +@body-bg: #fff; +//** Global text color on ``. +@text-color: @brand-dark; + +//** Global textual link color. +@link-color: @brand-primary; +//** Link hover color set via `darken()` function. +@link-hover-color: darken(@link-color, 15%); +//** Link hover decoration. +@link-hover-decoration: underline; + + +//== Typography +// +//## Font, line-height, and color for body text, headings, and more. + +@font-family-sans-serif: @font-primary; +@font-family-serif: @font-serif; +//** Default monospace fonts for ``, ``, and `
`.
+@font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace;
+@font-family-base:        @font-family-sans-serif;
+
+@font-size-base:          14px;
+@font-size-large:         floor((@font-size-base * 1.15)); // ~16px
+@font-size-small:         ceil((@font-size-base * 0.85)); // ~12px
+
+@font-size-h1:            floor((@font-size-base * 2.3)); // ~32px
+@font-size-h2:            floor((@font-size-base * 2)); // ~28px
+@font-size-h3:            ceil((@font-size-base * 1.5)); // ~21px
+@font-size-h4:            floor((@font-size-base * 1.15)); // ~16px
+@font-size-h5:            @font-size-base;
+@font-size-h6:            ceil((@font-size-base * 0.85)); // ~12px
+
+//** Unit-less `line-height` for use in components like buttons.
+@line-height-base:        1.428571429; // 20/14
+//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
+@line-height-computed:    floor((@font-size-base * @line-height-base)); // ~20px
+
+//** By default, this inherits from the ``.
+@headings-font-family:    @font-headline;
+@headings-font-weight:    400;
+@headings-line-height:    1.1;
+@headings-color:          inherit;
+
+
+//== Iconography
+//
+//## Specify custom location and filename of the included Glyphicons icon font. Useful for those including Bootstrap via Bower.
+
+//** Load fonts from this directory.
+@icon-font-path:          "../fonts/";
+//** File name for all font files.
+@icon-font-name:          "glyphicons-halflings-regular";
+//** Element ID within SVG icon file.
+@icon-font-svg-id:        "glyphicons_halflingsregular";
+
+
+//== Components
+//
+//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
+
+@padding-base-vertical:     6px;
+@padding-base-horizontal:   12px;
+
+@padding-large-vertical:    10px;
+@padding-large-horizontal:  16px;
+
+@padding-small-vertical:    5px;
+@padding-small-horizontal:  10px;
+
+@padding-xs-vertical:       1px;
+@padding-xs-horizontal:     5px;
+
+@line-height-large:         1.3333333; // extra decimals for Win 8.1 Chrome
+@line-height-small:         1.5;
+
+@border-radius-base:        0px;
+@border-radius-large:       0px;
+@border-radius-small:       0px;
+
+//** Global color for active items (e.g., navs or dropdowns).
+@component-active-color:    #fff;
+//** Global background color for active items (e.g., navs or dropdowns).
+@component-active-bg:       @brand-primary;
+
+//** Width of the `border` for generating carets that indicator dropdowns.
+@caret-width-base:          4px;
+//** Carets increase slightly in size for larger components.
+@caret-width-large:         5px;
+
+
+//== Tables
+//
+//## Customizes the `.table` component with basic values, each used across all table variations.
+
+//** Padding for ``s and ``s.
+@table-cell-padding:            8px;
+//** Padding for cells in `.table-condensed`.
+@table-condensed-cell-padding:  5px;
+
+//** Default background color used for all tables.
+@table-bg:                      transparent;
+//** Background color used for `.table-striped`.
+@table-bg-accent:               #f9f9f9;
+//** Background color used for `.table-hover`.
+@table-bg-hover:                #f5f5f5;
+@table-bg-active:               @table-bg-hover;
+
+//** Border color for table and cell borders.
+@table-border-color:            #ddd;
+
+
+//== Buttons
+//
+//## For each of Bootstrap's buttons, define text, background and border color.
+
+@btn-font-weight:                normal;
+
+@btn-default-color:              #333;
+@btn-default-bg:                 #fff;
+@btn-default-border:             #ccc;
+
+@btn-primary-color:              #fff;
+@btn-primary-bg:                 @brand-primary;
+@btn-primary-border:             @brand-primary; //darken(@btn-primary-bg, 5%);
+
+@btn-success-color:              #fff;
+@btn-success-bg:                 @brand-success;
+@btn-success-border:             @brand-success; //darken(@btn-success-bg, 5%);
+
+@btn-info-color:                 #fff;
+@btn-info-bg:                    @brand-info;
+@btn-info-border:                @brand-info; //darken(@btn-info-bg, 5%);
+
+@btn-warning-color:              #fff;
+@btn-warning-bg:                 @brand-warning;
+@btn-warning-border:             @brand-warning; //darken(@btn-warning-bg, 5%);
+
+@btn-danger-color:               #fff;
+@btn-danger-bg:                  @brand-danger;
+@btn-danger-border:              @brand-danger; //darken(@btn-danger-bg, 5%);
+
+@btn-link-disabled-color:        @gray-light;
+
+// Allows for customizing button radius independently from global border radius
+@btn-border-radius-base:         @border-radius-base;
+@btn-border-radius-large:        @border-radius-large;
+@btn-border-radius-small:        @border-radius-small;
+
+
+//== Forms
+//
+//##
+
+//** `` background color
+@input-bg:                       #fff;
+//** `` background color
+@input-bg-disabled:              @gray-lighter;
+
+//** Text color for ``s
+@input-color:                    @gray;
+//** `` border color
+@input-border:                   #ccc;
+
+// TODO: Rename `@input-border-radius` to `@input-border-radius-base` in v4
+//** Default `.form-control` border radius
+// This has no effect on ``s in CSS.
+@input-border-radius:            @border-radius-base;
+//** Large `.form-control` border radius
+@input-border-radius-large:      @border-radius-large;
+//** Small `.form-control` border radius
+@input-border-radius-small:      @border-radius-small;
+
+//** Border color for inputs on focus
+@input-border-focus:             #66afe9;
+
+//** Placeholder text color
+@input-color-placeholder:        #999;
+
+//** Default `.form-control` height
+@input-height-base:              (@line-height-computed + (@padding-base-vertical * 2) + 2);
+//** Large `.form-control` height
+@input-height-large:             (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);
+//** Small `.form-control` height
+@input-height-small:             (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);
+
+//** `.form-group` margin
+@form-group-margin-bottom:       15px;
+
+@legend-color:                   @gray-dark;
+@legend-border-color:            #e5e5e5;
+
+//** Background color for textual input addons
+@input-group-addon-bg:           @gray-lighter;
+//** Border color for textual input addons
+@input-group-addon-border-color: @input-border;
+
+//** Disabled cursor for form controls and buttons.
+@cursor-disabled:                not-allowed;
+
+
+//== Dropdowns
+//
+//## Dropdown menu container and contents.
+
+//** Background for the dropdown menu.
+@dropdown-bg:                    #fff;
+//** Dropdown menu `border-color`.
+@dropdown-border:                rgba(0,0,0,.15);
+//** Dropdown menu `border-color` **for IE8**.
+@dropdown-fallback-border:       #ccc;
+//** Divider color for between dropdown items.
+@dropdown-divider-bg:            #e5e5e5;
+
+//** Dropdown link text color.
+@dropdown-link-color:            @gray-dark;
+//** Hover color for dropdown links.
+@dropdown-link-hover-color:      darken(@gray-dark, 5%);
+//** Hover background for dropdown links.
+@dropdown-link-hover-bg:         #f5f5f5;
+
+//** Active dropdown menu item text color.
+@dropdown-link-active-color:     @component-active-color;
+//** Active dropdown menu item background color.
+@dropdown-link-active-bg:        @component-active-bg;
+
+//** Disabled dropdown menu item background color.
+@dropdown-link-disabled-color:   @gray-light;
+
+//** Text color for headers within dropdown menus.
+@dropdown-header-color:          @gray-light;
+
+//** Deprecated `@dropdown-caret-color` as of v3.1.0
+@dropdown-caret-color:           #000;
+
+
+//-- Z-index master list
+//
+// Warning: Avoid customizing these values. They're used for a bird's eye view
+// of components dependent on the z-axis and are designed to all work together.
+//
+// Note: These variables are not generated into the Customizer.
+
+@zindex-navbar:            1000;
+@zindex-dropdown:          1000;
+@zindex-popover:           1060;
+@zindex-tooltip:           1070;
+@zindex-navbar-fixed:      1030;
+@zindex-modal-background:  1040;
+@zindex-modal:             1050;
+
+
+//== Media queries breakpoints
+//
+//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
+
+// Extra small screen / phone
+//** Deprecated `@screen-xs` as of v3.0.1
+@screen-xs:                  480px;
+//** Deprecated `@screen-xs-min` as of v3.2.0
+@screen-xs-min:              @screen-xs;
+//** Deprecated `@screen-phone` as of v3.0.1
+@screen-phone:               @screen-xs-min;
+
+// Small screen / tablet
+//** Deprecated `@screen-sm` as of v3.0.1
+@screen-sm:                  768px;
+@screen-sm-min:              @screen-sm;
+//** Deprecated `@screen-tablet` as of v3.0.1
+@screen-tablet:              @screen-sm-min;
+
+// Medium screen / desktop
+//** Deprecated `@screen-md` as of v3.0.1
+@screen-md:                  992px;
+@screen-md-min:              @screen-md;
+//** Deprecated `@screen-desktop` as of v3.0.1
+@screen-desktop:             @screen-md-min;
+
+// Large screen / wide desktop
+//** Deprecated `@screen-lg` as of v3.0.1
+@screen-lg:                  1200px;
+@screen-lg-min:              @screen-lg;
+//** Deprecated `@screen-lg-desktop` as of v3.0.1
+@screen-lg-desktop:          @screen-lg-min;
+
+// So media queries don't overlap when required, provide a maximum
+@screen-xs-max:              (@screen-sm-min - 1);
+@screen-sm-max:              (@screen-md-min - 1);
+@screen-md-max:              (@screen-lg-min - 1);
+
+
+//== Grid system
+//
+//## Define your custom responsive grid.
+
+//** Number of columns in the grid.
+@grid-columns:              12;
+//** Padding between columns. Gets divided in half for the left and right.
+@grid-gutter-width:         30px;
+// Navbar collapse
+//** Point at which the navbar becomes uncollapsed.
+@grid-float-breakpoint:     @screen-sm-min;
+//** Point at which the navbar begins collapsing.
+@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);
+
+
+//== Container sizes
+//
+//## Define the maximum width of `.container` for different screen sizes.
+
+// Small screen / tablet
+@container-tablet:             (720px + @grid-gutter-width);
+//** For `@screen-sm-min` and up.
+@container-sm:                 @container-tablet;
+
+// Medium screen / desktop
+@container-desktop:            (940px + @grid-gutter-width);
+//** For `@screen-md-min` and up.
+@container-md:                 @container-desktop;
+
+// Large screen / wide desktop
+@container-large-desktop:      (1140px + @grid-gutter-width);
+//** For `@screen-lg-min` and up.
+@container-lg:                 @container-large-desktop;
+
+
+//== Navbar
+//
+//##
+
+// Basics of a navbar
+@navbar-height:                    50px;
+@navbar-margin-bottom:             @line-height-computed;
+@navbar-border-radius:             @border-radius-base;
+@navbar-padding-horizontal:        floor((@grid-gutter-width / 2));
+@navbar-padding-vertical:          ((@navbar-height - @line-height-computed) / 2);
+@navbar-collapse-max-height:       340px;
+
+@navbar-default-color:             #777;
+@navbar-default-bg:                #f8f8f8;
+@navbar-default-border:            darken(@navbar-default-bg, 6.5%);
+
+// Navbar links
+@navbar-default-link-color:                #777;
+@navbar-default-link-hover-color:          #333;
+@navbar-default-link-hover-bg:             transparent;
+@navbar-default-link-active-color:         #555;
+@navbar-default-link-active-bg:            darken(@navbar-default-bg, 6.5%);
+@navbar-default-link-disabled-color:       #ccc;
+@navbar-default-link-disabled-bg:          transparent;
+
+// Navbar brand label
+@navbar-default-brand-color:               @navbar-default-link-color;
+@navbar-default-brand-hover-color:         darken(@navbar-default-brand-color, 10%);
+@navbar-default-brand-hover-bg:            transparent;
+
+// Navbar toggle
+@navbar-default-toggle-hover-bg:           #ddd;
+@navbar-default-toggle-icon-bar-bg:        #888;
+@navbar-default-toggle-border-color:       #ddd;
+
+
+//=== Inverted navbar
+// Reset inverted navbar basics
+@navbar-inverse-color:                      lighten(@gray-light, 15%);
+@navbar-inverse-bg:                         #222;
+@navbar-inverse-border:                     darken(@navbar-inverse-bg, 10%);
+
+// Inverted navbar links
+@navbar-inverse-link-color:                 lighten(@gray-light, 15%);
+@navbar-inverse-link-hover-color:           #fff;
+@navbar-inverse-link-hover-bg:              transparent;
+@navbar-inverse-link-active-color:          @navbar-inverse-link-hover-color;
+@navbar-inverse-link-active-bg:             darken(@navbar-inverse-bg, 10%);
+@navbar-inverse-link-disabled-color:        #444;
+@navbar-inverse-link-disabled-bg:           transparent;
+
+// Inverted navbar brand label
+@navbar-inverse-brand-color:                @navbar-inverse-link-color;
+@navbar-inverse-brand-hover-color:          #fff;
+@navbar-inverse-brand-hover-bg:             transparent;
+
+// Inverted navbar toggle
+@navbar-inverse-toggle-hover-bg:            #333;
+@navbar-inverse-toggle-icon-bar-bg:         #fff;
+@navbar-inverse-toggle-border-color:        #333;
+
+
+//== Navs
+//
+//##
+
+//=== Shared nav styles
+@nav-link-padding:                          10px 15px;
+@nav-link-hover-bg:                         @gray-lighter;
+
+@nav-disabled-link-color:                   @gray-light;
+@nav-disabled-link-hover-color:             @gray-light;
+
+//== Tabs
+@nav-tabs-border-color:                     #ddd;
+
+@nav-tabs-link-hover-border-color:          @gray-lighter;
+
+@nav-tabs-active-link-hover-bg:             @body-bg;
+@nav-tabs-active-link-hover-color:          @gray;
+@nav-tabs-active-link-hover-border-color:   #ddd;
+
+@nav-tabs-justified-link-border-color:            #ddd;
+@nav-tabs-justified-active-link-border-color:     @body-bg;
+
+//== Pills
+@nav-pills-border-radius:                   @border-radius-base;
+@nav-pills-active-link-hover-bg:            @component-active-bg;
+@nav-pills-active-link-hover-color:         @component-active-color;
+
+
+//== Pagination
+//
+//##
+
+@pagination-color:                     @link-color;
+@pagination-bg:                        #fff;
+@pagination-border:                    #ddd;
+
+@pagination-hover-color:               @link-hover-color;
+@pagination-hover-bg:                  @gray-lighter;
+@pagination-hover-border:              #ddd;
+
+@pagination-active-color:              #fff;
+@pagination-active-bg:                 @brand-primary;
+@pagination-active-border:             @brand-primary;
+
+@pagination-disabled-color:            @gray-light;
+@pagination-disabled-bg:               #fff;
+@pagination-disabled-border:           #ddd;
+
+
+//== Pager
+//
+//##
+
+@pager-bg:                             @pagination-bg;
+@pager-border:                         @pagination-border;
+@pager-border-radius:                  15px;
+
+@pager-hover-bg:                       @pagination-hover-bg;
+
+@pager-active-bg:                      @pagination-active-bg;
+@pager-active-color:                   @pagination-active-color;
+
+@pager-disabled-color:                 @pagination-disabled-color;
+
+
+//== Jumbotron
+//
+//##
+
+@jumbotron-padding:              30px;
+@jumbotron-color:                inherit;
+@jumbotron-bg:                   @gray-lighter;
+@jumbotron-heading-color:        inherit;
+@jumbotron-font-size:            ceil((@font-size-base * 1.5));
+@jumbotron-heading-font-size:    ceil((@font-size-base * 4.5));
+
+
+//== Form states and alerts
+//
+//## Define colors for form feedback states and, by default, alerts.
+
+@state-success-text:             @brand-success;
+@state-success-bg:               #dff0d8;
+@state-success-border:           @brand-success;
+
+@state-info-text:                @brand-info;
+@state-info-bg:                  #d9dff7;
+@state-info-border:              @brand-info;
+
+@state-warning-text:             darken(@brand-warning, 10%);
+@state-warning-bg:               #fcf8e3;
+@state-warning-border:           @brand-warning;
+
+@state-danger-text:              @brand-danger;
+@state-danger-bg:                #f2dede;
+@state-danger-border:            @brand-danger;
+
+
+//== Tooltips
+//
+//##
+
+//** Tooltip max width
+@tooltip-max-width:           200px;
+//** Tooltip text color
+@tooltip-color:               #fff;
+//** Tooltip background color
+@tooltip-bg:                  #000;
+@tooltip-opacity:             .8;
+
+//** Tooltip arrow width
+@tooltip-arrow-width:         5px;
+//** Tooltip arrow color
+@tooltip-arrow-color:         @tooltip-bg;
+
+
+//== Popovers
+//
+//##
+
+//** Popover body background color
+@popover-bg:                          #fff;
+//** Popover maximum width
+@popover-max-width:                   276px;
+//** Popover border color
+@popover-border-color:                rgba(0,0,0,.2);
+//** Popover fallback border color
+@popover-fallback-border-color:       #ccc;
+
+//** Popover title background color
+@popover-title-bg:                    darken(@popover-bg, 3%);
+
+//** Popover arrow width
+@popover-arrow-width:                 10px;
+//** Popover arrow color
+@popover-arrow-color:                 @popover-bg;
+
+//** Popover outer arrow width
+@popover-arrow-outer-width:           (@popover-arrow-width + 1);
+//** Popover outer arrow color
+@popover-arrow-outer-color:           fadein(@popover-border-color, 5%);
+//** Popover outer arrow fallback color
+@popover-arrow-outer-fallback-color:  darken(@popover-fallback-border-color, 20%);
+
+
+//== Labels
+//
+//##
+
+//** Default label background color
+@label-default-bg:            @gray-light;
+//** Primary label background color
+@label-primary-bg:            @brand-primary;
+//** Success label background color
+@label-success-bg:            @brand-success;
+//** Info label background color
+@label-info-bg:               @brand-info;
+//** Warning label background color
+@label-warning-bg:            @brand-warning;
+//** Danger label background color
+@label-danger-bg:             @brand-danger;
+
+//** Default label text color
+@label-color:                 #fff;
+//** Default text color of a linked label
+@label-link-hover-color:      #fff;
+
+
+//== Modals
+//
+//##
+
+//** Padding applied to the modal body
+@modal-inner-padding:         30px;
+
+//** Padding applied to the modal title
+@modal-title-padding:         15px;
+//** Modal title line-height
+@modal-title-line-height:     @line-height-base;
+
+//** Background color of modal content area
+@modal-content-bg:                             #fff;
+//** Modal content border color
+@modal-content-border-color:                   #fff;
+//** Modal content border color **for IE8**
+@modal-content-fallback-border-color:          #fff;
+
+//** Modal backdrop background color
+@modal-backdrop-bg:           @gray-light;
+//** Modal backdrop opacity
+@modal-backdrop-opacity:      .6;
+//** Modal header border color
+@modal-header-border-color:   #e5e5e5;
+//** Modal footer border color
+@modal-footer-border-color:   @modal-header-border-color;
+
+@modal-lg:                    900px;
+@modal-md:                    900px;
+@modal-sm:                    auto;
+
+
+//== Alerts
+//
+//## Define alert colors, border radius, and padding.
+
+@alert-padding:               15px;
+@alert-border-radius:         @border-radius-base;
+@alert-link-font-weight:      bold;
+
+@alert-success-bg:            @state-success-bg;
+@alert-success-text:          @state-success-text;
+@alert-success-border:        @state-success-border;
+
+@alert-info-bg:               @state-info-bg;
+@alert-info-text:             @state-info-text;
+@alert-info-border:           @state-info-border;
+
+@alert-warning-bg:            @state-warning-bg;
+@alert-warning-text:          @state-warning-text;
+@alert-warning-border:        @state-warning-border;
+
+@alert-danger-bg:             @state-danger-bg;
+@alert-danger-text:           @state-danger-text;
+@alert-danger-border:         @state-danger-border;
+
+
+//== Progress bars
+//
+//##
+
+//** Background color of the whole progress component
+@progress-bg:                 @brand-lighter;
+//** Progress bar text color
+@progress-bar-color:          #fff;
+//** Variable for setting rounded corners on progress bar.
+@progress-border-radius:      @border-radius-base;
+
+//** Default progress bar color
+@progress-bar-bg:             @brand-primary;
+//** Success progress bar color
+@progress-bar-success-bg:     @brand-success;
+//** Warning progress bar color
+@progress-bar-warning-bg:     @brand-warning;
+//** Danger progress bar color
+@progress-bar-danger-bg:      @brand-danger;
+//** Info progress bar color
+@progress-bar-info-bg:        @brand-info;
+
+
+//== List group
+//
+//##
+
+//** Background color on `.list-group-item`
+@list-group-bg:                 #fff;
+//** `.list-group-item` border color
+@list-group-border:             #ddd;
+//** List group border radius
+@list-group-border-radius:      @border-radius-base;
+
+//** Background color of single list items on hover
+@list-group-hover-bg:           @brand-lighter;
+//** Text color of active list items
+@list-group-active-color:       @component-active-color;
+//** Background color of active list items
+@list-group-active-bg:          @component-active-bg;
+//** Border color of active list elements
+@list-group-active-border:      @list-group-active-bg;
+//** Text color for content within active list items
+@list-group-active-text-color:  lighten(@list-group-active-bg, 40%);
+
+//** Text color of disabled list items
+@list-group-disabled-color:      @gray-light;
+//** Background color of disabled list items
+@list-group-disabled-bg:         @gray-lighter;
+//** Text color for content within disabled list items
+@list-group-disabled-text-color: @list-group-disabled-color;
+
+@list-group-link-color:         #555;
+@list-group-link-hover-color:   @list-group-link-color;
+@list-group-link-heading-color: #333;
+
+
+//== Panels
+//
+//##
+
+@panel-bg:                    @brand-lighter;
+@panel-body-padding:          30px 15px;
+@panel-heading-padding:       8px 15px;
+@panel-footer-padding:        @panel-heading-padding;
+@panel-border-radius:         @border-radius-base;
+
+//** Border color for elements within panels
+@panel-inner-border:          #ddd;
+@panel-footer-bg:             @brand-light;
+
+@panel-default-text:          #fff;
+@panel-default-border:        @brand-light;
+@panel-default-heading-bg:    @brand-dark;
+
+@panel-primary-text:          #fff;
+@panel-primary-border:        @brand-primary;
+@panel-primary-heading-bg:    @brand-primary;
+
+@panel-success-text:          @state-success-text;
+@panel-success-border:        @state-success-border;
+@panel-success-heading-bg:    @state-success-bg;
+
+@panel-info-text:             @state-info-text;
+@panel-info-border:           @state-info-border;
+@panel-info-heading-bg:       @state-info-bg;
+
+@panel-warning-text:          @state-warning-text;
+@panel-warning-border:        @state-warning-border;
+@panel-warning-heading-bg:    @state-warning-bg;
+
+@panel-danger-text:           @state-danger-text;
+@panel-danger-border:         @state-danger-border;
+@panel-danger-heading-bg:     @state-danger-bg;
+
+
+//== Thumbnails
+//
+//##
+
+//** Padding around the thumbnail image
+@thumbnail-padding:           4px;
+//** Thumbnail background color
+@thumbnail-bg:                @body-bg;
+//** Thumbnail border color
+@thumbnail-border:            #ddd;
+//** Thumbnail border radius
+@thumbnail-border-radius:     @border-radius-base;
+
+//** Custom text color for thumbnail captions
+@thumbnail-caption-color:     @text-color;
+//** Padding around the thumbnail caption
+@thumbnail-caption-padding:   9px;
+
+
+//== Wells
+//
+//##
+
+@well-bg:                     @brand-lighter;
+@well-border:                 @border-color;
+
+
+//== Badges
+//
+//##
+
+@badge-color:                 #fff;
+//** Linked badge text color on hover
+@badge-link-hover-color:      #fff;
+@badge-bg:                    @gray-light;
+
+//** Badge text color in active nav link
+@badge-active-color:          @link-color;
+//** Badge background color in active nav link
+@badge-active-bg:             #fff;
+
+@badge-font-weight:           bold;
+@badge-line-height:           1;
+@badge-border-radius:         10px;
+
+
+//== Breadcrumbs
+//
+//##
+
+@breadcrumb-padding-vertical:   8px;
+@breadcrumb-padding-horizontal: 15px;
+//** Breadcrumb background color
+@breadcrumb-bg:                 #f5f5f5;
+//** Breadcrumb text color
+@breadcrumb-color:              #ccc;
+//** Text color of current page in the breadcrumb
+@breadcrumb-active-color:       @gray-light;
+//** Textual separator for between breadcrumb elements
+@breadcrumb-separator:          "/";
+
+
+//== Carousel
+//
+//##
+
+@carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6);
+
+@carousel-control-color:                      #fff;
+@carousel-control-width:                      15%;
+@carousel-control-opacity:                    .5;
+@carousel-control-font-size:                  20px;
+
+@carousel-indicator-active-bg:                #6f6f6f;
+@carousel-indicator-border-color:             #6f6f6f;
+
+@carousel-caption-color:                      #fff;
+
+
+//== Close
+//
+//##
+
+@close-font-weight:           bold;
+@close-color:                 #000;
+@close-text-shadow:           0 1px 0 #fff;
+
+
+//== Code
+//
+//##
+
+@code-color:                  #c7254e;
+@code-bg:                     #f9f2f4;
+
+@kbd-color:                   #fff;
+@kbd-bg:                      #333;
+
+@pre-bg:                      #f5f5f5;
+@pre-color:                   @gray-dark;
+@pre-border-color:            #ccc;
+@pre-scrollable-max-height:   340px;
+
+
+//== Type
+//
+//##
+
+//** Horizontal offset for forms and lists.
+@component-offset-horizontal: 180px;
+//** Text muted color
+@text-muted:                  @gray-light;
+//** Abbreviations and acronyms border color
+@abbr-border-color:           @gray-light;
+//** Headings small color
+@headings-small-color:        @gray-light;
+//** Blockquote small color
+@blockquote-small-color:      @gray-light;
+//** Blockquote font size
+@blockquote-font-size:        (@font-size-base * 1.25);
+//** Blockquote border color
+@blockquote-border-color:     @brand-primary;
+//** Page header border color
+@page-header-border-color:    @border-color;
+//** Width of horizontal description list titles
+@dl-horizontal-offset:        @component-offset-horizontal;
+//** Point at which .dl-horizontal becomes horizontal
+@dl-horizontal-breakpoint:    @grid-float-breakpoint;
+//** Horizontal line color.
+@hr-border:                   @border-color;
diff --git a/shuup_megastore_theme/static_src/less/style.less b/shuup_megastore_theme/static_src/less/style.less
new file mode 100644
index 0000000..a8f0d5e
--- /dev/null
+++ b/shuup_megastore_theme/static_src/less/style.less
@@ -0,0 +1,72 @@
+@bower: "../../bower_components";
+
+// Core variables and mixins
+@import "shuup_megastore_theme/variables.less";
+//@import "@{bower}/bootstrap/less/variables.less";
+@import "@{bower}/bootstrap/less/mixins.less";
+
+// Reset and dependencies
+@import "@{bower}/bootstrap/less/normalize.less";
+@import "@{bower}/bootstrap/less/print.less";
+@import "@{bower}/bootstrap/less/glyphicons.less";
+
+// Core CSS
+@import "@{bower}/bootstrap/less/scaffolding.less";
+@import "@{bower}/bootstrap/less/type.less";
+@import "@{bower}/bootstrap/less/code.less";
+@import "@{bower}/bootstrap/less/grid.less";
+@import "@{bower}/bootstrap/less/tables.less";
+@import "@{bower}/bootstrap/less/forms.less";
+@import "@{bower}/bootstrap/less/buttons.less";
+
+// Components
+@import "@{bower}/bootstrap/less/component-animations.less";
+@import "@{bower}/bootstrap/less/dropdowns.less";
+@import "@{bower}/bootstrap/less/button-groups.less";
+@import "@{bower}/bootstrap/less/input-groups.less";
+@import "@{bower}/bootstrap/less/navs.less";
+@import "@{bower}/bootstrap/less/navbar.less";
+//@import "@{bower}/bootstrap/less/breadcrumbs.less";
+//@import "@{bower}/bootstrap/less/pagination.less";
+@import "@{bower}/bootstrap/less/pager.less";
+@import "@{bower}/bootstrap/less/labels.less";
+@import "@{bower}/bootstrap/less/badges.less";
+//@import "@{bower}/bootstrap/less/jumbotron.less";
+//@import "@{bower}/bootstrap/less/thumbnails.less";
+@import "@{bower}/bootstrap/less/alerts.less";
+//@import "@{bower}/bootstrap/less/progress-bars.less";
+//@import "@{bower}/bootstrap/less/media.less";
+//@import "@{bower}/bootstrap/less/list-group.less";
+@import "@{bower}/bootstrap/less/panels.less";
+@import "@{bower}/bootstrap/less/responsive-embed.less";
+@import "@{bower}/bootstrap/less/wells.less";
+@import "@{bower}/bootstrap/less/close.less";
+
+// Components w/ JavaScript
+@import "@{bower}/bootstrap/less/modals.less";
+@import "@{bower}/bootstrap/less/tooltip.less";
+//@import "@{bower}/bootstrap/less/popovers.less";
+@import "@{bower}/bootstrap/less/carousel.less";
+
+// Utility classes
+@import "@{bower}/bootstrap/less/utilities.less";
+@import "@{bower}/bootstrap/less/responsive-utilities.less";
+
+// Vendor styles
+@import "@{bower}/font-awesome/less/font-awesome.less";
+@import "@{bower}/bootstrap-select/less/bootstrap-select.less";
+@import "vendor/image-lightbox.less";
+
+// Our custom styles
+@import "shuup_megastore_theme/base.less";
+@import "shuup_megastore_theme/navigation.less";
+@import "shuup_megastore_theme/footer.less";
+@import "shuup_megastore_theme/add-to-cart-indicator.less";
+@import "shuup_megastore_theme/product-card.less";
+@import "shuup_megastore_theme/carousels.less";
+@import "shuup_megastore_theme/category.less";
+@import "shuup_megastore_theme/modals.less";
+@import "shuup_megastore_theme/inputs.less";
+@import "shuup_megastore_theme/product-page.less";
+@import "shuup_megastore_theme/checkout.less";
+@import "shuup_megastore_theme/social-media-links.less";
diff --git a/shuup_megastore_theme/static_src/less/vendor/image-lightbox.less b/shuup_megastore_theme/static_src/less/vendor/image-lightbox.less
new file mode 100644
index 0000000..8a4f82d
--- /dev/null
+++ b/shuup_megastore_theme/static_src/less/vendor/image-lightbox.less
@@ -0,0 +1,78 @@
+// Lightbox styles for the lightbox image plugin
+
+#imagelightbox {
+    position: fixed;
+    z-index: 10000;
+    -ms-touch-action: none;
+    touch-action: none;
+}
+
+.imagelightbox-arrow {
+    width: 3.75em;
+    height: 7.5em;
+    background-color: @brand-primary;
+    color: #fff;
+    vertical-align: middle;
+    display: none;
+    position: fixed;
+    z-index: 10001;
+    top: 50%;
+    margin-top: -3.75em;
+    border: 0;
+    @media (max-width: @screen-xs-max) {
+        display: none !important;
+    }
+}
+
+.imagelightbox-arrow-left {
+    left: 2.5em;
+}
+
+.imagelightbox-arrow-right {
+    right: 2.5em;
+}
+
+#imagelightbox-overlay,
+#imagelightbox-close,
+.imagelightbox-arrow {
+    animation: 0.25s linear 0s normal none 1 running fade-in;
+}
+
+#imagelightbox-overlay {
+    background-color: rgba(255, 255, 255, 0.85);
+    position: fixed;
+    z-index: 9998;
+    top: 0px;
+    right: 0px;
+    bottom: 0px;
+    left: 0px;
+}
+
+#imagelightbox-close {
+    width: 2.5em;
+    height: 2.5em;
+    text-align: center;
+    background-color: @gray;
+    border: 0;
+    border-radius: 50%;
+    position: fixed;
+    z-index: 10002;
+    top: 2.5em;
+    right: 2.5em;
+    transition: color 0.3s ease 0s;
+    color: #fff;
+}
+
+#imagelightbox-loading {
+    position: fixed;
+    z-index: 9999;
+    top: 50%;
+    left: 50%;
+    margin-left: -20px;
+    margin-top: -20px;
+    i {
+        color: @gray-light;
+        font-size: 52px;
+        padding: 20px;
+    }
+}
diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/add_product_to_basket.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/add_product_to_basket.jinja
new file mode 100644
index 0000000..249a7f7
--- /dev/null
+++ b/shuup_megastore_theme/templates/shuup_megastore_theme/add_product_to_basket.jinja
@@ -0,0 +1,63 @@
+
+
+ +

{% trans %}Product added to cart{% endtrans %}

+
+
+ +

{% trans %}There was an error adding the product to the shopping cart{% endtrans %}

+
+
+ + diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/base_ajax_content_only.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/base_ajax_content_only.jinja new file mode 100644 index 0000000..ad46f9c --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/base_ajax_content_only.jinja @@ -0,0 +1 @@ +{% block ajax_content %}{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/highlight_plugin.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/highlight_plugin.jinja new file mode 100644 index 0000000..95518a7 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/highlight_plugin.jinja @@ -0,0 +1,12 @@ +{%- import "shoop/front/macros.jinja" as macros with context -%} + + diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/navigation_basket_partial.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/navigation_basket_partial.jinja new file mode 100644 index 0000000..ded1450 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/navigation_basket_partial.jinja @@ -0,0 +1,45 @@ + + diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/product_preview.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/product_preview.jinja new file mode 100644 index 0000000..6cc8a81 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/product_preview.jinja @@ -0,0 +1,37 @@ +{%- import "shoop/front/macros.jinja" as macros with context -%} +{% set product_url = url("shoop:product", pk=product.pk, slug=product.slug) %} +{% set price_info = product.get_price_info(request) %} + diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/customer_information/edit.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/customer_information/edit.jinja new file mode 100644 index 0000000..30b8c6b --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/customer_information/edit.jinja @@ -0,0 +1,58 @@ +{% extends "shoop/front/base.jinja" %} +{% block title %}{% trans %}User account information{% endtrans %}{% endblock %} +{% block content_title %}{% trans %}User account information{% endtrans %}{% endblock %} + +{% block content %} + +{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/base.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/base.jinja new file mode 100644 index 0000000..6a15734 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/base.jinja @@ -0,0 +1,138 @@ +{%- import "shoop/front/macros.jinja" as macros with context -%} + + + + + + {% block title %}{% trans %}Base{% endtrans %}{% endblock %} – {{ request.shop.public_name }} + {% block extrameta %}{% endblock %} + + + + + + + {% if messages %} +
+ {% for message in messages %} +
+ +
+ {% endfor %} +
+ {% endif %} + + + + + + {% include "shoop/front/includes/_navigation.jinja" %} + + + +
+
+
+
+ {% include "shoop/front/includes/megamenu.jinja" with context %} +
+
+ {% block banner %}{% endblock %} + {% block breadcrumb %}{% endblock %} +
+ {% block before_content_title %}{% endblock %} + {% if self.content_title() %} + + {% endif %} +
+ {% block content %}{% endblock %} +
+
+
+
+
+ {% block carousels %}{% endblock %} +
+
+ + + {% include "shoop/front/includes/_footer.jinja" %} +
+ + + {% block extrajs %}{% endblock %} + {# Enable adding products to basket with ajax #} + {% include "shuup_megastore_theme/add_product_to_basket.jinja" %} + + diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/basket/default_basket.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/basket/default_basket.jinja new file mode 100644 index 0000000..e6e1c6d --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/basket/default_basket.jinja @@ -0,0 +1,27 @@ +{% extends "shoop/front/base.jinja" %} + +{% block title %}{% trans %}Checkout{% endtrans %}{% endblock %} +{% block content_title %}{% endblock %} + +{% block content %} +
+
+

{% trans %}Checkout{% endtrans %}

+
+ {% if basket.is_empty %} +
+ {% trans %}Your shopping cart is empty.{% endtrans %} +
+ {% else %} + {% include "shoop/front/basket/partials/table.jinja" %} + + {% endif %} +
+ {% placeholder "basket_extra" %}{% endplaceholder %} +
+
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/basket/includes/_order_form.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/basket/includes/_order_form.jinja new file mode 100644 index 0000000..210f2a4 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/basket/includes/_order_form.jinja @@ -0,0 +1,120 @@ +{%- import "shoop/front/macros.jinja" as macros with context -%} + +{% if orderable %} +
+ {% csrf_token %} + + {# Set some nice shortcuts #} + {%- set sf = form.shipping -%} + {%- set bf = form.billing -%} + {%- set of = form.order -%} + + {# Render the hidden fields so we don't need to worry about them later #} + {% for field in sf.hidden_fields() %}{{ field|safe }}{% endfor %} + {% for field in bf.hidden_fields() %}{{ field|safe }}{% endfor %} + {% for field in of.hidden_fields() %}{{ field|safe }}{% endfor %} + + {% if errors %} +
+

{% trans %}Errors{% endtrans %}

+
    + {% for error in errors %} +
  • {{ error }}
  • + {% endfor %} +
+
+ {% endif %} + + {# Billing addresses #} +
+
+
+

1. {% trans %}Billing address{% endtrans %}

+
+
+
+
+ {% for field in bf.visible_fields() %} + {{ macros.render_order_field(field) }} + {% endfor %} +
+
+

{% trans %}Ordering for a company?{% endtrans %}

+

{% trans %}Please fill out these fields if you are ordering for a company.{% endtrans %}

+
+
+ {{ macros.render_order_field(form.order.company_name) }} + {{ macros.render_order_field(form.order.vat_code) }} +
+
+
+
+
+
+ {# Shipping addresses #} +
+
+
+

2. {% trans %}Shipping address{% endtrans %}

+
+
+
+ + +
+
+
+
+ {% for field in sf.visible_fields() %} + {{ macros.render_order_field(field) }} + {% endfor %} +
+
+
+
+
+
+ {# Other information #} +
+
+
+

3. {% trans %}Other information{% endtrans %}

+
+
+
+ {{ macros.render_order_field(of.shipping_method) }} + {{ macros.render_order_field(of.payment_method) }} +
+ {{ shipping_method_ui_html|default("")|safe }} +
+ {{ macros.render_order_field(of.comment) }} +
+
+
+
+ +
+ +
+
+ {% trans %}Total price{% endtrans %}: + {{ basket.taxful_total_price|money }} +
+
+ +
+ + {{ macros.render_order_field(of.accept_terms) }} + +
+
+ +
+ +
+
+{% endif %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/basket/includes/_order_overview.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/basket/includes/_order_overview.jinja new file mode 100644 index 0000000..ad5cff7 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/basket/includes/_order_overview.jinja @@ -0,0 +1,10 @@ +
+
+ {% trans %}Total items{% endtrans %}: + {{ basket.product_count }} +
+
+ {% trans %}Total price{% endtrans %}: + {{ basket.taxful_total_price|money }} +
+
diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/basket/partials/table.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/basket/partials/table.jinja new file mode 100644 index 0000000..4d0699b --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/basket/partials/table.jinja @@ -0,0 +1,99 @@ +
+
+ + {% csrf_token %} + + + + + + + + + + + + + + + + + + + + + + + + + + {% for line in basket.get_final_lines() %} + {% set product = line.product %} + + + + + + + + + {% endfor %} + +
{% trans %}Product{% endtrans %}{% trans %}Price{% endtrans %}{% trans %}Quantity{% endtrans %}{% trans %}Total{% endtrans %}
+ + + {% trans %}Total{% endtrans %}: + {{ basket.total_price|money }} +
+ {% if product %} + {% set image = product.primary_image %} + {% if image %} + + {{ line.name }} + + {% else %} + + {% endif %} + {% endif %} + + {% if product %} + {{ line.text }} + {% else %} + {{ line.text }} + {% endif %} + + {{ line.discounted_unit_price|money }} + {% if line.is_discounted %} + + {{ line.base_unit_price|money }} + + {% endif %} + + {% if product and line.can_change_quantity %} + + {% endif %} + + {{ line.price|money }} + + {% if line.can_delete %} + + {% endif %} +
+
+
diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/_base.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/_base.jinja new file mode 100644 index 0000000..e8ed722 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/_base.jinja @@ -0,0 +1,22 @@ +{% extends "shoop/front/base.jinja" %} + +{% block title %}{{ view.title }}{% endblock %} +{% block content_title %}{% endblock %} + +{% block before_content_title %} + {% block checkout_phase_bar %} + {% if view and view.phases %} +
+
+ +
+
+ {% endif %} + {% endblock %} +{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/_confirm_table.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/_confirm_table.jinja new file mode 100644 index 0000000..24560f6 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/_confirm_table.jinja @@ -0,0 +1,69 @@ +
+ + + + + + + + + + + + + + + + + + + + + + {% for line in basket.get_final_lines() %} + {% set product = line.product %} + {% set shop_product = line.shop_product %} + + + + + + + + {% endfor %} + +
{% trans %}Product{% endtrans %}{% trans %}Price{% endtrans %}{% trans %}Quantity{% endtrans %}{% trans %}Total{% endtrans %}
+ {% trans %}Total{% endtrans %}: + {% set taxful_total_price = basket.taxful_total_price %} + {% set taxless_total_price = basket.taxless_total_price %} + {{ taxful_total_price|money }} + {% if taxless_total_price != taxful_total_price %} +
+ ({{ taxless_total_price|money }} {{ _("excl. tax") }}) + {% endif %} +
+ {% if product %} + {% set image = product.primary_image %} + {% if image %} + {{ line.text }} + {% else %} + + {% endif %} + {% endif %} + + {{ line.text }} + + {{ line.taxful_discounted_unit_price|money }} + {% if line.tax_amount %} +
({{ line.taxless_discounted_unit_price|money }} excl. tax) + {% endif %} + {% if line.is_discounted %} +
{{ line.taxful_base_unit_price|money }} + {% endif %} +
+ {{ line.quantity|number }} + + {{ line.taxful_price|money }} +
+
+ diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/addresses.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/addresses.jinja new file mode 100644 index 0000000..83582e1 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/addresses.jinja @@ -0,0 +1,104 @@ +{% extends "shoop/front/checkout/_base.jinja" %} + +{% block content %} +
+
+ {% set forms = form.forms %} + {% csrf_token %} +
+
+

{% trans %}Billing address{% endtrans %}

+
+
+
+ {% for field in forms.billing %} + {{ bs3.field(field, layout="horizontal") }} + {% endfor %} +
+ {% if forms.company %} +
+
+
+

{% trans %}Ordering for a company?{% endtrans %}

+

{% trans %}Please fill out these fields if you are ordering for a company.{% endtrans %}

+
+
+
+ {{ bs3.field(forms.company.name, layout="horizontal") }} + {{ bs3.field(forms.company.tax_number, layout="horizontal") }} +
+ {% endif %} +
+
+ +
+
+

{% trans %}Shipping address{% endtrans %}

+
+
+
+
+
+ + +
+
+
+
+
+ {% for field in forms.shipping %} + {{ bs3.field(field, layout="horizontal") }} + {% endfor %} +
+
+
+ +
+
+{% endblock %} + +{% block extrajs %} + +{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/confirm.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/confirm.jinja new file mode 100644 index 0000000..e7d6a6b --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/confirm.jinja @@ -0,0 +1,83 @@ +{% extends "shoop/front/checkout/_base.jinja" %} +{% from "shoop/front/macros.jinja" import render_field with context %} + +{% macro format_address(address) %} +
+ {% for line in address.as_string_list() %} + {% if loop.first %} + {{ line }} + {% else %} + {{ line }} + {% endif %} + {% if not loop.last %}
{% endif %} + {% endfor %} +
+{% endmacro %} + +{% macro method_panel(panel_title, method_title, address_title, method, address) %} +
+
+

{{ panel_title }}

+
+
+
+
{{ method_title }}
+
{{ method.name }}
+
{{ address_title }}:
+
+ {{ format_address(address) }} +
+
+
+
+{% endmacro %} +{% block content %} +
+
+
+

+ {% trans %}Confirmation{% endtrans %} +

+
+
+ {% include "shoop/front/checkout/_confirm_table.jinja" %} +
+
+
+
+ {{ method_panel( + _("Delivery"), _("Delivery method"), _("Shipping address"), + basket.shipping_method, + basket.shipping_address + ) }} +
+
+ {{ method_panel( + _("Billing"), _("Payment method"), _("Billing address"), + basket.payment_method, + basket.billing_address + ) }} +
+
+
+ {% if orderable %} +
+ {% csrf_token %} + {{ macros.render_field(form.comment) }} + {{ macros.render_field(form.marketing) }} + {{ macros.render_field(form.accept_terms) }} +
+ +
+ {% else %} +

{% trans %}There are errors{% endtrans %}

+
    + {% for error in errors %} +
  • {{ error }}
  • + {% endfor %} +
+ {% endif %} +
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/empty.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/empty.jinja new file mode 100644 index 0000000..bd8734a --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/empty.jinja @@ -0,0 +1,9 @@ +{% extends "shoop/front/checkout/_base.jinja" %} +{% block checkout_phase_bar %}{% endblock %} +{% block content %} +
+
+ {% trans %}Your shopping cart is empty.{% endtrans %} +
+
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/method_choice.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/method_choice.jinja new file mode 100644 index 0000000..a0940c0 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/method_choice.jinja @@ -0,0 +1,41 @@ +{% for service_provider, services in grouped_methods.items() %} +
+
+ {% if service_provider.logo %} + {% set service_provider_logo = service_provider.logo|thumbnail(size=(0,100)) %} + {{ service_provider.name }} + {% else %} +

{{ service_provider.name }}

+ {% endif %} +
+ {% for service in services %} +
+ +
+ {% endfor %} +
+{% endfor %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/methods.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/methods.jinja new file mode 100644 index 0000000..4263553 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/checkout/methods.jinja @@ -0,0 +1,32 @@ +{% extends "shoop/front/checkout/_base.jinja" %} + +{% block content %} +
+
+ {% csrf_token %} +
+
+

+ {% trans %}Choose Shipping Method{% endtrans %} +

+
+
+ {{ form.shipping_method }} +
+
+
+
+

+ {% trans %}Choose Payment Method{% endtrans %} +

+
+
+ {{ form.payment_method }} +
+
+ +
+
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/errors/400.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/errors/400.jinja new file mode 100644 index 0000000..5b65bf1 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/errors/400.jinja @@ -0,0 +1,21 @@ +{% extends "shoop/front/base.jinja" %} + +{% block title %}{% trans %}Bad Request{% endtrans %} (400){% endblock %} +{% block content_title %}{{ self.title() }}{% endblock %} + +{% block breadcrumb %} +
+ +
+{% endblock %} + +{% block content %} +
+

{% trans %}Unfortunately the server couldn't process your request.{% endtrans %}

+
+ {% trans %}Back to Homepage{% endtrans %} +
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/errors/403.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/errors/403.jinja new file mode 100644 index 0000000..48475fa --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/errors/403.jinja @@ -0,0 +1,21 @@ +{% extends "shoop/front/base.jinja" %} + +{% block title %}{% trans %}Permission Denied{% endtrans %} (403){% endblock %} +{% block content_title %}{{ self.title() }}{% endblock %} + +{% block breadcrumb %} +
+ +
+{% endblock %} + +{% block content %} +
+

{% trans %}Unfortunately you didn't have permission to display this page.{% endtrans %}

+
+ {% trans %}Back to Homepage{% endtrans %} +
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/errors/404.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/errors/404.jinja new file mode 100644 index 0000000..be9574f --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/errors/404.jinja @@ -0,0 +1,21 @@ +{% extends "shoop/front/base.jinja" %} + +{% block title %}{% trans %}Page not Found{% endtrans %} (404){% endblock %} +{% block content_title %}{{ self.title() }}{% endblock %} + +{% block breadcrumb %} +
+ +
+{% endblock %} + +{% block content %} +
+

{% trans %}Unfortunately the page you were looking for does not exist.{% endtrans %}

+
+ {% trans %}Back to Homepage{% endtrans %} +
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/errors/500.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/errors/500.jinja new file mode 100644 index 0000000..16d5c79 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/errors/500.jinja @@ -0,0 +1,54 @@ + + + + + + + + + + + {% trans %}Internal Server Error{% endtrans %} (500) + + + +
+
+
+
+ +

{% trans %}Internal Server Error{% endtrans %} (500)

+

{% trans %}Unfortunately an internal server error occurred. Try refreshing the page or try again later.{% endtrans %}

+
+
+
+
+ + diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_footer.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_footer.jinja new file mode 100644 index 0000000..13a01de --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_footer.jinja @@ -0,0 +1,42 @@ +
+ + +
diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_frontpage-carousel.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_frontpage-carousel.jinja new file mode 100644 index 0000000..0d736bc --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_frontpage-carousel.jinja @@ -0,0 +1,19 @@ + diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_hot_deals_carousel.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_hot_deals_carousel.jinja new file mode 100644 index 0000000..f844873 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_hot_deals_carousel.jinja @@ -0,0 +1,25 @@ + diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_navigation.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_navigation.jinja new file mode 100644 index 0000000..e4ce4f7 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_navigation.jinja @@ -0,0 +1,147 @@ + diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_sale_and_offers_carousel.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_sale_and_offers_carousel.jinja new file mode 100644 index 0000000..a3d571f --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_sale_and_offers_carousel.jinja @@ -0,0 +1,19 @@ + diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_social_media_lift.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_social_media_lift.jinja new file mode 100644 index 0000000..8d8398b --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/_social_media_lift.jinja @@ -0,0 +1,15 @@ + diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/megamenu.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/megamenu.jinja new file mode 100644 index 0000000..5051a7c --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/includes/megamenu.jinja @@ -0,0 +1,39 @@ + + diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/index.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/index.jinja new file mode 100644 index 0000000..ba0d1a1 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/index.jinja @@ -0,0 +1,23 @@ +{% extends "shoop/front/base.jinja" %} +{% block content_title %}{% endblock %} + +{% block extra_main_class %}index{% endblock %} + +{% block content %} + +{% placeholder frontpage_carousel %}{% endplaceholder %} + {% placeholder "front_content" %} + {% row %} + {% plugin "shuup_megastore_theme.product_highlight" %} + type = "newest" + title = "New Products" + {% endplugin %} + {% endrow %} + {% row %} + {% plugin "shuup_megastore_theme.product_highlight" %} + type = "best_selling" + title = "Best selling products" + {% endplugin %} + {% endrow %} + {% endplaceholder %} +{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/macros.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/macros.jinja new file mode 100644 index 0000000..76b91ac --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/macros.jinja @@ -0,0 +1,370 @@ +{% macro product_box(product, show_image=True, show_description=False, extra_class="", thumbnail_size=(500,500), shop=None) %} + {% set u = url("shoop:product", pk=product.pk, slug=product.slug) %} + {% if product.is_variation_parent() %} + {% set price_info = product.get_cheapest_child_price_info(request) %} + {% else %} + {% set price_info = product.get_price_info(request) %} + {% endif %} + +{% endmacro %} + +{% macro render_product_price(product, show_units=False) %} +{% if show_prices() %} +
+ {%- if product.is_variation_parent() -%} + {% set min_price, max_price = product|price_range %} + {% if min_price == max_price %} + {{ min_price }} + {% else %} + {{ min_price }} – {{ max_price }} + {% endif %} + {%- else -%} + {%- if product|is_discounted -%} + {{- product|base_price -}} + {%- endif -%} + {{ product|price }} + {%- endif -%} + {%- if show_units -%} + / {{ product.sales_unit.short_name }} + {%- endif -%} +
+{% endif %} +{% endmacro %} + +{% macro render_cross_sell_products(product, relation_type="", title="") %} + {%- set cross_sell_products = shoop.product.get_product_cross_sells(product, relation_type, count=8) %} + {% if cross_sell_products %} + + {% endif %} +{% endmacro %} + +{% macro alert(message, title=None, mode="") %} +
+ {% if title %} + {{ title }} + {% endif %} + {% if not caller %} + {{ message|safe }} + {% else %} + {{ caller() }} + {% endif %} +
+{% endmacro %} + +{% macro render_field(field, classes="") %} + {% if field.field.widget.is_hidden %} + {{ field.as_widget()|safe }} + {% else %} + {% set widget_name = field.field.widget.__class__.__name__|lower %} + {% if widget_name == "checkboxinput" %} +
+ {{ field.as_widget()|safe }} + +
+ {% elif widget_name == "select" %} +
+ + {{ field.as_widget(attrs={"class": "form-control selectpicker"})|safe }} + {% if field.help_text %} +

{{ field.help_text }}

+ {% endif %} + {% if field.errors %} +

+ {% for error in field.errors %} + {{ error}} + {% endfor %} +

+ {% endif %} +
+ {% else %} +
+ + {{ field.as_widget(attrs={"class": "form-control"})|safe }} + {% if field.help_text %} +

{{ field.help_text }}

+ {% endif %} + {% if field.errors %} +

+ {% for error in field.errors %} + {{ error}} + {% endfor %} +

+ {% endif %} +
+ {% endif %} + {% endif %} +{% endmacro %} + +{% macro render_order_field(field, classes="") %} + {% if field.field.widget.is_hidden %} + {{ field.as_widget()|safe }} + {% else %} + {% set widget_name = field.field.widget.__class__.__name__|lower %} + {% if widget_name == "checkboxinput" %} +
+ {{ field.as_widget()|safe }} + +
+ {% elif widget_name == "lazyselect" or widget_name == "select" %} +
+ +
+ {% if widget_name == "lazyselect" %} + {{ field.as_widget(attrs={"class": "form-control selectpicker", "data-live-search": "true"})|safe }} + {% else %} + {{ field.as_widget(attrs={"class": "form-control selectpicker"})|safe }} + {% endif %} + {% if field.help_text %} +

{{ field.help_text }}

+ {% endif %} + {% if field.errors %} +

+ {% for error in field.errors %} + {{ error}} + {% endfor %} +

+ {% endif %} +
+
+ {% else %} +
+ +
+ {{ field.as_widget(attrs={"class": "form-control"})|safe }} + {% if field.help_text %} +

{{ field.help_text }}

+ {% endif %} + {% if field.errors %} +

+ {% for error in field.errors %} + {{ error}} + {% endfor %} +

+ {% endif %} +
+
+ {% endif %} + {% endif %} +{% endmacro %} + +{% macro order_list(orders) %} + {% if orders %} + + + + + + + + + + + + {% for order in orders %} + + + + + + + + {% endfor %} + +
{% trans %}Order{% endtrans %}{% trans %}Ordered{% endtrans %}{% trans %}Status{% endtrans %}{% trans %}Total{% endtrans %}{% trans %}Operations{% endtrans %}
{{ order.reference_number }}{{ order.order_date|localtime|date("j.n.Y H:i") }}{{ order.get_status_display() }}{{ order.total_price|money }}{% trans %}View{% endtrans %}
+ {% else %} +

{% trans %}No orders{% endtrans %}

+ {% endif %} +{% endmacro %} + +{% macro print_order_detail(order, show_attachments=False) %} + +
+
+

{% trans %}Products ordered{% endtrans %}

+
+
+ {% set lines = order.lines.order_by("ordering") %} +
+ {% include "shoop/front/order/partials/product_table.jinja" %} +
+
+
+ +
+
+

{% trans %}Tax breakdown{% endtrans %}

+
+
+
+ {% include "shoop/front/order/partials/taxes.jinja" %} +
+
+
+ + {% if show_attachments %} + {% set attachments = order.get_purchased_attachments() %} + {% if attachments %} +

{% trans %}Files{% endtrans %}

+ + {% for attachment in attachments %} + + + + + {% endfor %} +
{{ attachment.title }} + {% if attachment.description %} + {{ attachment.description|linebreaksbr }} + {% endif %} +
+ {% endif %} + {% endif %} + +
+
+
+
+

{% trans %}Delivery{% endtrans %}

+
+
+
+
{% trans %}Delivery method{% endtrans %}:
+
{{ order.shipping_method_name }}
+
{% trans %}Shipping address{% endtrans %}:
+
+
+ {% for line in order.shipping_address.as_string_list() %} + {% if loop.first %} + {{ line }} + {% else %} + {{ line }} + {% endif %} + {% if not loop.last %}
{% endif %} + {% endfor %} +
+
+
+
+
+
+
+
+
+

{% trans %}Payment{% endtrans %}

+
+
+
+
{% trans %}Payment method{% endtrans %}:
+
{{ order.payment_method_name }}
+
{% trans %}Billing address{% endtrans %}:
+
+
+ {% for line in order.billing_address.as_string_list() %} + {% if loop.first %} + {{ line }} + {% else %} + {{ line }} + {% endif %} + {% if not loop.last %}
{% endif %} + {% endfor %} +
+
+
+
+
+
+
+ + {% if order.company %} +
+
+

{% trans %}Company{% endtrans %}

+
+
+

{{ order.company.name }} ({% trans %}Y-tunnus{% endtrans %} {{ order.company.vat_id }})

+
+
+ {% endif %} + +{% endmacro %} + +{% macro pagination(page, paginator) %} + + +{% endmacro %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/order/complete.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/order/complete.jinja new file mode 100644 index 0000000..32e6b6d --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/order/complete.jinja @@ -0,0 +1,12 @@ +{% extends "shoop/front/base.jinja" %} + +{% block title %}{% trans %}Thank you for your order!{% endtrans %}{% endblock %} +{% block content_title %}{% trans name=order.billing_address.name %}Thank you for your order!{% endtrans %}{% endblock %} + +{% block content %} +
+

{% trans %}Your order has been received. You can see the details of your order below.{% endtrans %}

+
+ {{ macros.print_order_detail(order, True) }} +
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/order/partials/product_table.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/order/partials/product_table.jinja new file mode 100644 index 0000000..2e45311 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/order/partials/product_table.jinja @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + {% for line in lines %} + {% set product = line.product %} + + + + + + + + {% endfor %} + +
{% trans %}Title{% endtrans %}{% trans %}Price{% endtrans %}{% trans %}Quantity{% endtrans %}{% trans %}Total{% endtrans %}
+ {% trans %}Total{% endtrans %}: + {% set taxful_total_price = order.taxful_total_price %} + {% set taxless_total_price = order.taxless_total_price %} + {{ taxful_total_price|money }} + {% if taxless_total_price != taxful_total_price %} +
+ ({{ taxless_total_price|money }} {{ _("excl. tax") }}) + {% endif %} +
+ {% if product %} + {% set image = product.primary_image %} + {% if image %} + + {% else %} + + {% endif %} + {% endif %} + + {{ line.text }} + + {{ line.taxful_discounted_unit_price|money }} + {% if line.tax_amount %} +
({{ line.taxless_discounted_unit_price|money }} excl. tax) + {% endif %} + {% if line.is_discounted %} +
{{ line.taxful_base_unit_price|money }} + {% endif %} +
+ {{ line.quantity|number }} + + {{ line.taxful_price|money }} +
diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/order/partials/taxes.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/order/partials/taxes.jinja new file mode 100644 index 0000000..0fd2cae --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/order/partials/taxes.jinja @@ -0,0 +1,29 @@ + + + + + + + + + + + + {% set tax_summary = order.get_tax_summary() %} + {% if tax_summary %} + {% for item in tax_summary %} + + + + + + + + {% endfor %} + {% endif %} + +
{% trans %}Tax{% endtrans %}{% trans %}Tax percentage{% endtrans %}{% trans %}Based on amount{% endtrans %}{% trans %}Amount of tax{% endtrans %}{% trans %}Total including tax{% endtrans %}
{{ item.tax_name }} + {%- if item.tax_rate is not none -%} + {{ item.tax_rate|percent(ndigits=3) }} + {%- endif -%} + {{ item.based_on|money }}{{ item.tax_amount|money }}{{ item.taxful|money }}
diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/order/payment_canceled.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/order/payment_canceled.jinja new file mode 100644 index 0000000..0ff1f5a --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/order/payment_canceled.jinja @@ -0,0 +1,10 @@ +{% extends "shoop/front/base.jinja" %} + +{% block content_title %}{% trans %}Payment canceled{% endtrans %}{% endblock %} + +{% block content %} +
+

{% trans %}You have canceled payment{% endtrans %}

+

{% trans %}Retry payment{% endtrans %}

+
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/_detail_attributes_section.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/_detail_attributes_section.jinja new file mode 100644 index 0000000..28e09ee --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/_detail_attributes_section.jinja @@ -0,0 +1,10 @@ + + {% for attribute in shoop.product.get_visible_attributes(product) %} + + {% if attribute.value is not none %} + + + {% endif %} + + {% endfor %} +
{{ attribute.name }}{{ attribute.formatted_value }}
diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/_detail_details_section.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/_detail_details_section.jinja new file mode 100644 index 0000000..842b04f --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/_detail_details_section.jinja @@ -0,0 +1,5 @@ +{% if product.description %} + {{ product.description|markdown|safe }} +{% else %} + {% trans %}No product description available.{% endtrans %} +{% endif %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/_detail_order_section.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/_detail_order_section.jinja new file mode 100644 index 0000000..fcb6624 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/_detail_order_section.jinja @@ -0,0 +1,132 @@ +{% if request.is_ajax() %} + +{% endif %} + +{% if not quantity %} + {% set quantity = shop_product.rounded_minimum_purchase_quantity %} +{% endif %} + +{% macro add_to_cart_btn(is_orderable) %} + {% if is_orderable %} +
+ +
+ {% else %} +
+ +

{% trans %}Product is not orderable.{% endtrans %}

+
+ {% endif %} +{% endmacro %} + +{% macro quantity_box() %} +
+ +
+ +
+
+{% endmacro %} + +{% macro product_order_section(product, quantity, is_orderable) %} +
+
+ {{ quantity_box() }} +
+ + {{ add_to_cart_btn(is_orderable) }} +
+{% endmacro %} + +{% macro product_price_div(product, quantity) %} +
+ {% set price_info = product.get_price_info(request, quantity) %} +

+ {% trans %}Total{% endtrans %}: + {{ price_info.price|money }} +

+ + {% if price_info.is_discounted %} + ({{ price_info.base_unit_price|money }}) + {% endif %} + {{ price_info.discounted_unit_price|money }}/{{ product.sales_unit.short_name }} + +
+{% endmacro %} + +{% macro variable_variation_form() %} + + +
+ {% for var in variation_variables %} +
+ + +
+ {% endfor %} + {{ product_order_section(product, quantity, True) }} +
+{% endmacro %} + +{% macro simple_variation_form() %} + {% set is_orderable = (orderable_variation_children|length > 0) %} +
+ +
+ + +
+ {{ product_order_section(product, quantity, is_orderable) }} +
+{% endmacro %} + +{% macro simple_product_form() %} + + + {% set is_orderable=shop_product.is_orderable(supplier=None, customer=request.customer, quantity=quantity) %} +
+ {{ product_order_section(product, quantity, is_orderable) }} +
+{% endmacro %} + +
+ {% set return_path = return_url if return_url else request.path %} + + {% if unorderability_reason %} +

{{ unorderability_reason }}

+ {% elif variation_variables %} + {{ variable_variation_form() }} + {% elif variation_children %} + {{ simple_variation_form() }} + {% else %} + {{ simple_product_form() }} + {% endif %} +
diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/_detail_order_section_no_product.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/_detail_order_section_no_product.jinja new file mode 100644 index 0000000..caf9b5b --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/_detail_order_section_no_product.jinja @@ -0,0 +1,7 @@ +
+

+ {% trans %}Total{% endtrans %}: + -- +

+ {% trans %}Combination not available{% endtrans %} +
diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/_product_image.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/_product_image.jinja new file mode 100644 index 0000000..b6de7c2 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/_product_image.jinja @@ -0,0 +1,38 @@ + diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/category.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/category.jinja new file mode 100644 index 0000000..1a74cb8 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/category.jinja @@ -0,0 +1,67 @@ +{% if request.is_ajax() %} + {% extends "shuup_megastore_theme/base_ajax_content_only.jinja" %} + {% import "shuup_megastore_theme/shoop/front/macros.jinja" as macros with context %} +{% else %} + {% extends "shoop/front/base.jinja" %} +{% endif %} + + +{% block title %}{{ category.name }}{% endblock %} +{% block content_title %}{% endblock %} + +{% block banner %} +
+

{{ category.name }}

+ +
+{% endblock %} + +{% block breadcrumb %} + +{% endblock %} + +{% block content %} +
+
+
+
+ {{ form.sort|safe }} +
+
+
+
+ {% block ajax_content %} +
+ {% set pagination = shoop.general.get_pagination_variables(products, 20) %} + {% for product in pagination.objects if shoop.product.is_visible(product) %} + {{ macros.product_box(product, extra_class="category-view") }} + {% endfor %} +
+ {% if pagination.is_paginated %} +
+ {{ macros.pagination(pagination.page, pagination.paginator) }} +
+ {% endif %} + {% endblock %} +
+
+ +{% endblock %} +{% block carousels %} + {% placeholder "category_bottom_extra" %}{% endplaceholder %} +{% endblock %} +{% block extrajs %} + +{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/detail.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/detail.jinja new file mode 100644 index 0000000..77891ee --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/product/detail.jinja @@ -0,0 +1,213 @@ +{% extends "shoop/front/base.jinja" %} + +{% if product.is_variation_parent() %} + {% set priceinfo = product.get_cheapest_child_price_info(request) %} +{% else %} + {% set priceinfo = product.get_price_info(request) %} +{% endif %} + +{% block extrameta %} + + + + + {% if primary_image %} + + {% endif %} +{% endblock %} + +{% block title %}{{ product.name }}{% endblock %} +{% block content_title %}{% endblock %} + +{% block breadcrumb %} +
+ +
+{% endblock %} + +{% block content %} +
+
+ +
+ {% include "shoop/front/product/_product_image.jinja" %} +
+ +
+

{{ product.name }}

+
+

{{ product.sku }} / {{ product.manufacturer.name }}

+
+ + + {% if product|is_discounted %} + + + + + + + + + + + + + +
{{ _("List Price") }}:{{ product|base_price }}
{{ _("Discounted Price") }}:{{ product|price }}
{{ _("You Save") }}:{{ product|discount_amount }} ({{ product|discount_percent }})
+{# Discounted Price: {{ product|price }}.
#} +{# You Save: {{ product|discount_amount }} ({{ product|discount_percent }})
#} + {% else %} + {% endif %} +{#
#} +
+ {% include "shoop/front/product/_detail_order_section.jinja" with context %} +
+
+
    +
  • + {% trans %}Delivery terms{% endtrans %} +
  • +
  • + {% trans %}Refund terms{% endtrans %} +
  • +
+
+
+ + + + + + + + + + + + +
+
+
+ +
+ +
+
+ {% include "shoop/front/product/_detail_details_section.jinja" %} +
+ {% if shoop.product.get_visible_attributes(product) %} +
+ {% include "shoop/front/product/_detail_attributes_section.jinja" %} +
+ {% endif %} +
+
+ + {% if package_children %} + + {% elif package_parents %} + + {% endif %} + + {{ macros.render_cross_sell_products( + product, relation_type="computed", title=_("Users who bought this product also bought") + ) }} + + {{ macros.render_cross_sell_products( + product, relation_type="recommended", title=_("We recommend these products") + ) }} + + {{ macros.render_cross_sell_products( + product, relation_type="related", title=_("Related products") + ) }} +
+ +{% endblock %} + +{% block extrajs %} + +{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/simple_message.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/simple_message.jinja new file mode 100644 index 0000000..01939da --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/front/simple_message.jinja @@ -0,0 +1,20 @@ +{% extends "shoop/front/base.jinja" %} + +{% block title -%} +{% if title %}{{ title }}{% endif %} +{%- endblock %} + +{% block content %} +
+
+

+ {{ self.title() }} +

+
+ {% block message %} + {% if message %}{{ message }}{% endif %} + {% endblock %} +
+
+
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/personal_order_history/order_detail.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/personal_order_history/order_detail.jinja new file mode 100644 index 0000000..9a38ad3 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/personal_order_history/order_detail.jinja @@ -0,0 +1,170 @@ +{% extends "shoop/front/base.jinja" %} + +{% block title -%} + {{ _("Order %(identifier)s", identifier=order.identifier) }} +{%- endblock %} + +{% block content %} +
+

+ {{ _("Details of order %(identifier)s", identifier=order.identifier) }} +

+
+
+ {{ _basic_info() }} +
+
+ {{ _status() }} +
+
+ {{ _shipping_address() }} +
+
+ {{ _billing_address() }} +
+
+ {{ _rows() }} +
+
+
+{% endblock %} + +{% macro _basic_info() %} + {% call content_block(_("Basic Information")) %} +
+ + {{ info_row(_("Order Number"), order.identifier) }} + {{ info_row(_("Order Date"), order.order_date|datetime) }} + {{ info_row(_("Reference"), order.reference_number) }} + {{ info_row(_("Label"), order.label) }} + {{ info_row(_("Customer"), order.customer) }} + {{ info_row(_("Ordered by"), order.orderer) }} + {{ info_row(_("Creator"), order.creator) }} + {{ info_row(_("Phone"), order.phone, "tel:" ~ order.phone) }} + {{ info_row(_("Email"), order.email, "mailto:" ~ order.email) }} + {{ info_row(_("VAT Code"), order.vat_code) }} + {{ price_row(_("Total Price"), order.taxful_total_price) }} + {{ price_row(_("Total Price (taxless)"), order.taxless_total_price) }} +
+
+ {% endcall %} +{% endmacro %} + +{% macro _status() %} + {% call content_block(_("Status")) %} + + {{ info_row(_("Order Status"), order.get_status_display()) }} + {{ info_row(_("Payment Status"), order.get_payment_status_display()) }} + {{ info_row(_("Shipping Status"), order.get_shipping_status_display()) }} +
+ {% endcall %} +{% endmacro %} + +{% macro _shipping_address() %} + {% if order.shipping_address_id %} + {% call content_block(_("Shipping Address")) %} + {% for line in order.shipping_address %} + {{ line }}
+ {% endfor %} + {% endcall %} + {% endif %} +{% endmacro %} + +{% macro _billing_address() %} + {% if order.billing_address_id %} + {% call content_block(_("Billing Address")) %} + {% for line in order.billing_address %} + {{ line }}
+ {% endfor %} + {% endcall %} + {% endif %} +{% endmacro %} + +{% macro _rows() %} + {% call content_block(_("Order Contents")) %} +
+ + + + + + + + + + + + + + + {% for line in order.lines.order_by("ordering") %} + + + + {{ price_cell(line.taxless_base_unit_price) }} + {{ number_cell(line.quantity) }} + {{ price_or_empty_cell(line.taxless_discount_amount) }} + {{ number_cell(line.tax_rate|percent) }} + {{ price_cell(line.taxless_price) }} + {{ price_cell(line.taxful_price) }} + + {% endfor %} + + + + + {{ price_cell(order.taxless_total_price, 'th') }} + {{ price_cell(order.taxful_total_price, 'th') }} + + +
{{ _("SKU") }}{{ _("Text") }}{{ _("Taxless Unit Price") }}{{ _("Quantity") }}{{ _("Taxless Discount") }}{{ _("Tax") }}{{ _("Taxless Total") }}{{ _("Total incl. Tax") }}
{{ line.sku }}{{ line.text }}
{{ _("Total") }}
+
+ {% endcall %} +{% endmacro %} + +{% macro content_block(heading) %} +
+
+ {% if heading %} +

{{ heading }}

+ {% endif %} +
+
+ {{ caller() }} +
+
+{% endmacro %} + +{% macro info_row(header, value, url=None, class="") %} + {% if value is defined and value is not none and value != "" %} + + {{ header }} + + {%- if url %}{% endif -%} + {{ value }} + {%- if url %}{% endif -%} + + + {% endif %} +{% endmacro %} + +{% macro price_row(header, value) %} + {{ info_row(header, value|money) }} +{% endmacro %} + +{% macro price_cell(value, elem="td") %} + {{ number_cell(value|money, elem) }} +{% endmacro %} + +{% macro number_cell(value, elem="td") %} + {% if value is number %}{% set value=value|number %}{% endif %} + <{{ elem }} class="text-right">{{ value }} +{% endmacro %} + +{% macro price_or_empty_cell(value, elem="td") %} + {%- if value != 0 -%} + {{ price_cell(value, elem) }} + {%- else -%} + {{ number_cell("", elem) }} + {%- endif -%} +{% endmacro %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/personal_order_history/order_list.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/personal_order_history/order_list.jinja new file mode 100644 index 0000000..b4c8223 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/personal_order_history/order_list.jinja @@ -0,0 +1,43 @@ +{% extends "shoop/front/base.jinja" %} + +{% block title -%} + {{ _("Order History") }} +{%- endblock %} + +{% block content %} +
+
+
+

+ {{ _("Order history") }} +

+
+
+ {% if orders %} +
+ + + + + + + + + {% for order in orders %} + + + + + + + + {% endfor %} +
{{ _('Identifier') }}{{ _('Order date') }}{{ _('Status') }}{{ _('Total price') }}
{{- order.identifier -}}{{ order.order_date|datetime }}{{ order.get_status_display() }}{{ order.taxful_total_price|money }} {% trans %}Details{% endtrans %}
+
+ {% else %} +

{{ _("You haven't made any orders yet.") }}

+ {% endif %} +
+
+
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/registration/activation_failed.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/registration/activation_failed.jinja new file mode 100644 index 0000000..a35a5ea --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/registration/activation_failed.jinja @@ -0,0 +1,11 @@ +{% extends "shoop/front/base.jinja" %} +{% block title %}Account activation{% endblock %} + +{% block content %} +
+
+

{% trans %}Account activation{% endtrans %}

+

{% trans %}Account activation failed.{% endtrans %}

+
+
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/registration/register.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/registration/register.jinja new file mode 100644 index 0000000..b08920c --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/registration/register.jinja @@ -0,0 +1,26 @@ +{% extends "shoop/front/base.jinja" %} +{% from "shoop/front/macros.jinja" import render_field %} + +{% block title %}Register{% endblock %} + +{% block content %} +
+
+
+
+
+

{% trans %}Registration{% endtrans %}

+
+
+
+ {% csrf_token %} + {% for field in form.hidden_fields() %}{{ field|safe }}{% endfor %} + {% for field in form.visible_fields() %}{{ render_field(field) }}{% endfor %} + +
+
+
+
+
+
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/simple_cms/page.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/simple_cms/page.jinja new file mode 100644 index 0000000..0df759c --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/simple_cms/page.jinja @@ -0,0 +1,18 @@ +{% extends "shoop/front/base.jinja" %} + +{% block title %}{{ page.title }}{% endblock %} +{% block content_title %}{{ page.title }}{% endblock %} + +{% block breadcrumb %} +
+ +
+{% endblock %} +{% block content %} +
+ {{ page.get_html()|safe }} +
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/simple_search/search.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/simple_search/search.jinja new file mode 100644 index 0000000..b9675b7 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/simple_search/search.jinja @@ -0,0 +1,31 @@ +{% extends "shoop/front/base.jinja" %} +{% block title %}{% trans %}Search{% endtrans %}{% endblock %} +{% block content %} +
+

{% trans %}Search{% endtrans %}

+
+
+
{{ bs3.field(form.q) }}
+
+
+
{{ bs3.field(form.sort) }}
+
+ +
+
+ {% if no_results %} +

{% trans query=form.cleaned_data.q %}No results found for "{{ query }}".{% endtrans %}

+ {% elif products %} +
+

{% trans %}Search results found for{% endtrans %} "{{ form.cleaned_data.q }}"

+
+
+ {% for product in products if shoop.product.is_visible(product) %} + {{ macros.product_box(product, extra_class="search-view") }} + {% endfor %} +
+ {% endif %} +
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/stripe/checkout_phase.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/stripe/checkout_phase.jinja new file mode 100644 index 0000000..fce4bc2 --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/stripe/checkout_phase.jinja @@ -0,0 +1,19 @@ +{% extends "shoop/front/checkout/_base.jinja" %} + +{% block content %} +
+
+ {% csrf_token %} +

{% trans %}We use Stripe for secure payment handling.{% endtrans %}

+

{% trans %}Click the button below to enter your card details. You will only be charged when your order completes.{% endtrans %}

+ +
+
+{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/user/login.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/user/login.jinja new file mode 100644 index 0000000..6cc89cb --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/user/login.jinja @@ -0,0 +1,38 @@ +{% extends "shoop/front/base.jinja" %} +{% from "shoop/front/macros.jinja" import render_field with context %} + +{% block title %}{% trans %}Log in{% endtrans %}{% endblock %} +{% block content_title %}{% endblock %} + +{% block content %} + +
+
+
+ {% for error in form.non_field_errors() %} + {{ macros.alert(error, mode="danger") }} + {% endfor %} +
+ {{ _("You can use admin/admin to log in.") }} +
+
+
+

{% trans %}Log in{% endtrans %}

+
+
+
+ {% csrf_token %} + + {{ render_field(form.username) }} + {{ render_field(form.password) }} + +
+ {% trans %}Forgot your password?{% endtrans %} +
+
+
+
+
+
+ +{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/user/logout.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/user/logout.jinja new file mode 100644 index 0000000..687826a --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/user/logout.jinja @@ -0,0 +1,3 @@ +{% extends "shoop/front/simple_message.jinja" %} +{% block title %}{% trans %}Logged out{% endtrans %}{% endblock %} +{% block message %}{% trans %}You have been logged out. Thank you for visiting!{% endtrans %}{% endblock %} diff --git a/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/user/recover_password.jinja b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/user/recover_password.jinja new file mode 100644 index 0000000..a8fb2ba --- /dev/null +++ b/shuup_megastore_theme/templates/shuup_megastore_theme/shoop/user/recover_password.jinja @@ -0,0 +1,31 @@ +{% extends "shoop/front/base.jinja" %} +{% from "shoop/front/macros.jinja" import render_field with context %} + +{% block title %}{% trans %}Recover your password{% endtrans %}{% endblock %} +{% block content_title %}{% endblock %} + +{% block content %} +
+
+
+
+
+

{% trans %}Recover your password{% endtrans %}

+
+
+

{% trans %}You can recover your password with either username or email.{% endtrans %}

+
+
+ {% csrf_token %} + {{ render_field(form.username) }} + {{ render_field(form.email) }} + +
+
+
+
+
+
+{% endblock %} diff --git a/shuup_megastore_theme/views/__init__.py b/shuup_megastore_theme/views/__init__.py new file mode 100644 index 0000000..2c11511 --- /dev/null +++ b/shuup_megastore_theme/views/__init__.py @@ -0,0 +1,5 @@ +from shoop.themes.classic_gray.views import product_price # noqa +from ._product_preview import product_preview +from ._basket import basket_partial # noqa + +__all__ = ["basket_partial", "product_price", "product_preview"] diff --git a/shuup_megastore_theme/views/_basket.py b/shuup_megastore_theme/views/_basket.py new file mode 100644 index 0000000..39337ba --- /dev/null +++ b/shuup_megastore_theme/views/_basket.py @@ -0,0 +1,11 @@ +from django.http import HttpResponse +from django.template.loader import render_to_string + + +def basket_partial(request): + return HttpResponse( + render_to_string( + "shuup_megastore_theme/navigation_basket_partial.jinja", + request=request, + ) + ) diff --git a/shuup_megastore_theme/views/_product_preview.py b/shuup_megastore_theme/views/_product_preview.py new file mode 100644 index 0000000..f02b306 --- /dev/null +++ b/shuup_megastore_theme/views/_product_preview.py @@ -0,0 +1,21 @@ +from shoop.front.views.product import ProductDetailView + + +class ProductPreviewView(ProductDetailView): + template_name = "shuup_megastore_theme/product_preview.jinja" + + def get_context_data(self, **kwargs): + # By default the template rendering the basket add form + # uses the `request.path` as its' `next` value. + # This is fine if you are on product page but here in + # preview, we cannot redirect back to `/xtheme/product_preview`. + + context = super(ProductPreviewView, self).get_context_data(**kwargs) + # Add `return_url` to context to avoid usage of `request.path` in + # `shuup_megastore_theme/shoop/front/product/_detail_order_section.jinja` + context["return_url"] = "/xtheme/products" + return context + + +def product_preview(request): + return ProductPreviewView.as_view()(request, pk=request.GET["id"])