added product grid template

added default product grid theme part
added sort to area
master
A1Gard 3 days ago
parent 1e6b040c4e
commit 48ae713ae1

@ -17,7 +17,7 @@ class AreaController extends Controller
// //
public function index() public function index()
{ {
$areas = Area::all('name', 'icon')->sortBy('name'); $areas = Area::orderByDesc('sort')->orderBy('name')->get();
return view('admin.areas.area-list', compact('areas')); return view('admin.areas.area-list', compact('areas'));
} }

@ -46,6 +46,7 @@ class Area extends Model
'preloader', 'preloader',
'product', 'product',
'products', 'products',
'product_grid',
'products_page', 'products_page',
'register', 'register',
'questions', 'questions',
@ -60,15 +61,23 @@ class Area extends Model
public function getSegmentAttribute() public function getSegmentAttribute()
{ {
return json_decode($this->valid_segments,true); return json_decode($this->valid_segments, true);
} }
public function getRouteKeyName(){ public function getRouteKeyName()
{
return 'name'; return 'name';
} }
public function parts(){ public function parts()
{
return $this->hasMany(Part::class); return $this->hasMany(Part::class);
} }
public function defPart()
{
$p = $this->parts()->first();
return 'segments.' . $p->segment . '.' . $p->part . '.' . $p->part;
}
} }

@ -19,6 +19,7 @@ return new class extends Migration
$table->json('valid_segments'); $table->json('valid_segments');
$table->string('preview')->nullable(); $table->string('preview')->nullable();
$table->boolean('use_default')->default(true); $table->boolean('use_default')->default(true);
$table->integer('sort')->default(0);
$table->timestamps(); $table->timestamps();
}); });
} }

@ -41,6 +41,7 @@ class AreaSeeder extends Seeder
'max' => 2, 'max' => 2,
'preview' => null, 'preview' => null,
'icon' => 'ri-window-line', 'icon' => 'ri-window-line',
'sort' => 99
], ],
[ [
'name' => 'defaultFooter', 'name' => 'defaultFooter',
@ -50,6 +51,7 @@ class AreaSeeder extends Seeder
'max' => 2, 'max' => 2,
'preview' => null, 'preview' => null,
'icon' => 'ri-window-line rotate-180', 'icon' => 'ri-window-line rotate-180',
'sort' => 98
], ],
[ [
'name' => 'index', 'name' => 'index',
@ -61,6 +63,7 @@ class AreaSeeder extends Seeder
'max' => 10, 'max' => 10,
'preview' => 'client.welcome', 'preview' => 'client.welcome',
'icon' => 'ri-home-smile-line', 'icon' => 'ri-home-smile-line',
'sort' => 97
], ],
[ [
'name' => 'post', 'name' => 'post',
@ -271,12 +274,22 @@ class AreaSeeder extends Seeder
'preview' => null, 'preview' => null,
'icon' => 'ri-mail-open-line', 'icon' => 'ri-mail-open-line',
], ],
[
'name' => 'product-grid',
'valid_segments' => json_encode(
["product_grid"]
),
'max' => 1,
'preview' => null,
'icon' => 'ri-layout-grid-line',
],
]; ];
foreach ($areas as $area) { foreach ($areas as $area) {
$a = new Area(); $a = new Area();
$a->name = $area['name']; $a->name = $area['name'];
$a->max = $area['max']; $a->max = $area['max'];
$a->sort = $area['sort']??0;
$a->valid_segments = $area['valid_segments']; $a->valid_segments = $area['valid_segments'];
$a->icon = $area['icon']; $a->icon = $area['icon'];
$a->preview = $area['preview']; $a->preview = $area['preview'];

@ -306,6 +306,15 @@ class PartSeeder extends Seeder
$part->sort = 1; $part->sort = 1;
$part->save(); $part->save();
// -------------------------------------------------------------
$part = new Part();
$part->segment = 'product_grid';
$part->part = 'DefaultProductGrid';
$part->area_id = Area::where('name', 'product-grid')->first()->id;
$part->sort = 1;
$part->save();
} }
} }

