diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index 6b0ef9c..5e232a6 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers; use App\Http\Controllers\Controller; +use App\Http\Requests\Products\IndexFilterRequest; use App\Http\Requests\Products\StoreProductRequest; use App\Http\Requests\Products\UpdateProductRequest; use App\Jobs\ExportProduct; @@ -12,7 +13,6 @@ use App\Models\Product; use App\Traits\Controllers\HasDocuments; use Illuminate\Database\Eloquent\Builder; use Illuminate\Http\Request; -use Illuminate\Support\Arr; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; @@ -23,27 +23,29 @@ class ProductController extends Controller /** * Display a listing of the resource. * - * @param \Illuminate\Http\Request $request + * @param \App\Http\Requests\Products\IndexFilterRequest $request * @return \Illuminate\Contracts\View\View */ - public function index(Request $request) + public function index(IndexFilterRequest $request) { + // DB::enableQueryLog(); /** @var \Illuminate\Database\Eloquent\Builder $brands */ - $brands = Brand::query(); + $brandsQuery = Brand::query(); - /** @var \Illuminate\Database\Eloquent\Builder $products */ - $products = Product::query(); + /** @var \Illuminate\Database\Eloquent\Builder $productsQuery */ + $productsQuery = Product::query(); - $this->requestFilters($products, $request); + $this->requestFilters($request, $productsQuery); - $this->sortQuery($products); + $this->sortQuery($productsQuery); - $products = $this->paginate($products); + $products = $this->paginate($productsQuery); + // dd(DB::getQueryLog(), $products->items()); /** @var array $printMultiProduct Array of id */ $printMultiProduct = session('printMultiProduct') ?? []; - $brands = $brands->get(); + $brands = $brandsQuery->get(); $keywords = Keyword::query()->where('keyword_cat', 'LIKE', 'product_%')->get(); @@ -51,8 +53,7 @@ class ProductController extends Controller 'products' => $products, 'brands' => $brands, 'keywords' => $keywords, - 'printMultiProduct' => $printMultiProduct, - 'queryParameters' => $request->all(), + 'printMultiProduct' => $printMultiProduct ]); } @@ -385,47 +386,60 @@ class ProductController extends Controller } /** - * Show the form for creating a new resource. + * Applies filters from products.index * - * @param \Illuminate\Database\Eloquent\Builder $products - * @param \Illuminate\Http\Request $request + * @param \App\Http\Requests\Products\IndexFilterRequest $request + * @param \Illuminate\Database\Eloquent\Builder $productsQuery * @return \Illuminate\Contracts\View\View * @phpcs:disable Generic.Metrics.NestingLevel.TooHigh */ - private function requestFilters(Builder $products, Request $request): \Illuminate\Database\Eloquent\Builder - { + private function requestFilters( + IndexFilterRequest $request, + Builder $productsQuery + ): \Illuminate\Database\Eloquent\Builder { //phpcs:enable - $queryFetch = ['name', 'claims', 'origins', 'keywords', 'date_before', 'date_after']; - foreach (Arr::only($request->all(), $queryFetch) as $key => $queryParameter) { - if ($request->sort_col === null && $request->sort_way === null && $request->rst === null) { - $products->when( - isset($queryParameter) && $queryParameter != 0, - function ($q) use ($queryParameter, $key) { - if ($key === "name") { - $q->where($key, 'LIKE', '%' . $queryParameter . '%'); - } elseif ($key === "claims" || $key === "origins") { - foreach ($queryParameter as $item) { - $q->where($key, 'LIKE', '%{"id":"' . $item['value'] . '"}%'); - } - } elseif ($key === "keywords") { - foreach ($queryParameter as $keyword) { - $q->whereHas('productKeywords', function ($q) use ($keyword, $key) { - $q->where($key . '.id', intval($keyword['value'])); - }); - } - } elseif ($key === "date_before" || $key === "date_after") { - if ($key === "date_before") { - $q->whereDate('created_at', '>=', $queryParameter); - } else { - $q->whereDate('created_at', '<=', $queryParameter); - } - } else { - $q->where($key, $queryParameter); - } //end if - } - ); - } //end if + foreach ($request->validated() as $parameterName => $queryParameter) { + $productsQuery->when( + !empty($queryParameter), + function (Builder $q) use ($queryParameter, $parameterName) { + switch ($parameterName) { + // * String type parameters (Approx search) + case 'name': + case 'shop': + case 'fair': + case 'catalogue': + case 'specified_claim': + $q->where($parameterName, 'LIKE', "%{$queryParameter}%"); + break; + // * Number type parameters (Approx search) + case 'gencode': + $q->where($parameterName, \intval($queryParameter)); + break; + // * Date type parameters + case 'date_before': + $q->whereDate('created_at', '>=', $queryParameter); + break; + case 'date_after': + $q->whereDate('created_at', '<=', $queryParameter); + break; + // * Enums Array + case 'claims': + case 'origins': + $q->whereJsonContains($parameterName, \collect($queryParameter) + ->map(fn ($enumValue) => \intval($enumValue))); + break; + // * RelationShips parameters + case 'keywords': + $q->whereHas('productKeywords', function (Builder $subQ) use ($queryParameter) { + $subQ->whereIn('keywords.id', $queryParameter); + }); + break; + default: + $q->where($parameterName, $queryParameter); + } //end switch + } + ); } //end foreach - return $products; + return $productsQuery; } } diff --git a/app/Http/Requests/Products/IndexFilterRequest.php b/app/Http/Requests/Products/IndexFilterRequest.php new file mode 100644 index 0000000..e6009cd --- /dev/null +++ b/app/Http/Requests/Products/IndexFilterRequest.php @@ -0,0 +1,60 @@ + + */ + public function rules(): array + { + return [ + 'name' => 'nullable|string', + 'brand_id' => 'nullable|exists:brands,id', + 'gencod' => 'nullable|string', + + 'source' => ['nullable', new Enum(SourceEnum::class)], + 'shop' => 'nullable|string', + 'fair' => 'nullable|string', + 'catalogue' => 'nullable|string', + 'claims' => 'nullable|array', + 'claims.*' => ['required', new Enum(ClaimEnum::class)], + 'specified_claim' => 'nullable|string', + 'origins' => 'nullable|array', + 'origins.*' => ['required', new Enum(OriginEnum::class)], + 'certification' => ['nullable', new Enum(CertificationEnum::class)], + 'distribution_network' => ['nullable', new Enum(DistributionNetworkEnum::class)], + 'ray' => ['nullable', new Enum(RayEnum::class)], + 'product_range' => ['nullable', new Enum(RangeEnum::class)], + 'geo_area' => ['nullable', new Enum(GeoAreaEnum::class)], + 'keywords' => 'nullable|array', + 'keywords.*' => 'required|exists:keywords,id', + 'date_before' => 'nullable|date:Y-m-d', + 'date_after' => 'nullable|date:Y-m-d', + ]; + } +} diff --git a/resources/ts/components/SelectMultipleEnumComponent.vue b/resources/ts/components/SelectMultipleEnumComponent.vue index 63353e7..78d3d00 100644 --- a/resources/ts/components/SelectMultipleEnumComponent.vue +++ b/resources/ts/components/SelectMultipleEnumComponent.vue @@ -41,7 +41,7 @@ {{ intHelper }} @@ -149,13 +149,13 @@ export default defineComponent({ parseTags(intSelectedItem: number[]): CustomTag[] { const out: CustomTag[] = []; intSelectedItem.forEach((intItem: number) => { - const selectedItem = this.intAllItems.find(item => String(item.value) === String(intItem)); + const selectedItem = this.intAllItems.find(item => String(item.id ?? item.value) === String(intItem)); if (!selectedItem) { console.debug(intItem); throw new Error(`Could not find enum ${intItem}`); } out.push({ - id: String(selectedItem.value), + id: String(selectedItem.id ?? selectedItem.value), value: String(selectedItem.value), text: String(selectedItem.text) } as LaravelModel as CustomTag); diff --git a/resources/views/pages/products/product-filters.blade.php b/resources/views/pages/products/product-filters.blade.php index 430f80d..366b139 100644 --- a/resources/views/pages/products/product-filters.blade.php +++ b/resources/views/pages/products/product-filters.blade.php @@ -1,10 +1,10 @@ @php $iArgs = []; - if(request()->sort_col) { + if (request()->sort_col) { $iArgs['sort_col'] = request()->sort_col; } - if(request()->search) { + if (request()->search) { $iArgs['search'] = request()->sort_way; } @endphp @@ -12,173 +12,181 @@
-
+ {{-- ALWAYS RESET SEARCH TO PAGE 1 --}} +
- +
-
+
- +
-
+ {{-- FIXME: Pourquoi dans le modèle il est Set une source, mais dans la recherche 3 champs complémentaire + peuvent etre utilisés, dans le modele également => il n'est pas nécessaire de cacher les + champs complémentaires dans le formulaire ? --}} +
-
- +
+
- +
- +
-
+
- @php - $itemsList = collect(\App\Enums\Products\ClaimEnum::toArray())->values(); - $values = collect($queryParameters['claims'] ?? [])->values(); - $selectedItemList = collect($itemsList)->filter(fn($claim) => - $values->filter(fn($value) => intval($value['value']) === $claim->value)->count())->values(); - @endphp @include('partials.inputs.select-multiple-enum', [ 'id' => 'productsClaim', 'name' => 'claims', - 'itemsSelected' => $selectedItemList, - 'itemsList' => $itemsList, - 'itemLimit' => [0, count($itemsList)], + 'itemsSelected' => collect(request()->get('claims', []))->filter(fn($value) => is_numeric($value)), + 'itemsList' => collect(\App\Enums\Products\ClaimEnum::toArray())->values(), + 'itemLimit' => [0, count(\App\Enums\Products\ClaimEnum::toArray())], 'placeholder' => __('Recherchez une Allégation'), 'simpleComponent' => true, ])
-
- +
+
-
+
- @php - $itemsList = collect(\App\Enums\Products\OriginEnum::toArray())->values(); - $values = collect($queryParameters['origins'] ?? [])->values(); - $selectedItemList = collect($itemsList)->filter(fn($origin) => - $values->filter(fn($value) => intval($value['value']) === $origin->value)->count())->values(); - @endphp @include('partials.inputs.select-multiple-enum', [ 'id' => 'productsOrigin', 'name' => 'origins', - 'itemsSelected' => $selectedItemList, - 'itemsList' => $itemsList, - 'itemLimit' => [0, count($itemsList)], + 'itemsSelected' => collect(request()->get('origins', []))->filter( + fn($value) => is_numeric($value)), + 'itemsList' => collect(\App\Enums\Products\OriginEnum::toArray())->values(), + 'itemLimit' => [0, count(\App\Enums\Products\OriginEnum::toArray())], 'placeholder' => __('Recherchez une Origine'), 'simpleComponent' => true, ])
-
+
-
+
@php $itemsList = collect($keywords)->map(function ($keyword) { - return ["name" => $keyword->keyword_cat->value, "label" => $keyword->label, "value" => $keyword->id]; - })->values(); - $values = collect($queryParameters['keywords'] ?? [])->values(); - $selectedItemList = collect($itemsList)->filter(fn($keyword) => - $values->filter(fn($value) => intval($value['value']) === $keyword['value'])->count())->values(); + return ['name' => $keyword->keyword_cat->value, 'label' => $keyword->label, 'value' => $keyword->id]; + }); @endphp @include('partials.inputs.select-multiple-enum', [ - 'id' => 'productsKeywordsn', + 'id' => 'productsKeywords', 'name' => 'keywords', - 'itemsSelected' => $selectedItemList, - 'itemsList' => $itemsList, - 'itemLimit' => [0, count($itemsList)], - 'placeholder' => __('Recherchez un mot clé'), + 'itemsSelected' => collect(request()->get('keywords', []))->filter( + fn($value) => is_numeric($value)), + 'itemsList' => $itemsList->values(), + 'itemLimit' => [0, $itemsList->count()], + 'placeholder' => __('Recherchez une tendance'), 'simpleComponent' => true, ])
-
+
- - -
-
- + +
+
+ +
-
- -