added product grid template

added default product grid theme part
added sort to area
pull/49/head
A1Gard 1 month ago
parent 1e6b040c4e
commit 48ae713ae1

@ -17,7 +17,7 @@ class AreaController extends Controller
//
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'));
}

@ -46,6 +46,7 @@ class Area extends Model
'preloader',
'product',
'products',
'product_grid',
'products_page',
'register',
'questions',
@ -60,15 +61,23 @@ class Area extends Model
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';
}
public function parts(){
public function parts()
{
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->string('preview')->nullable();
$table->boolean('use_default')->default(true);
$table->integer('sort')->default(0);
$table->timestamps();
});
}

@ -41,6 +41,7 @@ class AreaSeeder extends Seeder
'max' => 2,
'preview' => null,
'icon' => 'ri-window-line',
'sort' => 99
],
[
'name' => 'defaultFooter',
@ -50,6 +51,7 @@ class AreaSeeder extends Seeder
'max' => 2,
'preview' => null,
'icon' => 'ri-window-line rotate-180',
'sort' => 98
],
[
'name' => 'index',
@ -61,6 +63,7 @@ class AreaSeeder extends Seeder
'max' => 10,
'preview' => 'client.welcome',
'icon' => 'ri-home-smile-line',
'sort' => 97
],
[
'name' => 'post',
@ -271,12 +274,22 @@ class AreaSeeder extends Seeder
'preview' => null,
'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) {
$a = new Area();
$a->name = $area['name'];
$a->max = $area['max'];
$a->sort = $area['sort']??0;
$a->valid_segments = $area['valid_segments'];
$a->icon = $area['icon'];
$a->preview = $area['preview'];

@ -306,6 +306,15 @@ class PartSeeder extends Seeder
$part->sort = 1;
$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": "تصویر شاخص",
"Information": "اطلاعات",
"Interaction": "تعامل",
"Invalid area segment": "محیط نامطلوب است",
"Invalid area segment": "",
"Invalid json file!": "فایل جی‌سان معتبر نیست",
"Invalid morph": "چند ریخیتی نا معتبر",
"Invoice": "صورت حساب",
@ -353,6 +353,7 @@
"Print": "چاپ",
"Product": "محصول",
"Product added to compare": "محصول به فهرست مقایسه افزوده شد",
"Product grid": "کاشی محصول",
"Product added to favorites": "محصول به علاقه‌مندی شما افزوده شد",
"Product removed from compare": "محصول از فهرست مقایسه حذف شد",
"Product removed from favorites": "محصول از علاقه مندی های شما حذف شد",

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

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

@ -7,82 +7,4 @@
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">
@foreach($products as $product)
<div class="col-md-4 p-2">
<div class="product-item">
<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>
@include(\App\Models\Area::where('name','product-grid')->first()->defPart(),compact('product'))
</div>
@endforeach
</div>

@ -25,84 +25,6 @@
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{

Loading…
Cancel
Save