diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index b59b5f5..0faf0e8 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -7,6 +7,7 @@ use App\Models\Category; use App\Models\Area; use App\Models\Part; use App\Models\Menu; +use App\Models\Product; use Illuminate\Support\Facades\Route; @@ -969,7 +970,7 @@ function isGuestMaxAttemptTry($action, $max = 5, $minutes = 60) { if (\App\Models\GuestLog::where('ip', request()->ip()) ->where('action', $action) - ->where('created_at', '<' ,time() - ($minutes * 60) )->count() >= $max) { + ->where('created_at', '<', time() - ($minutes * 60))->count() >= $max) { return true; } else { return false; @@ -980,15 +981,18 @@ function isGuestMaxAttemptTry($action, $max = 5, $minutes = 60) * home url to best experience for multi lang shops * @return string */ -function homeUrl(){ +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 tagUrl($slug) +{ + return route('client.tag', $slug); } function usableProp($props) @@ -1011,3 +1015,50 @@ function usableProp($props) return $result; } + + +/** + * shopping card items + * @return array|\Illuminate\Http\Resources\Json\AnonymousResourceCollection + */ +function cardItems() +{ + if (cardCount() == 0) { + return []; + } + $products = Product::whereIn('id', json_decode(\Cookie::get('card'), true)) + ->where('status', 1) + ->get(); + + return \App\Http\Resources\ProductCardCollection::collection($products); +} + +/** + * shopping card items count + * @return int + */ +function cardCount() +{ + if (!\Cookie::has('card')) { + return 0; + } + return count(json_decode(\Cookie::get('card'), true)); +} + +/** + * transports json + * @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection + */ +function transports() +{ + return \App\Http\Resources\TransportCollection::collection(\App\Models\Transport::all()); +} + +function defTrannsport() +{ + if (\App\Models\Transport::where('is_default',1)->count() == 0){ + return null; + } + + return \App\Models\Transport::where('is_default',1)->first()->id; +} diff --git a/app/Http/Controllers/CardController.php b/app/Http/Controllers/CardController.php new file mode 100644 index 0000000..5b6f298 --- /dev/null +++ b/app/Http/Controllers/CardController.php @@ -0,0 +1,168 @@ +input('quantity', null); + if (\Cookie::has('card')) { + $cards = json_decode(\Cookie::get('card'), true); + $qs = json_decode(\Cookie::get('q'), true); + if (in_array($product->id, $cards)) { + $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; + $msg = "Product added to card"; + } + $count = count($cards); + \Cookie::queue('card', json_encode($cards), 2000); + \Cookie::queue('q', json_encode($qs), 2000); + } else { + $count = 1; + $msg = "Product added to card"; + \Cookie::queue('card', "[$product->id]", 2000); + \Cookie::queue('q', "[$quantity]", 2000); + $qs = [$quantity]; + $cards = [$product->id]; + } + + if ($count > 0 && auth('customer')->check()) { + $customer = auth('customer')->user(); + $customer->card = json_encode(['cards' => $cards, 'quantities' => $qs]); + $customer->save(); + } + + if (\request()->ajax()) { + return success(['count' => $count], $msg); + } else { + return redirect()->back()->with(['message' => $msg]); + } + } + + public function index() + { + $area = 'card'; + $title = __("Shopping card"); + $subtitle = ''; + return view('client.default-list', compact('area', 'title', 'subtitle')); + } + + public function check(Request $request) + { + + $request->validate([ + 'product_id' => ['required', 'array'], + 'count' => ['required', 'array'], + 'address_id' => ['required', 'exists:addresses,id'], + 'desc' => ['nullable', 'string'] + ]); + $total = 0; +// return $request->all(); + $inv = new Invoice(); + $inv->customer_id = auth('customer')->user()->id; + $inv->count = array_sum($request->count); + $inv->address_id = $request->address_id; + $inv->desc = $request->desc; + if ($request->has('transport_id')) { + $request->transport_id = $request->input('transport_id'); + $t = Transport::find($request->input('transport_id')); + $inv->transport_price = $t->price; + $total += $t->price; + } + if ($request->has('discount_id')) { + $request->discount_id = $request->input('discount_id'); + } + + $inv->save(); + + foreach ($request->product_id as $i => $product) { + $order = new Order(); + $order->product_id = $product; + $order->invoice_id = $inv->id; + $order->count = $request->count[$i]; + if ($request->quantity_id[$i] != '') { + $order->quantity_id = $request->quantity_id[$i]; + $q = Quantity::find($request->quantity_id[$i]); + $order->price_total = $q->price * $request->count[$i]; + $order->data = $q->data; + + } else { + $p = Product::find($request->product_id[$i]); + $order->price_total = $p->price * $request->count[$i]; + } + $total += $order->price_total; + $order->save(); + } + + $inv->total_price = $total; + $inv->save(); + return [$inv,$inv->orders]; + } + + + public static function clear() + { + \Cookie::expire('card'); + \Cookie::expire('q'); + return true; + } + + public function clearing() + { + self::clear(); + return __("Card cleared"); + } + + public function discount($code) + { + $discount = Discount::where('code', trim($code))->where(function ($query) { + $query->where('expire', '>=', date('Y-m-d')) + ->orWhereNull('expire'); + })->first(); + if ($discount == null) { + return [ + 'OK' => false, + 'err' => __("Discount code isn't valid."), + ]; + } else { + if ($discount->type == 'PERCENT') { + $human = $discount->title . '( ' . $discount->amount . '%' . ' )'; + } else { + $human = '- ' . $discount->title . '( ' . $discount->amount . config('app.currency.symbol') . ' )'; + } + return [ + 'OK' => true, + 'msg' => __("Discount code is valid."), + 'data' => $discount, + 'human' => $human, + ]; + } + } +} diff --git a/app/Http/Controllers/ClientController.php b/app/Http/Controllers/ClientController.php index cdb23ae..a1e2397 100644 --- a/app/Http/Controllers/ClientController.php +++ b/app/Http/Controllers/ClientController.php @@ -89,6 +89,8 @@ class ClientController extends Controller return view('client.default-list', compact('area', 'products', 'title', 'subtitle')); } + + public function galleries() { $area = 'galleries-list'; @@ -310,59 +312,7 @@ class ClientController extends Controller } - public function productCardToggle(Product $product) - { - $quantity = \request()->input('quantity', null); - if (\Cookie::has('card')) { - $cards = json_decode(\Cookie::get('card'), true); - $qs = json_decode(\Cookie::get('q'), true); - if (in_array($product->id, $cards)) { - $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; - $msg = "Product added to card"; - } - $count = count($cards); - \Cookie::queue('card', json_encode($cards), 2000); - \Cookie::queue('q', json_encode($qs), 2000); - } else { - $count = 1; - $msg = "Product added to card"; - \Cookie::queue('card', "[$product->id]", 2000); - \Cookie::queue('q', "[$quantity]", 2000); - $qs = [$quantity]; - $cards = [$product->id]; - } - - if ($count > 0 && auth('customer')->check()) { - $customer = auth('customer')->user(); - $customer->card = json_encode(['cards' => $cards, 'quantities' => $qs]); - $customer->save(); - } - - if (\request()->ajax()) { - return success(['count' => $count], $msg); - } else { - return redirect()->back()->with(['message' => $msg]); - } - } public function productCompareToggle(Product $product) { @@ -546,4 +496,6 @@ class ClientController extends Controller } + + } diff --git a/app/Http/Resources/ProductCardCollection.php b/app/Http/Resources/ProductCardCollection.php new file mode 100644 index 0000000..7901c31 --- /dev/null +++ b/app/Http/Resources/ProductCardCollection.php @@ -0,0 +1,30 @@ + + */ + public function toArray(Request $request): array + { + return [ + + 'id'=> $this->id, + 'slug' => $this->slug, + 'name' => $this->name, + 'price' => $this->price, + 'image' => $this->imgUrl(), + 'meta' => $this->fullMeta(), + 'max' => $this->stock_quantity, + 'qz' => QunatityCollection::collection($this->quantities), + ]; + } +} diff --git a/app/Http/Resources/QunatityCollection.php b/app/Http/Resources/QunatityCollection.php new file mode 100644 index 0000000..e4f8cb3 --- /dev/null +++ b/app/Http/Resources/QunatityCollection.php @@ -0,0 +1,28 @@ + + */ + public function toArray(Request $request): array + { + return [ + 'id' => $this->id, + 'product_name' => $this->product->name, + 'count' => $this->count, + 'data'=> json_decode($this->data), + 'meta' => $this->meta, + 'price'=> $this->price, + 'image' => $this->image, + ]; + } +} diff --git a/app/Http/Resources/TransportCollection.php b/app/Http/Resources/TransportCollection.php new file mode 100644 index 0000000..82a97c3 --- /dev/null +++ b/app/Http/Resources/TransportCollection.php @@ -0,0 +1,27 @@ + + */ + public function toArray(Request $request): array + { + return [ + 'id' => $this->id, + 'title' => $this->title, + 'description' => $this->description, + 'price' => $this->price, + 'is_default' => $this->is_default, + 'icon' => $this->icon, + ]; + } +} diff --git a/app/Models/Quantity.php b/app/Models/Quantity.php index 92e262a..5f786f9 100644 --- a/app/Models/Quantity.php +++ b/app/Models/Quantity.php @@ -9,4 +9,70 @@ use Illuminate\Database\Eloquent\SoftDeletes; class Quantity extends Model { use HasFactory,SoftDeletes; + protected $casts = [ + 'meta', + ]; + + + public function product(){ + return $this->belongsTo(Product::class); + } + + public function getMetaAttribute(){ + + $data = json_decode($this->data,true); + if ($data == null) { + return []; + } + $props = $this->product->category->props()->whereIn('name', array_keys($data))->get(); + $result = []; + foreach ($props as $key => $prop) { + $result[$prop->name] = [ + 'label' => $prop->label, + 'human_value' => '', + 'type' => $prop->type, + 'value' => $data[$prop->name], + ]; + switch ($prop->type) { + case 'color': + $result[$prop->name]['human_value'] = "
 
"; + break; + case 'checkbox': + $result[$prop->name]['human_value'] = $data[$prop->name] ? '' : ''; + break; + case 'select': + case 'singlemulti': + $tmp = $prop->datas; + if (!is_array($data[$prop->name])) { + if (isset($tmp[$data[$prop->name]])){ + $result[$prop->name]['human_value'] = $tmp[$data[$prop->name]]; + }else{ + $result[$prop->name]['human_value'] = '-'; + } + } else { + $result[$prop->name]['human_value'] = ''; + $tmp = $prop->datas; + foreach ($data[$prop->name] as $k => $v) { + $result[$prop->name]['human_value'] = $tmp[$v] . ', '; + } + $result[$prop->name]['human_value'] = trim($result[$prop->name], ' ,'); + } + break; + default: + if (is_array($data[$prop->name])) { + $result[$prop->name]['human_value'] = ''.implode(' ', $data[$prop->name]).''; + } else { + if ($data[$prop->name] == '' || $data[$prop->name] == null) { + $result[$prop->name]['human_value'] = '-'; + }else{ + $result[$prop->name]['human_value'] = $data[$prop->name]; + } + } + } + + $result[$prop->name]['human_value'] .= ' ' . $prop->unit; + } + + return $result; + } } diff --git a/database/seeders/AreaSeeder.php b/database/seeders/AreaSeeder.php index 41e1cb4..4c2fa01 100644 --- a/database/seeders/AreaSeeder.php +++ b/database/seeders/AreaSeeder.php @@ -51,7 +51,7 @@ class AreaSeeder extends Seeder "parallax", "other", "post", "comments", "ads", "attachments"] ), 'max' => 6, - 'preview' => 'client.post', + 'preview' => null, 'icon' => 'ri-file-text-line', ], [ @@ -71,7 +71,7 @@ class AreaSeeder extends Seeder "parallax", "other", "clip", "comments", "ads", "attachments"] ), 'max' => 6, - 'preview' => 'client.clip', + 'preview' => null, 'icon' => 'ri-video-line', ], [ @@ -91,7 +91,7 @@ class AreaSeeder extends Seeder "parallax", "other", "gallery", "comments", "ads", "attachments"] ), 'max' => 6, - 'preview' => 'client.gallery', + 'preview' => null, 'icon' => 'ri-image-line', ], [ @@ -111,7 +111,7 @@ class AreaSeeder extends Seeder "parallax", "other", "product", "comments", "ads", "attachments"] ), 'max' => 6, - 'preview' => 'client.product', + 'preview' => null, 'icon' => 'ri-vip-diamond-line', ], [ @@ -131,7 +131,7 @@ class AreaSeeder extends Seeder "parallax", "other", "attachment", "comments", "ads"] ), 'max' => 6, - 'preview' => 'client.attachment', + 'preview' => null, 'icon' => 'ri-attachment-line', ], [ @@ -151,7 +151,7 @@ class AreaSeeder extends Seeder "parallax", "other", "category", "ads", "products_page", "attachments"] ), 'max' => 6, - 'preview' => 'client.attachment', + 'preview' => null, 'icon' => 'ri-book-3-line', ], // [ @@ -171,7 +171,7 @@ class AreaSeeder extends Seeder "parallax", "other", "group", "ads", 'posts_page', "attachments"] ), 'max' => 6, - 'preview' => 'client.group', + 'preview' => null, 'icon' => 'ri-book-shelf-line', ], // [ diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 23cae9c..3cbe2d1 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -39,6 +39,7 @@ class DatabaseSeeder extends Seeder PartSeeder::class, InvoiceSeeder::class, VisitorSeeder::class, + TransportSeeder::class, MenuSeeder::class, ] ); diff --git a/database/seeders/TransportSeeder.php b/database/seeders/TransportSeeder.php index 21722d3..53c3732 100644 --- a/database/seeders/TransportSeeder.php +++ b/database/seeders/TransportSeeder.php @@ -2,6 +2,7 @@ namespace Database\Seeders; +use App\Models\Transport; use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; @@ -13,5 +14,20 @@ class TransportSeeder extends Seeder public function run(): void { // + $t = new Transport(); + $t->title = __("Motor bike delivery"); + $t->description = "Transport just for Tehran orders (pay by customer)"; + $t->icon = 'ri-motorbike-line'; + $t->is_default = false; + $t->price = 0; + $t->save(); + + $t = new Transport(); + $t->title = __("Post office delivery"); + $t->description = "Transport with post around country"; + $t->icon = 'ri-signpost-line'; + $t->is_default = true; + $t->price = 30000; + $t->save(); } } diff --git a/resources/js/client-custom/assetsNode.js b/resources/js/client-custom/assetsNode.js index 273f24d..727f883 100644 --- a/resources/js/client-custom/assetsNode.js +++ b/resources/js/client-custom/assetsNode.js @@ -22,6 +22,10 @@ app.component('mp4player', videoPlayer); import mp3player from "../client-vue/mp3player.vue"; app.component('mp3player', mp3player); +import NsCard from "../client-vue/NsCard.vue"; +app.component('ns-card', NsCard); + + app.use(ToastPlugin); app.use(store); app.mount('#app'); diff --git a/resources/js/client-custom/customerActions.js b/resources/js/client-custom/customerActions.js index 7a3fb60..fe1e44e 100644 --- a/resources/js/client-custom/customerActions.js +++ b/resources/js/client-custom/customerActions.js @@ -1,4 +1,5 @@ window.addEventListener('load', function () { + const favUrl = document.querySelector('#api-fav-toggle').value; const compUrl = document.querySelector('#api-compare-toggle').value; document.querySelectorAll('.fav-btn')?.forEach(function (el) { diff --git a/resources/js/client-custom/safeForm.js b/resources/js/client-custom/safeForm.js index 194a691..6a6514d 100644 --- a/resources/js/client-custom/safeForm.js +++ b/resources/js/client-custom/safeForm.js @@ -5,4 +5,5 @@ window.addEventListener('load',function () { el.setAttribute('action',url); }) },1220); + }) diff --git a/resources/js/client-vue/NsCard.vue b/resources/js/client-vue/NsCard.vue new file mode 100644 index 0000000..bbbc5fe --- /dev/null +++ b/resources/js/client-vue/NsCard.vue @@ -0,0 +1,555 @@ + + + + + diff --git a/resources/js/client-vue/Qindex.vue b/resources/js/client-vue/Qindex.vue new file mode 100644 index 0000000..c1d1c0a --- /dev/null +++ b/resources/js/client-vue/Qindex.vue @@ -0,0 +1,121 @@ + + + + + diff --git a/resources/js/client-vue/Qpreview.vue b/resources/js/client-vue/Qpreview.vue new file mode 100644 index 0000000..eff9d54 --- /dev/null +++ b/resources/js/client-vue/Qpreview.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/resources/js/client-vue/Quantity.vue b/resources/js/client-vue/Quantity.vue index 52c242f..8cf5bfd 100644 --- a/resources/js/client-vue/Quantity.vue +++ b/resources/js/client-vue/Quantity.vue @@ -1,20 +1,35 @@ diff --git a/resources/js/components/MetaInput.vue b/resources/js/components/MetaInput.vue index 017a9a7..f052c5a 100644 --- a/resources/js/components/MetaInput.vue +++ b/resources/js/components/MetaInput.vue @@ -78,7 +78,8 @@