Merge pull request #5020 from devansh-webkul/web-vital-v2

Web Vital Work
This commit is contained in:
Jitendra Singh 2021-08-06 17:09:08 +05:30 committed by GitHub
commit 01468edb83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 2370 additions and 1669 deletions

View File

@ -6,6 +6,7 @@ end_of_line = lf
insert_final_newline = false
indent_style = space
indent_size = 4
quote_type = single
trim_trailing_whitespace = true
[*.md]

View File

@ -14,10 +14,11 @@ class Kernel extends HttpKernel
* @var array
*/
protected $middleware = [
\Webkul\Core\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Webkul\Core\Http\Middleware\CheckForMaintenanceMode::class,
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Webkul\Core\Http\Middleware\SecureHeaders::class,
];
/**

View File

@ -7,8 +7,7 @@
"watch-poll": "npm run watch -- --watch-poll",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"postinstall": "opencollective-postinstall"
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"axios": "^0.21.0",
@ -25,12 +24,6 @@
"vue-template-compiler": "^2.6.11"
},
"dependencies": {
"opencollective": "^1.0.3",
"opencollective-postinstall": "^2.0.1",
"vee-validate": "^3.3.0"
},
"collective": {
"type": "opencollective",
"url": "https://opencollective.com/bagisto"
}
}

View File

@ -0,0 +1,62 @@
<?php
namespace Webkul\Core\Http\Middleware;
use Closure;
class SecureHeaders
{
/**
* Unwanted header list.
*
* @var array
*/
private $unwantedHeaderList = [
'X-Powered-By',
'Server',
];
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$this->removeUnwantedHeaders();
$response = $next($request);
$this->setHeaders($response);
return $response;
}
/**
* Set headers.
*
* @return void
*/
private function setHeaders($response)
{
$response->headers->set('Referrer-Policy', 'no-referrer-when-downgrade');
$response->headers->set('X-Content-Type-Options', 'nosniff');
$response->headers->set('X-XSS-Protection', '1; mode=block');
$response->headers->set('X-Frame-Options', 'DENY');
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
}
/**
* Remove unwanted headers.
*
* @return void
*/
private function removeUnwantedHeaders()
{
foreach ($this->unwantedHeaderList as $header) {
header_remove($header);
}
}
}

View File

@ -23,9 +23,8 @@
"bootstrap-sass": "^3.4.1",
"font-awesome": "^4.7.0",
"lazysizes": "^5.2.2",
"material-icons": "^0.3.1",
"material-icons": "^0.7.6",
"vee-validate": "^2.2.15",
"vue-slider-component": "^3.1.0",
"vue-toast-notification": "0.0.2"
"vue-slider-component": "^3.1.0"
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,6 @@
{
"/js/velocity.js": "/js/velocity.js?id=1c12a991b9a3d04715bd",
"/js/velocity.js": "/js/velocity.js?id=9113e2a844686a29cad2",
"/css/velocity-admin.css": "/css/velocity-admin.css?id=4322502d80a0e4a0affd",
"/css/velocity.css": "/css/velocity.css?id=e17eb072b66c4c8c1227"
"/css/velocity.css": "/css/velocity.css?id=b3d53fa8c0b5a7da14b6",
"/js/velocity-core.js": "/js/velocity-core.js?id=b1b985fa23df3e237bc1"
}

View File

@ -2,15 +2,15 @@
namespace Webkul\Velocity\Helpers;
use Webkul\Product\Helpers\Review;
use Illuminate\Support\Facades\Storage;
use Webkul\Product\Facades\ProductImage;
use Webkul\Product\Models\Product as ProductModel;
use Webkul\Product\Repositories\ProductRepository;
use Webkul\Product\Repositories\ProductFlatRepository;
use Webkul\Velocity\Repositories\OrderBrandsRepository;
use Webkul\Product\Repositories\ProductReviewRepository;
use Webkul\Attribute\Repositories\AttributeOptionRepository;
use Webkul\Product\Facades\ProductImage;
use Webkul\Product\Helpers\Review;
use Webkul\Product\Models\Product as ProductModel;
use Webkul\Product\Repositories\ProductFlatRepository;
use Webkul\Product\Repositories\ProductRepository;
use Webkul\Product\Repositories\ProductReviewRepository;
use Webkul\Velocity\Repositories\OrderBrandsRepository;
use Webkul\Velocity\Repositories\VelocityMetadataRepository;
class Helper extends Review
@ -247,6 +247,36 @@ class Helper extends Review
return $reviews;
}
/**
* Get messages from session.
*
* @return void
*/
public function getMessage()
{
$message = [
'message' => '',
'messageType' => '',
'messageLabel' => '',
];
if ($message['message'] = session('success')) {
$message['messageType'] = 'alert-success';
$message['messageLabel'] = __('velocity::app.shop.general.alert.success');
} else if ($message['message'] = session('warning')) {
$message['messageType'] = 'alert-warning';
$message['messageLabel'] = __('velocity::app.shop.general.alert.warning');
} else if ($message['message'] = session('error')) {
$message['messageType'] = 'alert-danger';
$message['messageLabel'] = __('velocity::app.shop.general.alert.error');
} else if ($message['message'] = session('info')) {
$message['messageType'] = 'alert-info';
$message['messageLabel'] = __('velocity::app.shop.general.alert.info');
}
return $message;
}
/**
* Get json translations.
*

View File

@ -2,8 +2,9 @@
namespace Webkul\Velocity\Providers;
use Illuminate\Routing\Router;
use Illuminate\Foundation\AliasLoader;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;
use Webkul\Velocity\Facades\Velocity as VelocityFacade;
@ -55,11 +56,13 @@ class VelocityServiceProvider extends ServiceProvider
protected function registerConfig()
{
$this->mergeConfigFrom(
dirname(__DIR__) . '/Config/admin-menu.php', 'menu.admin'
dirname(__DIR__) . '/Config/admin-menu.php',
'menu.admin'
);
$this->mergeConfigFrom(
dirname(__DIR__) . '/Config/acl.php', 'acl'
dirname(__DIR__) . '/Config/acl.php',
'acl'
);
}
@ -90,7 +93,7 @@ class VelocityServiceProvider extends ServiceProvider
__DIR__ . '/../Resources/views/shop' => resource_path('themes/velocity/views'),
]);
$this->publishes([__DIR__.'/../Resources/lang' => resource_path('lang/vendor/velocity')]);
$this->publishes([__DIR__ . '/../Resources/lang' => resource_path('lang/vendor/velocity')]);
return true;
}
@ -103,11 +106,11 @@ class VelocityServiceProvider extends ServiceProvider
private function loadGloableVariables()
{
view()->composer('*', function ($view) {
$velocityHelper = app('Webkul\Velocity\Helpers\Helper');
$velocityMetaData = $velocityHelper->getVelocityMetaData();
$velocityHelper = app(\Webkul\Velocity\Helpers\Helper::class);
$view->with('showRecentlyViewed', true);
$view->with('velocityMetaData', $velocityMetaData);
$view->with('velocityHelper', $velocityHelper);
$view->with('velocityMetaData', $velocityHelper->getVelocityMetaData());
});
return true;

View File

@ -0,0 +1,65 @@
<template>
<div :class="`slides-container ${direction}`">
<carousel-component
loop="true"
timeout="5000"
autoplay="true"
slides-per-page="1"
navigation-enabled="hide"
paginationEnabled="hide"
:locale-direction="direction"
:slides-count="banners.length > 0 ? banners.length : 1"
>
<template v-if="banners.length > 0">
<slide
v-for="(banner, index) in banners"
:key="index"
:slot="`slide-${index}`"
title=" "
>
<a
:href="
banner.slider_path != ''
? banner.slider_path
: 'javascript:void(0);'
"
>
<img
class="col-12 no-padding banner-icon"
:src="`${$root.baseUrl}/storage/${banner.path}`"
/>
<div
class="show-content"
v-html="banner.content.replace('\r\n', '')"
></div>
</a>
</slide>
</template>
<template v-else>
<slide slot="slide-0">
<img
loading="lazy"
class="col-12 no-padding banner-icon"
:src="defaultBanner"
alt=""
/>
</slide>
</template>
</carousel-component>
</div>
</template>
<script>
export default {
props: ['direction', 'defaultBanner', 'banners'],
mounted: function() {
let banners = this.$el.querySelectorAll('img');
banners.forEach(banner => {
banner.style.display = 'block';
});
}
};
</script>

View File

@ -0,0 +1,54 @@
<template>
<a class="compare-btn unset" :href="src">
<i class="material-icons">compare_arrows</i>
<div class="badge-container" v-if="compareCount > 0">
<span class="badge" v-text="compareCount"></span>
</div>
<span v-text="__('customer.compare.text')" v-if="isText == 'true'"></span>
</a>
</template>
<script type="text/javascript">
export default {
props: ['isCustomer', 'isText', 'src'],
data: function() {
return {
compareCount: 0
};
},
watch: {
'$root.headerItemsCount': function() {
this.updateHeaderItemsCount();
}
},
created: function() {
this.updateHeaderItemsCount();
},
methods: {
updateHeaderItemsCount: function() {
if (this.isCustomer !== 'true') {
let comparedItems = this.getStorageValue('compared_product');
if (comparedItems) {
this.compareCount = comparedItems.length;
}
} else {
this.$http
.get(`${this.$root.baseUrl}/items-count`)
.then(response => {
this.compareCount = response.data.compareProductsCount;
})
.catch(exception => {
console.log(this.__('error.something_went_wrong'));
});
}
}
}
};
</script>

View File

@ -0,0 +1,475 @@
<template>
<div class="row">
<div class="col-6">
<div v-if="hamburger" class="nav-container scrollable">
<div class="wrapper" v-if="this.rootCategories">
<div class="greeting drawer-section fw6">
<i class="material-icons">perm_identity</i>
<span>
<slot name="greetings"></slot>
<i
@click="closeDrawer()"
class="material-icons float-right text-dark"
>
cancel
</i>
</span>
</div>
<ul
type="none"
class="velocity-content"
v-if="headerContent.length > 0"
>
<li
:key="index"
v-for="(content, index) in headerContent"
>
<a
class="unset"
v-text="content.title"
:href="`${$root.baseUrl}/${content.page_link}`"
>
</a>
</li>
</ul>
<ul
type="none"
class="category-wrapper"
v-if="rootCategoriesCollection.length > 0"
>
<li
v-for="(category,
index) in rootCategoriesCollection"
>
<a
class="unset"
:href="`${$root.baseUrl}/${category.slug}`"
>
<div class="category-logo">
<img
class="category-icon"
v-if="category.category_icon_path"
:src="
`${$root.baseUrl}/storage/${category.category_icon_path}`
"
alt=""
width="20"
height="20"
/>
</div>
<span v-text="category.name"></span>
</a>
<i
class="rango-arrow-right"
@click="toggleSubcategories(index, $event)"
></i>
</li>
</ul>
<slot name="customer-navigation"></slot>
<ul type="none" class="meta-wrapper">
<li>
<template v-if="locale">
<div class="language-logo-wrapper">
<img
class="language-logo"
:src="
`${$root.baseUrl}/storage/${locale.locale_image}`
"
alt=""
v-if="locale.locale_image"
/>
<img
class="language-logo"
:src="
`${$root.baseUrl}/themes/velocity/assets/images/flags/en.png`
"
alt=""
v-else-if="locale.code == 'en'"
/>
</div>
<span v-text="locale.name"></span>
</template>
<i
class="rango-arrow-right"
@click="toggleMetaInfo('languages')"
>
</i>
</li>
<li>
<span v-text="currency.code"></span>
<i
class="rango-arrow-right"
@click="toggleMetaInfo('currencies')"
>
</i>
</li>
<slot name="extra-navigation"></slot>
</ul>
</div>
<div class="wrapper" v-else-if="subCategory">
<div class="drawer-section">
<i
class="rango-arrow-left fs24 text-down-4"
@click="toggleSubcategories('root')"
></i>
<h4 class="display-inbl" v-text="subCategory.name"></h4>
<i
class="material-icons float-right text-dark"
@click="closeDrawer()"
>
cancel
</i>
</div>
<ul type="none">
<li
:key="index"
v-for="(nestedSubCategory,
index) in subCategory.children"
>
<a
class="unset"
:href="
`${$root.baseUrl}/${subCategory.slug}/${nestedSubCategory.slug}`
"
>
<div class="category-logo">
<img
class="category-icon"
v-if="
nestedSubCategory.category_icon_path
"
:src="
`${$root.baseUrl}/storage/${nestedSubCategory.category_icon_path}`
"
alt=""
width="20"
height="20"
/>
</div>
<span v-text="nestedSubCategory.name"></span>
</a>
<ul
type="none"
class="nested-category"
v-if="
nestedSubCategory.children &&
nestedSubCategory.children.length > 0
"
>
<li
:key="`index-${Math.random()}`"
v-for="(thirdLevelCategory,
index) in nestedSubCategory.children"
>
<a
class="unset"
:href="
`${$root.baseUrl}/${subCategory.slug}/${nestedSubCategory.slug}/${thirdLevelCategory.slug}`
"
>
<div class="category-logo">
<img
class="category-icon"
v-if="
thirdLevelCategory.category_icon_path
"
:src="
`${$root.baseUrl}/storage/${thirdLevelCategory.category_icon_path}`
"
alt=""
width="20"
height="20"
/>
</div>
<span
v-text="thirdLevelCategory.name"
></span>
</a>
</li>
</ul>
</li>
</ul>
</div>
<div class="wrapper" v-else-if="languages">
<div class="drawer-section">
<i
class="rango-arrow-left fs24 text-down-4"
@click="toggleMetaInfo('languages')"
></i>
<h4
class="display-inbl"
v-text="__('responsive.header.languages')"
></h4>
<i
class="material-icons float-right text-dark"
@click="closeDrawer()"
>cancel</i
>
</div>
<ul type="none">
<li v-for="(locale, index) in allLocales" :key="index">
<a class="unset" :href="`?locale=${locale.code}`">
<div class="category-logo">
<img
class="category-icon"
:src="
`${$root.baseUrl}/themes/velocity/assets/images/flags/en.png`
"
alt=""
width="20"
height="20"
v-if="locale.code == 'en'"
/>
<img
class="category-icon"
:src="
`${$root.baseUrl}/storage/${locale.locale_image}`
"
alt=""
width="20"
height="20"
v-else
/>
</div>
<span v-text="locale.name"></span>
</a>
</li>
</ul>
</div>
<div class="wrapper" v-else-if="currencies">
<div class="drawer-section">
<i
class="rango-arrow-left fs24 text-down-4"
@click="toggleMetaInfo('currencies')"
></i>
<h4
class="display-inbl"
v-text="__('shop.general.currencies')"
></h4>
<i
class="material-icons float-right text-dark"
@click="closeDrawer()"
>cancel</i
>
</div>
<ul type="none">
<li
v-for="(currency, index) in allCurrencies"
:key="index"
>
<a
class="unset"
:href="`?currency=${currency.code}`"
>
<span v-text="currency.code"></span>
</a>
</li>
</ul>
</div>
</div>
<div class="hamburger-wrapper" @click="toggleHamburger">
<i class="rango-toggle hamburger"></i>
</div>
<slot name="logo"></slot>
</div>
<div class="right-vc-header col-6">
<slot name="top-header"></slot>
<a class="unset cursor-pointer" @click="openSearchBar">
<i class="material-icons">search</i>
</a>
<a :href="cartRoute" class="unset">
<i class="material-icons text-down-3">shopping_cart</i>
<div class="badge-wrapper">
<span class="badge" v-text="updatedCartItemsCount"></span>
</div>
</a>
</div>
<div class="right searchbar" v-if="isSearchbar">
<slot name="search-bar"></slot>
</div>
</div>
</template>
<script type="text/javascript">
export default {
props: [
'isCustomer',
'heading',
'headerContent',
'categoryCount',
'cartItemsCount',
'cartRoute',
'locale',
'allLocales',
'currency',
'allCurrencies'
],
data: function() {
return {
compareCount: 0,
wishlistCount: 0,
languages: false,
hamburger: false,
currencies: false,
subCategory: null,
isSearchbar: false,
rootCategories: true,
rootCategoriesCollection: this.$root.sharedRootCategories,
updatedCartItemsCount: this.cartItemsCount
};
},
watch: {
hamburger: function(value) {
if (value) {
document.body.classList.add('open-hamburger');
} else {
document.body.classList.remove('open-hamburger');
}
},
'$root.headerItemsCount': function() {
this.updateHeaderItemsCount();
},
'$root.miniCartKey': function() {
this.getMiniCartDetails();
},
'$root.sharedRootCategories': function(categories) {
this.formatCategories(categories);
}
},
created: function() {
this.getMiniCartDetails();
this.updateHeaderItemsCount();
},
methods: {
openSearchBar: function() {
this.isSearchbar = !this.isSearchbar;
let footer = $('.footer');
let homeContent = $('#home-right-bar-container');
if (this.isSearchbar) {
footer[0].style.opacity = '.3';
homeContent[0].style.opacity = '.3';
} else {
footer[0].style.opacity = '1';
homeContent[0].style.opacity = '1';
}
},
toggleHamburger: function() {
this.hamburger = !this.hamburger;
},
closeDrawer: function() {
$('.nav-container').hide();
this.toggleHamburger();
this.rootCategories = true;
},
toggleSubcategories: function(index, event) {
if (index == 'root') {
this.rootCategories = true;
this.subCategory = false;
} else {
event.preventDefault();
let categories = this.$root.sharedRootCategories;
this.rootCategories = false;
this.subCategory = categories[index];
}
},
toggleMetaInfo: function(metaKey) {
this.rootCategories = !this.rootCategories;
this[metaKey] = !this[metaKey];
},
updateHeaderItemsCount: function() {
if (this.isCustomer != 'true') {
let comparedItems = this.getStorageValue('compared_product');
if (comparedItems) {
this.compareCount = comparedItems.length;
}
} else {
this.$http
.get(`${this.$root.baseUrl}/items-count`)
.then(response => {
this.compareCount = response.data.compareProductsCount;
this.wishlistCount =
response.data.wishlistedProductsCount;
})
.catch(exception => {
console.log(this.__('error.something_went_wrong'));
});
}
},
getMiniCartDetails: function() {
this.$http
.get(`${this.$root.baseUrl}/mini-cart`)
.then(response => {
if (response.data.status) {
this.updatedCartItemsCount =
response.data.mini_cart.cart_items.length;
}
})
.catch(exception => {
console.log(this.__('error.something_went_wrong'));
});
},
formatCategories: function(categories) {
let slicedCategories = categories;
let categoryCount = this.categoryCount ? this.categoryCount : 9;
if (slicedCategories && slicedCategories.length > categoryCount) {
slicedCategories = categories.slice(0, categoryCount);
}
this.rootCategoriesCollection = slicedCategories;
}
}
};
</script>

View File

@ -0,0 +1,22 @@
<template>
<ul type="none" class="no-margin">
<li v-for="(content, index) in headerContent" :key="index">
<a
v-text="content.title"
:href="`${$root.baseUrl}/${content['page_link']}`"
v-if="
content['content_type'] == 'link' ||
content['content_type'] == 'category'
"
:target="content['link_target'] ? '_blank' : '_self'"
>
</a>
</li>
</ul>
</template>
<script>
export default {
props: ['headerContent']
};
</script>

View File

@ -0,0 +1,112 @@
<template>
<div class="btn-group full-width force-center">
<div class="selectdiv">
<select
class="form-control fs13 styled-select"
name="category"
aria-label="Category"
@change="focusInput($event)"
>
<option value="" v-text="__('header.all-categories')"></option>
<template
v-for="(category, index) in $root.sharedRootCategories"
>
<option
:key="index"
selected="selected"
:value="category.id"
v-if="category.id == searchedQuery.category"
v-text="category.name"
>
</option>
<option
:key="index"
:value="category.id"
v-text="category.name"
v-else
></option>
</template>
</select>
<div class="select-icon-container d-inline-block float-right">
<span class="select-icon rango-arrow-down"></span>
</div>
</div>
<input
required
name="term"
type="search"
class="form-control"
:placeholder="__('header.search-text')"
aria-label="Search"
v-model:value="inputVal"
/>
<slot name="image-search"></slot>
<button
class="btn"
type="button"
id="header-search-icon"
aria-label="Search"
@click="submitForm"
>
<i class="fs16 fw6 rango-search"></i>
</button>
</div>
</template>
<script type="text/javascript">
export default {
data: function() {
return {
inputVal: '',
searchedQuery: []
};
},
created: function() {
let searchedItem = window.location.search.replace('?', '');
searchedItem = searchedItem.split('&');
let updatedSearchedCollection = {};
searchedItem.forEach(item => {
let splitedItem = item.split('=');
updatedSearchedCollection[splitedItem[0]] = decodeURI(
splitedItem[1]
);
});
if (updatedSearchedCollection['image-search'] == 1) {
updatedSearchedCollection.term = '';
}
this.searchedQuery = updatedSearchedCollection;
if (this.searchedQuery.term) {
this.inputVal = decodeURIComponent(
this.searchedQuery.term.split('+').join(' ')
);
}
},
methods: {
focusInput: function(event) {
$(event.target.parentElement.parentElement)
.find('input')
.focus();
},
submitForm: function() {
if (this.inputVal !== '') {
$('input[name=term]').val(this.inputVal);
$('#search-form').submit();
}
}
}
};
</script>

View File

@ -0,0 +1,29 @@
<template>
<div
id="main-category"
:class="
`main-category fs16 unselectable fw6 ${
$root.sharedRootCategories.length > 0
? 'cursor-pointer'
: 'cursor-not-allowed'
} left`
"
@mouseout="toggleSidebar('0', $event, 'mouseout')"
@mouseover="toggleSidebar('0', $event, 'mouseover')"
>
<i class="rango-view-list text-down-4 align-vertical-top fs18"> </i>
<span
class="pl5"
v-text="heading"
@mouseover="toggleSidebar('0', $event, 'mouseover')"
>
</span>
</div>
</template>
<script>
export default {
props: ['heading']
};
</script>

View File

@ -0,0 +1,49 @@
<template>
<a class="wishlist-btn unset" :href="src">
<i class="material-icons">favorite_border</i>
<div class="badge-container" v-if="wishlistCount > 0">
<span class="badge" v-text="wishlistCount"></span>
</div>
<span v-text="__('header.wishlist')" v-if="isText == 'true'"></span>
</a>
</template>
<script type="text/javascript">
export default {
props: ['isCustomer', 'isText', 'src'],
data: function() {
return {
wishlistCount: 0
};
},
watch: {
'$root.headerItemsCount': function() {
this.updateHeaderItemsCount();
}
},
created: function() {
this.updateHeaderItemsCount();
},
methods: {
updateHeaderItemsCount: function() {
if (this.isCustomer == 'true') {
this.$http
.get(`${this.$root.baseUrl}/items-count`)
.then(response => {
this.wishlistCount =
response.data.wishlistedProductsCount;
})
.catch(exception => {
console.log(this.__('error.something_went_wrong'));
});
}
}
}
};
</script>

View File

@ -0,0 +1,19 @@
<template>
<div class="container-fluid hot-categories-container">
<card-list-header :heading="heading"></card-list-header>
<div class="row">
<hot-category
v-for="(category, index) in categories"
:key="index"
:slug="category"
></hot-category>
</div>
</div>
</template>
<script>
export default {
props: ['heading', 'categories']
};
</script>

View File

@ -0,0 +1,16 @@
<template>
<a
:class="`left ${addClass}`"
:href="redirectSrc"
aria-label="Logo"
>
<img class="logo" :src="imgSrc" alt="" />
</a>
</template>
<script>
export default {
template: '#logo-template',
props: ['addClass', 'imgSrc', 'redirectSrc']
};
</script>

View File

@ -0,0 +1,164 @@
<template>
<div class="d-inline-block image-search-container" v-if="status == 'true'">
<label for="image-search-container">
<i class="icon camera-icon"></i>
<input
type="file"
class="d-none"
ref="image_search_input"
id="image-search-container"
v-on:change="loadLibrary()"
/>
<img
class="d-none"
id="uploaded-image-url"
:src="uploadedImageUrl"
alt=""
width="20"
height="20"
/>
</label>
</div>
</template>
<script>
export default {
props: ['status', 'uploadSrc', 'viewSrc', 'commonError', 'sizeLimitEror'],
data: function() {
return {
uploadedImageUrl: ''
};
},
methods: {
/**
* This method will dynamically load the scripts. Because image search library
* only used when someone clicks or interact with the image button. This will
* reduce some data usage for mobile user.
*/
loadLibrary: function() {
this.loadDynamicScript(
'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs',
() => {
this.loadDynamicScript(
'https://cdn.jsdelivr.net/npm/@tensorflow-models/mobilenet',
() => {
this.uploadImage();
}
);
}
);
},
/**
* This method will analyze the image and load the sets on the bases of trained model.
*/
uploadImage: function() {
var imageInput = this.$refs.image_search_input;
if (imageInput.files && imageInput.files[0]) {
if (imageInput.files[0].type.includes('image/')) {
if (imageInput.files[0].size <= 2000000) {
this.$root.showLoader();
var formData = new FormData();
formData.append('image', imageInput.files[0]);
axios
.post(this.uploadSrc, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(response => {
var net;
var self = this;
this.uploadedImageUrl = response.data;
async function app() {
var analysedResult = [];
var queryString = '';
net = await mobilenet.load();
const imgElement = document.getElementById(
'uploaded-image-url'
);
try {
const result = await net.classify(
imgElement
);
result.forEach(function(value) {
queryString = value.className.split(
','
);
if (queryString.length > 1) {
analysedResult = analysedResult.concat(
queryString
);
} else {
analysedResult.push(
queryString[0]
);
}
});
} catch (error) {
self.$root.hideLoader();
window.showAlert(
`alert-danger`,
this.__('shop.general.alert.error'),
this.commonError
);
}
localStorage.searchedImageUrl =
self.uploadedImageUrl;
queryString = localStorage.searched_terms = analysedResult.join(
'_'
);
self.$root.hideLoader();
window.location.href = `${self.viewSrc}?term=${queryString}&image-search=1`;
}
app();
})
.catch(() => {
this.$root.hideLoader();
window.showAlert(
`alert-danger`,
this.__('shop.general.alert.error'),
this.commonError
);
});
} else {
imageInput.value = '';
window.showAlert(
`alert-danger`,
this.__('shop.general.alert.error'),
this.sizeLimitEror
);
}
} else {
imageInput.value = '';
alert('Only images (.jpeg, .jpg, .png, ..) are allowed.');
}
}
}
}
};
</script>