@ -271,7 +271,7 @@
"Index image": "تصویر شاخص", "Index image": "تصویر شاخص",
"Information": "اطلاعات", "Information": "اطلاعات",
"Interaction": "تعامل", "Interaction": "تعامل",
"Invalid area segment": "محیط نامطلوب است", "Invalid area segment": "",
"Invalid json file!": "فایل جی‌سان معتبر نیست", "Invalid json file!": "فایل جی‌سان معتبر نیست",
"Invalid morph": "چند ریخیتی نا معتبر", "Invalid morph": "چند ریخیتی نا معتبر",
"Invoice": "صورت حساب", "Invoice": "صورت حساب",
@ -353,6 +353,7 @@
"Print": "چاپ", "Print": "چاپ",
"Product": "محصول", "Product": "محصول",
"Product added to compare": "محصول به فهرست مقایسه افزوده شد", "Product added to compare": "محصول به فهرست مقایسه افزوده شد",
"Product grid": "کاشی محصول",
"Product added to favorites": "محصول به علاقه‌مندی شما افزوده شد", "Product added to favorites": "محصول به علاقه‌مندی شما افزوده شد",
"Product removed from compare": "محصول از فهرست مقایسه حذف شد", "Product removed from compare": "محصول از فهرست مقایسه حذف شد",
"Product removed from favorites": "محصول از علاقه مندی های شما حذف شد", "Product removed from favorites": "محصول از علاقه مندی های شما حذف شد",

@ -201,18 +201,13 @@
<h3 class="mt-4"> <h3 class="mt-4">
{{__("Related products")}} {{__("Related products")}}
</h3> </h3>
<div id="rel-products"> <div id="rel-products" class="mb-2">
@foreach($product->category->products()->where('status',1)->limit(10)->get() as $p) @foreach($product->category->products()->where('status',1)->limit(10)->get() as $p)
<div class="item"> @foreach($product->category->products()->where('status',1)->limit(10)->get() as $p)
<div class="aria-product-list"> <div class="item">
<a href="{{$p->imgUrl()}}"> @include(\App\Models\Area::where('name','product-grid')->first()->defPart(),['$product' => $p])
<img src="{{$p->imgUrl()}}" alt="{{$p->name}}" loading="lazy">
<h5>
{{$p->name}}
</h5>
</a>
</div> </div>
</div> @endforeach
@endforeach @endforeach
</div> </div>
</div> </div>

@ -197,17 +197,10 @@
<h3 class="mt-4"> <h3 class="mt-4">
{{__("Related products")}} {{__("Related products")}}
</h3> </h3>
<div id="rel-products"> <div id="rel-products" class="mb-2">
@foreach($product->category->products()->where('status',1)->limit(10)->get() as $p) @foreach($product->category->products()->where('status',1)->limit(10)->get() as $p)
<div class="item"> <div class="item">
<div class="karen-product-list"> @include(\App\Models\Area::where('name','product-grid')->first()->defPart(),['$product' => $p])
<a href="{{$p->imgUrl()}}">
<img src="{{$p->imgUrl()}}" alt="{{$p->name}}" loading="lazy">
<h5>
{{$p->name}}
</h5>
</a>
</div>
</div> </div>
@endforeach @endforeach
</div> </div>

@ -0,0 +1,37 @@
<div class="DefaultProductGrid">
<a class="fav-btn" data-slug="{{$product->slug}}" data-is-fav="{{$product->isFav()}}"
data-bs-custom-class="custom-tooltip"
data-bs-toggle="tooltip" data-bs-placement="auto" title="{{__("Add to / Remove from favorites")}}">
<i class="ri-heart-line"></i>
<i class="ri-heart-fill"></i>
</a>
<a class="compare-btn" data-slug="{{$product->slug}}"
data-bs-custom-class="custom-tooltip"
data-bs-toggle="tooltip" data-bs-placement="auto"
title="{{__("Add to/ Remove from compare list")}}">
<i class="ri-scales-3-line"></i>
</a>
<a href="{{$product->webUrl()}}">
<img src="{{$product->imgUrl()}}" alt="{{$product->name}}" loading="lazy">
<h3>
{{$product->name}}
</h3>
<div class="prices">
@if($product->hasDiscount())
<span class="old-price">
{{$product->oldPrice()}}
</span>
@endif
<span class="price">
{{$product->getPrice()}}
</span>
</div>
<div class="p-2">
<a href="{{ route('client.product-card-toggle',$product->slug) }}"
class="btn btn-outline-primary w-100 add-to-card">
<i class="ri-shopping-bag-3-line"></i>
{{__("Add to card")}}
</a>
</div>
</a>
</div>

