From 85480162008472dd5abe255153a1963d776024fa Mon Sep 17 00:00:00 2001 From: Bayu Lukman Yusuf Date: Wed, 7 Jan 2026 11:58:22 +0700 Subject: [PATCH] filter query --- app/Http/Controllers/ProductController.php | 44 +- app/Models/Items.php | 154 +++--- .../Catalog/ProductRepository.php | 85 +++- lang/en/header.php | 4 + lang/id/header.php | 4 + .../views/components/layout/header.blade.php | 477 +++++++++++++----- .../layout/navbar-category.blade.php | 2 +- resources/views/home/fashion-v1.blade.php | 188 +------ .../views/shop/catalog-fashion.blade.php | 202 +------- .../views/shop/product-fashion.blade.php | 190 +------ 10 files changed, 559 insertions(+), 791 deletions(-) create mode 100644 lang/en/header.php create mode 100644 lang/id/header.php diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index 3f81d91..5bf24aa 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -8,29 +8,62 @@ use App\Repositories\Catalog\CategoryRepository; use App\Repositories\Catalog\GenderRepository; use App\Repositories\Catalog\ProductRepository; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Cache; class ProductController extends Controller { public function index(Request $request) { - + $limit = 20; $page = $request->page ?? 1; + $search = $request->search; + $filter = $request->filter ?? []; $sortBy = $request->sort_by ?? 'relevance'; + $price_range_start = $request->price_range_start ?? null; + $price_range_end = $request->price_range_end ?? null; + $genderRepository = new GenderRepository; $categoryRepository = new CategoryRepository; $genders = $genderRepository->getList([]); $categories = $categoryRepository->getList([]); + + + $user = auth()->user(); + $userId = $user ? $user->id : 0; + [$location_id, $is_consignment] = Cache::remember('employee_user_'.$userId, 60 * 60 * 24, function () use ($user) { + + if ($user == null) { + return [10, false]; + } + + $employee = @$user->employee; + $location_id = @$employee->location_id; + $location = @$employee->location; + $is_consignment = (bool) @$location->is_consignment; + + return [$location_id, $is_consignment]; + + }); + $productRepository = new ProductRepository; $products = $productRepository->getList([ - 'limit' => 20, - 'sort_by' => $sortBy, + 'limit' => $page * $limit, + 'sort' => $sortBy, + 'category_id' => $filter['category'] ?? null, + 'gender_id' => $filter['gender'] ?? null, + 'search' => $search, + 'location_id' => $location_id, + 'is_consignment' => $is_consignment, + 'price_range_start' => $price_range_start, + 'price_range_end' => $price_range_end, ]); + if (isset($filter['category']) && $filter['category']){ $category = StoreCategory::find($filter['category']); @@ -53,7 +86,9 @@ class ProductController extends Controller } $filters = $filter; - + + $min_max_price = $productRepository->getMinMaxPrice(); + return view('shop.catalog-fashion', [ 'filters' => $filters, @@ -62,6 +97,7 @@ class ProductController extends Controller 'products' => $products, 'page' => $page, + 'min_max_price' => $min_max_price, ]); } diff --git a/app/Models/Items.php b/app/Models/Items.php index c45528c..c768d64 100644 --- a/app/Models/Items.php +++ b/app/Models/Items.php @@ -2,32 +2,31 @@ namespace App\Models; -use Illuminate\Database\Eloquent\Model; +use Awobaz\Compoships\Compoships; use Illuminate\Database\Eloquent\Builder; -use Cviebrock\EloquentSluggable\Sluggable; -use Illuminate\Database\Eloquent\SoftDeletes; -use Carbon\Carbon; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\DB; -use Awobaz\Compoships\Compoships; -use Spatie\Activitylog\LogOptions; - use Illuminate\Support\Facades\Storage; +use Spatie\Activitylog\LogOptions; class Items extends Model { - use HasFactory, SoftDeletes; use Compoships; + use HasFactory, SoftDeletes; public function getActivitylogOptions(): LogOptions { return LogOptions::defaults(); - } + } // protected $with = ['brands', 'categories']; protected $table = 'items'; + protected $primaryKey = 'id'; + protected $guarded = ['id']; protected $fillable = [ @@ -63,15 +62,15 @@ class Items extends Model 'group_type', 'model_type', - 'slug' + 'slug', ]; public function scopeFilter(Builder $query, array $filters) { $query->when($filters['search'] ?? false, function ($query, $search) { return $query - ->where('number', 'iLIKE', '%' . $search . '%') - ->orWhere('name', 'iLIKE', '%' . $search . '%'); + ->where('number', 'iLIKE', '%'.$search.'%') + ->orWhere('name', 'iLIKE', '%'.$search.'%'); }); } @@ -82,39 +81,38 @@ class Items extends Model public function dimension() { - return $this->hasOne(ItemDimension::class,"no","number"); + return $this->hasOne(ItemDimension::class, 'no', 'number'); } public function reference() { - return $this->hasOne(ItemReference::class,'item_id') - ->where(function($query){ - $query->whereNull("item_variant_id")->orWhere("item_variant_id",0); - }); + return $this->hasOne(ItemReference::class, 'item_id') + ->where(function ($query) { + $query->whereNull('item_variant_id')->orWhere('item_variant_id', 0); + }); } public function variants() { - return $this->hasMany(ItemVariant::class,"item_id") - ->leftJoin("stocks","item_variant_id","=","item_variants.id") - ->select("item_variants.id","item_variants.code","item_variants.display_name","item_variants.is_publish", DB::raw("SUM(quantity) as stock"),"description","item_variants.item_id") - ->groupBy("item_variants.id","item_variants.code","description","item_variants.item_id","item_variants.display_name","item_variants.is_publish"); + return $this->hasMany(ItemVariant::class, 'item_id') + ->leftJoin('stocks', 'item_variant_id', '=', 'item_variants.id') + ->select('item_variants.id', 'item_variants.code', 'item_variants.display_name', 'item_variants.is_publish', DB::raw('SUM(quantity) as stock'), 'description', 'item_variants.item_id') + ->groupBy('item_variants.id', 'item_variants.code', 'description', 'item_variants.item_id', 'item_variants.display_name', 'item_variants.is_publish'); } - public function images() { - return $this->hasMany(ItemImage::class,'item_id')->whereNull('item_variant_id'); + return $this->hasMany(ItemImage::class, 'item_id')->whereNull('item_variant_id'); } public function itemVariants() { - return $this->hasMany(ItemVariant::class,"item_id")->with("reference"); + return $this->hasMany(ItemVariant::class, 'item_id')->with('reference'); } public function publishedItemVariants() { - return $this->hasMany(ItemVariant::class,"item_id")->with("reference")->where('is_publish', true); + return $this->hasMany(ItemVariant::class, 'item_id')->with('reference')->where('is_publish', true); } public function brands() @@ -147,10 +145,10 @@ class Items extends Model $user = auth()->user(); [$location_id, $is_consignment] = Cache::remember( - 'employee_user_' . optional($user)->id, + 'employee_user_'.optional($user)->id, 60 * 60 * 24, function () use ($user) { - if (!$user) { + if (! $user) { return [10, false]; } @@ -163,7 +161,6 @@ class Items extends Model ]; } ); - // return $this->hasOne(Discount::class,DB::raw("item_reference.item_id")) // ->leftJoin('discount_items', 'discount_items.discount_id', '=', 'discounts.id') @@ -192,55 +189,56 @@ class Items extends Model // 'discount_items.price', // ]); - return $this->hasOne(DiscountItem::class, 'item_reference_id', 'id') - ->leftJoin('discounts', 'discounts.id', '=', 'discount_items.discount_id') - ->leftJoin('item_reference', 'item_reference.id', '=', 'discount_items.item_reference_id') - ->where('discounts.type', 'discount') - ->where(function ($q) { - $q->whereNull('discounts.valid_at') - ->orWhere('discounts.valid_at', '<=', now()); - }) - ->where(function ($q) { - $q->whereNull('discounts.expired_at') - ->orWhere('discounts.expired_at', '>=', now()); - }) - ->where(function ($q) use ($location_id, $is_consignment) { - if (!$is_consignment) { - $q->whereNull('discounts.location_id'); - } + return $this->hasOne(DiscountItem::class, 'item_reference_id', 'id') + ->leftJoin('discounts', 'discounts.id', '=', 'discount_items.discount_id') + ->leftJoin('item_reference', 'item_reference.id', '=', 'discount_items.item_reference_id') + ->where('discounts.type', 'discount') + ->where(function ($q) { + $q->whereNull('discounts.valid_at') + ->orWhere('discounts.valid_at', '<=', now()); + }) + ->where(function ($q) { + $q->whereNull('discounts.expired_at') + ->orWhere('discounts.expired_at', '>=', now()); + }) + ->where(function ($q) use ($location_id, $is_consignment) { + if (! $is_consignment) { + $q->whereNull('discounts.location_id'); + } - if ($location_id) { - $q->orWhere('discounts.location_id', $location_id); - } - }) - ->orderByDesc('discounts.created_at') - ->select([ - 'item_reference.item_id', - 'discount_items.price', - ]); + if ($location_id) { + $q->orWhere('discounts.location_id', $location_id); + } + }) + ->orderByDesc('discounts.created_at') + ->select([ + 'item_reference.item_id', + 'discount_items.price', + ]); } - public function price() { $user = auth()->user(); $userId = $user ? $user->id : 0; - list($location_id, $is_consignment) = Cache::remember("employee_user_".$userId, 60 * 60 * 24, function() use ($user){ + [$location_id, $is_consignment] = Cache::remember('employee_user_'.$userId, 60 * 60 * 24, function () use ($user) { - if ($user == null) - return [10, false]; + if ($user == null) { + return [10, false]; + } $employee = @$user->employee; $location_id = @$employee->location_id; $location = @$employee->location; - $is_consignment = (boolean) @$location->is_consignment; + $is_consignment = (bool) @$location->is_consignment; + return [$location_id, $is_consignment]; }); - return $this->hasOne(Discount::class, 'id', 'item_reference_id') + return $this->hasOne(Discount::class, 'id', 'item_reference_id') ->leftJoin('discount_items', 'discount_items.discount_id', '=', 'discounts.id') ->where('discounts.type', 'price') ->where(function ($query) { @@ -252,7 +250,7 @@ class Items extends Model ->orWhereNull('expired_at'); }) ->where(function ($query) use ($location_id, $is_consignment) { - if (!$is_consignment) { + if (! $is_consignment) { $query->whereNull('discounts.location_id'); } @@ -269,13 +267,13 @@ class Items extends Model public function stock() { - return $this->hasOne(Stock::class,"item_id") - ->leftJoin("locations","locations.id","=","location_id") - ->whereNotNull("locations.display_name") - ->where("locations.display_name","<>","") - ->where("quantity",">","0") - ->groupBy("item_id") - ->select("item_id",DB::raw("SUM(quantity) as quantity")); + return $this->hasOne(Stock::class, 'item_id') + ->leftJoin('locations', 'locations.id', '=', 'location_id') + ->whereNotNull('locations.display_name') + ->where('locations.display_name', '<>', '') + ->where('quantity', '>', '0') + ->groupBy('item_id') + ->select('item_id', DB::raw('SUM(quantity) as quantity')); } public function attributes() @@ -287,28 +285,23 @@ class Items extends Model { $image = $this->images->first()->filename ?? null; - - - if (str_contains($image,"http")) { + if (str_contains($image, 'http')) { return $image; } return $image ? Storage::disk('wms')->url($image) : null; } - public function getImageUrlsAttribute() { $images = $this->images ?? []; - $imgs = []; - foreach ($images as $img) { $image = $img->filename; - if (str_contains($image,"http")) { + if (str_contains($image, 'http')) { $imgs[] = $image; } else { $imgs[] = $image ? Storage::disk('wms')->url($image) : null; @@ -318,15 +311,14 @@ class Items extends Model return $imgs; } - public function conversion_value() { $convertion = 1; - if (($this->display_unit != $this->unit) and ($this->display_unit)){ - $convertions = DB::select("select to_qty / from_qty as conv - from item_convertions where from_unit = ? and to_unit = ?", - [$this->display_unit, $this->unit] ); - $convertion = max((float) @$convertions[0]->conv,1); + if (($this->display_unit != $this->unit) and ($this->display_unit)) { + $convertions = DB::select('select to_qty / from_qty as conv + from item_convertions where from_unit = ? and to_unit = ?', + [$this->display_unit, $this->unit]); + $convertion = max((float) @$convertions[0]->conv, 1); } return $convertion; @@ -346,13 +338,13 @@ class Items extends Model } } - public function getDisplayDiscountPriceAttribute() { try { $convertion = $this->conversion_value(); $discountPrice = @$this->discount->price ?? 0; + return (float) $discountPrice * $convertion; } catch (\Exception $e) { return 0; diff --git a/app/Repositories/Catalog/ProductRepository.php b/app/Repositories/Catalog/ProductRepository.php index 9c9061c..1eb75c5 100644 --- a/app/Repositories/Catalog/ProductRepository.php +++ b/app/Repositories/Catalog/ProductRepository.php @@ -2,6 +2,7 @@ namespace App\Repositories\Catalog; +use App\Models\DiscountItem; use App\Models\Items; use App\Models\StoreCategoryMap; use Illuminate\Support\Facades\DB; @@ -18,6 +19,67 @@ class ProductRepository $brand_id = @$params["brand_id"]; $gender_id = @$params["gender_id"]; $limit = @$params["limit"]; + + $location_id = @$params["location_id"]; + $is_consignment = @$params["is_consignment"]; + + $price_range_start = @$params["price_range_start"]; + $price_range_end = @$params["price_range_end"]; + + + $sorting_ids = []; + if ($sort == "price_low_to_high" || $sort == "price_high_to_low"){ + $sorting_ids = DiscountItem::whereHas('discount', function($query) use ($location_id, $is_consignment) { + $query->where('type', 'price') + ->where(function ($query) { + $query->where('valid_at', '<=', now()) + ->orWhereNull('valid_at'); + }) + ->where(function ($query) { + $query->where('expired_at', '>', now()) + ->orWhereNull('expired_at'); + }) + ->where(function ($query) use ($location_id, $is_consignment) { + if (! $is_consignment) { + $query->whereNull('discounts.location_id'); + } + + if ($location_id) { + $query->orWhere('discounts.location_id', $location_id); + } + }); + }) + ->orderBy('discount_items.price', $sort == "price_low_to_high" ? 'asc' : 'desc') + ->pluck('item_reference_id')->toArray(); + } + + $where_ids = []; + if ($price_range_start && $price_range_end) { + $where_ids = DiscountItem::whereHas('discount', function($query) use ($location_id, $is_consignment, $price_range_start, $price_range_end) { + $query->where('type', 'price') + ->where(function ($query) { + $query->where('valid_at', '<=', now()) + ->orWhereNull('valid_at'); + }) + ->where(function ($query) { + $query->where('expired_at', '>', now()) + ->orWhereNull('expired_at'); + }) + ->where(function ($query) use ($location_id, $is_consignment) { + if (! $is_consignment) { + $query->whereNull('discounts.location_id'); + } + + if ($location_id) { + $query->orWhere('discounts.location_id', $location_id); + } + }) + ->where('discount_items.price', '>=', $price_range_start) + ->where('discount_items.price', '<=', $price_range_end); + }) + ->pluck('item_reference_id')->toArray(); + } + $builder = Items::select('items.*','percent') ->leftJoin('item_dimension', 'item_dimension.no', 'items.number') ->leftJoin(DB::raw("(select distinct on (item_id) item_id, percent, discounts.created_at, @@ -30,7 +92,7 @@ class ProductRepository ( discounts.valid_at is null or discounts.expired_at >= now()) order by item_id, discounts.created_at desc ) as d"),"d.item_id","=","items.id") - ->when(true, function($query) use ($event, $sort){ + ->when(true, function($query) use ($event, $sort,$sorting_ids){ if ($event){ $query->orderByRaw("case when brand = 'CHAMELO' then 1 else 2 end ASC "); @@ -41,11 +103,12 @@ class ProductRepository $query->orderByRaw("case when brand = 'CHAMELO' then 1 else 2 end ASC "); } */ - if ($sort == "new"){ - \Log::info($sort); - + if (!empty($sorting_ids)) { + $ids = implode(',', $sorting_ids); + $query->orderByRaw("array_position(ARRAY[$ids], items.id)"); + }else if ($sort == "new"){ $query->orderByRaw("case when category1 in ('CLUBS','CLUB','COMPONENT HEAD') and brand = 'PXG' then 1 else 2 end ASC"); - }else{ + } else { $query->orderByRaw("case when d.created_at is not null then 1 else 2 end ASC, random()"); } @@ -92,9 +155,21 @@ class ProductRepository }); } + return $builder->paginate($limit); } + + public function getMinMaxPrice() + { + return [ + 'min' => DiscountItem::min('price'), + 'max' => DiscountItem::max('price'), + ]; + } + + + public function show($slug) { $product = Items::where('slug', $slug)->first(); diff --git a/lang/en/header.php b/lang/en/header.php new file mode 100644 index 0000000..4f684ba --- /dev/null +++ b/lang/en/header.php @@ -0,0 +1,4 @@ + 'Categories', +]; \ No newline at end of file diff --git a/lang/id/header.php b/lang/id/header.php new file mode 100644 index 0000000..a694c66 --- /dev/null +++ b/lang/id/header.php @@ -0,0 +1,4 @@ + 'Kategori', +]; \ No newline at end of file diff --git a/resources/views/components/layout/header.blade.php b/resources/views/components/layout/header.blade.php index a6910a5..3747604 100644 --- a/resources/views/components/layout/header.blade.php +++ b/resources/views/components/layout/header.blade.php @@ -1,145 +1,364 @@ - + diff --git a/resources/views/components/layout/navbar-category.blade.php b/resources/views/components/layout/navbar-category.blade.php index dac690e..1096d0d 100644 --- a/resources/views/components/layout/navbar-category.blade.php +++ b/resources/views/components/layout/navbar-category.blade.php @@ -3,7 +3,7 @@ -
- - -
-
-

Shopping cart

- -
-

Buy $53 more to get Free Shipping

-
-
-
-
-
- - -
- - -
- - Thumbnail - -
-
- Leather sneakers - with golden laces -
-
$74.00
-
-
- - - -
- -
-
-
- - -
- - Thumbnail - -
-
- Classic cotton - men's shirt -
-
$27.00
-
-
- - - -
- -
-
-
- - -
- - Thumbnail - -
-
- Polarized - sunglasses for men -
-
$96.00 112.00
-
-
- - - -
- -
-
-
-
- - -
-
- Subtotal: - $197.00 -
- -
-
- - - -
-
-
- -
-
-
🎉 Free Shipping on orders over $250. Don't miss a discount!
-
💰 Money back guarantee. We return money within 30 days.
-
💪 Friendly 24/7 customer support. We've got you covered!
-
-
- -
- -
-
+