diff --git a/app/Console/Commands/clientAssetGenerator.php b/app/Console/Commands/clientAssetGenerator.php index 5ad3746..f32e44c 100644 --- a/app/Console/Commands/clientAssetGenerator.php +++ b/app/Console/Commands/clientAssetGenerator.php @@ -33,6 +33,7 @@ class clientAssetGenerator extends Command $vars['xshop-background'] = $gfxes['background'] ?? '#000000'; $vars['xshop-primary'] = $gfxes['primary'] ?? '#6e0000'; $vars['xshop-diff'] = getGrayscaleTextColor($gfxes['primary']) ?? '#6e0000'; + $vars['xshop-diff2'] = getGrayscaleTextColor($gfxes['secondary']) ?? '#6e0000'; $vars['xshop-secondary'] = $gfxes['secondary'] ?? '#ff0000'; $vars['xshop-text'] = $gfxes['text'] ?? '#111111'; $vars['xshop-border-radius'] = $gfxes['border-radius'] ?? '7px'; diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index 03c4eea..b59b5f5 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -975,3 +975,39 @@ function isGuestMaxAttemptTry($action, $max = 5, $minutes = 60) return false; } } + +/** + * home url to best experience for multi lang shops + * @return string + */ +function homeUrl(){ + return \route('client.welcome'); +} +/** + * tag url to best experience for multi lang shops + * @return string + */ +function tagUrl($slug){ + return route('client.tag',$slug); +} + +function usableProp($props) +{ + $result = []; + + foreach ($props as $prop) { + $tmp = []; + foreach (json_decode($prop->options) as $item) { + $tmp[$item->value] = $item->title; + } + $result[$prop->name]['data'] = $tmp; + $result[$prop->name]['icon'] = $prop->icon; + $result[$prop->name]['unit'] = $prop->unit; + $result[$prop->name]['searchable'] = $prop->searchable; + $result[$prop->name]['priceable'] = $prop->priceable; + $result[$prop->name]['type'] = $prop->type; + $result[$prop->name]['label'] = $prop->label; + } + + return $result; +} diff --git a/app/Http/Controllers/ClientController.php b/app/Http/Controllers/ClientController.php index 021aa8b..703d65a 100644 --- a/app/Http/Controllers/ClientController.php +++ b/app/Http/Controllers/ClientController.php @@ -13,6 +13,7 @@ use App\Models\Product; use App\Models\Quantity; use App\Models\User; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Log; use Plank\Metable\Meta; use Spatie\Tags\Tag; @@ -147,6 +148,14 @@ class ClientController extends Controller return view('client.group', compact('area', 'posts', 'title', 'subtitle', 'group')); } + public function product(Product $product) + { + $area = 'product'; + $title = $product->name; + $subtitle = $product->excerpt; // WIP SEO + return view('client.default-list', compact('area', 'product', 'title', 'subtitle')); + } + public function category(Category $category, Request $request) { $area = 'category'; @@ -267,10 +276,22 @@ class ClientController extends Controller $cards = json_decode(\Cookie::get('card'), true); $qs = json_decode(\Cookie::get('q'), true); if (in_array($product->id, $cards)) { - $msg = "Product removed from card"; - $i = array_search($product->id, $cards); - unset($cards[$i]); - unset($qs[$i]); + $found = false; + foreach ($cards as $i => $card) { + if ($card == $product->id && $qs[$i] == $quantity) { + $found = true; + break; + } + } + if ($found) { + $msg = "Product removed from card"; + unset($cards[$i]); + unset($qs[$i]); + }else{ + $cards[] = $product->id; + $qs[] = $quantity; + $msg = "Product added to card"; + } } else { $cards[] = $product->id; $qs[] = $quantity; @@ -427,6 +448,8 @@ class ClientController extends Controller guestLog('sms'); $customer = Customer::where('mobile', $request->input('tel')); $code = rand(11111, 99999); + + Log::info('auth code: '.$code ); if ($customer->count() == 0) { $customer = new Customer(); $customer->mobile = $request->input('tel'); diff --git a/app/Models/Product.php b/app/Models/Product.php index 5a5193d..e3c622f 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -158,7 +158,11 @@ class Product extends Model implements HasMedia if (!$this->isAvailable()){ return false; } - return $this->discounts()->where('expire', '>', date('Y-m-d'))->count() > 0; + return $this->discounts() + ->where(function ($query) { + $query->where('expire', '>=', date('Y-m-d')) + ->orWhereNull('expire'); + })->count() > 0; } @@ -278,8 +282,7 @@ class Product extends Model implements HasMedia public function webUrl() { - return '#';// WIP - return route(''); + return route('client.product',$this->slug); } diff --git a/database/seeders/PropSeeder.php b/database/seeders/PropSeeder.php index 8a67000..5d1c3dc 100644 --- a/database/seeders/PropSeeder.php +++ b/database/seeders/PropSeeder.php @@ -47,7 +47,7 @@ class PropSeeder extends Seeder 'label' => __('Internal storage'), 'name'=>'hdd', 'type'=>'select', - 'options' => '[{"title":"16 Gig","value":"16"},{"title":"32 Gig","value":"32"},{"title":"64 gig","value":"64"},{"title":"128 Gig","value":"128"},{"title":"256 G","value":"256"}]', + 'options' => '[{"title":"16 Gig","value":"16"},{"title":"32 Gig","value":"32"},{"title":"64 gig","value":"64"},{"title":"128 Gig","value":"128"},{"title":"256 Gig","value":"256"}]', 'searchable'=> 1, 'priceable' => 1, 'icon' => 'ri-hard-drive-3-line', diff --git a/resources/js/client-custom/assetsNode.js b/resources/js/client-custom/assetsNode.js index 75fd11a..888a95d 100644 --- a/resources/js/client-custom/assetsNode.js +++ b/resources/js/client-custom/assetsNode.js @@ -1,4 +1,3 @@ -import 'bootstrap'; import { createApp } from 'vue'; import ToastPlugin from 'vue-toast-notification'; import {useToast} from 'vue-toast-notification'; @@ -11,9 +10,10 @@ const $toast = useToast({ duration: 10000, }); - import MetaFilter from '../client-vue/MetaFilter.vue'; app.component('meta-filter', MetaFilter); +import QunatotiesAddToCard from "../client-vue/QuantitiesAddToCard.vue"; +app.component('quantities-add-to-card', QunatotiesAddToCard); app.use(ToastPlugin); app.use(store); diff --git a/resources/js/client-custom/windowLoader.js b/resources/js/client-custom/windowLoader.js index 57d3b31..e27b910 100644 --- a/resources/js/client-custom/windowLoader.js +++ b/resources/js/client-custom/windowLoader.js @@ -1,3 +1,5 @@ +import bootstrap from 'bootstrap/dist/js/bootstrap.bundle.min.js'; + window.addEventListener('load', function () { const API_COOKIE_NAME = 'last_api_call'; const COOKIE_EXPIRY_MINUTES = 59; @@ -46,4 +48,17 @@ window.addEventListener('load', function () { } else { console.log('Data was sent recently. Skipping this time.'); } + + + // bootstrap fix start + const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]') + const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl)) + + // add table class autho + document.querySelectorAll('.content table')?.forEach(function (el) { + el.classList.add('table') + }); + + // bootstrap fix end + }); diff --git a/resources/js/client-vue/QuantitiesAddToCard.vue b/resources/js/client-vue/QuantitiesAddToCard.vue new file mode 100644 index 0000000..9207cd7 --- /dev/null +++ b/resources/js/client-vue/QuantitiesAddToCard.vue @@ -0,0 +1,187 @@ + + + + + diff --git a/resources/js/client-vue/Quantity.vue b/resources/js/client-vue/Quantity.vue new file mode 100644 index 0000000..52c242f --- /dev/null +++ b/resources/js/client-vue/Quantity.vue @@ -0,0 +1,44 @@ + + + + + diff --git a/resources/sass/client-custom/_general.scss b/resources/sass/client-custom/_general.scss index e52ae6e..2e44a4c 100644 --- a/resources/sass/client-custom/_general.scss +++ b/resources/sass/client-custom/_general.scss @@ -63,3 +63,11 @@ body{ font-size: 25px; } } + +[id^="hidden-img"]{ + display: none; +} +#hidden-images{ + display: none; +} + diff --git a/resources/sass/client-custom/_zfix.scss b/resources/sass/client-custom/_zfix.scss index 553c29a..28ebe02 100644 --- a/resources/sass/client-custom/_zfix.scss +++ b/resources/sass/client-custom/_zfix.scss @@ -44,7 +44,7 @@ a, a:visited { &:hover { border-color: var(--xshop-secondary); - color: var(--xshop-diff) !important; + color: var(--xshop-diff2) !important; background: var(--xshop-secondary);; } } @@ -52,7 +52,7 @@ a, a:visited { .btn-secondary { background: var(--xshop-secondary); border-color: var(--xshop-secondary); - color: var(--xshop-diff) !important; + color: var(--xshop-diff2) !important; &:hover { border-color: var(--xshop-primary); @@ -99,7 +99,7 @@ ul.pagination { &:hover{ background: var(--xshop-secondary); - color: var(--xshop-diff); + color: var(--xshop-diff2); } } } @@ -117,3 +117,23 @@ ul.pagination { background-color: var(--xshop-primary); border-right-color: var(--xshop-secondary); } + +.modal.lightbox{ + backdrop-filter: blur(7px); + .ratio{ + background: #33333355 !important; + border-radius: var(--xshop-border-radius); + overflow: hidden; + } +} + + +.custom-tooltip { + --bs-tooltip-bg: var(--xshop-primary); + --bs-tooltip-color: var(--xshop-diff); +} + + +.accordion-button:not(.collapsed){ + background: transparent; +} diff --git a/resources/views/admin/products/sub-pages/product-step3.blade.php b/resources/views/admin/products/sub-pages/product-step3.blade.php index 85a1694..be4cc54 100644 --- a/resources/views/admin/products/sub-pages/product-step3.blade.php +++ b/resources/views/admin/products/sub-pages/product-step3.blade.php @@ -102,7 +102,7 @@ {{$dis->code}} - {{$dis->expire->ldate('Y-m-d H:i:s')}} + {{$dis->expire?->ldate('Y-m-d H:i:s')??'-'}} diff --git a/resources/views/admin/templates/panel-list-template.blade.php b/resources/views/admin/templates/panel-list-template.blade.php index cfc8ede..fb8ce29 100644 --- a/resources/views/admin/templates/panel-list-template.blade.php +++ b/resources/views/admin/templates/panel-list-template.blade.php @@ -208,7 +208,7 @@ @case('expire') @case('created_at') @case('updated_at') - {{$item->$col->ldate("Y-m-d H:i")}} + {{$item->$col?->ldate("Y-m-d H:i")??'-'}} @break @case('icon') diff --git a/resources/views/segments/post/PostSidebar/PostSidebar.blade.php b/resources/views/segments/post/PostSidebar/PostSidebar.blade.php index 24ee33c..7b57baa 100644 --- a/resources/views/segments/post/PostSidebar/PostSidebar.blade.php +++ b/resources/views/segments/post/PostSidebar/PostSidebar.blade.php @@ -35,7 +35,7 @@
{{__("Tags")}}: @foreach($post->tags as $tag) - + {{$tag->name}} diff --git a/resources/views/segments/post/SimplePost/SimplePost.blade.php b/resources/views/segments/post/SimplePost/SimplePost.blade.php index 128834f..126e32e 100644 --- a/resources/views/segments/post/SimplePost/SimplePost.blade.php +++ b/resources/views/segments/post/SimplePost/SimplePost.blade.php @@ -28,7 +28,7 @@
{{__("Tags")}}: @foreach($post->tags as $tag) - + {{$tag->name}} diff --git a/resources/views/segments/product/ProductAria/ProductAria.blade.php b/resources/views/segments/product/ProductAria/ProductAria.blade.php new file mode 100644 index 0000000..e04208a --- /dev/null +++ b/resources/views/segments/product/ProductAria/ProductAria.blade.php @@ -0,0 +1,223 @@ +
+ +
+ +
+
+ + {{$product->name}} + +
+ @foreach($product->getMedia() as $media) +
+ + {{$product->name}} + +
+ @endforeach +
+
+
+ + + + + + + + + +

+ {{$product->name}} +

+
+
+ {{$product->getPrice()}} +
+ + @if($product->hasDiscount()) +
+ {{$product->oldPrice()}} +
+ @endif +
+
+

+ {{$product->excerpt}} +

+
+
 
+ @if($product->quantities()->count()>0) + hasDiscount()) + :discount='@json($product->activeDiscounts()->first())' + @endif + > + @else + + + {{__("Add to card")}} + + @endif +
 