@ -0,0 +1,10 @@
{
"name": "DefaultProductGrid",
"version": "1.0",
"author": "xStack",
"email": "xshop@xstack.ir",
"license": "GPL-3.0-or-later",
"url": "https:\/\/xstack.ir",
"author_url": "https:\/\/4xmen.ir",
"packages": []
}

@ -0,0 +1,21 @@
<?php
namespace Resources\Views\Segments;
use App\Models\Part;
class DefaultProductGrid
{
public static function onAdd(Part $part = null)
{
}
public static function onRemove(Part $part = null)
{
}
public static function onMount(Part $part = null)
{
return $part;
}
}

@ -0,0 +1,84 @@
.DefaultProductGrid {
border: 1px solid silver;
box-shadow: var(--xshop-shadow);
border-radius: var(--xshop-border-radius);
position: relative;
overflow: hidden;
img{
width: 100%;
}
h3 {
margin-top: 1rem;
text-align: center;
font-size: 20px;
font-weight: 300;
color: var(--xshop-text);
height: 2.1em;
overflow: hidden;
}
.prices {
display: grid;
grid-auto-columns: minmax(0, 1fr);
grid-auto-flow: column;
text-align: center;
span {
display: block;
padding: .5rem;
}
.old-price{
text-decoration: red line-through;
color: gray;
}
}
.fav-btn, .compare-btn {
position: absolute;
inset-inline-start: -12%;
top: 3%;
width: 40px;
height: 40px;
background: #ffffff55;
font-size: 25px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
z-index: 4;
cursor: pointer;
transition: .4s;
&:hover {
background: var(--xshop-primary);
color: var(--xshop-diff);
}
}
.fav-btn {
top: calc(3% + 50px);
&[data-is-fav="-1"]{
display: none;
}
&[data-is-fav="1"]{
.ri-heart-line{
display: none;
}
}
&[data-is-fav="0"]{
.ri-heart-fill{
display: none;
}
}
}
&:hover {
.fav-btn, .compare-btn {
inset-inline-start: 3%;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 KiB

@ -6,41 +6,7 @@
<div class="row"> <div class="row">
@foreach($products as $product) @foreach($products as $product)
<div class="col-md-4 p-2"> <div class="col-md-4 p-2">
<div class="product-item"> @include(\App\Models\Area::where('name','product-grid')->first()->defPart(),compact('product'))
<a class="fav-btn" data-slug="{{$product->slug}}" data-is-fav="{{$product->isFav()}}"
data-bs-custom-class="custom-tooltip"
data-bs-toggle="tooltip" data-bs-placement="auto" title="{{__("Add to / Remove from favorites")}}">
<i class="ri-heart-line"></i>
<i class="ri-heart-fill"></i>
</a>
<a class="compare-btn" data-slug="{{$product->slug}}"
data-bs-custom-class="custom-tooltip"
data-bs-toggle="tooltip" data-bs-placement="auto" title="{{__("Add to/ Remove from compare list")}}">
<i class="ri-scales-3-line"></i>
</a>
<a href="{{$product->webUrl()}}">
<img src="{{$product->imgUrl()}}" alt="{{$product->name}}" loading="lazy">
<h3>
{{$product->name}}
</h3>
<div class="prices">
@if($product->hasDiscount())
<span class="old-price">
{{$product->oldPrice()}}
</span>
@endif
<span class="price">
{{$product->getPrice()}}
</span>
</div>
<div class="p-2">
<a href="{{ route('client.product-card-toggle',$product->slug) }}" class="btn btn-outline-primary w-100 add-to-card">
<i class="ri-shopping-bag-3-line"></i>
{{__("Add to card")}}
</a>
</div>
</a>
</div>
</div> </div>
@endforeach @endforeach
</div> </div>

@ -7,82 +7,4 @@
object-fit: cover; object-fit: cover;
} }
.product-item {
border: 1px solid silver;
box-shadow: var(--xshop-shadow);
border-radius: var(--xshop-border-radius);
position: relative;
overflow: hidden;
h3 {
margin-top: 1rem;
text-align: center;
font-size: 20px;
font-weight: 300;
color: var(--xshop-text);
}
.prices {
display: grid;
grid-auto-columns: minmax(0, 1fr);
grid-auto-flow: column;
text-align: center;
span {
display: block;
padding: .5rem;
}
.old-price{
text-decoration: red line-through;
color: gray;
}
}
.fav-btn, .compare-btn {
position: absolute;
inset-inline-start: -12%;
top: 3%;
width: 40px;
height: 40px;
background: #ffffff55;
font-size: 25px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
z-index: 4;
cursor: pointer;
transition: .4s;
&:hover {
background: var(--xshop-primary);
color: var(--xshop-diff);
}
}
.fav-btn {
top: calc(3% + 50px);
&[data-is-fav="-1"]{
display: none;
}
&[data-is-fav="1"]{
.ri-heart-line{
display: none;
}
}
&[data-is-fav="0"]{
.ri-heart-fill{
display: none;
}
}
}
&:hover {
.fav-btn, .compare-btn {
inset-inline-start: 3%;
}
}
}
} }

