分类筛选前端
This commit is contained in:
parent
79f6f77e2d
commit
fe66b21e9c
|
|
@ -41,14 +41,14 @@ class ProductRepo
|
|||
* 通过单个或多个商品分类获取商品列表
|
||||
*
|
||||
* @param $categoryId
|
||||
* @return AnonymousResourceCollection
|
||||
* @return
|
||||
*/
|
||||
public static function getProductsByCategory($categoryId, $filterData): AnonymousResourceCollection
|
||||
public static function getProductsByCategory($categoryId, $filterData)
|
||||
{
|
||||
$builder = self::getBuilder(array_merge(['category_id' => $categoryId, 'active' => 1], $filterData));
|
||||
$products = $builder->with('inCurrentWishlist')->paginate(perPage());
|
||||
$products = $builder->with('inCurrentWishlist')->paginate($filterData['per_page'] ?? perPage());
|
||||
|
||||
return ProductSimple::collection($products);
|
||||
return $products;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -161,7 +161,7 @@ class ProductRepo
|
|||
$builder->onlyTrashed();
|
||||
}
|
||||
|
||||
$sort = $data['sort'] ?? 'products.updated_at';
|
||||
$sort = $data['sort'] ?? 'products.position';
|
||||
$order = $data['order'] ?? 'desc';
|
||||
$builder->orderBy($sort, $order);
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ class ProductRepo
|
|||
->select(['pa.attribute_id', 'pa.attribute_value_id'])
|
||||
->distinct()
|
||||
->reorder('pa.attribute_id');
|
||||
$productAttributes = $builder->get();
|
||||
$productAttributes = $builder->get()->toArray();
|
||||
|
||||
$attributeMap = array_column(Attribute::query()->with('description')->orderBy('sort_order')->get()->toArray(), null, 'id');
|
||||
$attributeValueMap = array_column(AttributeValue::query()->with('description')->get()->toArray(), null, 'id');
|
||||
|
|
@ -222,7 +222,12 @@ class ProductRepo
|
|||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
$results = array_map(function($item) {
|
||||
$item['values'] = array_values($item['values']);
|
||||
return $item;
|
||||
}, $results);
|
||||
|
||||
return array_values($results);
|
||||
}
|
||||
|
||||
public static function getFilterPrice($data)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ namespace Beike\Shop\Http\Controllers;
|
|||
use Beike\Models\Category;
|
||||
use Beike\Repositories\CategoryRepo;
|
||||
use Beike\Repositories\ProductRepo;
|
||||
use Beike\Shop\Http\Resources\ProductSimple;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CategoryController extends Controller
|
||||
|
|
@ -16,16 +17,16 @@ class CategoryController extends Controller
|
|||
|
||||
public function show(Request $request, Category $category)
|
||||
{
|
||||
$filterData = $request->only('attr', 'price');
|
||||
$filterData = $request->only('attr', 'price', 'sort', 'order', 'per_page');
|
||||
$products = ProductRepo::getProductsByCategory($category->id, $filterData);
|
||||
|
||||
$category->load('description');
|
||||
$filterData = array_merge($filterData, ['category_id' => $category->id, 'active' => 1]);
|
||||
|
||||
$data = [
|
||||
'all_categories' => CategoryRepo::getTwoLevelCategories(),
|
||||
'category' => $category,
|
||||
'filter_data' => ['attr' => ProductRepo::getFilterAttribute($filterData), 'price' => ProductRepo::getFilterPrice($filterData)],
|
||||
'products_format' => $products->jsonSerialize(),
|
||||
'products_format' => ProductSimple::collection($products)->jsonSerialize(),
|
||||
'products' => $products,
|
||||
'per_pages' => CategoryRepo::getPerPages(),
|
||||
];
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -185,6 +185,7 @@
|
|||
|
||||
$http.post('design/builder/preview?design=1', data, {hload: true}).then((res) => {
|
||||
$(previewWindow.document).find('#module-' + data.module_id).replaceWith(res);
|
||||
$(previewWindow.document).find('.tooltip').remove();
|
||||
const tooltipTriggerList = previewWindow.document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
||||
const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new previewWindow.bootstrap.Tooltip(tooltipTriggerEl))
|
||||
})
|
||||
|
|
|
|||
|
|
@ -324,14 +324,7 @@
|
|||
|
||||
<div class="tab-pane fade" id="tab-seo">
|
||||
<h6 class="border-bottom pb-3 mb-4">SEO</h6>
|
||||
<x-admin::form.row title="Meta title">
|
||||
@foreach ($languages as $language)
|
||||
<div class="input-group w-max-600">
|
||||
<span class="input-group-text wp-100">{{ $language['name'] }}</span>
|
||||
<textarea rows="2" type="text" name="descriptions[{{ $language['code'] }}][meta_title]" class="form-control wp-400" placeholder="Meta title">{{ old('meta_title', $product->descriptions->keyBy('locale')[$language->code]->meta_title ?? '') }}</textarea>
|
||||
</div>
|
||||
@endforeach
|
||||
</x-admin::form.row>
|
||||
<x-admin-form-input-locale :width="600" name="descriptions.*.meta_title" title="Meta title" :value="$descriptions"/>
|
||||
<x-admin::form.row title="Meta keywords">
|
||||
@foreach ($languages as $language)
|
||||
<div class="input-group w-max-600">
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ $primary: #fd560f;
|
|||
@import './page-product';
|
||||
@import './cart';
|
||||
@import './page-checkout';
|
||||
@import './page-categories';
|
||||
@import './element-ui';
|
||||
@import './order-success';
|
||||
@import './page-account-order';
|
||||
|
|
|
|||
|
|
@ -9,5 +9,100 @@
|
|||
*/
|
||||
|
||||
body.page-categories {
|
||||
.right-column {
|
||||
@media (min-width: 992px) {
|
||||
width: 78%;
|
||||
}
|
||||
}
|
||||
|
||||
.left-column {
|
||||
@media (min-width: 992px) {
|
||||
width: 22%;
|
||||
}
|
||||
|
||||
.card:not(:last-of-type) {
|
||||
border-bottom: 1px solid #E6E6E6;
|
||||
margin-bottom: 1.4rem;
|
||||
padding-bottom: 1.4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.style-wrap {
|
||||
span {
|
||||
cursor: pointer;
|
||||
&.active {
|
||||
svg {
|
||||
fill: $primary;
|
||||
}
|
||||
}
|
||||
|
||||
svg {
|
||||
fill: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filter-value-wrap {
|
||||
.list-group {
|
||||
display: block;
|
||||
|
||||
.list-group-item {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
background: #f3f3f3;
|
||||
border: none;
|
||||
color: #666;
|
||||
padding: 4px 12px;
|
||||
&.delete-all {
|
||||
background: $primary;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $primary;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.product-tool {
|
||||
.order-wrap {
|
||||
min-width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
.ui-widget-content {
|
||||
border-radius: 0;
|
||||
position: relative;
|
||||
border: none;
|
||||
margin-right: 4px;
|
||||
margin-bottom: 0;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
|
||||
.ui-widget-header {
|
||||
background: $primary;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
border-radius: 0;
|
||||
height: 2px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.ui-slider-active {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.ui-slider-handle {
|
||||
width: 4px;
|
||||
margin-left: 0;
|
||||
cursor: ew-resize;
|
||||
border: none !important;
|
||||
border-radius: 0;
|
||||
background: $primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -8,6 +8,28 @@
|
|||
* @LastEditTime 2022-09-16 20:56:27
|
||||
*/
|
||||
|
||||
.product-list-wrap {
|
||||
.col-12:not(:last-of-type) {
|
||||
.product-wrap {
|
||||
border-bottom: 1px solid #E6E6E6;
|
||||
margin-bottom: 1.4rem;
|
||||
padding-bottom: 1.4rem;
|
||||
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
.image {
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.button-wrap {
|
||||
bottom: 10px;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.product-wrap {
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
|
|
@ -15,6 +37,28 @@
|
|||
transition: all 0.3s ease-in-out;
|
||||
background-color: #fff;
|
||||
|
||||
&.list {
|
||||
display: flex;
|
||||
padding-bottom: 0;
|
||||
|
||||
.image {
|
||||
width: 200px;
|
||||
margin-bottom: 0;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.product-bottom-info {
|
||||
padding-top: 10px;
|
||||
padding-left: 20px;
|
||||
flex: 1;
|
||||
text-align: left;
|
||||
|
||||
.product-name {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.image {
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
|
|
|
|||
|
|
@ -144,4 +144,20 @@ export default {
|
|||
|
||||
return typeof(defaultValue) != 'undefined' ? defaultValue : '';
|
||||
},
|
||||
|
||||
removeURLParameters(url, ...parameters) {
|
||||
const parsed = new URL(url);
|
||||
parameters.forEach(e => parsed.searchParams.delete(e))
|
||||
return parsed.toString()
|
||||
},
|
||||
|
||||
updateQueryStringParameter(uri, key, value) {
|
||||
var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
|
||||
var separator = uri.indexOf('?') !== -1 ? "&" : "?";
|
||||
if (uri.match(re)) {
|
||||
return uri.replace(re, '$1' + key + "=" + value + '$2');
|
||||
} else {
|
||||
return uri + separator + key + "=" + value;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -38,6 +38,7 @@ return [
|
|||
'no' => 'nein',
|
||||
'yes' => 'ja',
|
||||
'delete' => 'löschen',
|
||||
'delete_all' => 'alle löschen',
|
||||
'sign_out' => 'Abmelden',
|
||||
'contact_us' => 'kontaktiere uns',
|
||||
'input' => 'Geben Sie hier Ihre Suche ein',
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ return [
|
|||
'no' => 'No',
|
||||
'yes' => 'Yes',
|
||||
'delete' => 'Delete',
|
||||
'delete_all' => 'Delete all',
|
||||
'sign_out' => 'Sign Out',
|
||||
'contact_us' => 'Contact us',
|
||||
'input' => 'Type your search here',
|
||||
|
|
@ -67,6 +68,9 @@ return [
|
|||
'whether_open' => 'Status',
|
||||
'default' => 'Default',
|
||||
'to_setting' => 'to configure',
|
||||
'low' => 'Low',
|
||||
'high' => 'High',
|
||||
'sales' => 'Sales',
|
||||
|
||||
'id' => 'ID',
|
||||
'created_at' => 'Created At',
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ return [
|
|||
'no' => 'no',
|
||||
'yes' => 'Sí',
|
||||
'delete' => 'Eliminar',
|
||||
'delete_all' => 'borrar todo',
|
||||
'sign_out' => 'desconectar',
|
||||
'contact_us' => 'Contáctenos',
|
||||
'input' => 'ingrese su búsqueda aquí',
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ return [
|
|||
'no' => 'non',
|
||||
'yes' => 'Oui',
|
||||
'delete' => 'effacer',
|
||||
'delete_all' => 'supprimer tout',
|
||||
'sign_out' => 'se déconnecter',
|
||||
'contact_us' => 'Nous contacter',
|
||||
'input' => 'entrez votre recherche ici',
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ return [
|
|||
'no' => 'No',
|
||||
'yes' => 'Yes',
|
||||
'delete' => 'Elimina',
|
||||
'delete_all' => 'elimina tutto',
|
||||
'sign_out' => 'disconnessione',
|
||||
'contact_us' => 'Contattaci',
|
||||
'input' => 'inserisci qui la tua ricerca',
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ return [
|
|||
'no' => '番号',
|
||||
'yes' => 'はい',
|
||||
'delete' => '消去',
|
||||
'delete_all' => 'すべて削除',
|
||||
'sign_out' => 'サインアウト',
|
||||
'contact_us' => 'お問い合わせ',
|
||||
'input' => 'ここに検索を入力してください',
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ return [
|
|||
'no' => 'нет',
|
||||
'yes' => 'да',
|
||||
'delete' => 'удалить',
|
||||
'delete_all' => 'удалить все',
|
||||
'sign_out' => 'Выйти',
|
||||
'contact_us' => 'свяжитесь с нами',
|
||||
'input' => 'Введите свой поиск здесь',
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ return [
|
|||
'no' => '否',
|
||||
'yes' => '是',
|
||||
'delete' => '删除',
|
||||
'delete_all' => '删除所有',
|
||||
'sign_out' => '退出登录',
|
||||
'contact_us' => '联系我们',
|
||||
'input' => '在此处输入您的搜索',
|
||||
|
|
@ -67,6 +68,9 @@ return [
|
|||
'whether_open' => '是否开启',
|
||||
'default' => '默认',
|
||||
'to_setting' => '去配置',
|
||||
'low' => '低',
|
||||
'high' => '高',
|
||||
'sales' => '销量',
|
||||
|
||||
'id' => 'ID',
|
||||
'created_at' => '创建时间',
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ return [
|
|||
'no' => '否',
|
||||
'yes' => '是',
|
||||
'delete' => '刪除',
|
||||
'delete_all' => '刪除所有',
|
||||
'sign_out' => '退出登錄',
|
||||
'contact_us' => '聯繫我們',
|
||||
'input' => '在此處輸入您的搜索',
|
||||
|
|
@ -66,6 +67,9 @@ return [
|
|||
'menu' => '菜單',
|
||||
'whether_open' => '是否開啟',
|
||||
'to_setting' => '去配置',
|
||||
'low' => '低',
|
||||
'high' => '高',
|
||||
'sales' => '銷量',
|
||||
|
||||
'id' => 'ID',
|
||||
'created_at' => '創建時間',
|
||||
|
|
|
|||
|
|
@ -31,7 +31,9 @@
|
|||
<el-input @keyup.enter.native="checkedBtnLogin('loginForm')" type="password" v-model="loginForm.password" placeholder="{{ __('shop/login.password') }}"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<a class="text-muted forgotten-link" href="{{ shop_route('forgotten.index') }}"><i class="bi bi-question-circle"></i> {{ __('shop/login.forget_password') }}</a>
|
||||
@if (!request('iframe'))
|
||||
<a class="text-muted forgotten-link" href="{{ shop_route('forgotten.index') }}"><i class="bi bi-question-circle"></i> {{ __('shop/login.forget_password') }}</a>
|
||||
@endif
|
||||
|
||||
<div class="mt-4 mb-3">
|
||||
<button type="button" @click="checkedBtnLogin('loginForm')" class="btn btn-dark btn-lg w-100 fw-bold"><i class="bi bi-box-arrow-in-right"></i> {{ __('shop/login.login') }}</button>
|
||||
|
|
|
|||
|
|
@ -4,19 +4,114 @@
|
|||
@section('keywords', $category->description->meta_keywords ?: system_setting('base.meta_keyword'))
|
||||
@section('description', $category->description->meta_description ?: system_setting('base.meta_description'))
|
||||
|
||||
@push('header')
|
||||
<script src="{{ asset('vendor/jquery/jquery-ui/jquery-ui.min.js') }}"></script>
|
||||
<link rel="stylesheet" href="{{ asset('vendor/jquery/jquery-ui/jquery-ui.min.css') }}">
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<div class="container">
|
||||
|
||||
<x-shop-breadcrumb type="category" :value="$category" />
|
||||
|
||||
<div class="row">
|
||||
@if (count($products_format))
|
||||
@foreach ($products_format as $product)
|
||||
<div class="col-6 col-md-3">@include('shared.product')</div>
|
||||
@endforeach
|
||||
@else
|
||||
<div class="col-12 col-lg-3 pe-lg-4 left-column">
|
||||
<div class="filter-box">
|
||||
@if ($filter_data['price']['min'] != $filter_data['price']['max'])
|
||||
<div class="card">
|
||||
<div class="card-header p-0">
|
||||
<h4 class="mb-3">{{ __('product.price') }}</h4>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="text-secondary mb-3 price-range">
|
||||
{{ currency_format($filter_data['price']['select_min'], current_currency_code()) }}
|
||||
-
|
||||
{{ currency_format($filter_data['price']['select_max'], current_currency_code()) }}
|
||||
</div>
|
||||
<input value="{{ $filter_data['price']['select_min'] }}" class="price-min d-none">
|
||||
<input value="{{ $filter_data['price']['select_max'] }}" class="price-max d-none">
|
||||
<div id="slider" class="mb-2"></div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@foreach ($filter_data['attr'] as $index => $attr)
|
||||
<div class="card">
|
||||
<div class="card-header fw-bold p-0">
|
||||
<h4 class="mb-3">{{ $attr['name'] }}</h4>
|
||||
</div>
|
||||
<ul class="list-group list-group-flush attribute-item" data-attribute-id="{{ $attr['id'] }}">
|
||||
@foreach ($attr['values'] as $value_index => $value)
|
||||
<li class="list-group-item border-0 px-0">
|
||||
<label class="form-check-label d-block">
|
||||
<input class="form-check-input attr-value-check me-2" data-attr="{{ $index }}" data-attrval="{{ $value_index }}" {{ $value['selected'] ? 'checked' : '' }} name="6" type="checkbox" value="{{ $value['id'] }}">{{ $value['name'] }}
|
||||
</label>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-9 right-column">
|
||||
<div class="filter-value-wrap mb-2 d-none">
|
||||
<ul class="list-group list-group-horizontal">
|
||||
@foreach ($filter_data['attr'] as $index => $attr)
|
||||
@foreach ($attr['values'] as $value_index => $value)
|
||||
@if ($value['selected'])
|
||||
<li class="list-group-item me-1 mb-1" data-attr="{{ $index }}" data-attrval="{{ $value_index }}">
|
||||
{{ $attr['name'] }}: {{ $value['name'] }} <i class="bi bi-x-lg ms-1"></i>
|
||||
</li>
|
||||
@endif
|
||||
@endforeach
|
||||
@endforeach
|
||||
<li class="list-group-item me-1 mb-1 delete-all">{{ __('common.delete_all') }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="product-tool d-flex justify-content-between align-items-center mb-4">
|
||||
<div class="style-wrap">
|
||||
<span class="{{ !request('style_list') || request('style_list') == 'grid' ? 'active' : ''}}">
|
||||
<svg viewBox="0 0 19 19" xmlns="http://www.w3.org/2000/svg" width="18" height="18"><rect width="5" height="5"></rect><rect x="7" width="5" height="5"></rect><rect x="14" width="5" height="5"></rect><rect y="7" width="5" height="5"></rect><rect x="7" y="7" width="5" height="5"></rect><rect x="14" y="7" width="5" height="5"></rect><rect y="14" width="5" height="5"></rect><rect x="7" y="14" width="5" height="5"></rect><rect x="14" y="14" width="5" height="5"></rect></svg>
|
||||
</span>
|
||||
<span class="ms-1 class="{{ request('style_list') == 'list' ? 'active' : ''}}">
|
||||
<svg viewBox="0 0 19 19" xmlns="http://www.w3.org/2000/svg" width="18" height="18"><rect width="5" height="5"></rect><rect x="7" height="5" width="12"></rect><rect y="7" width="5" height="5"></rect><rect x="7" y="7" height="5" width="12"></rect><rect y="14" width="5" height="5"></rect><rect x="7" y="14" height="5" width="12"></rect></svg>
|
||||
</span>
|
||||
</div>
|
||||
<div class="d-flex">
|
||||
{{-- <div>Showing 1-19 of 20 item(s)</div> --}}
|
||||
|
||||
<select class="form-select perpage-select">
|
||||
@foreach ($per_pages as $val)
|
||||
<option value="{{ $val }}" {{ request('per_page') == $val ? 'selected' : '' }}>{{ $val }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
<select class="form-select order-select ms-2">
|
||||
<option value="">{{ __('common.default') }}</option>
|
||||
<option value="products.sales|asc" {{ request('sort') == 'products.sales' && request('order') == 'asc' ? 'selected' : '' }}>{{ __('common.sales') }} ({{ __('common.low') . '-' . __('common.high')}})</option>
|
||||
<option value="products.sales|desc" {{ request('sort') == 'products.sales' && request('order') == 'desc' ? 'selected' : '' }}>{{ __('common.sales') }} ({{ __('common.high') . '-' . __('common.low')}})</option>
|
||||
<option value="pd.name|asc" {{ request('sort') == 'pd.name' && request('order') == 'asc' ? 'selected' : '' }}>{{ __('common.name') }} (A - Z)</option>
|
||||
<option value="pd.name|desc" {{ request('sort') == 'pd.name' && request('order') == 'desc' ? 'selected' : '' }}>{{ __('common.name') }} (Z - A)</option>
|
||||
<option value="product_skus.price|asc" {{ request('sort') == 'product_skus.price' && request('order') == 'asc' ? 'selected' : '' }}>{{ __('product.price') }} ({{ __('common.low') . '-' . __('common.high')}})</option>
|
||||
<option value="product_skus.price|desc" {{ request('sort') == 'product_skus.price' && request('order') == 'desc' ? 'selected' : '' }}>{{ __('product.price') }} ({{ __('common.high') . '-' . __('common.low')}})</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (count($products_format))
|
||||
<div class="row {{ request('style_list') == 'list' ? 'product-list-wrap' : ''}}">
|
||||
@foreach ($products_format as $product)
|
||||
<div class="{{ !request('style_list') || request('style_list') == 'grid' ? 'col-6 col-md-4' : 'col-12'}}">
|
||||
@include('shared.product')
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
<x-shop-no-data />
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ $products->links('shared/pagination/bootstrap-4') }}
|
||||
|
|
@ -24,3 +119,104 @@
|
|||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('add-scripts')
|
||||
<script>
|
||||
let filterAttr = @json($filter_data['attr'] ?? []);
|
||||
|
||||
$('.filter-value-wrap li').click(function(event) {
|
||||
let [attr, val] = [$(this).data('attr'),$(this).data('attrval')];
|
||||
if ($(this).hasClass('delete-all')) {
|
||||
deleteFilterAll();
|
||||
return;
|
||||
}
|
||||
|
||||
filterAttr[attr].values[val].selected = false;
|
||||
filterProductData();
|
||||
});
|
||||
|
||||
if ($('.filter-value-wrap li').length > 1) {
|
||||
$('.filter-value-wrap').removeClass('d-none')
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$("#slider").slider({
|
||||
range: true,
|
||||
min: {{ $filter_data['price']['min'] }},
|
||||
max: {{ $filter_data['price']['max'] }},
|
||||
values: [{{ $filter_data['price']['select_min'] }}, {{ $filter_data['price']['select_max'] }}],
|
||||
change: function(event, ui) {
|
||||
$('input.price-min').val(ui.values[0])
|
||||
$('input.price-max').val(ui.values[1])
|
||||
filterProductData();
|
||||
},
|
||||
slide: function(event, ui) {
|
||||
$('.price-range').html(`${ui.values[0]} - ${ui.values[1]}`)
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('.attr-value-check').change(function(event) {
|
||||
let [attr, val] = [$(this).data('attr'),$(this).data('attrval')];
|
||||
filterAttr[attr].values[val].selected = $(this).is(":checked");
|
||||
filterProductData();
|
||||
});
|
||||
|
||||
$('.form-select').change(function(event) {
|
||||
filterProductData();
|
||||
});
|
||||
|
||||
function filterAttrChecked(data) {
|
||||
let filterAtKey = [];
|
||||
data.forEach((item) => {
|
||||
let checkedAtValues = [];
|
||||
|
||||
item.values.forEach((val) => {
|
||||
if (val.selected) {
|
||||
checkedAtValues.push(val.id)
|
||||
}
|
||||
})
|
||||
|
||||
if (checkedAtValues.length) {
|
||||
filterAtKey.push(`${item.id}:${checkedAtValues.join('/')}`)
|
||||
}
|
||||
})
|
||||
|
||||
return filterAtKey.join('|')
|
||||
}
|
||||
|
||||
function filterProductData() {
|
||||
let url = bk.removeURLParameters(window.location.href, 'attr', 'price', 'sort', 'order');
|
||||
let [priceMin, priceMax] = [$('.price-min').val(), $('.price-max').val()];
|
||||
let order = $('.order-select').val();
|
||||
let perpage = $('.perpage-select').val();
|
||||
|
||||
layer.load(2, {shade: [0.3,'#fff'] })
|
||||
|
||||
if (filterAttrChecked(filterAttr)) {
|
||||
url = bk.updateQueryStringParameter(url, 'attr', filterAttrChecked(filterAttr));
|
||||
}
|
||||
|
||||
if (priceMin || priceMax) {
|
||||
url = bk.updateQueryStringParameter(url, 'price', `${priceMin}-${priceMax}`);
|
||||
}
|
||||
|
||||
if (order) {
|
||||
let orderKeys = order.split('|');
|
||||
url = bk.updateQueryStringParameter(url, 'sort', orderKeys[0]);
|
||||
url = bk.updateQueryStringParameter(url, 'order', orderKeys[1]);
|
||||
}
|
||||
|
||||
if (perpage) {
|
||||
url = bk.updateQueryStringParameter(url, 'per_page', perpage);
|
||||
}
|
||||
|
||||
location = url;
|
||||
}
|
||||
|
||||
function deleteFilterAll() {
|
||||
let url = bk.removeURLParameters(window.location.href, 'attr', 'price');
|
||||
location = url;
|
||||
}
|
||||
</script>
|
||||
@endpush
|
||||
|
|
@ -1,33 +1,54 @@
|
|||
<div class="product-wrap">
|
||||
<div class="product-wrap {{ $style_list ?? '' }}">
|
||||
<div class="image">
|
||||
<a href="{{ $product['url'] }}">
|
||||
<div class="image-old">
|
||||
<img src="{{ $product['images'][0] ?? image_resize('', 400, 400) }}" class="img-fluid">
|
||||
</div>
|
||||
</a>
|
||||
<div class="button-wrap">
|
||||
<button
|
||||
class="btn btn-dark text-light mx-1 rounded-3"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-placement="top"
|
||||
title="{{ __('shop/products.add_to_favorites') }}"
|
||||
data-in-wishlist="{{ $product['in_wishlist'] }}"
|
||||
onclick="bk.addWishlist('{{ $product['id'] }}', this)">
|
||||
<i class="bi bi-heart{{ $product['in_wishlist'] ? '-fill' : '' }}"></i>
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-dark text-light mx-1 rounded-3"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-placement="top"
|
||||
title="{{ __('shop/products.add_to_cart') }}"
|
||||
onclick="bk.addCart({sku_id: '{{ $product['sku_id'] }}'}, this)">
|
||||
<i class="bi bi-cart"></i>
|
||||
</button>
|
||||
</div>
|
||||
@if (!request('style_list') || request('style_list') == 'grid')
|
||||
<div class="button-wrap">
|
||||
<button
|
||||
class="btn btn-dark text-light mx-1 rounded-3"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-placement="top"
|
||||
title="{{ __('shop/products.add_to_favorites') }}"
|
||||
data-in-wishlist="{{ $product['in_wishlist'] }}"
|
||||
onclick="bk.addWishlist('{{ $product['id'] }}', this)">
|
||||
<i class="bi bi-heart{{ $product['in_wishlist'] ? '-fill' : '' }}"></i>
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-dark text-light mx-1 rounded-3"
|
||||
data-bs-toggle="tooltip"
|
||||
data-bs-placement="top"
|
||||
title="{{ __('shop/products.add_to_cart') }}"
|
||||
onclick="bk.addCart({sku_id: '{{ $product['sku_id'] }}'}, this)">
|
||||
<i class="bi bi-cart"></i>
|
||||
</button>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="product-name">{{ $product['name_format'] }}</div>
|
||||
<div class="product-price">
|
||||
<span class="price-new">{{ $product['price_format'] }}</span>
|
||||
<span class="price-lod">{{ $product['origin_price_format'] }}</span>
|
||||
<div class="product-bottom-info">
|
||||
<div class="product-name">{{ $product['name_format'] }}</div>
|
||||
<div class="product-price">
|
||||
<span class="price-new">{{ $product['price_format'] }}</span>
|
||||
<span class="price-lod">{{ $product['origin_price_format'] }}</span>
|
||||
</div>
|
||||
|
||||
@if (request('style_list') == 'list')
|
||||
<div class="button-wrap mt-3">
|
||||
<button
|
||||
class="btn btn-dark text-light"
|
||||
onclick="bk.addCart({sku_id: '{{ $product['sku_id'] }}'}, this)">
|
||||
<i class="bi bi-cart"></i>
|
||||
{{ __('shop/products.add_to_cart') }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button class="btn btn-link ps-0 text-secondary" data-in-wishlist="{{ $product['in_wishlist'] }}" onclick="bk.addWishlist('{{ $product['id'] }}', this)">
|
||||
<i class="bi bi-heart{{ $product['in_wishlist'] ? '-fill' : '' }} me-1"></i> {{ __('shop/products.add_to_favorites') }}
|
||||
</button>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
Loading…
Reference in New Issue