added tag page

fixed readme
fixed map bugs (inline map & icons)
master
A1Gard 3 weeks ago
parent ddb5b346f2
commit b75f078c56

@ -50,7 +50,7 @@ php artisan seeding:prepare
``` ```
- Seeding image for models: [Group, Category, Post, Product, Slider] - Seeding image for models: [Group, Category, Post, Product, Slider]
```bash ```bash
pa seeding:image Product digital php artisan seeding:image Product digital
``` ```
> First parameter is Model, Second is image seeder directory available [bag, clothe, digital, sport, posts, makeup] > First parameter is Model, Second is image seeder directory available [bag, clothe, digital, sport, posts, makeup]
> You can create your directory and put your image into new directory then use image seeder > You can create your directory and put your image into new directory then use image seeder

@ -29,10 +29,10 @@ class ClientController extends Controller
$this->middleware(function ($request, $next) { $this->middleware(function ($request, $next) {
if ($request->attributes->get('set_lang') != true){ if ($request->attributes->get('set_lang') != true) {
app()->setLocale(config('app.locale')); app()->setLocale(config('app.locale'));
\Session::remove('locate'); \Session::remove('locate');
}elseif (\Session::has('locate')) { } elseif (\Session::has('locate')) {
app()->setLocale(\Session::get('locate')); app()->setLocale(\Session::get('locate'));
} }
@ -177,7 +177,12 @@ class ClientController extends Controller
{ {
$tag = Tag::where('slug->' . config('app.locale'), 'like', $slug)->first(); $tag = Tag::where('slug->' . config('app.locale'), 'like', $slug)->first();
return $tag; $posts = Post::withAnyTags([$tag])->where('status', 1)->paginate(100);
$products = Product::withAnyTags([$tag])->where('status', 1)->paginate(100);
$clips = Clip::withAnyTags([$tag])->where('status', 1)->paginate(100);
$title = __('Tag') . ': ' . $tag->name;
$subtitle = '';
return view('client.tag', compact('tag', 'posts', 'products', 'clips', 'title', 'subtitle'));
} }
@ -229,7 +234,7 @@ class ClientController extends Controller
public function group($slug) public function group($slug)
{ {
$group = Group::where('slug',$slug)->firstOrFail(); $group = Group::where('slug', $slug)->firstOrFail();
$area = 'group'; $area = 'group';
$title = $group->name; $title = $group->name;
$subtitle = $group->subtitle; $subtitle = $group->subtitle;
@ -400,10 +405,6 @@ class ClientController extends Controller
} }
public function compare() public function compare()
{ {
$area = 'compare'; $area = 'compare';
@ -413,13 +414,15 @@ class ClientController extends Controller
$products = Product::whereIn('id', $ids)->where('status', 1)->get(); $products = Product::whereIn('id', $ids)->where('status', 1)->get();
return view('client.default-list', compact('area', 'products', 'title', 'subtitle')); return view('client.default-list', compact('area', 'products', 'title', 'subtitle'));
} }
public function contact() public function contact()
{ {
$area = 'contact-us'; $area = 'contact-us';
$title = __("Contact us"); $title = __("Contact us");
$subtitle = ''; $subtitle = '';
return view('client.default-list', compact('area', 'title', 'subtitle')); return view('client.default-list', compact('area', 'title', 'subtitle'));
} }
public function sendContact(ContactSubmitRequest $request) public function sendContact(ContactSubmitRequest $request)
{ {
$con = new Contact(); $con = new Contact();
@ -581,14 +584,14 @@ class ClientController extends Controller
} }
$method = explode('@', $r)[1]; $method = explode('@', $r)[1];
$segments = $request->segments(); $segments = $request->segments();
$routes = explode('/',$n); $routes = explode('/', $n);
$args = []; $args = [];
foreach ($routes as $i => $route) { foreach ($routes as $i => $route) {
if ($route[0] == '{'){ if ($route[0] == '{') {
$args[] = $segments[$i+1]; $args[] = $segments[$i + 1];
} }
} }
$args[]= $request; $args[] = $request;
return $this->$method(...$args); return $this->$method(...$args);
} }

@ -10,9 +10,9 @@ use Spatie\Translatable\HasTranslations;
class Clip extends Model class Clip extends Model
{ {
use HasFactory, SoftDeletes, HasTranslations,HasTags; use HasFactory, SoftDeletes, HasTranslations, HasTags;
public $translatable = ['title','body']; public $translatable = ['title', 'body'];
public function getRouteKeyName() public function getRouteKeyName()
{ {
@ -27,6 +27,7 @@ class Clip extends Model
return \Storage::url('cover/optimized-' . $this->cover); return \Storage::url('cover/optimized-' . $this->cover);
} }
public function imgOriginalUrl() public function imgOriginalUrl()
{ {
if ($this->cover == null) { if ($this->cover == null) {
@ -50,12 +51,14 @@ class Clip extends Model
return $this->belongsTo(\App\Models\User::class); return $this->belongsTo(\App\Models\User::class);
} }
public function attachs(){ public function attachs()
return $this->morphMany(Attachment::class,'attachable'); {
return $this->morphMany(Attachment::class, 'attachable');
} }
public function webUrl(){ public function webUrl()
return fixUrlLang(route('client.clip',$this->slug)); {
return fixUrlLang(route('client.clip', $this->slug));
} }
@ -69,12 +72,13 @@ class Clip extends Model
return $this->morphMany(Comment::class, 'commentable')->where('status', 1); return $this->morphMany(Comment::class, 'commentable')->where('status', 1);
} }
public function markup(){ public function markup()
{
$app = config('app.name'); $app = config('app.name');
$logo = asset('upload/images/logo.png'); $logo = asset('upload/images/logo.png');
$desc = str_replace('"','',strip_tags($this->body)); $desc = str_replace('"', '', strip_tags($this->body));
$count = $this->comments()->count() ; $count = $this->comments()->count();
return <<<RESULT return <<<RESULT
<script type="application/ld+json"> <script type="application/ld+json">
@ -106,11 +110,12 @@ RESULT;
} }
public function tagsList(){ public function tagsList()
if ($this->tags()->count() == 0){ {
if ($this->tags()->count() == 0) {
return getSetting('keyword'); return getSetting('keyword');
}else{ } else {
return implode(',',$this->tags()->pluck('name')->toArray()); return implode(',', $this->tags()->pluck('name')->toArray());
} }
} }

@ -41,28 +41,28 @@ class Post extends Model implements HasMedia
{ {
$optimize = getSetting('optimize'); $optimize = getSetting('optimize');
if ($optimize == false){ if ($optimize == false) {
$optimize = 'webp'; $optimize = 'webp';
} }
$t = explode('x', config('app.media.post_thumb')); $t = explode('x', config('app.media.post_thumb'));
$t = imageSizeConvertValidate('post_thumb'); $t = imageSizeConvertValidate('post_thumb');
$mc = $this->addMediaConversion('post-image') $mc = $this->addMediaConversion('post-image')
->width($t[0]) ->width($t[0])
->height($t[1]) ->height($t[1])
->crop( $t[0], $t[1]) ->crop($t[0], $t[1])
->optimize() ->optimize()
->sharpen(10) ->sharpen(10)
->nonQueued() ->nonQueued()
->format($optimize); ->format($optimize);
if (getSetting('watermark')){ if (getSetting('watermark')) {
$mc->watermark(public_path('upload/images/logo.png'), $mc->watermark(public_path('upload/images/logo.png'),
AlignPosition::BottomLeft, 5, 5, Unit::Percent, AlignPosition::BottomLeft, 5, 5, Unit::Percent,
config('app.media.watermark_size'), Unit::Percent, config('app.media.watermark_size'), Unit::Percent,
config('app.media.watermark_size'), Unit::Percent, Fit::Contain, config('app.media.watermark_size'), Unit::Percent, Fit::Contain,
config('app.media.watermark_opacity')); config('app.media.watermark_opacity'));
} }
} }
@ -106,12 +106,14 @@ class Post extends Model implements HasMedia
return $this->morphMany(Comment::class, 'commentable'); return $this->morphMany(Comment::class, 'commentable');
} }
public function mainGroup(){ public function mainGroup()
return $this->belongsTo(Group::class,'group_id'); {
return $this->belongsTo(Group::class, 'group_id');
} }
public function attachs(){ public function attachs()
return $this->morphMany(Attachment::class,'attachable'); {
return $this->morphMany(Attachment::class, 'attachable');
} }
@ -130,23 +132,25 @@ class Post extends Model implements HasMedia
// ]; // ];
// } // }
public function webUrl(){ public function webUrl()
return fixUrlLang(route('client.post',$this->slug)); {
return fixUrlLang(route('client.post', $this->slug));
} }
public function markup(){ public function markup()
{
$type = 'BlogPosting'; $type = 'BlogPosting';
if (strpos(strtolower(implode(',',$this->groups()->pluck('name')->toArray())),__('article')) !== false){ if (strpos(strtolower(implode(',', $this->groups()->pluck('name')->toArray())), __('article')) !== false) {
$type = 'Article'; $type = 'Article';
} }
if (strpos(strtolower(implode(',',$this->groups()->pluck('name')->toArray())),__('news')) !== false){ if (strpos(strtolower(implode(',', $this->groups()->pluck('name')->toArray())), __('news')) !== false) {
$type = 'NewsArticle'; $type = 'NewsArticle';
} }
$app = config('app.name'); $app = config('app.name');
$logo = asset('upload/images/logo.png'); $logo = asset('upload/images/logo.png');
$author = $this->author->name??$app; $author = $this->author->name ?? $app;
return <<<RESULT return <<<RESULT
<script type="application/ld+json"> <script type="application/ld+json">
{ {
@ -184,11 +188,12 @@ RESULT;
} }
public function tagsList(){ public function tagsList()
if ($this->tags()->count() == 0){ {
if ($this->tags()->count() == 0) {
return getSetting('keyword'); return getSetting('keyword');
}else{ } else {
return implode(',',$this->tags()->pluck('name')->toArray()); return implode(',', $this->tags()->pluck('name')->toArray());
} }
} }
} }

@ -144,9 +144,9 @@ class Product extends Model implements HasMedia
{ {
return $this->hasMany(Discount::class, 'product_id', 'id') return $this->hasMany(Discount::class, 'product_id', 'id')
->where(function ($query) { ->where(function ($query) {
$query->where('expire', '>=', date('Y-m-d')) $query->where('expire', '>=', date('Y-m-d'))
->orWhereNull('expire'); ->orWhereNull('expire');
}); });
} }
public function quesions() public function quesions()
@ -156,7 +156,7 @@ class Product extends Model implements HasMedia
function hasDiscount() function hasDiscount()
{ {
if (!$this->isAvailable()){ if (!$this->isAvailable()) {
return false; return false;
} }
return $this->discounts() return $this->discounts()
@ -242,11 +242,11 @@ class Product extends Model implements HasMedia
case 'select': case 'select':
case 'singlemulti': case 'singlemulti':
if (!is_array($value)) { if (!is_array($value)) {
if (isset( $result[$key]['data']->datas[$value])){ if (isset($result[$key]['data']->datas[$value])) {
$result[$key]['human_value'] = $result[$key]['human_value'] =
$result[$key]['data']->datas[$value]; $result[$key]['data']->datas[$value];
}else{ } else {
$result[$key]['human_value'] = '-'; $result[$key]['human_value'] = '-';
} }
} else { } else {
@ -259,11 +259,11 @@ class Product extends Model implements HasMedia
break; break;
default: default:
if (is_array($value)) { if (is_array($value)) {
$result[$key]['human_value'] = '<span class="meta-tag">'.implode('</span> <span class="meta-tag">', $value).'</span>'; $result[$key]['human_value'] = '<span class="meta-tag">' . implode('</span> <span class="meta-tag">', $value) . '</span>';
} else { } else {
if ($value == '' || $value == null) { if ($value == '' || $value == null) {
$result[$key]['human_value'] = '-'; $result[$key]['human_value'] = '-';
}else{ } else {
$result[$key]['human_value'] = $value; $result[$key]['human_value'] = $value;
} }
} }
@ -283,7 +283,7 @@ class Product extends Model implements HasMedia
public function webUrl() public function webUrl()
{ {
return fixUrlLang(route('client.product',$this->slug)); return fixUrlLang(route('client.product', $this->slug));
} }
@ -296,16 +296,16 @@ class Product extends Model implements HasMedia
$price = $this->quantities()->min('price'); $price = $this->quantities()->min('price');
} }
if (!$this->isAvailable()){ if (!$this->isAvailable()) {
return __('Unavailable'); return __('Unavailable');
} }
if ($this->hasDiscount()) { if ($this->hasDiscount()) {
$d = $this->activeDiscounts()->first(); $d = $this->activeDiscounts()->first();
if ($d->type == 'PRICE') { if ($d->type == 'PRICE') {
$price -= $d->amount; $price -= $d->amount;
}else{ } else {
$price = ( (100 - $d->amount) * $price ) / 100; $price = ((100 - $d->amount) * $price) / 100;
} }
} }
@ -315,6 +315,7 @@ class Product extends Model implements HasMedia
return number_format($price) . ' ' . config('app.currency.symbol'); return number_format($price) . ' ' . config('app.currency.symbol');
} }
public function oldPricePure() public function oldPricePure()
{ {
$price = 0; $price = 0;
@ -330,6 +331,7 @@ class Product extends Model implements HasMedia
return $price; return $price;
} }
public function oldPrice() public function oldPrice()
{ {
$price = 0; $price = 0;
@ -346,29 +348,32 @@ class Product extends Model implements HasMedia
return number_format($price) . ' ' . config('app.currency.symbol'); return number_format($price) . ' ' . config('app.currency.symbol');
} }
public function isFav(){ public function isFav()
{
if (!auth('customer')->check()) { if (!auth('customer')->check()) {
return -1; return -1;
} }
if (\auth('customer')->user()->products()->where('product_id', $this->id)->exists()) { if (\auth('customer')->user()->products()->where('product_id', $this->id)->exists()) {
return 1; return 1;
}else{ } else {
return 0; return 0;
} }
} }
public function isAvailable(){ public function isAvailable()
if ($this->stock_quantity == 0){ {
return false; if ($this->stock_quantity == 0) {
return false;
} }
if ($this->stock_status != 'IN_STOCK'){ if ($this->stock_status != 'IN_STOCK') {
return false; return false;
} }
return true; return true;
} }
public function markup(){ public function markup()
{
$currency = config('app.currency.code'); $currency = config('app.currency.code');
@ -413,25 +418,26 @@ RESULT;
public function seoDesc() public function seoDesc()
{ {
$template = getSetting('product_description'); $template = getSetting('product_description');
if ($template == null || $template == ''){ if ($template == null || $template == '') {
$template = __('%name% sale in our shop by %price% %category.name%'); $template = __('%name% sale in our shop by %price% %category.name%');
} }
$template = str_replace('%name%', $this->name,$template); $template = str_replace('%name%', $this->name, $template);
$template = str_replace('%price%', $this->getPrice() ,$template); $template = str_replace('%price%', $this->getPrice(), $template);
$template = str_replace('%excerpt%', $this->excerpt,$template); $template = str_replace('%excerpt%', $this->excerpt, $template);
$template = str_replace('%stock_quantity%', $this->stock_quantity,$template); $template = str_replace('%stock_quantity%', $this->stock_quantity, $template);
$template = str_replace('%category.name%', $this->category->name,$template); $template = str_replace('%category.name%', $this->category->name, $template);
return $template; return $template;
} }
public function tagsList(){ public function tagsList()
if ($this->tags()->count() == 0){ {
if ($this->tags()->count() == 0) {
return getSetting('keyword'); return getSetting('keyword');
}else{ } else {
return implode(',',$this->tags()->pluck('name')->toArray()); return implode(',', $this->tags()->pluck('name')->toArray());
} }
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

@ -1,11 +1,12 @@
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
if (document.querySelectorAll('.tab-control a').length > 0) { if (document.querySelectorAll('.tab-control a').length > 0) {
document.querySelectorAll('.tab-control a')?.forEach(function (el) { document.querySelectorAll('.tab-control a')?.forEach(function (el) {
el.addEventListener('click', function () { el.addEventListener('click', function () {
try { try {
document.querySelector('.tab-control a.active').classList.remove('active'); document.querySelector('.tab-control a.active').classList.remove('active');
this.classList.add('active'); this.classList.add('active');
document.querySelector('.tab.active').classList.remove('active'); document.querySelector('.tab.active,.tab-content.active').classList.remove('active');
document.querySelector(this.getAttribute('href')).classList.add('active'); document.querySelector(this.getAttribute('href')).classList.add('active');
} catch { } catch {
} }

@ -274,8 +274,17 @@ export default {
}, },
initMap() { initMap() {
if (!import.meta.env.DEV){
L.Icon.Default.mergeOptions({
iconRetinaUrl: "/assets/vendor/leaflet/marker-icon-2x.png",
iconUrl: "/assets/vendor/leaflet/marker-icon.png",
shadowUrl: "/assets/vendor/leaflet/marker-shadow.png"
});
}
this.map = L.map(this.$refs.mapContainer).setView([35.83266000, 50.99155000], 10); this.map = L.map(this.$refs.mapContainer).setView([35.83266000, 50.99155000], 10);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; openstreetmap', attribution: '&copy; openstreetmap',
attributionControl: false, attributionControl: false,

@ -274,6 +274,16 @@ export default {
}, },
initMap() { initMap() {
if (!import.meta.env.DEV){
L.Icon.Default.mergeOptions({
iconRetinaUrl: "/assets/vendor/leaflet/marker-icon-2x.png",
iconUrl: "/assets/vendor/leaflet/marker-icon.png",
shadowUrl: "/assets/vendor/leaflet/marker-shadow.png"
});
}
this.map = L.map(this.$refs.mapContainer).setView([35.83266000, 50.99155000], 10); this.map = L.map(this.$refs.mapContainer).setView([35.83266000, 50.99155000], 10);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {

@ -70,6 +70,14 @@ export default {
}, },
methods: { methods: {
initMap() { initMap() {
if (!import.meta.env.DEV){
L.Icon.Default.mergeOptions({
iconRetinaUrl: "/assets/vendor/leaflet/marker-icon-2x.png",
iconUrl: "/assets/vendor/leaflet/marker-icon.png",
shadowUrl: "/assets/vendor/leaflet/marker-shadow.png"
});
}
this.map = L.map(this.$refs.mapContainer).setView([this.lat, this.lng], this.zoom); this.map = L.map(this.$refs.mapContainer).setView([this.lat, this.lng], this.zoom);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {

@ -127,3 +127,31 @@ body {
color: var(--xshop-diff2); color: var(--xshop-diff2);
} }
} }
.tag-page{
min-height: 60vh;
.tab-control{
padding-left: 12px;
padding-right: 12px;
}
.tab-control a.active{
background: var(--xshop-primary);
color: var(--xshop-diff);
}
.tab-content{
background: transparent;
}
}
.tab-content {
display: none;
padding: 1rem;
background: var(--karen-tab-bg-color,#ffffff);
&.active {
display: block;
}
}

@ -0,0 +1,83 @@
@extends('website.inc.website-layout')
@section('title')
{{$title}} - {{config('app.name')}}
@endsection
@section('content')
@foreach(getParts('default_header') as $part)
@php($p = $part->getBladeWithData())
@include($p['blade'],['data' => $p['data']])
@endforeach
<div class="{{gfx()['container']}} content tag-page">
<div class="tab-control">
<div class="row text-center">
<a class="col-md py-2 active" href="#posts">
{{__("Posts")}} ({{count($posts)}})
</a>
<a class="col-md py-2" href="#products">
{{__("Products")}} ({{count($products)}})
</a>
<a class="col-md py-2" href="#clips">
{{__("Video clips")}} ({{count($clips)}})
</a>
</div>
</div>
<div>
<div class="tab-content active px-0" id="posts">
@if(count($posts) == 0)
<div class="alert alert-info">
{{__("There is nothing to show!")}}
</div>
@else
<ul class="list-group">
@foreach($posts as $post)
<li class="list-group-item">
<a href="{{$post->webUrl()}}">
{{$post->title}}
</a>
</li>
@endforeach
</ul>
@endif
</div>
<div class="tab-content px-0" id="products">
@if(count($products) == 0)
<div class="alert alert-info">
{{__("There is nothing to show!")}}
</div>
@else
<ul class="list-group">
@foreach($products as $product)
<li class="list-group-item">
<a href="{{$product->webUrl()}}">
{{$product->name}}
</a>
</li>
@endforeach
</ul>
@endif
</div>
<div class="tab-content px-0" id="clips">
@if(count($clips) == 0)
<div class="alert alert-info">
{{__("There is nothing to show!")}}
</div>
@else
<ul class="list-group">
@foreach($clips as $clip)
<li class="list-group-item">
<a href="{{$clip->webUrl()}}">
{{$clip->title}}
</a>
</li>
@endforeach
</ul>
@endif
</div>
</div>
</div>
@foreach(getParts('default_footer') as $part)
@php($p = $part->getBladeWithData())
@include($p['blade'],['data' => $p['data']])
@endforeach
@endsection

@ -3,21 +3,31 @@ import L from 'leaflet';
var map,marker ; var map,marker ;
window.addEventListener('load',function () { window.addEventListener('load',function () {
const lat = parseFloat(document.querySelector('#maplat').value); // delete L.icon.default.prototype._getIconUrl ;
const lng = parseFloat(document.querySelector('#maplng').value); if (!import.meta.env.DEV){
const zoom = parseInt(document.querySelector('#mapzoom').value); L.Icon.Default.mergeOptions({
map = L.map(document.querySelector('#mapContainer')).setView([lat,lng], zoom); iconRetinaUrl: "/assets/vendor/leaflet/marker-icon-2x.png",
iconUrl: "/assets/vendor/leaflet/marker-icon.png",
shadowUrl: "/assets/vendor/leaflet/marker-shadow.png"
});
}
if (document.querySelectorAll('#mapContainer').length != 0) {
const lat = parseFloat(document.querySelector('#maplat').value);
const lng = parseFloat(document.querySelector('#maplng').value);
const zoom = parseInt(document.querySelector('#mapzoom').value);
map = L.map(document.querySelector('#mapContainer')).setView([lat, lng], zoom);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; openstreetmap', attribution: '&copy; openstreetmap',
attributionControl: false, attributionControl: false,
}).addTo(map); }).addTo(map);
map.attributionControl.setPrefix('xShop'); map.attributionControl.setPrefix('xShop');
if (this.marker) { if (this.marker) {
map.removeLayer(marker); map.removeLayer(marker);
} }
marker = L.marker({lat: lat, lng: lng}).addTo(map); marker = L.marker({lat: lat, lng: lng}).addTo(map);
}
}); });

@ -160,13 +160,5 @@
background: var(--xshop-primary); background: var(--xshop-primary);
transition: left 0.3s ease, width 0.3s ease; transition: left 0.3s ease, width 0.3s ease;
} }
.tab-content {
display: none;
padding: 1rem;
background: var(--karen-tab-bg-color,#ffffff);
}
.tab-content.active {
display: block;
}
} }

Loading…
Cancel
Save