@ -13,43 +13,7 @@
<div class="row"> <div class="row">
@foreach($products as $product) @foreach($products as $product)
<div class="col-md-4 p-2"> <div class="col-md-4 p-2">
<div class="product-item"> @include(\App\Models\Area::where('name','product-grid')->first()->defPart(),compact('product'))
<a class="fav-btn" data-slug="{{$product->slug}}" data-is-fav="{{$product->isFav()}}"
data-bs-custom-class="custom-tooltip"
data-bs-toggle="tooltip" data-bs-placement="auto" title="{{__("Add to / Remove from favorites")}}">
<i class="ri-heart-line"></i>
<i class="ri-heart-fill"></i>
</a>
<a class="compare-btn" data-slug="{{$product->slug}}"
data-bs-custom-class="custom-tooltip"
data-bs-toggle="tooltip" data-bs-placement="auto"
title="{{__("Add to/ Remove from compare list")}}">
<i class="ri-scales-3-line"></i>
</a>
<a href="{{$product->webUrl()}}">
<img src="{{$product->imgUrl()}}" alt="{{$product->name}}" loading="lazy">
<h3>
{{$product->name}}
</h3>
<div class="prices">
@if($product->hasDiscount())
<span class="old-price">
{{$product->oldPrice()}}
</span>
@endif
<span class="price">
{{$product->getPrice()}}
</span>
</div>
<div class="p-2">
<a href="{{ route('client.product-card-toggle',$product->slug) }}"
class="btn btn-outline-primary w-100 add-to-card">
<i class="ri-shopping-bag-3-line"></i>
{{__("Add to card")}}
</a>
</div>
</a>
</div>
</div> </div>
@endforeach @endforeach
</div> </div>

@ -25,84 +25,6 @@
object-fit: cover; object-fit: cover;
} }
.product-item {
border: 1px solid silver;
box-shadow: var(--xshop-shadow);
border-radius: var(--xshop-border-radius);
position: relative;
overflow: hidden;
h3 {
margin-top: 1rem;
text-align: center;
font-size: 20px;
font-weight: 300;
color: var(--xshop-text);
}
.prices {
display: grid;
grid-auto-columns: minmax(0, 1fr);
grid-auto-flow: column;
text-align: center;
span {
display: block;
padding: .5rem;
}
.old-price{
text-decoration: red line-through;
color: gray;
}
}
.fav-btn, .compare-btn {
position: absolute;
inset-inline-start: -12%;
top: 3%;
width: 40px;
height: 40px;
background: #ffffff55;
font-size: 25px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
z-index: 4;
cursor: pointer;
transition: .4s;
&:hover {
background: var(--xshop-primary);
color: var(--xshop-diff);
}
}
.fav-btn {
top: calc(3% + 50px);
&[data-is-fav="-1"]{
display: none;
}
&[data-is-fav="1"]{
.ri-heart-line{
display: none;
}
}
&[data-is-fav="0"]{
.ri-heart-fill{
display: none;
}
}
}
&:hover {
.fav-btn, .compare-btn {
inset-inline-start: 3%;
}
}
}
aside{ aside{

Loading…
Cancel
Save