+ @if($product->sku != null && $product->sku != '') +
+ + + {{__("SKU")}}: + + + {{$product->sku}} + +
+ @endif + @if($product->categories()->count() > 0) +
+ + {{__("Categories")}}: + + @foreach($product->categories()->where('id','<>',$product->category->id)->get() as $cat) + + {{$cat->name}}, + + @endforeach + + {{$product->category->name}} + +
+ @endif + @if($product->tags()->count() > 0) +
+ + {{__("Tags")}}: + + @foreach($product->tags as $tag) + + + {{$tag->name}} + + @endforeach +
+ @endif +
+
+
+
+

+ +

+
+
+ {!! $product->description !!} +
+
+
+ @if($product->table != null || trim($product->table) != '') + +
+

+ +

+
+
+ {!! $product->table !!} +
+
+
+ @endif +
+

+ +

+
+
+ + + + + + @foreach($product->fullMeta() as $meta) + + + + + @endforeach +
+ {{__("Item")}} + + {{__("Value")}} +
+ +   + {{$meta['data']->label}} + + {!! $meta['human_value'] !!} +
+
+
+
+
+

+ {{__("Related products")}} +

+
+ @foreach($product->category->products()->where('status',1)->limit(10)->get() as $p) + + @endforeach +
+
+
+ @foreach($product->getMedia() as $k => $media) + + {{$product->name}} + + @endforeach +
+
diff --git a/resources/views/segments/product/ProductAria/ProductAria.js b/resources/views/segments/product/ProductAria/ProductAria.js new file mode 100644 index 0000000..49d362b --- /dev/null +++ b/resources/views/segments/product/ProductAria/ProductAria.js @@ -0,0 +1,62 @@ +import Lightbox from 'bs5-lightbox' ; +import {tns} from "tiny-slider/src/tiny-slider"; + +var ariaImgSlider, ariaRelativeSlider; +document.addEventListener('DOMContentLoaded',function () { + + for (const el of document.querySelectorAll('.light-box')) { + el.addEventListener('click', Lightbox.initialize); + } + ariaImgSlider = tns({ + container: '#aria-img-slider', + items: 3, + autoplay: true, + autoplayButton: false, + // nextButton: false, + controls: false, + autoplayHoverPause: true, + mouseDrag: true, + gutter: 5, + slideBy: 1, + autoplayTimeout: 5000, + // speed:10000, + }); + ariaRelativeSlider = tns({ + container: '#rel-products', + items: 3, + autoplay: true, + autoplayButton: false, + // nextButton: false, + controls: false, + autoplayHoverPause: true, + mouseDrag: true, + gutter: 5, + slideBy: 1, + autoplayTimeout: 5000, + responsive:{ + 560:{ + items: 1, + }, + 768:{ + items: 2, + }, + 1000:{ + items: 4, + }, + 1400:{ + items: 5, + }, + + } + // speed:10000, + }); + + document.querySelectorAll('#aria-img-slider a')?.forEach(function (el) { + el.addEventListener('click',function (e) { + e.preventDefault(); + document.querySelector('#aria-main-img').setAttribute('href',el.getAttribute('href')); + document.querySelector('#aria-main-img img').setAttribute('src',el.querySelector('img').getAttribute('src')); + }) + }); + +}); diff --git a/resources/views/segments/product/ProductAria/ProductAria.json b/resources/views/segments/product/ProductAria/ProductAria.json new file mode 100644 index 0000000..92cc81a --- /dev/null +++ b/resources/views/segments/product/ProductAria/ProductAria.json @@ -0,0 +1,10 @@ +{ + "name": "ProductAria", + "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": [] +} \ No newline at end of file diff --git a/resources/views/segments/product/ProductAria/ProductAria.php b/resources/views/segments/product/ProductAria/ProductAria.php new file mode 100644 index 0000000..7c78b75 --- /dev/null +++ b/resources/views/segments/product/ProductAria/ProductAria.php @@ -0,0 +1,21 @@ +area->name.'_'.$data->part.'_color')}}; - --gx1: {{getSetting($data->area->name.'_'.$data->part.'_gradx1')}}; - --gx2: {{getSetting($data->area->name.'_'.$data->part.'_gradx2')}}; - --gy1: {{getSetting($data->area->name.'_'.$data->part.'_grady1')}}; - --gy2: {{getSetting($data->area->name.'_'.$data->part.'_grady2')}}; - " -> +
diff --git a/resources/views/segments/products_page/ProductGrid/ProductGrid.blade.php b/resources/views/segments/products_page/ProductGrid/ProductGrid.blade.php index 0199d21..c93ca0f 100644 --- a/resources/views/segments/products_page/ProductGrid/ProductGrid.blade.php +++ b/resources/views/segments/products_page/ProductGrid/ProductGrid.blade.php @@ -7,11 +7,15 @@ @foreach($products as $product)
- + - + diff --git a/resources/views/segments/products_page/ProductGridSidebar/ProductGridSidebar.blade.php b/resources/views/segments/products_page/ProductGridSidebar/ProductGridSidebar.blade.php index 99ac313..9fc4372 100644 --- a/resources/views/segments/products_page/ProductGridSidebar/ProductGridSidebar.blade.php +++ b/resources/views/segments/products_page/ProductGridSidebar/ProductGridSidebar.blade.php @@ -14,11 +14,15 @@ @foreach($products as $product)