View File

@ -0,0 +1,42 @@
<template>
<button
type="button"
id="mini-cart"
@click="toggleMiniCart"
:class="
`btn btn-link disable-box-shadow ${
itemCount == 0 ? 'cursor-not-allowed' : ''
}`
"
>
<div class="mini-cart-content">
<i class="material-icons-outlined text-down-3">shopping_cart</i>
<span class="badge" v-text="itemCount" v-if="itemCount != 0"></span>
<span class="fs18 fw6 cart-text" v-text="cartText"></span>
</div>
<div class="down-arrow-container">
<span class="rango-arrow-down"></span>
</div>
</button>
</template>
<script>
export default {
props: ['itemCount', 'cartText'],
methods: {
toggleMiniCart: function() {
let modal = $('#cart-modal-content')[0];
if (modal) modal.classList.toggle('hide');
let accountModal = $('.account-modal')[0];
if (accountModal) accountModal.classList.add('hide');
event.stopPropagation();
}
}
};
</script>

View File

@ -1,37 +1,63 @@
<template>
<div :class="`dropdown ${cartItems.length > 0 ? '' : 'disable-active'}`">
<cart-btn :item-count="cartItems.length"></cart-btn>
<mini-cart-button
:item-count="cartItems.length"
:cart-text="cartText"
></mini-cart-button>
<div
id="cart-modal-content"
v-if="cartItems.length > 0"
class="modal-content sensitive-modal cart-modal-content hide">
class="modal-content sensitive-modal cart-modal-content hide"
>
<div class="mini-cart-container">
<div class="row small-card-container" :key="index" v-for="(item, index) in cartItems">
<div
class="row small-card-container"
:key="index"
v-for="(item, index) in cartItems"
>
<div class="col-3 product-image-container mr15">
<a @click="removeProduct(item.id)">
<span class="rango-close"></span>
</a>
<a class="unset" :href="`${$root.baseUrl}/${item.url_key}`">
<a
class="unset"
:href="`${$root.baseUrl}/${item.url_key}`"
>
<div
class="product-image"
:style="`background-image: url(${item.images.medium_image_url});`">
</div>
:style="
`background-image: url(${item.images.medium_image_url});`
"
></div>
</a>
</div>
<div class="col-9 no-padding card-body align-vertical-top">
<div class="no-padding">
<div class="fs16 text-nowrap fw6" v-html="item.name"></div>
<div
class="fs16 text-nowrap fw6"
v-html="item.name"
></div>
<div class="fs18 card-current-price fw6">
<div class="display-inbl">
<label class="fw5">{{ __('checkout.qty') }}</label>
<input type="text" disabled :value="item.quantity" class="ml5" />
<label class="fw5">{{
__('checkout.qty')
}}</label>
<input
type="text"
disabled
:value="item.quantity"
class="ml5"
/>
</div>
<span class="card-total-price fw6">
{{ isTaxInclusive == '1' ? item.base_total_with_tax : item.base_total }}
{{
isTaxInclusive == '1'
? item.base_total_with_tax
: item.base_total
}}
</span>
</div>
</div>
@ -44,17 +70,25 @@
{{ subtotalText }}
</h5>
<h5 class="col-6 text-right fw6 no-padding">{{ isTaxInclusive == '1' ? cartInformation.base_grand_total : cartInformation.base_sub_total }}</h5>
<h5 class="col-6 text-right fw6 no-padding">
{{
isTaxInclusive == '1'
? cartInformation.base_grand_total
: cartInformation.base_sub_total
}}
</h5>
</div>
<div class="modal-footer">
<a class="col text-left fs16 link-color remove-decoration" :href="viewCart">{{ cartText }}</a>
<a
class="col text-left fs16 link-color remove-decoration"
:href="viewCartRoute"
>{{ viewCartText }}</a
>
<div class="col text-right no-padding">
<a :href="checkoutUrl" @click="checkMinimumOrder($event)">
<button
type="button"
class="theme-btn fs16 fw6">
<a :href="checkoutRoute" @click="checkMinimumOrder($event)">
<button type="button" class="theme-btn fs16 fw6">
{{ checkoutText }}
</button>
</a>
@ -65,79 +99,88 @@
</template>
<style lang="scss">
.hide {
display: none !important;
}
.hide {
display: none !important;
}
</style>
<script>
export default {
props: [
'isTaxInclusive',
'cartText',
'viewCart',
'checkoutUrl',
'checkoutText',
'subtotalText',
'checkMinimumOrderUrl'
],
export default {
props: [
'isTaxInclusive',
'viewCartRoute',
'checkoutRoute',
'checkMinimumOrderRoute',
'cartText',
'viewCartText',
'checkoutText',
'subtotalText'
],
data: function () {
return {
cartItems: [],
cartInformation: [],
}
},
data: function() {
return {
cartItems: [],
cartInformation: []
};
},
mounted: function () {
mounted: function() {
this.getMiniCartDetails();
},
watch: {
'$root.miniCartKey': function() {
this.getMiniCartDetails();
},
}
},
watch: {
'$root.miniCartKey': function () {
this.getMiniCartDetails();
}
},
methods: {
getMiniCartDetails: function () {
this.$http.get(`${this.$root.baseUrl}/mini-cart`)
methods: {
getMiniCartDetails: function() {
this.$http
.get(`${this.$root.baseUrl}/mini-cart`)
.then(response => {
if (response.data.status) {
this.cartItems = response.data.mini_cart.cart_items;
this.cartInformation = response.data.mini_cart.cart_details;
this.cartInformation =
response.data.mini_cart.cart_details;
}
})
.catch(exception => {
console.log(this.__('error.something_went_wrong'));
});
},
},
removeProduct: function (productId) {
this.$http.delete(`${this.$root.baseUrl}/cart/remove/${productId}`)
removeProduct: function(productId) {
this.$http
.delete(`${this.$root.baseUrl}/cart/remove/${productId}`)
.then(response => {
this.cartItems = this.cartItems.filter(item => item.id != productId);
this.cartItems = this.cartItems.filter(
item => item.id != productId
);
this.$root.miniCartKey++;
window.showAlert(`alert-${response.data.status}`, response.data.label, response.data.message);
window.showAlert(
`alert-${response.data.status}`,
response.data.label,
response.data.message
);
})
.catch(exception => {
console.log(this.__('error.something_went_wrong'));
});
},
},
checkMinimumOrder: function (e) {
e.preventDefault();
checkMinimumOrder: function(e) {
e.preventDefault();
this.$http.post(this.checkMinimumOrderUrl)
.then(({ data }) => {
if (! data.status) {
window.showAlert(`alert-warning`, 'Warning', data.message);
} else {
window.location.href = this.checkoutUrl;
}
});
}
this.$http.post(this.checkMinimumOrderRoute).then(({ data }) => {
if (!data.status) {
window.showAlert(`alert-warning`, 'Warning', data.message);
} else {
window.location.href = this.checkoutRoute;
}
});
}
}
};
</script>

View File

@ -0,0 +1,11 @@
<template>
<div class="modal-parent" v-if="$root.loading">
<div class="overlay-loader">
<div class="cp-spinner cp-round"></div>
</div>
</div>
</template>
<script>
export default {};
</script>

View File

@ -0,0 +1,19 @@
<template>
<div class="container-fluid popular-categories-container">
<card-list-header :heading="heading"></card-list-header>
<div class="row">
<popular-category
v-for="(category, index) in categories"
:key="index"
:slug="category"
></popular-category>
</div>
</div>
</template>
<script>
export default {
props: ['heading', 'categories']
};
</script>

View File

@ -59,7 +59,7 @@
:title="product.name"
:href="`${baseUrl}/${product.slug}`">
<span class="fs16">{{ product.name | truncate }}</span>
<span class="fs16">{{ product.name }}</span>
</a>
</div>

View File

@ -51,7 +51,7 @@
props: {
count: {
type: String,
default: 10
default: '10'
},
productId: {
type: String,

View File

@ -0,0 +1,96 @@
<template>
<div
:class="
`quantity control-group ${
errors.has(controlName) ? 'has-error' : ''
}`
"
>
<label
class="required"
for="quantity-changer"
v-text="quantityText"
></label>
<button type="button" class="decrease" @click="decreaseQty()">-</button>
<input
:value="qty"
class="control"
:name="controlName"
:v-validate="validations"
id="quantity-changer"
:data-vv-as="`&quot;${quantityText}&quot;`"
readonly
/>
<button type="button" class="increase" @click="increaseQty()">+</button>
<span class="control-error" v-if="errors.has(controlName)">{{
errors.first(controlName)
}}</span>
</div>
</template>
<script>
export default {
template: '#quantity-changer-template',
inject: ['$validator'],
props: {
controlName: {
type: String,
default: 'quantity'
},
quantity: {
type: [Number, String],
default: 1
},
quantityText: {
type: String,
default: 'Quantity'
},
minQuantity: {
type: [Number, String],
default: 1
},
validations: {
type: String,
default: 'required|numeric|min_value:1'
}
},
data: function() {
return {
qty: this.quantity
};
},
watch: {
quantity: function(val) {
this.qty = val;
this.$emit('onQtyUpdated', this.qty);
}
},
methods: {
decreaseQty: function() {
if (this.qty > this.minQuantity) this.qty = parseInt(this.qty) - 1;
this.$emit('onQtyUpdated', this.qty);
},
increaseQty: function() {
this.qty = parseInt(this.qty) + 1;
this.$emit('onQtyUpdated', this.qty);
}
}
};
</script>

View File

@ -0,0 +1,93 @@
/**
* Main imports.
*/
import Vue from 'vue';
import axios from 'axios';
/**
* Helper functions.
*/
import {
getBaseUrl,
isMobile,
loadDynamicScript,
showAlert,
removeTrailingSlash
} from './app-helpers';
/**
* Vue prototype.
*/
Vue.prototype.$http = axios;
/**
* Window assignation.
*/
window.Vue = Vue;
window.eventBus = new Vue();
window.axios = axios;
window.jQuery = window.$ = require('jquery');
window.BootstrapSass = require('bootstrap-sass');
window.getBaseUrl = getBaseUrl;
window.isMobile = isMobile;
window.loadDynamicScript = loadDynamicScript;
window.showAlert = showAlert;
/**
* Dynamic loading for mobile.
*/
$(function() {
/**
* Base url.
*/
let baseUrl = getBaseUrl();
/**
* Velocity JS path. Just make sure if you are renaming
* file then update this path also for mobile.
*/
let velocityJSPath = 'themes/velocity/assets/js/velocity.js';
if (
isMobile() &&
removeTrailingSlash(baseUrl) ===
removeTrailingSlash(window.location.href)
) {
/**
* Event for mobile to check the user interaction for the homepage. In mobile,
* if your viewport is having dynamic content then, feel free to override this.
* Else it is recommended to have some, static content in the viewport as the
* first impression to reduce LCP.
*/
document.addEventListener(
'touchstart',
function dynamicScript() {
window.scrollTo(0, 0);
document.body.style.overflow = 'hidden';
loadDynamicScript(`${baseUrl}/${velocityJSPath}`, () => {
window.scrollTo(0, 0);
document.body.style.overflow = '';
this.removeEventListener('touchstart', dynamicScript);
});
},
false
);
} else {
/**
* Else leave it default as previous.
*/
loadDynamicScript(`${baseUrl}/${velocityJSPath}`, () => {});
}
});

View File

@ -0,0 +1,49 @@
export function getBaseUrl() {
return document.querySelector('meta[name="base-url"]').content;
}
export function isMobile() {
if (
/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i |
/mobi/i.test(navigator.userAgent)
) {
return true;
}
return false;
}
export function loadDynamicScript(src, onScriptLoaded) {
let dynamicScript = document.createElement('script');
dynamicScript.setAttribute('src', src);
document.body.appendChild(dynamicScript);
dynamicScript.addEventListener('load', onScriptLoaded, false);
}
export function showAlert(messageType, messageLabel, message) {
if (messageType && message !== '') {
let alertId = Math.floor(Math.random() * 1000);
let html = `<div class="alert ${messageType} alert-dismissible" id="${alertId}">
<a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
<strong>${
messageLabel ? messageLabel + '!' : ''
} </strong> ${message}.
</div>`;
$('#alert-container')
.append(html)
.ready(() => {
window.setTimeout(() => {
$(`#alert-container #${alertId}`).remove();
}, 5000);
});
}
}
export function removeTrailingSlash(site) {
return site.replace(/\/$/, '');
}

361
packages/Webkul/Velocity/src/Resources/assets/js/app.js vendored Executable file → Normal file
View File

@ -1,140 +1,169 @@
import Vue from 'vue';
import accounting from 'accounting';
/**
* Main imports.
*/
import Accounting from 'accounting';
import VeeValidate from 'vee-validate';
import VueCarousel from 'vue-carousel';
import VueToast from 'vue-toast-notification';
import 'vue-toast-notification/dist/index.css';
import de from 'vee-validate/dist/locale/de';
import 'lazysizes';
/**
* Lang imports.
*/
import ar from 'vee-validate/dist/locale/ar';
import de from 'vee-validate/dist/locale/de';
import fa from 'vee-validate/dist/locale/fa';
import fr from 'vee-validate/dist/locale/fr';
import nl from 'vee-validate/dist/locale/nl';
import tr from 'vee-validate/dist/locale/tr';
import VeeValidate, { Validator } from 'vee-validate';
import axios from 'axios';
import 'lazysizes';
window.axios = axios;
window.VeeValidate = VeeValidate;
window.jQuery = window.$ = require("jquery");
window.BootstrapSass = require("bootstrap-sass");
Vue.use(VueToast);
/**
* Vue plugins.
*/
Vue.use(VueCarousel);
Vue.use(BootstrapSass);
Vue.prototype.$http = axios;
Vue.use(VeeValidate, {
dictionary: {
ar: ar,
de: de,
fa: fa,
fr: fr,
nl: nl,
tr: tr,
fa: fa,
fr: fr,
nl: nl,
tr: tr
}
});
Vue.filter('currency', function (value, argument) {
return accounting.formatMoney(value, argument);
})
/**
* Filters.
*/
Vue.filter('currency', function(value, argument) {
return Accounting.formatMoney(value, argument);
});
window.Vue = Vue;
window.Carousel = VueCarousel;
// UI components
Vue.component("vue-slider", require("vue-slider-component"));
/**
* Global components.
**/
Vue.component('vue-slider', require('vue-slider-component'));
Vue.component('mini-cart-button', require('./UI/components/mini-cart-button'));
Vue.component('mini-cart', require('./UI/components/mini-cart'));
Vue.component('modal-component', require('./UI/components/modal'));
Vue.component("add-to-cart", require("./UI/components/add-to-cart"));
Vue.component('add-to-cart', require('./UI/components/add-to-cart'));
Vue.component('star-ratings', require('./UI/components/star-rating'));
Vue.component('quantity-btn', require('./UI/components/quantity-btn'));
Vue.component('quantity-changer', require('./UI/components/quantity-changer'));
Vue.component('proceed-to-checkout', require('./UI/components/proceed-to-checkout'));
Vue.component('compare-component-with-badge', require('./UI/components/header-compare-with-badge'));
Vue.component('searchbar-component', require('./UI/components/header-searchbar'));
Vue.component('wishlist-component-with-badge', require('./UI/components/header-wishlist-with-badge'));
Vue.component('mobile-header', require('./UI/components/header-mobile'));
Vue.component('sidebar-header', require('./UI/components/header-sidebar'));
Vue.component('right-side-header', require('./UI/components/header-right-side'));
Vue.component('sidebar-component', require('./UI/components/sidebar'));
Vue.component("product-card", require("./UI/components/product-card"));
Vue.component("wishlist-component", require("./UI/components/wishlist"));
Vue.component('product-card', require('./UI/components/product-card'));
Vue.component('wishlist-component', require('./UI/components/wishlist'));
Vue.component('carousel-component', require('./UI/components/carousel'));
Vue.component('slider-component', require('./UI/components/banners'));
Vue.component('child-sidebar', require('./UI/components/child-sidebar'));
Vue.component('card-list-header', require('./UI/components/card-header'));
Vue.component('logo-component', require('./UI/components/image-logo'));
Vue.component('magnify-image', require('./UI/components/image-magnifier'));
Vue.component('image-search-component', require('./UI/components/image-search'));
Vue.component('compare-component', require('./UI/components/product-compare'));
Vue.component("shimmer-component", require("./UI/components/shimmer-component"));
Vue.component('shimmer-component', require('./UI/components/shimmer-component'));
Vue.component('responsive-sidebar', require('./UI/components/responsive-sidebar'));
Vue.component('product-quick-view', require('./UI/components/product-quick-view'));
Vue.component('product-quick-view-btn', require('./UI/components/product-quick-view-btn'));
Vue.component('recently-viewed', require('./UI/components/recently-viewed'));
Vue.component('product-collections', require('./UI/components/product-collections'));
Vue.component('hot-category', require('./UI/components/hot-category'));
Vue.component('hot-categories', require('./UI/components/hot-categories'));
Vue.component('popular-category', require('./UI/components/popular-category'));
Vue.component('popular-categories', require('./UI/components/popular-categories'));
Vue.component('velocity-overlay-loader', require('./UI/components/overlay-loader'));
Vue.component('vnode-injector', {
functional: true,
props: ['nodes'],
render(h, { props }) {
return props.nodes;
}
});
window.eventBus = new Vue();
$(document).ready(function () {
// define a mixin object
/**
* Start from here.
**/
$(function() {
/**
* Define a mixin object.
*/
Vue.mixin(require('./UI/components/trans'));
Vue.mixin({
data: function () {
data: function() {
return {
'imageObserver': null,
'navContainer': false,
'headerItemsCount': 0,
'sharedRootCategories': [],
'responsiveSidebarTemplate': '',
'responsiveSidebarKey': Math.random(),
'baseUrl': document.querySelector("script[src$='velocity.js']").getAttribute('baseUrl')
}
imageObserver: null,
navContainer: false,
headerItemsCount: 0,
sharedRootCategories: [],
responsiveSidebarTemplate: '',
responsiveSidebarKey: Math.random(),
baseUrl: getBaseUrl(),
};
},
methods: {
redirect: function (route) {
route ? window.location.href = route : '';
redirect: function(route) {
route ? (window.location.href = route) : '';
},
debounceToggleSidebar: function (id, {target}, type) {
// setTimeout(() => {
this.toggleSidebar(id, target, type);
// }, 500);
debounceToggleSidebar: function(id, { target }, type) {
this.toggleSidebar(id, target, type);
},
toggleSidebar: function (id, {target}, type) {
toggleSidebar: function(id, { target }, type) {
if (
Array.from(target.classList)[0] == "main-category"
|| Array.from(target.parentElement.classList)[0] == "main-category"
Array.from(target.classList)[0] == 'main-category' ||
Array.from(target.parentElement.classList)[0] ==
'main-category'
) {
let sidebar = $(`#sidebar-level-${id}`);
if (sidebar && sidebar.length > 0) {
if (type == "mouseover") {
if (type == 'mouseover') {
this.show(sidebar);
} else if (type == "mouseout") {
} else if (type == 'mouseout') {
this.hide(sidebar);
}
}
} else if (
Array.from(target.classList)[0] == "category"
|| Array.from(target.classList)[0] == "category-icon"
|| Array.from(target.classList)[0] == "category-title"
|| Array.from(target.classList)[0] == "category-content"
|| Array.from(target.classList)[0] == "rango-arrow-right"
Array.from(target.classList)[0] == 'category' ||
Array.from(target.classList)[0] == 'category-icon' ||
Array.from(target.classList)[0] == 'category-title' ||
Array.from(target.classList)[0] == 'category-content' ||
Array.from(target.classList)[0] == 'rango-arrow-right'
) {
let parentItem = target.closest('li');
if (target.id || parentItem.id.match('category-')) {
let subCategories = $(`#${target.id ? target.id : parentItem.id} .sub-categories`);
let subCategories = $(
`#${
target.id ? target.id : parentItem.id
} .sub-categories`
);
if (subCategories && subCategories.length > 0) {
let subCategories1 = Array.from(subCategories)[0];
subCategories1 = $(subCategories1);
if (type == "mouseover") {
if (type == 'mouseover') {
this.show(subCategories1);
let sidebarChild = subCategories1.find('.sidebar');
let sidebarChild = subCategories1.find(
'.sidebar'
);
this.show(sidebarChild);
} else if (type == "mouseout") {
} else if (type == 'mouseout') {
this.hide(subCategories1);
}
} else {
if (type == "mouseout") {
if (type == 'mouseout') {
let sidebar = $(`#${id}`);
sidebar.hide();
}
@ -143,57 +172,53 @@ $(document).ready(function () {
}
},
show: function (element) {
show: function(element) {
element.show();
element.mouseleave(({target}) => {
element.mouseleave(({ target }) => {
$(target.closest('.sidebar')).hide();
});
},
hide: function (element) {
hide: function(element) {
element.hide();
},
toggleButtonDisability ({event, actionType}) {
toggleButtonDisability({ event, actionType }) {
let button = event.target.querySelector('button[type=submit]');
button ? button.disabled = actionType : '';
button ? (button.disabled = actionType) : '';
},
onSubmit: function (event) {
this.toggleButtonDisability({event, actionType: true});
onSubmit: function(event) {
this.toggleButtonDisability({ event, actionType: true });
if(typeof tinyMCE !== 'undefined')
tinyMCE.triggerSave();
if (typeof tinyMCE !== 'undefined') tinyMCE.triggerSave();
this.$validator.validateAll().then(result => {
if (result) {
event.target.submit();
} else {
this.toggleButtonDisability({event, actionType: false});
this.toggleButtonDisability({
event,
actionType: false
});
eventBus.$emit('onFormError')
eventBus.$emit('onFormError');
}
});
},
isMobile: function () {
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i|/mobi/i.test(navigator.userAgent)) {
if (this.isMaxWidthCrossInLandScape()) {
return false;
}
return true
} else {
return false
}
isMobile: function() {
return isMobile();
},
isMaxWidthCrossInLandScape: function() {
return window.innerWidth > 900;
loadDynamicScript: function(src, onScriptLoaded) {
loadDynamicScript(src, onScriptLoaded);
},
getDynamicHTML: function (input) {
var _staticRenderFns;
getDynamicHTML: function(input) {
let _staticRenderFns, output;
const { render, staticRenderFns } = Vue.compile(input);
if (this.$options.staticRenderFns.length > 0) {
@ -203,7 +228,7 @@ $(document).ready(function () {
}
try {
var output = render.call(this, this.$createElement);
output = render.call(this, this.$createElement);
} catch (exception) {
console.log(this.__('error.something_went_wrong'));
}
@ -213,7 +238,7 @@ $(document).ready(function () {
return output;
},
getStorageValue: function (key) {
getStorageValue: function(key) {
let value = window.localStorage.getItem(key);
if (value) {
@ -223,92 +248,75 @@ $(document).ready(function () {
return value;
},
setStorageValue: function (key, value) {
setStorageValue: function(key, value) {
window.localStorage.setItem(key, JSON.stringify(value));
return true;
},
}
}
});
const app = new Vue({
el: "#app",
VueToast,
el: '#app',
data: function () {
data: function() {
return {
loading: false,
modalIds: {},
miniCartKey: 0,
quickView: false,
productDetails: [],
showPageLoader: false,
}
};
},
created: function () {
setTimeout(() => {
document.body.classList.remove("modal-open");
}, 0);
window.addEventListener('click', () => {
let modals = document.getElementsByClassName('sensitive-modal');
Array.from(modals).forEach(modal => {
modal.classList.add('hide');
});
});
},
mounted: function () {
setTimeout(() => {
this.addServerErrors();
}, 0);
document.body.style.display = "block";
mounted: function() {
this.$validator.localize(document.documentElement.lang);
this.addServerErrors();
this.loadCategories();
this.addIntersectionObserver();
},
methods: {
onSubmit: function (event) {
this.toggleButtonDisability({event, actionType: true});
onSubmit: function(event) {
this.toggleButtonDisability({ event, actionType: true });
if(typeof tinyMCE !== 'undefined')
tinyMCE.triggerSave();
if (typeof tinyMCE !== 'undefined') tinyMCE.triggerSave();
this.$validator.validateAll().then(result => {
if (result) {
event.target.submit();
} else {
this.toggleButtonDisability({event, actionType: false});
this.toggleButtonDisability({
event,
actionType: false
});
eventBus.$emit('onFormError')
eventBus.$emit('onFormError');
}
});
},
toggleButtonDisable (value) {
var buttons = document.getElementsByTagName("button");
toggleButtonDisable(value) {
let buttons = document.getElementsByTagName('button');
for (var i = 0; i < buttons.length; i++) {
for (let i = 0; i < buttons.length; i++) {
buttons[i].disabled = value;
}
},
addServerErrors: function (scope = null) {
for (var key in serverErrors) {
var inputNames = [];
addServerErrors: function(scope = null) {
for (let key in serverErrors) {
let inputNames = [];
key.split('.').forEach(function(chunk, index) {
if(index) {
inputNames.push('[' + chunk + ']')
if (index) {
inputNames.push('[' + chunk + ']');
} else {
inputNames.push(chunk)
inputNames.push(chunk);
}
})
});
var inputName = inputNames.join('');
let inputName = inputNames.join('');
const field = this.$validator.fields.find({
name: inputName,
@ -326,61 +334,62 @@ $(document).ready(function () {
}
},
addFlashMessages: function () {
addFlashMessages: function() {
if (window.flashMessages.alertMessage)
window.alert(window.flashMessages.alertMessage);
},
showModal: function (id) {
showModal: function(id) {
this.$set(this.modalIds, id, true);
},
loadCategories: function () {
this.$http.get(`${this.baseUrl}/categories`)
.then(response => {
this.sharedRootCategories = response.data.categories;
$(`<style type='text/css'> .sub-categories{ min-height:${response.data.categories.length * 30}px;} </style>`).appendTo("head");
})
.catch(error => {
console.log('failed to load categories');
})
},
addIntersectionObserver: function () {
this.imageObserver = new IntersectionObserver((entries, imgObserver) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const lazyImage = entry.target
lazyImage.src = lazyImage.dataset.src
}
loadCategories: function() {
this.$http
.get(`${this.baseUrl}/categories`)
.then(response => {
this.sharedRootCategories = response.data.categories;
$(
`<style type='text/css'> .sub-categories{ min-height:${response
.data.categories.length * 30}px;} </style>`
).appendTo('head');
})
});
.catch(error => {
console.log('failed to load categories');
});
},
showLoader: function () {
$('#loader').show();
$('.overlay-loader').show();
document.body.classList.add("modal-open");
addIntersectionObserver: function() {
this.imageObserver = new IntersectionObserver(
(entries, imgObserver) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src;
}
});
}
);
},
hideLoader: function () {
$('#loader').hide();
$('.overlay-loader').hide();
showLoader: function() {
this.loading = true;
},
document.body.classList.remove("modal-open");
}
hideLoader: function() {
this.loading = false;
},
togglePopup: function() {
let accountModal = $('#account-modal');
let modal = $('#cart-modal-content');
if (modal) modal.addClass('hide');
accountModal.toggleClass('hide');
},
}
});
window.app = app;
// for compilation of html coming from server
Vue.component('vnode-injector', {
functional: true,
props: ['nodes'],
render(h, {props}) {
return props.nodes;
}
});
});

View File

@ -1746,9 +1746,15 @@
min-height: 65vh;
position: relative;
}
.main-container-wrapper {
/**
* Sticky header for logo and search component. Just make sure
* this class should have height otherwise CLS score will reduce.
*/
.sticky-header {
top: 0px;
height: 55px;
z-index: 100;
position: sticky;
background: white;
@ -1759,7 +1765,6 @@
}
}
.search-container {
padding: 30px 20px;
@ -2223,9 +2228,8 @@
position: relative;
.VueCarousel-pagination {
bottom: 10px;
position: absolute;
display: none;
button:focus,
button:active {
outline: none;

View File

@ -1,6 +1,4 @@
body {
display: none;
overflow-x: hidden;
scroll-behavior: smooth;
.container-margin {
@ -463,8 +461,6 @@ header #search-form > *:focus {
.main-content-wrapper {
@extend .fs14;
margin: 0;
margin-bottom: 60px;
display: inline-block;
> .row {
@ -714,6 +710,10 @@ body::after {
max-width: 1300px !important;
}
.slider-container {
min-height: 400px;
}
.remove-padding-margin {
width: 100% !important;
margin: 0px !important;

View File

@ -46,6 +46,10 @@
}
}
}
.slider-container {
min-height: 290px;
}
}
/* medium devices */
@ -143,7 +147,7 @@
.badge-wrapper,
.badge-container {
top: -2px;
top: -32px;
left: -12px;
position: relative;
@ -987,6 +991,10 @@
position: absolute;
display: inline-block;
}
.slider-container {
min-height: 220px;
}
}
/* medium devices */
@ -1057,6 +1065,10 @@
.product-card-new {
max-width: 18rem;
}
.slider-container {
min-height: 220px;
}
}
/* small devices */
@ -1069,6 +1081,22 @@
position: unset;
top: unset;
}
.slider-container {
min-height: 100px;
}
.advertisement-four-container {
min-height: 992px;
.advertisement-container-block {
min-height: 425px;
}
.offers-ct-panel {
min-height: 425px;
}
}
}
/* very small devices */
@ -1085,4 +1113,20 @@
.quick-view-in-list {
display: none;
}
.slider-container {
min-height: 100px;
}
.advertisement-four-container {
min-height: 992px;
.advertisement-container-block {
min-height: 425px;
}
.offers-ct-panel {
min-height: 425px;
}
}
}

View File

@ -890,11 +890,12 @@ button[disabled] {
}
.modal-parent {
top: 0;
width: 100%;
height: 100%;
z-index: 5000;
position: fixed;
background: rgba(255, 255, 255, 0.9);
background: rgba(256, 256, 256, 0.9);
z-index: 125;
}
.compare-icon,

View File

@ -44,6 +44,8 @@
}
.material-icons {
max-width: 30px;
overflow: hidden;
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
@ -60,6 +62,8 @@
}
.material-icons-outlined {
max-width: 30px;
overflow: hidden;
font-family: 'Material Icons Outlined';
font-weight: normal;
font-style: normal;

View File

@ -1,575 +0,0 @@
@push('scripts')
<script type="text/x-template" id="content-header-template">
<header class="row velocity-divide-page vc-header header-shadow active">
<div class="vc-small-screen container">
<div class="row">
<div class="col-6">
<div v-if="hamburger" class="nav-container scrollable">
<div class="wrapper" v-if="this.rootCategories">
<div class="greeting drawer-section fw6">
<i class="material-icons">perm_identity</i>
<span>
@guest('customer')
<a class="unset" href="{{ route('customer.session.index') }}">
{{ __('velocity::app.responsive.header.greeting', ['customer' => 'Guest']) }}
</a>
@endguest
@auth('customer')
<a class="unset" href="{{ route('customer.profile.index') }}">
{{ __('velocity::app.responsive.header.greeting', ['customer' => auth()->guard('customer')->user()->first_name]) }}
</a>
@endauth
<i
@click="closeDrawer()"
class="material-icons float-right text-dark">
cancel
</i>
</span>
</div>
@php
$currency = $locale = null;
$currentLocale = app()->getLocale();
$currentCurrency = core()->getCurrentCurrencyCode();
$allLocales = core()->getCurrentChannel()->locales;
$allCurrency = core()->getCurrentChannel()->currencies;
@endphp
@foreach ($allLocales as $appLocale)
@if ($appLocale->code == $currentLocale)
@php
$locale = $appLocale;
@endphp
@endif
@endforeach
@foreach ($allCurrency as $appCurrency)
@if ($appCurrency->code == $currentCurrency)
@php
$currency = $appCurrency;
@endphp
@endif
@endforeach
<ul type="none" class="velocity-content" v-if="headerContent.length > 0">
<li :key="index" v-for="(content, index) in headerContent">
<a
class="unset"
v-text="content.title"
:href="`${$root.baseUrl}/${content.page_link}`">
</a>
</li>
</ul>
<ul type="none" class="category-wrapper" v-if="rootCategoriesCollection.length > 0">
<li v-for="(category, index) in rootCategoriesCollection">
<a class="unset" :href="`${$root.baseUrl}/${category.slug}`">
<div class="category-logo">
<img
class="category-icon"
v-if="category.category_icon_path"
:src="`${$root.baseUrl}/storage/${category.category_icon_path}`" alt="" width="20" height="20" />
</div>
<span v-text="category.name"></span>
</a>
<i class="rango-arrow-right" @click="toggleSubcategories(index, $event)"></i>
</li>
</ul>
@auth('customer')
<ul type="none" class="vc-customer-options">
<li>
<a href="{{ route('customer.profile.index') }}" class="unset">
<i class="icon profile text-down-3"></i>
<span>{{ __('shop::app.header.profile') }}</span>
</a>
</li>
<li>
<a href="{{ route('customer.address.index') }}" class="unset">
<i class="icon address text-down-3"></i>
<span>{{ __('velocity::app.shop.general.addresses') }}</span>
</a>
</li>
<li>
<a href="{{ route('customer.reviews.index') }}" class="unset">
<i class="icon reviews text-down-3"></i>
<span>{{ __('velocity::app.shop.general.reviews') }}</span>
</a>
</li>
@if (core()->getConfigData('general.content.shop.wishlist_option'))
<li>
<a href="{{ route('customer.wishlist.index') }}" class="unset">
<i class="icon wishlist text-down-3"></i>
<span>{{ __('shop::app.header.wishlist') }}</span>
</a>
</li>
@endif
@if (core()->getConfigData('general.content.shop.compare_option'))
<li>
<a href="{{ route('velocity.customer.product.compare') }}" class="unset">
<i class="icon compare text-down-3"></i>
<span>{{ __('shop::app.customer.compare.text') }}</span>
</a>
</li>
@endif
<li>
<a href="{{ route('customer.orders.index') }}" class="unset">
<i class="icon orders text-down-3"></i>
<span>{{ __('velocity::app.shop.general.orders') }}</span>
</a>
</li>
<li>
<a href="{{ route('customer.downloadable_products.index') }}" class="unset">
<i class="icon downloadables text-down-3"></i>
<span>{{ __('velocity::app.shop.general.downloadables') }}</span>
</a>
</li>
</ul>
@endauth
<ul type="none" class="meta-wrapper">
<li>
@if ($locale)
<div class="language-logo-wrapper">
@if ($locale->locale_image)
<img
class="language-logo"
src="{{ asset('/storage/' . $locale->locale_image) }}" alt="" />
@elseif ($locale->code == "en")
<img
class="language-logo"
src="{{ asset('/themes/velocity/assets/images/flags/en.png') }}" alt="" />
@endif
</div>
<span>{{ $locale->name }}</span>
@endif
<i
class="rango-arrow-right"
@click="toggleMetaInfo('languages')">
</i>
</li>
<li>
<span>{{ $currency->code }}</span>
<i
class="rango-arrow-right"
@click="toggleMetaInfo('currencies')">
</i>
</li>
<li>
@auth('customer')
<a
class="unset"
href="{{ route('customer.session.destroy') }}">
<span>{{ __('shop::app.header.logout') }}</span>
</a>
@endauth
@guest('customer')
<a
class="unset"
href="{{ route('customer.session.create') }}">
<span>{{ __('shop::app.customer.login-form.title') }}</span>
</a>
@endguest
</li>
<li>
@guest('customer')
<a
class="unset"
href="{{ route('customer.register.index') }}">
<span>{{ __('shop::app.header.sign-up') }}</span>
</a>
@endguest
</li>
</ul>
</div>
<div class="wrapper" v-else-if="subCategory">
<div class="drawer-section">
<i class="rango-arrow-left fs24 text-down-4" @click="toggleSubcategories('root')"></i>
<h4 class="display-inbl">@{{ subCategory.name }}</h4>
<i class="material-icons float-right text-dark" @click="closeDrawer()">
cancel
</i>
</div>
<ul type="none">
<li
:key="index"
v-for="(nestedSubCategory, index) in subCategory.children">
<a
class="unset"
:href="`${$root.baseUrl}/${subCategory.slug}/${nestedSubCategory.slug}`">
<div class="category-logo">
<img
class="category-icon"
v-if="nestedSubCategory.category_icon_path"
:src="`${$root.baseUrl}/storage/${nestedSubCategory.category_icon_path}`" alt="" width="20" height="20" />
</div>
<span>@{{ nestedSubCategory.name }}</span>
</a>
<ul
type="none"
class="nested-category"
v-if="nestedSubCategory.children && nestedSubCategory.children.length > 0">
<li
:key="`index-${Math.random()}`"
v-for="(thirdLevelCategory, index) in nestedSubCategory.children">
<a
class="unset"
:href="`${$root.baseUrl}/${subCategory.slug}/${nestedSubCategory.slug}/${thirdLevelCategory.slug}`">
<div class="category-logo">
<img
class="category-icon"
v-if="thirdLevelCategory.category_icon_path"
:src="`${$root.baseUrl}/storage/${thirdLevelCategory.category_icon_path}`" alt="" width="20" height="20" />
</div>
<span>@{{ thirdLevelCategory.name }}</span>
</a>
</li>
</ul>
</li>
</ul>
</div>
<div class="wrapper" v-else-if="languages">
<div class="drawer-section">
<i class="rango-arrow-left fs24 text-down-4" @click="toggleMetaInfo('languages')"></i>
<h4 class="display-inbl">{{ __('velocity::app.responsive.header.languages') }}</h4>
<i class="material-icons float-right text-dark" @click="closeDrawer()">cancel</i>
</div>
<ul type="none">
@foreach ($allLocales as $locale)
<li>
<a
class="unset"
@if (isset($serachQuery))
href="?{{ $serachQuery }}&locale={{ $locale->code }}"
@else
href="?locale={{ $locale->code }}"
@endif>
@if( $locale->code == 'en')
<div class="category-logo">
<img
class="category-icon"
src="{{ asset('/themes/velocity/assets/images/flags/en.png') }}" alt="" width="20" height="20" />
</div>
@else
<div class="category-logo">
<img
class="category-icon"
src="{{ asset('/storage/' . $locale->locale_image) }}" alt="" width="20" height="20" />
</div>
@endif
<span>
{{ isset($serachQuery) ? $locale->title : $locale->name }}
</span>
</a>
</li>
@endforeach
</ul>
</div>
<div class="wrapper" v-else-if="currencies">
<div class="drawer-section">
<i class="rango-arrow-left fs24 text-down-4" @click="toggleMetaInfo('currencies')"></i>
<h4 class="display-inbl">{{ __('velocity::app.shop.general.currencies') }}</h4>
<i class="material-icons float-right text-dark" @click="closeDrawer()">cancel</i>
</div>
<ul type="none">
@foreach ($allCurrency as $currency)
<li>
@if (isset($serachQuery))
<a
class="unset"
href="?{{ $serachQuery }}&locale={{ $currency->code }}">
<span>{{ $currency->code }}</span>
</a>
@else
<a
class="unset"
href="?currency={{ $currency->code }}">
<span>{{ $currency->code }}</span>
</a>
@endif
</li>
@endforeach
</ul>
</div>
</div>
<div class="hamburger-wrapper" @click="toggleHamburger">
<i class="rango-toggle hamburger"></i>
</div>
<logo-component></logo-component>
</div>
@php
$showCompare = core()->getConfigData('general.content.shop.compare_option') == "1" ? true : false;
$showWishlist = core()->getConfigData('general.content.shop.wishlist_option') == "1" ? true : false;
@endphp
<div class="right-vc-header col-6">
@if ($showCompare)
<a
class="compare-btn unset"
@auth('customer')
href="{{ route('velocity.customer.product.compare') }}"
@endauth
@guest('customer')
href="{{ route('velocity.product.compare') }}"
@endguest
>
<div class="badge-container" v-if="compareCount > 0">
<span class="badge" v-text="compareCount"></span>
</div>
<i class="material-icons">compare_arrows</i>
</a>
@endif
@if ($showWishlist)
<a class="wishlist-btn unset" :href="`{{ route('customer.wishlist.index') }}`">
<div class="badge-container" v-if="wishlistCount > 0">
<span class="badge" v-text="wishlistCount"></span>
</div>
<i class="material-icons">favorite_border</i>
</a>
@endif
<a class="unset cursor-pointer" @click="openSearchBar">
<i class="material-icons">search</i>
</a>
<a href="{{ route('shop.checkout.cart.index') }}" class="unset">
<div class="badge-wrapper">
<span class="badge">@{{ cartItemsCount }}</span>
</div>
<i class="material-icons text-down-3">shopping_cart</i>
</a>
</div>
<searchbar-component v-if="isSearchbar"></searchbar-component>
</div>
</div>
<div
id="main-category"
@mouseout="toggleSidebar('0', $event, 'mouseout')"
@mouseover="toggleSidebar('0', $event, 'mouseover')"
:class="`main-category fs16 unselectable fw6 ${($root.sharedRootCategories.length > 0) ? 'cursor-pointer' : 'cursor-not-allowed'} left`">
<i class="rango-view-list text-down-4 align-vertical-top fs18">
</i>
<span
class="pl5"
v-text="heading"
@mouseover="toggleSidebar('0', $event, 'mouseover')">
</span>
</div>
<div class="content-list right">
<ul type="none" class="no-margin">
<li v-for="(content, index) in headerContent" :key="index">
<a
v-text="content.title"
:href="`${$root.baseUrl}/${content['page_link']}`"
v-if="(content['content_type'] == 'link' || content['content_type'] == 'category')"
:target="content['link_target'] ? '_blank' : '_self'">
</a>
</li>
</ul>
</div>
</header>
</script>
@endpush
@php
$cart = cart()->getCart();
$cartItemsCount = trans('shop::app.minicart.zero');
if ($cart) {
$cartItemsCount = $cart->items->count();
}
@endphp
@push('scripts')
<script type="text/javascript">
(() => {
Vue.component('content-header', {
template: '#content-header-template',
props: [
'heading',
'headerContent',
'categoryCount',
],
data: function () {
return {
'compareCount': 0,
'wishlistCount': 0,
'languages': false,
'hamburger': false,
'currencies': false,
'subCategory': null,
'isSearchbar': false,
'rootCategories': true,
'cartItemsCount': '{{ $cartItemsCount }}',
'rootCategoriesCollection': this.$root.sharedRootCategories,
'isCustomer': '{{ auth()->guard('customer')->user() ? "true" : "false" }}' == "true",
}
},
watch: {
hamburger: function (value) {
if (value) {
document.body.classList.add('open-hamburger');
} else {
document.body.classList.remove('open-hamburger');
}
},
'$root.headerItemsCount': function () {
this.updateHeaderItemsCount();
},
'$root.miniCartKey': function () {
this.getMiniCartDetails();
},
'$root.sharedRootCategories': function (categories) {
this.formatCategories(categories);
}
},
created: function () {
this.getMiniCartDetails();
this.updateHeaderItemsCount();
},
methods: {
openSearchBar: function () {
this.isSearchbar = !this.isSearchbar;
let footer = $('.footer');
let homeContent = $('#home-right-bar-container');
if (this.isSearchbar) {
footer[0].style.opacity = '.3';
homeContent[0].style.opacity = '.3';
} else {
footer[0].style.opacity = '1';
homeContent[0].style.opacity = '1';
}
},
toggleHamburger: function () {
this.hamburger = !this.hamburger;
},
closeDrawer: function() {
$('.nav-container').hide();
this.toggleHamburger();
this.rootCategories = true;
},
toggleSubcategories: function (index, event) {
if (index == "root") {
this.rootCategories = true;
this.subCategory = false;
} else {
event.preventDefault();
let categories = this.$root.sharedRootCategories;
this.rootCategories = false;
this.subCategory = categories[index];
}
},
toggleMetaInfo: function (metaKey) {
this.rootCategories = ! this.rootCategories;
this[metaKey] = !this[metaKey];
},
updateHeaderItemsCount: function () {
if (! this.isCustomer) {
let comparedItems = this.getStorageValue('compared_product');
if (comparedItems) {
this.compareCount = comparedItems.length;
}
} else {
this.$http.get(`${this.$root.baseUrl}/items-count`)
.then(response => {
this.compareCount = response.data.compareProductsCount;
this.wishlistCount = response.data.wishlistedProductsCount;
})
.catch(exception => {
console.log(this.__('error.something_went_wrong'));
});
}
},
getMiniCartDetails: function () {
this.$http.get(`${this.$root.baseUrl}/mini-cart`)
.then(response => {
if (response.data.status) {
this.cartItemsCount = response.data.mini_cart.cart_items.length;
}
})
.catch(exception => {
console.log(this.__('error.something_went_wrong'));
});
},
formatCategories: function (categories) {
let slicedCategories = categories;
let categoryCount = this.categoryCount ? this.categoryCount : 9;
if (
slicedCategories
&& slicedCategories.length > categoryCount
) {
slicedCategories = categories.slice(0, categoryCount);
}
this.rootCategoriesCollection = slicedCategories;
},
},
});
})()
</script>
@endpush

View File

@ -1,475 +0,0 @@
@push('scripts')
<script type="text/x-template" id="cart-btn-template">
<button
type="button"
id="mini-cart"
@click="toggleMiniCart"
:class="`btn btn-link disable-box-shadow ${itemCount == 0 ? 'cursor-not-allowed' : ''}`">
<div class="mini-cart-content">
<i class="material-icons-outlined text-down-3">shopping_cart</i>
<span class="badge" v-text="itemCount" v-if="itemCount != 0"></span>
<span class="fs18 fw6 cart-text">{{ __('velocity::app.minicart.cart') }}</span>
</div>
<div class="down-arrow-container">
<span class="rango-arrow-down"></span>
</div>
</button>
</script>
<script type="text/x-template" id="close-btn-template">
<button type="button" class="close disable-box-shadow">
<span class="white-text fs20" @click="togglePopup">×</span>
</button>
</script>
<script type="text/x-template" id="quantity-changer-template">
<div :class="`quantity control-group ${errors.has(controlName) ? 'has-error' : ''}`">
<label class="required" for="quantity-changer">{{ __('shop::app.products.quantity') }}</label>
<button type="button" class="decrease" @click="decreaseQty()">-</button>
<input
:value="qty"
class="control"
:name="controlName"
:v-validate="validations"
id="quantity-changer"
data-vv-as="&quot;{{ __('shop::app.products.quantity') }}&quot;"
readonly />
<button type="button" class="increase" @click="increaseQty()">+</button>
<span class="control-error" v-if="errors.has(controlName)">@{{ errors.first(controlName) }}</span>
</div>
</script>
@endpush
@include('velocity::UI.header')
@push('scripts')
<script type="text/x-template" id="logo-template">
<a
:class="`left ${addClass}`"
href="{{ route('shop.home.index') }}"
aria-label="Logo">
@if ($logo = core()->getCurrentChannel()->logo_url)
<img class="logo" src="{{ $logo }}" alt="" width="200" height="50" />
@else
<img class="logo" src="{{ asset('themes/velocity/assets/images/logo-text.png') }}" alt="" width="200" height="50" />
@endif
</a>
</script>
<script type="text/x-template" id="searchbar-template">
<div class="right searchbar">
<div class="row">
<div class="col-lg-5 col-md-12">
<div class="input-group">
<form
method="GET"
role="search"
id="search-form"
action="{{ route('velocity.search.index') }}">
<div
class="btn-toolbar full-width"
role="toolbar">
<div class="btn-group full-width force-center">
<div class="selectdiv">
<select class="form-control fs13 styled-select" name="category" @change="focusInput($event)" aria-label="Category">
<option value="">
{{ __('velocity::app.header.all-categories') }}
</option>
<template v-for="(category, index) in $root.sharedRootCategories">
<option
:key="index"
selected="selected"
:value="category.id"
v-if="(category.id == searchedQuery.category)">
@{{ category.name }}
</option>
<option :key="index" :value="category.id" v-else>
@{{ category.name }}
</option>
</template>
</select>
<div class="select-icon-container d-inline-block float-right">
<span class="select-icon rango-arrow-down"></span>
</div>
</div>
<input
required
name="term"
type="search"
class="form-control"
placeholder="{{ __('velocity::app.header.search-text') }}"
aria-label="Search"
v-model:value="inputVal" />
<image-search-component></image-search-component>
<button class="btn" type="button" id="header-search-icon" aria-label="Search" @click="submitForm">
<i class="fs16 fw6 rango-search"></i>
</button>
</div>
</div>
</form>
</div>
</div>
<div class="col-lg-7 col-md-12 vc-full-screen">
<div class="left-wrapper">
@php
$showWishlist = core()->getConfigData('general.content.shop.wishlist_option') == "1" ? true : false;
$showCompare = core()->getConfigData('general.content.shop.compare_option') == "1" ? true : false;
@endphp
{!! view_render_event('bagisto.shop.layout.header.wishlist.before') !!}
@if($showWishlist)
<a class="wishlist-btn unset" :href="`{{ route('customer.wishlist.index') }}`">
<i class="material-icons">favorite_border</i>
<div class="badge-container" v-if="wishlistCount > 0">
<span class="badge" v-text="wishlistCount"></span>
</div>
<span>{{ __('shop::app.layouts.wishlist') }}</span>
</a>
@endif
{!! view_render_event('bagisto.shop.layout.header.wishlist.after') !!}
{!! view_render_event('bagisto.shop.layout.header.compare.before') !!}
@if ($showCompare)
<a
class="compare-btn unset"
@auth('customer')
href="{{ route('velocity.customer.product.compare') }}"
@endauth
@guest('customer')
href="{{ route('velocity.product.compare') }}"
@endguest
>
<i class="material-icons">compare_arrows</i>
<div class="badge-container" v-if="compareCount > 0">
<span class="badge" v-text="compareCount"></span>
</div>
<span>{{ __('velocity::app.customer.compare.text') }}</span>
</a>
@endif
{!! view_render_event('bagisto.shop.layout.header.compare.after') !!}
{!! view_render_event('bagisto.shop.layout.header.cart-item.before') !!}
@include('shop::checkout.cart.mini-cart')
{!! view_render_event('bagisto.shop.layout.header.cart-item.after') !!}
</div>
</div>
</div>
</div>
</script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/mobilenet"></script>
<script type="text/x-template" id="image-search-component-template">
<div class="d-inline-block image-search-container" v-if="image_search_status">
<label for="image-search-container">
<i class="icon camera-icon"></i>
<input
type="file"
class="d-none"
ref="image_search_input"
id="image-search-container"
v-on:change="uploadImage()" />
<img
class="d-none"
id="uploaded-image-url"
:src="uploadedImageUrl" alt="" width="20" height="20" />
</label>
</div>
</script>
<script type="text/javascript">
(() => {
Vue.component('cart-btn', {
template: '#cart-btn-template',
props: ['itemCount'],
methods: {
toggleMiniCart: function () {
let modal = $('#cart-modal-content')[0];
if (modal)
modal.classList.toggle('hide');
let accountModal = $('.account-modal')[0];
if (accountModal)
accountModal.classList.add('hide');
event.stopPropagation();
}
}
});
Vue.component('close-btn', {
template: '#close-btn-template',
methods: {
togglePopup: function () {
$('#cart-modal-content').hide();
}
}
});
Vue.component('quantity-changer', {
template: '#quantity-changer-template',
inject: ['$validator'],
props: {
controlName: {
type: String,
default: 'quantity'
},
quantity: {
type: [Number, String],
default: 1
},
minQuantity: {
type: [Number, String],
default: 1
},
validations: {
type: String,
default: 'required|numeric|min_value:1'
}
},
data: function() {
return {
qty: this.quantity
}
},
watch: {
quantity: function (val) {
this.qty = val;
this.$emit('onQtyUpdated', this.qty)
}
},
methods: {
decreaseQty: function() {
if (this.qty > this.minQuantity)
this.qty = parseInt(this.qty) - 1;
this.$emit('onQtyUpdated', this.qty)
},
increaseQty: function() {
this.qty = parseInt(this.qty) + 1;
this.$emit('onQtyUpdated', this.qty)
}
}
});
Vue.component('logo-component', {
template: '#logo-template',
props: ['addClass'],
});
Vue.component('searchbar-component', {
template: '#searchbar-template',
data: function () {
return {
inputVal: '',
compareCount: 0,
wishlistCount: 0,
searchedQuery: [],
isCustomer: '{{ auth()->guard('customer')->user() ? "true" : "false" }}' == "true",
}
},
watch: {
'$root.headerItemsCount': function () {
this.updateHeaderItemsCount();
}
},
created: function () {
let searchedItem = window.location.search.replace("?", "");
searchedItem = searchedItem.split('&');
let updatedSearchedCollection = {};
searchedItem.forEach(item => {
let splitedItem = item.split('=');
updatedSearchedCollection[splitedItem[0]] = decodeURI(splitedItem[1]);
});
if (updatedSearchedCollection['image-search'] == 1) {
updatedSearchedCollection.term = '';
}
this.searchedQuery = updatedSearchedCollection;
if (this.searchedQuery.term) {
this.inputVal = decodeURIComponent(this.searchedQuery.term.split('+').join(' '));
}
this.updateHeaderItemsCount();
},
methods: {
'focusInput': function (event) {
$(event.target.parentElement.parentElement).find('input').focus();
},
'submitForm': function () {
if (this.inputVal !== '') {
$('input[name=term]').val(this.inputVal);
$('#search-form').submit();
}
},
'updateHeaderItemsCount': function () {
if (! this.isCustomer) {
let comparedItems = this.getStorageValue('compared_product');
if (comparedItems) {
this.compareCount = comparedItems.length;
}
} else {
this.$http.get(`${this.$root.baseUrl}/items-count`)
.then(response => {
this.compareCount = response.data.compareProductsCount;
this.wishlistCount = response.data.wishlistedProductsCount;
})
.catch(exception => {
console.log(this.__('error.something_went_wrong'));
});
}
}
}
});
Vue.component('image-search-component', {
template: '#image-search-component-template',
data: function() {
return {
uploadedImageUrl: '',
image_search_status: "{{core()->getConfigData('general.content.shop.image_search') == '1' ? 'true' : 'false'}}" == 'true'
}
},
methods: {
uploadImage: function() {
var imageInput = this.$refs.image_search_input;
if (imageInput.files && imageInput.files[0]) {
if (imageInput.files[0].type.includes('image/')) {
if (imageInput.files[0].size <= 2000000) {
this.$root.showLoader();
var formData = new FormData();
formData.append('image', imageInput.files[0]);
axios.post(
"{{ route('shop.image.search.upload') }}",
formData,
{
headers: {
'Content-Type': 'multipart/form-data'
}
}
).then(response => {
var net;
var self = this;
this.uploadedImageUrl = response.data;
async function app() {
var analysedResult = [];
var queryString = '';
net = await mobilenet.load();
const imgElement = document.getElementById('uploaded-image-url');
try {
const result = await net.classify(imgElement);
result.forEach(function(value) {
queryString = value.className.split(',');
if (queryString.length > 1) {
analysedResult = analysedResult.concat(queryString)
} else {
analysedResult.push(queryString[0])
}
});
} catch (error) {
self.$root.hideLoader();
window.showAlert(
`alert-danger`,
this.__('shop.general.alert.error'),
"{{ __('shop::app.common.error') }}"
);
}
localStorage.searchedImageUrl = self.uploadedImageUrl;
queryString = localStorage.searched_terms = analysedResult.join('_');
self.$root.hideLoader();
window.location.href = "{{ route('shop.search.index') }}" + '?term=' + queryString + '&image-search=1';
}
app();
}).catch(() => {
this.$root.hideLoader();
window.showAlert(
`alert-danger`,
this.__('shop.general.alert.error'),
"{{ __('shop::app.common.error') }}"
);
});
} else {
imageInput.value = '';
window.showAlert(
`alert-danger`,
this.__('shop.general.alert.error'),
"{{ __('shop::app.common.image-upload-limit') }}"
);
}
} else {
imageInput.value = '';
alert('Only images (.jpeg, .jpg, .png, ..) are allowed.');
}
}
}
}
});
})()
</script>
@endpush

View File

@ -166,7 +166,8 @@
<div class="product-quantity col-3 no-padding">
<quantity-changer
:control-name="'qty[{{$item->id}}]'"
quantity="{{ $item->quantity }}">
quantity="{{ $item->quantity }}"
quantity-text="{{ __('shop::app.products.quantity') }}">
</quantity-changer>
</div>
@ -222,7 +223,8 @@
<div class="product-quantity col-lg-4 col-6 no-padding">
<quantity-changer
:control-name="'qty[{{$item->id}}]'"
quantity="{{ $item->quantity }}">
quantity="{{ $item->quantity }}"
quantity-text="{{ __('shop::app.products.quantity') }}">
</quantity-changer>
</div>

View File

@ -1,11 +1,12 @@
<div class="mini-cart-container">
<mini-cart
is-tax-inclusive="{{ Webkul\Tax\Helpers\Tax::isTaxInclusive() }}"
view-cart="{{ route('shop.checkout.cart.index') }}"
cart-text="{{ __('shop::app.minicart.view-cart') }}"
view-cart-route="{{ route('shop.checkout.cart.index') }}"
checkout-route="{{ route('shop.checkout.onepage.index') }}"
check-minimum-order-route="{{ route('shop.checkout.check-minimum-order') }}"
cart-text="{{ __('shop::app.minicart.cart') }}"
view-cart-text="{{ __('shop::app.minicart.view-cart') }}"
checkout-text="{{ __('shop::app.minicart.checkout') }}"
checkout-url="{{ route('shop.checkout.onepage.index') }}"
subtotal-text="{{ __('shop::app.checkout.cart.cart-subtotal') }}"
check-minimum-order-url="{{ route('shop.checkout.check-minimum-order') }}">
subtotal-text="{{ __('shop::app.checkout.cart.cart-subtotal') }}">
</mini-cart>
</div>

View File

@ -9,6 +9,8 @@
@endsection
@push('scripts')
<script type="text/javascript" src="{{ asset('vendor/webkul/ui/assets/js/ui.js') }}"></script>
@include('shop::checkout.cart.coupon')
<script type="text/x-template" id="checkout-template">

View File

@ -10,4 +10,8 @@
@yield('page-detail-wrapper')
</div>
</div>
@endsection
@endsection
@push('scripts')
<script type="text/javascript" src="{{ asset('vendor/webkul/ui/assets/js/ui.js') }}"></script>
@endpush

View File

@ -1,12 +1,13 @@
@php
$isRendered = false;
$advertisementFour = null;
$isLazyLoad = ! isset($lazyload) ? true : ( $lazyload ? true : false );
@endphp
@if ($velocityMetaData && $velocityMetaData->advertisement)
@php
$advertisement = json_decode($velocityMetaData->advertisement, true);
if (isset($advertisement[4]) && is_array($advertisement[4])) {
$advertisementFour = array_values(array_filter($advertisement[4]));
}
@ -21,27 +22,39 @@
<div class="row">
@if ( isset($advertisementFour[0]))
<a @if (isset($one)) href="{{ $one }}" @endif class="col-lg-4 col-12 no-padding" aria-label="Advertisement">
<img class="col-12 lazyload" data-src="{{ asset('/storage/' . $advertisementFour[0]) }}" alt="" />
<img
class="col-12 {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementFour[0]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementFour[0]) }}" alt="" />
</a>
@endif
<div class="col-lg-4 col-12 offers-ct-panel">
@if ( isset($advertisementFour[1]))
<a @if (isset($two)) href="{{ $two }}" @endif class="row col-12 remove-padding-margin" aria-label="Advertisement">
<img class="col-12 offers-ct-top lazyload" data-src="{{ asset('/storage/' . $advertisementFour[1]) }}" alt="" />
<img
class="col-12 offers-ct-top {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementFour[1]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementFour[1]) }}" alt="" />
</a>
@endif
@if ( isset($advertisementFour[2]))
<a @if (isset($three)) href="{{ $three }}" @endif class="row col-12 remove-padding-margin" aria-label="Advertisement">
<img class="col-12 offers-ct-bottom lazyload" data-src="{{ asset('/storage/' . $advertisementFour[2]) }}" alt="" />
<img
class="col-12 offers-ct-bottom {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementFour[2]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementFour[2]) }}" alt="" />
</a>
@endif
</div>
@if ( isset($advertisementFour[3]))
<a @if (isset($four)) href="{{ $four }}" @endif class="col-lg-4 col-12 no-padding" aria-label="Advertisement">
<img class="col-12 lazyload" data-src="{{ asset('/storage/' . $advertisementFour[3]) }}" alt="" />
<img
class="col-12 {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementFour[3]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementFour[3]) }}" alt="" />
</a>
@endif
</div>
@ -52,22 +65,38 @@
@if (! $isRendered)
<div class="container-fluid advertisement-four-container">
<div class="row">
<a @if (isset($one)) href="{{ $one }}" @endif class="col-lg-4 col-12 no-padding" aria-label="Advertisement">
<img class="col-12 lazyload" data-src="{{ asset('/themes/velocity/assets/images/big-sale-banner.webp') }}" alt="" />
</a>
<div class="col-lg-4 col-12 offers-ct-panel">
<a @if (isset($two)) href="{{ $two }}" @endif class="row col-12 remove-padding-margin" aria-label="Advertisement">
<img class="col-12 offers-ct-top lazyload" data-src="{{ asset('/themes/velocity/assets/images/seasons.webp') }}" alt="" />
</a>
<a @if (isset($three)) href="{{ $three }}" @endif class="row col-12 remove-padding-margin" aria-label="Advertisement">
<img class="col-12 offers-ct-bottom lazyload" data-src="{{ asset('/themes/velocity/assets/images/deals.webp') }}" alt="" />
<div class="col-lg-4 col-12 advertisement-container-block no-padding">
<a @if (isset($one)) href="{{ $one }}" @endif class="col-lg-4 col-12 no-padding" aria-label="Advertisement">
<img
class="col-12 {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/themes/velocity/assets/images/big-sale-banner.webp') }}" @endif
data-src="{{ asset('/themes/velocity/assets/images/big-sale-banner.webp') }}" alt="" />
</a>
</div>
<a @if (isset($four)) href="{{ $four }}" @endif class="col-lg-4 col-12 no-padding" aria-label="Advertisement">
<img class="col-12 lazyload" data-src="{{ asset('/themes/velocity/assets/images/kids.webp') }}" alt="" />
</a>
<div class="col-lg-4 col-12 advertisement-container-block offers-ct-panel">
<a @if (isset($two)) href="{{ $two }}" @endif class="row col-12 remove-padding-margin" aria-label="Advertisement">
<img
class="col-12 offers-ct-top {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/themes/velocity/assets/images/seasons.webp') }}" @endif
data-src="{{ asset('/themes/velocity/assets/images/seasons.webp') }}" alt="" />
</a>
<a @if (isset($three)) href="{{ $three }}" @endif class="row col-12 remove-padding-margin" aria-label="Advertisement">
<img
class="col-12 offers-ct-bottom {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/themes/velocity/assets/images/deals.webp') }}" @endif
data-src="{{ asset('/themes/velocity/assets/images/deals.webp') }}" alt="" />
</a>
</div>
<div class="col-lg-4 col-12 advertisement-container-block no-padding">
<a @if (isset($four)) href="{{ $four }}" @endif class="col-lg-4 col-12 no-padding" aria-label="Advertisement">
<img
class="col-12 {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/themes/velocity/assets/images/kids.webp') }}" @endif
data-src="{{ asset('/themes/velocity/assets/images/kids.webp') }}" alt="" />
</a>
</div>
</div>
</div>
@endif

View File

@ -1,12 +1,13 @@
@php
$isRendered = false;
$advertisementThree = null;
$isLazyLoad = ! isset($lazyload) ? true : ( $lazyload ? true : false );
@endphp
@if ($velocityMetaData && $velocityMetaData->advertisement)
@php
$advertisement = json_decode($velocityMetaData->advertisement, true);
if (isset($advertisement[3]) && is_array($advertisement[3])) {
$advertisementThree = array_values(array_filter($advertisement[3]));
}
@ -21,19 +22,28 @@
<div class="row">
@if ( isset($advertisementThree[0]))
<a @if (isset($one)) href="{{ $one }}" @endif class="col-lg-6 col-md-12 no-padding">
<img data-src="{{ asset('/storage/' . $advertisementThree[0]) }}" class="full-width lazyload" alt="" />
<img
class="full-width {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementThree[0]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementThree[0]) }}" alt="" />
</a>
@endif
<div class="col-lg-6 col-md-12 second-panel">
@if ( isset($advertisementThree[1]))
<a @if (isset($two)) href="{{ $two }}" @endif class="row top-container">
<img data-src="{{ asset('/storage/' . $advertisementThree[1]) }}" class="col-12 pr0 lazyload" alt="" />
<img
class="col-12 pr0 {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementThree[1]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementThree[1]) }}" alt="" />
</a>
@endif
@if ( isset($advertisementThree[2]))
<a @if (isset($three)) href="{{ $three }}" @endif class="row bottom-container">
<img data-src="{{ asset('/storage/' . $advertisementThree[2]) }}" class="col-12 pr0 lazyload" alt="" />
<img
class="col-12 pr0 {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementThree[2]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementThree[2]) }}" alt="" />
</a>
@endif
</div>
@ -46,15 +56,24 @@
<div class="container-fluid advertisement-three-container">
<div class="row">
<a @if (isset($one)) href="{{ $one }}" @endif class="col-lg-6 col-md-12 no-padding">
<img data-src="{{ asset('/themes/velocity/assets/images/headphones.webp') }}" class="full-width lazyload" alt="" />
<img
class="full-width {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/themes/velocity/assets/images/headphones.webp') }}" @endif
data-src="{{ asset('/themes/velocity/assets/images/headphones.webp') }}" alt="" />
</a>
<div class="col-lg-6 col-md-12 second-panel">
<a @if (isset($two)) href="{{ $two }}" @endif class="row top-container">
<img data-src="{{ asset('/themes/velocity/assets/images/watch.webp') }}" class="col-12 pr0 lazyload" alt="" />
<img
class="col-12 pr0 {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/themes/velocity/assets/images/watch.webp') }}" @endif
data-src="{{ asset('/themes/velocity/assets/images/watch.webp') }}" alt="" />
</a>
<a @if (isset($three)) href="{{ $three }}" @endif class="row bottom-container">
<img data-src="{{ asset('/themes/velocity/assets/images/kids-2.webp') }}" class="col-12 pr0 lazyload" alt="" />
<img
class="col-12 pr0 {{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/themes/velocity/assets/images/kids-2.webp') }}" @endif
data-src="{{ asset('/themes/velocity/assets/images/kids-2.webp') }}" alt="" />
</a>
</div>
</div>

View File

@ -1,12 +1,13 @@
@php
$isRendered = false;
$advertisementTwo = null;
$isLazyLoad = ! isset($lazyload) ? true : ( $lazyload ? true : false );
@endphp
@if ($velocityMetaData && $velocityMetaData->advertisement)
@php
$advertisement = json_decode($velocityMetaData->advertisement, true);
if (isset($advertisement[2]) && is_array($advertisement[2])) {
$advertisementTwo = array_values(array_filter($advertisement[2]));
}
@ -21,13 +22,19 @@
<div class="row">
@if ( isset($advertisementTwo[0]))
<a class="col-lg-9 col-md-12 no-padding">
<img data-src="{{ asset('/storage/' . $advertisementTwo[0]) }}" class="lazyload" alt="" />
<img
class="{{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementTwo[0]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementTwo[0]) }}" alt="" />
</a>
@endif
@if ( isset($advertisementTwo[1]))
<a class="col-lg-3 col-md-12 pr0">
<img data-src="{{ asset('/storage/' . $advertisementTwo[1]) }}" class="lazyload" alt="" />
<img
class="{{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/storage/' . $advertisementTwo[1]) }}" @endif
data-src="{{ asset('/storage/' . $advertisementTwo[1]) }}" alt="" />
</a>
@endif
</div>
@ -39,11 +46,17 @@
<div class="container-fluid advertisement-two-container">
<div class="row">
<a class="col-lg-9 col-md-12 no-padding">
<img data-src="{{ asset('/themes/velocity/assets/images/toster.webp') }}" class="lazyload" alt="" />
<img
class="{{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/themes/velocity/assets/images/toster.webp') }}" @endif
data-src="{{ asset('/themes/velocity/assets/images/toster.webp') }}" alt="" />
</a>
<a class="col-lg-3 col-md-12 pr0">
<img data-src="{{ asset('/themes/velocity/assets/images/trimmer.webp') }}" class="lazyload" alt="" />
<img
class="{{ $isLazyLoad ? 'lazyload' : '' }}"
@if (! $isLazyLoad) src="{{ asset('/themes/velocity/assets/images/trimmer.webp') }}" @endif
data-src="{{ asset('/themes/velocity/assets/images/trimmer.webp') }}" alt="" />
</a>
</div>
</div>

View File

@ -1,10 +1,4 @@
<div class="container-fluid hot-categories-container">
<card-list-header heading="{{ __('velocity::app.home.hot-categories') }}">
</card-list-header>
<div class="row">
@foreach ($category as $slug)
<hot-category slug="{{ $slug }}"></hot-category>
@endforeach
</div>
</div>
<hot-categories
heading="{{ __('velocity::app.home.hot-categories') }}"
:categories="{{ json_encode($category) }}">
</hot-categories>

View File

@ -23,7 +23,6 @@
@endsection
@section('head')
@if (isset($homeSEO))
@isset($metaTitle)
<meta name="title" content="{{ $metaTitle }}" />
@ -40,6 +39,12 @@
@endsection
@push('css')
@if (! empty($sliderData))
<link rel="preload" as="image" href="{{ asset('/storage/' . $sliderData[0]['path']) }}">
@else
<link rel="preload" as="image" href="{{ asset('/themes/velocity/assets/images/banner.webp') }}">
@endif
<style type="text/css">
.product-price span:first-child, .product-price span:last-child {
font-size: 18px;

View File

@ -1,10 +1,4 @@
<div class="container-fluid popular-categories-container">
<card-list-header heading="{{ __('velocity::app.home.popular-categories') }}">
</card-list-header>
<div class="row">
@foreach ($category as $slug)
<popular-category slug="{{ $slug }}"></popular-category>
@endforeach
</div>
</div>
<popular-categories
heading="{{ __('velocity::app.home.popular-categories') }}"
:categories="{{ json_encode($category) }}">
</popular-categories>

View File

@ -1,68 +1,17 @@
@php
$direction = core()->getCurrentLocale()->direction;
@endphp
@if ($velocityMetaData && $velocityMetaData->slider)
<slider-component direction="{{ $direction }}"></slider-component>
<div class="slider-container">
<slider-component
direction="{{ core()->getCurrentLocale()->direction }}"
default-banner="{{ asset('/themes/velocity/assets/images/banner.webp') }}"
:banners="{{ json_encode($sliderData) }}">
{{-- this is default content if js is not loaded --}}
@if(! empty($sliderData))
<img class="col-12 no-padding banner-icon" src="{{ asset('/storage/' . $sliderData[0]['path']) }}" alt=""/>
@else
<img class="col-12 no-padding banner-icon" src="{{ asset('/themes/velocity/assets/images/banner.webp') }}" alt=""/>
@endif
</slider-component>
</div>
@endif
@push('scripts')
<script type="text/x-template" id="slider-template">
<div class="slides-container {{ $direction }}">
<carousel-component
loop="true"
timeout="5000"
autoplay="true"
slides-per-page="1"
navigation-enabled="hide"
:locale-direction="direction"
:slides-count="{{ ! empty($sliderData) ? sizeof($sliderData) : 1 }}">
@if (! empty($sliderData))
@foreach ($sliderData as $index => $slider)
@php
$textContent = str_replace("\r\n", '', $slider['content']);
@endphp
<slide slot="slide-{{ $index }}" title=" ">
<a @if($slider['slider_path']) href="{{ $slider['slider_path'] }}" @endif>
<img
class="col-12 no-padding banner-icon"
src="{{ url()->to('/') . '/storage/' . $slider['path'] }}" />
<div class="show-content" v-html="'{{ $textContent }}'">
</div>
</a>
</slide>
@endforeach
@else
<slide slot="slide-0">
<img
loading="lazy"
class="col-12 no-padding banner-icon"
src="{{ asset('/themes/velocity/assets/images/banner.webp') }}"
alt=""/>
</slide>
@endif
</carousel-component>
</div>
</script>
<script type='text/javascript'>
(() => {
Vue.component('slider-component', {
template: '#slider-template',
props: ['direction'],
mounted: function () {
let banners = this.$el.querySelectorAll('img');
banners.forEach(banner => {
banner.style.display = 'block';
});
}
})
})()
</script>
@endpush

View File

@ -0,0 +1,22 @@
<div>
<sidebar-header heading= "{{ __('velocity::app.menu-navbar.text-category') }}">
{{-- this is default content if js is not loaded --}}
<div class="main-category fs16 unselectable fw6 left">
<i class="rango-view-list text-down-4 align-vertical-top fs18"></i>
<span class="pl5">{{ __('velocity::app.menu-navbar.text-category') }}</span>
</div>
</sidebar-header>
</div>
<div class="content-list right">
<right-side-header :header-content="{{ json_encode(app('Webkul\Velocity\Repositories\ContentRepository')->getAllContents()) }}">
{{-- this is default content if js is not loaded --}}
<ul type="none" class="no-margin">
</ul>
</right-side-header>
</div>

View File

@ -1,7 +1,39 @@
<header class="sticky-header">
<div class="row remove-padding-margin velocity-divide-page">
<logo-component add-class="navbar-brand"></logo-component>
<searchbar-component></searchbar-component>
<a class="left navbar-brand" href="{{ route('shop.home.index') }}" aria-label="Logo">
<img class="logo" src="{{ core()->getCurrentChannel()->logo_url ?? asset('themes/velocity/assets/images/logo-text.png') }}" alt="" />
</a>
<div class="right searchbar">
<div class="row">
<div class="col-lg-5 col-md-12">
@include('velocity::shop.layouts.particals.search-bar')
</div>
<div class="col-lg-7 col-md-12 vc-full-screen">
<div class="left-wrapper">
{!! view_render_event('bagisto.shop.layout.header.wishlist.before') !!}
@include('velocity::shop.layouts.particals.wishlist', ['isText' => true])
{!! view_render_event('bagisto.shop.layout.header.wishlist.after') !!}
{!! view_render_event('bagisto.shop.layout.header.compare.before') !!}
@include('velocity::shop.layouts.particals.compare', ['isText' => true])
{!! view_render_event('bagisto.shop.layout.header.compare.after') !!}
{!! view_render_event('bagisto.shop.layout.header.cart-item.before') !!}
@include('shop::checkout.cart.mini-cart')
{!! view_render_event('bagisto.shop.layout.header.cart-item.after') !!}
</div>
</div>
</div>
</div>
</div>
</header>
@ -11,12 +43,12 @@
document.addEventListener('scroll', e => {
scrollPosition = Math.round(window.scrollY);
if (scrollPosition > 50){
if (scrollPosition > 50) {
document.querySelector('header').classList.add('header-shadow');
} else {
document.querySelector('header').classList.remove('header-shadow');
}
});
})()
})();
</script>
@endpush

View File

@ -0,0 +1,173 @@
@php
$cart = cart()->getCart();
$cartItemsCount = $cart ? $cart->items->count() : trans('shop::app.minicart.zero');
@endphp
<mobile-header
is-customer="{{ auth()->guard('customer')->check() ? 'true' : 'false' }}"
heading= "{{ __('velocity::app.menu-navbar.text-category') }}"
:header-content="{{ json_encode(app('Webkul\Velocity\Repositories\ContentRepository')->getAllContents()) }}"
category-count="{{ $velocityMetaData ? $velocityMetaData->sidebar_category_count : 10 }}"
cart-items-count="{{ $cartItemsCount }}"
cart-route="{{ route('shop.checkout.cart.index') }}"
:locale="{{ json_encode(core()->getCurrentLocale()) }}"
:all-locales="{{ json_encode(core()->getCurrentChannel()->locales) }}"
:currency="{{ json_encode(core()->getCurrentCurrency()) }}"
:all-currencies="{{ json_encode(core()->getCurrentChannel()->currencies) }}"
>
{{-- this is default content if js is not loaded --}}
<div class="row">
<div class="col-6">
<div class="hamburger-wrapper">
<i class="rango-toggle hamburger"></i>
</div>
<a class="left" href="{{ route('shop.home.index') }}" aria-label="Logo">
<img class="logo" src="{{ core()->getCurrentChannel()->logo_url ?? asset('themes/velocity/assets/images/logo-text.png') }}" alt="" />
</a>
</div>
<div class="right-vc-header col-6">
<a href="{{ auth()->guard('customer')->check() ? route('velocity.customer.product.compare') : route('velocity.product.compare') }}" class="compare-btn unset">
<i class="material-icons">compare_arrows</i>
</a>
<a href="{{ route('customer.wishlist.index') }}" class="wishlist-btn unset">
<i class="material-icons">favorite_border</i>
</a>
<a class="unset cursor-pointer">
<i class="material-icons">search</i>
</a>
<a href="{{ route('shop.checkout.cart.index') }}" class="unset">
<i class="material-icons text-down-3">shopping_cart</i>
<div class="badge-wrapper">
<span class="badge">{{ $cartItemsCount }}</span>
</div>
</a>
</div>
</div>
<template v-slot:greetings>
@guest('customer')
<a class="unset" href="{{ route('customer.session.index') }}">
{{ __('velocity::app.responsive.header.greeting', ['customer' => 'Guest']) }}
</a>
@endguest
@auth('customer')
<a class="unset" href="{{ route('customer.profile.index') }}">
{{ __('velocity::app.responsive.header.greeting', ['customer' => auth()->guard('customer')->user()->first_name]) }}
</a>
@endauth
</template>
<template v-slot:customer-navigation>
@auth('customer')
<ul type="none" class="vc-customer-options">
<li>
<a href="{{ route('customer.profile.index') }}" class="unset">
<i class="icon profile text-down-3"></i>
<span>{{ __('shop::app.header.profile') }}</span>
</a>
</li>
<li>
<a href="{{ route('customer.address.index') }}" class="unset">
<i class="icon address text-down-3"></i>
<span>{{ __('velocity::app.shop.general.addresses') }}</span>
</a>
</li>
<li>
<a href="{{ route('customer.reviews.index') }}" class="unset">
<i class="icon reviews text-down-3"></i>
<span>{{ __('velocity::app.shop.general.reviews') }}</span>
</a>
</li>
@if (core()->getConfigData('general.content.shop.wishlist_option'))
<li>
<a href="{{ route('customer.wishlist.index') }}" class="unset">
<i class="icon wishlist text-down-3"></i>
<span>{{ __('shop::app.header.wishlist') }}</span>
</a>
</li>
@endif
@if (core()->getConfigData('general.content.shop.compare_option'))
<li>
<a href="{{ route('velocity.customer.product.compare') }}" class="unset">
<i class="icon compare text-down-3"></i>
<span>{{ __('shop::app.customer.compare.text') }}</span>
</a>
</li>
@endif
<li>
<a href="{{ route('customer.orders.index') }}" class="unset">
<i class="icon orders text-down-3"></i>
<span>{{ __('velocity::app.shop.general.orders') }}</span>
</a>
</li>
<li>
<a href="{{ route('customer.downloadable_products.index') }}" class="unset">
<i class="icon downloadables text-down-3"></i>
<span>{{ __('velocity::app.shop.general.downloadables') }}</span>
</a>
</li>
</ul>
@endauth
</template>
<template v-slot:extra-navigation>
<li>
@auth('customer')
<a
class="unset"
href="{{ route('customer.session.destroy') }}">
<span>{{ __('shop::app.header.logout') }}</span>
</a>
@endauth
@guest('customer')
<a
class="unset"
href="{{ route('customer.session.create') }}">
<span>{{ __('shop::app.customer.login-form.title') }}</span>
</a>
@endguest
</li>
<li>
@guest('customer')
<a
class="unset"
href="{{ route('customer.register.index') }}">
<span>{{ __('shop::app.header.sign-up') }}</span>
</a>
@endguest
</li>
</template>
<template v-slot:logo>
<a class="left" href="{{ route('shop.home.index') }}" aria-label="Logo">
<img class="logo" src="{{ core()->getCurrentChannel()->logo_url ?? asset('themes/velocity/assets/images/logo-text.png') }}" alt="" />
</a>
</template>
<template v-slot:top-header>
@include('velocity::shop.layouts.particals.compare', ['isText' => false])
@include('velocity::shop.layouts.particals.wishlist', ['isText' => false])
</template>
<template v-slot:search-bar>
<div class="row">
<div class="col-md-12">
@include('velocity::shop.layouts.particals.search-bar')
</div>
</div>
</template>
</mobile-header>

View File

@ -8,8 +8,9 @@
{{-- meta data --}}
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta http-equiv="content-language" content="{{ app()->getLocale() }}">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta name="base-url" content="{{ url()->to('/') }}">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
{!! view_render_event('bagisto.shop.layout.head') !!}
@ -36,8 +37,6 @@
<body @if (core()->getCurrentLocale() && core()->getCurrentLocale()->direction == 'rtl') class="rtl" @endif>
{!! view_render_event('bagisto.shop.layout.body.before') !!}
@include('shop::UI.particals')
{{-- main app --}}
<div id="app">
<product-quick-view v-if="$root.quickView"></product-quick-view>
@ -45,25 +44,30 @@
<div class="main-container-wrapper">
@section('body-header')
{{-- top nav which contains currency, locale and login header --}}
@include('shop::layouts.top-nav.index')
{!! view_render_event('bagisto.shop.layout.header.before') !!}
{{-- primary header after top nav --}}
@include('shop::layouts.header.index')
{!! view_render_event('bagisto.shop.layout.header.after') !!}
<div class="main-content-wrapper col-12 no-padding">
@php
$velocityContent = app('Webkul\Velocity\Repositories\ContentRepository')->getAllContents();
@endphp
<content-header
url="{{ url()->to('/') }}"
:header-content="{{ json_encode($velocityContent) }}"
heading= "{{ __('velocity::app.menu-navbar.text-category') }}"
category-count="{{ $velocityMetaData ? $velocityMetaData->sidebar_category_count : 10 }}"
></content-header>
{{-- secondary header --}}
<header class="row velocity-divide-page vc-header header-shadow active">
{{-- mobile header --}}
<div class="vc-small-screen container">
@include('velocity::shop.layouts.header.mobile')
</div>
{{-- desktop header --}}
@include('velocity::shop.layouts.header.desktop')
</header>
<div class="">
<div class="row col-12 remove-padding-margin">
@ -75,18 +79,14 @@
add-class="category-list-container pt10">
</sidebar-component>
<div
class="col-12 no-padding content" id="home-right-bar-container">
<div class="col-12 no-padding content" id="home-right-bar-container">
<div class="container-right row no-margin col-12 no-padding">
{!! view_render_event('bagisto.shop.layout.content.before') !!}
@yield('content-wrapper')
@yield('content-wrapper')
{!! view_render_event('bagisto.shop.layout.content.after') !!}
</div>
</div>
</div>
</div>
@ -94,19 +94,16 @@
@show
<div class="container">
{!! view_render_event('bagisto.shop.layout.full-content.before') !!}
@yield('full-content-wrapper')
{!! view_render_event('bagisto.shop.layout.full-content.after') !!}
</div>
</div>
<div class="modal-parent" id="loader" style="top: 0" v-show="showPageLoader">
<overlay-loader :is-open="true"></overlay-loader>
</div>
{{-- overlay loader --}}
<velocity-overlay-loader></velocity-overlay-loader>
</div>
{{-- footer --}}
@ -120,6 +117,7 @@
{!! view_render_event('bagisto.shop.layout.body.after') !!}
{{-- alert container --}}
<div id="alert-container"></div>
{{-- all scripts --}}

View File

@ -0,0 +1,13 @@
@php
$showCompare = core()->getConfigData('general.content.shop.compare_option') == "1" ? true : false;
@endphp
@if ($showCompare)
<compare-component-with-badge
is-customer="{{ auth()->guard('customer')->check() ? 'true' : 'false' }}"
is-text="{{ isset($isText) && $isText ? 'true' : 'false' }}"
src="{{ auth()->guard('customer')->check() ? route('velocity.customer.product.compare') : route('velocity.product.compare') }}">
</compare-component-with-badge>
@endif

View File

@ -0,0 +1,25 @@
<div class="input-group">
<form
method="GET"
role="search"
id="search-form"
action="{{ route('velocity.search.index') }}">
<div
class="btn-toolbar full-width search-form"
role="toolbar">
<searchbar-component>
<template v-slot:image-search>
<image-search-component
status="{{core()->getConfigData('general.content.shop.image_search') == '1' ? 'true' : 'false'}}"
upload-src="{{ route('shop.image.search.upload') }}"
view-src="{{ route('shop.search.index') }}"
common-error="{{ __('shop::app.common.error') }}"
size-limit-error="{{ __('shop::app.common.image-upload-limit') }}">
</image-search-component>
</template>
</searchbar-component>
</div>
</form>
</div>

View File

@ -0,0 +1,13 @@
@php
$showWishlist = core()->getConfigData('general.content.shop.wishlist_option') == "1" ? true : false;
@endphp
@if($showWishlist)
<wishlist-component-with-badge
is-customer="{{ auth()->guard('customer')->check() ? 'true' : 'false' }}"
is-text="{{ isset($isText) && $isText ? 'true' : 'false' }}"
src="{{ route('customer.wishlist.index') }}">
</wishlist-component-with-badge>
@endif

View File

@ -1,59 +1,17 @@
<script
type="text/javascript"
baseUrl="{{ url()->to('/') }}"
src="{{ asset('themes/velocity/assets/js/velocity.js') }}">
</script>
<script
type="text/javascript"
src="{{ asset('vendor/webkul/ui/assets/js/ui.js') }}">
</script>
<script
type="text/javascript"
src="{{ asset('themes/velocity/assets/js/jquery.ez-plus.js') }}">
src="{{ asset('themes/velocity/assets/js/velocity-core.js') }}">
</script>
<script type="text/javascript">
(() => {
window.showAlert = (messageType, messageLabel, message) => {
if (messageType && message !== '') {
let alertId = Math.floor(Math.random() * 1000);
let html = `<div class="alert ${messageType} alert-dismissible" id="${alertId}">
<a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
<strong>${messageLabel ? messageLabel + '!' : ''} </strong> ${message}.
</div>`;
$('#alert-container').append(html).ready(() => {
window.setTimeout(() => {
$(`#alert-container #${alertId}`).remove();
}, 5000);
});
}
}
let messageType = '';
let messageLabel = '';
@if ($message = session('success'))
messageType = 'alert-success';
messageLabel = "{{ __('velocity::app.shop.general.alert.success') }}";
@elseif ($message = session('warning'))
messageType = 'alert-warning';
messageLabel = "{{ __('velocity::app.shop.general.alert.warning') }}";
@elseif ($message = session('error'))
messageType = 'alert-danger';
messageLabel = "{{ __('velocity::app.shop.general.alert.error') }}";
@elseif ($message = session('info'))
messageType = 'alert-info';
messageLabel = "{{ __('velocity::app.shop.general.alert.info') }}";
@endif
if (messageType && '{{ $message }}' !== '') {
window.showAlert(messageType, messageLabel, '{{ $message }}');
/* activate session messages */
let message = @json($velocityHelper->getMessage());
if (message.messageType && message.message !== '') {
window.showAlert(message.messageType, message.messageLabel, message.message);
}
/* activate server error messages */
window.serverErrors = [];
@if (isset($errors))
@if (count($errors))
@ -61,7 +19,8 @@
@endif
@endif
window._translations = @json(app('Webkul\Velocity\Helpers\Helper')->jsonTranslations());
/* add translations */
window._translations = @json($velocityHelper->jsonTranslations());
})();
</script>

View File

@ -1,13 +1,21 @@
{{-- preloaded fonts --}}
<link rel="preload" href="{{ asset('themes/velocity/assets/fonts/font-rango/rango.ttf') . '?o0evyv' }}" as="font" crossorigin="anonymous" />
{{-- bootstrap --}}
<link rel="stylesheet" href="{{ asset('themes/velocity/assets/css/bootstrap.min.css') }}" />
{{-- bootstrap flipped for rtl --}}
@if (core()->getCurrentLocale() && core()->getCurrentLocale()->direction == 'rtl')
<link href="{{ asset('themes/velocity/assets/css/bootstrap-flipped.css') }}" rel="stylesheet">
@endif
<link rel="stylesheet" href="{{ asset('themes/velocity/assets/css/velocity.css') }}" />
{{-- mix versioned compiled file --}}
<link rel="stylesheet" href="{{ asset(mix('/css/velocity.css', 'themes/velocity/assets')) }}" />
{{-- extra css --}}
@stack('css')
{{-- custom css --}}
<style>
{!! core()->getConfigData('general.content.custom_scripts.custom_css') !!}
</style>

View File

@ -1,134 +1,106 @@
{!! view_render_event('bagisto.shop.layout.header.account-item.before') !!}
<login-header></login-header>
{!! view_render_event('bagisto.shop.layout.header.account-item.after') !!}
@push('scripts')
<script type="text/x-template" id="login-header-template">
<div class="dropdown">
<div id="account">
<div class="d-inline-block welcome-content" @click="togglePopup">
<i class="material-icons align-vertical-top">perm_identity</i>
<span class="text-center">
@guest('customer')
{{ __('velocity::app.header.welcome-message', ['customer_name' => trans('velocity::app.header.guest')]) }}!
@endguest
<div class="dropdown">
<div id="account">
<div class="d-inline-block welcome-content" @click="togglePopup">
<i class="material-icons align-vertical-top">perm_identity</i>
@auth('customer')
{{ __('velocity::app.header.welcome-message', ['customer_name' => auth()->guard('customer')->user()->first_name]) }}
@endauth
</span>
<span class="select-icon rango-arrow-down"></span>
</div>
</div>
<span class="text-center">
@guest('customer')
{{ __('velocity::app.header.welcome-message', ['customer_name' => trans('velocity::app.header.guest')]) }}!
@endguest
<div class="account-modal sensitive-modal hide mt5">
@guest('customer')
<div class="modal-content">
<!-- header -->
<div class="modal-header no-border pb0">
<label class="fs18 grey">{{ __('shop::app.header.title') }}</label>
@auth('customer')
{{ __('velocity::app.header.welcome-message', ['customer_name' => auth()->guard('customer')->user()->first_name]) }}
@endauth
</span>
<button type="button" class="close disable-box-shadow" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true" class="white-text fs20" @click="togglePopup">×</span>
</button>
</div>
<!-- body -->
<div class="pl10 fs14">
<p>{{ __('shop::app.header.dropdown-text') }}</p>
</div>
<!-- footer -->
<div class="modal-footer">
<div>
<a href="{{ route('customer.session.index') }}">
<button
type="button"
class="theme-btn fs14 fw6">
{{ __('shop::app.header.sign-in') }}
</button>
</a>
</div>
<div>
<a href="{{ route('customer.register.index') }}">
<button
type="button"
class="theme-btn fs14 fw6">
{{ __('shop::app.header.sign-up') }}
</button>
</a>
</div>
</div>
</div>
@endguest
@auth('customer')
<div class="modal-content customer-options">
<div class="customer-session">
<label class="">
{{ auth()->guard('customer')->user()->first_name }}
</label>
</div>
<ul type="none">
<li>
<a href="{{ route('customer.profile.index') }}" class="unset">{{ __('shop::app.header.profile') }}</a>
</li>
<li>
<a href="{{ route('customer.orders.index') }}" class="unset">{{ __('velocity::app.shop.general.orders') }}</a>
</li>
@php
$showCompare = core()->getConfigData('general.content.shop.compare_option') == "1" ? true : false;
$showWishlist = core()->getConfigData('general.content.shop.wishlist_option') == "1" ? true : false;
@endphp
@if ($showWishlist)
<li>
<a href="{{ route('customer.wishlist.index') }}" class="unset">{{ __('shop::app.header.wishlist') }}</a>
</li>
@endif
@if ($showCompare)
<li>
<a href="{{ route('velocity.customer.product.compare') }}" class="unset">{{ __('velocity::app.customer.compare.text') }}</a>
</li>
@endif
<li>
<a href="{{ route('customer.session.destroy') }}" class="unset">{{ __('shop::app.header.logout') }}</a>
</li>
</ul>
</div>
@endauth
<span class="select-icon rango-arrow-down"></span>
</div>
</div>
</script>
<script type="text/javascript">
<div id="account-modal" class="account-modal sensitive-modal hide mt5">
@guest('customer')
<div class="modal-content">
<div class="modal-header no-border pb0">
<label class="fs18 grey">{{ __('shop::app.header.title') }}</label>
Vue.component('login-header', {
template: '#login-header-template',
<button type="button" class="close disable-box-shadow" data-dismiss="modal" aria-label="Close" @click="togglePopup">
<span aria-hidden="true" class="white-text fs20">×</span>
</button>
</div>
methods: {
togglePopup: function (event) {
let accountModal = this.$el.querySelector('.account-modal');
let modal = $('#cart-modal-content')[0];
<div class="pl10 fs14">
<p>{{ __('shop::app.header.dropdown-text') }}</p>
</div>
if (modal)
modal.classList.add('hide');
<div class="modal-footer">
<div>
<a href="{{ route('customer.session.index') }}">
<button
type="button"
class="theme-btn fs14 fw6">
accountModal.classList.toggle('hide');
{{ __('shop::app.header.sign-in') }}
</button>
</a>
</div>
event.stopPropagation();
}
}
})
<div>
<a href="{{ route('customer.register.index') }}">
<button
type="button"
class="theme-btn fs14 fw6">
{{ __('shop::app.header.sign-up') }}
</button>
</a>
</div>
</div>
</div>
@endguest
</script>
@endpush
@auth('customer')
<div class="modal-content customer-options">
<div class="customer-session">
<label class="">
{{ auth()->guard('customer')->user()->first_name }}
</label>
</div>
<ul type="none">
<li>
<a href="{{ route('customer.profile.index') }}" class="unset">{{ __('shop::app.header.profile') }}</a>
</li>
<li>
<a href="{{ route('customer.orders.index') }}" class="unset">{{ __('velocity::app.shop.general.orders') }}</a>
</li>
@php
$showCompare = core()->getConfigData('general.content.shop.compare_option') == "1" ? true : false;
$showWishlist = core()->getConfigData('general.content.shop.wishlist_option') == "1" ? true : false;
@endphp
@if ($showWishlist)
<li>
<a href="{{ route('customer.wishlist.index') }}" class="unset">{{ __('shop::app.header.wishlist') }}</a>
</li>
@endif
@if ($showCompare)
<li>
<a href="{{ route('velocity.customer.product.compare') }}" class="unset">{{ __('velocity::app.customer.compare.text') }}</a>
</li>
@endif
<li>
<a href="{{ route('customer.session.destroy') }}" class="unset">{{ __('shop::app.header.logout') }}</a>
</li>
</ul>
</div>
@endauth
</div>
</div>
{!! view_render_event('bagisto.shop.layout.header.account-item.after') !!}

View File

@ -111,3 +111,7 @@
</div>
@endsection
@push('scripts')
<script type="text/javascript" src="{{ asset('vendor/webkul/ui/assets/js/ui.js') }}"></script>
@endpush

View File

@ -175,7 +175,7 @@
@if ($product->getTypeInstance()->showQuantityBox())
<div>
<quantity-changer></quantity-changer>
<quantity-changer quantity-text="{{ __('shop::app.products.quantity') }}"></quantity-changer>
</div>
@else
<input type="hidden" name="quantity" value="1">
@ -216,6 +216,10 @@
@endsection
@push('scripts')
<script type="text/javascript" src="{{ asset('vendor/webkul/ui/assets/js/ui.js') }}"></script>
<script type="text/javascript" src="{{ asset('themes/velocity/assets/js/jquery.ez-plus.js') }}"></script>
<script type='text/javascript' src='https://unpkg.com/spritespin@4.1.0/release/spritespin.js'></script>
<script type="text/x-template" id="product-view-template">

View File

@ -34,7 +34,7 @@
<div class="bundle-summary">
<h3 class="mb10">{{ __('shop::app.products.your-customization') }}</h3>
<quantity-changer></quantity-changer>
<quantity-changer quantity-text="{{ __('shop::app.products.quantity') }}"></quantity-changer>
<div class="control-group">
<label>{{ __('shop::app.products.total-amount') }}</label>
@ -132,6 +132,7 @@
:control-name="'bundle_option_qty[' + option.id + ']'"
:validations="parseInt(selected_product) ? 'required|numeric|min_value:1' : ''"
:quantity="product_qty"
quantity-text="{{ __('shop::app.products.quantity') }}"
@onQtyUpdated="qtyUpdated($event)">
</quantity-changer>
</div>

View File

@ -23,6 +23,7 @@
:control-name="'qty[{{$groupedProduct->associated_product_id}}]'"
:validations="'required|numeric|min_value:0'"
quantity="{{ $groupedProduct->qty }}"
quantity-text="{{ __('shop::app.products.quantity') }}"
min-quantity="0">
</quantity-changer>
</span>

View File

@ -1,7 +1,8 @@
const { mix } = require("laravel-mix");
require("laravel-mix-merge-manifest");
const { mix } = require('laravel-mix');
var publicPath = "../../../public/themes/velocity/assets";
require('laravel-mix-merge-manifest');
let publicPath = '../../../public/themes/velocity/assets';
if (mix.inProduction()) {
publicPath = 'publishable/assets';
@ -11,12 +12,13 @@ mix.setPublicPath(publicPath).mergeManifest();
mix.disableNotifications();
mix
.js(__dirname + '/src/Resources/assets/js/app-core.js', 'js/velocity-core.js')
.js(
__dirname + "/src/Resources/assets/js/app.js",
"js/velocity.js"
__dirname + '/src/Resources/assets/js/app.js',
'js/velocity.js'
)
.copy(__dirname + "/src/Resources/assets/images", publicPath + "/images")
.copy(__dirname + '/src/Resources/assets/images', publicPath + '/images')
.sass(
__dirname + '/src/Resources/assets/sass/admin.scss',
@ -24,8 +26,9 @@ mix
)
.sass(
__dirname + '/src/Resources/assets/sass/app.scss',
__dirname + '/' + publicPath + '/css/velocity.css', {
includePaths: ['node_modules/bootstrap-sass/assets/stylesheets/'],
__dirname + '/' + publicPath + '/css/velocity.css',
{
includePaths: ['node_modules/bootstrap-sass/assets/stylesheets/']
}
)