From 4d25b1fc1303d38a9f14f5d992053903b45ee21c Mon Sep 17 00:00:00 2001 From: Andrey Dmitrakovich Date: Fri, 17 Jan 2025 23:06:58 +0300 Subject: [PATCH] 48. adapt catalog for api --- .../Controllers/Api/CatalogController.php | 111 ++++++++++++++++++ .../Controllers/Api/ProductController.php | 49 -------- .../Controllers/Api/TemporaryController.php | 25 ---- src/app/Http/Requests/FilterRequest.php | 17 +-- src/app/Models/Category.php | 8 ++ src/app/Services/CatalogService.php | 26 ++-- src/routes/api.php | 13 +- 7 files changed, 151 insertions(+), 98 deletions(-) create mode 100644 src/app/Http/Controllers/Api/CatalogController.php delete mode 100644 src/app/Http/Controllers/Api/ProductController.php delete mode 100644 src/app/Http/Controllers/Api/TemporaryController.php diff --git a/src/app/Http/Controllers/Api/CatalogController.php b/src/app/Http/Controllers/Api/CatalogController.php new file mode 100644 index 00000000..fe449371 --- /dev/null +++ b/src/app/Http/Controllers/Api/CatalogController.php @@ -0,0 +1,111 @@ +get('promocode')) { + Sale::applyPromocode($promocode); + } + + $sort = $filterRequest->getSorting(); + $currentFilters = $filterRequest->getFilters(); + $currentCity = $filterRequest->getCity(); + $searchQuery = $filterRequest->input('search'); + UrlHelper::setCurrentFilters($currentFilters); + UrlHelper::setCurrentCity($currentCity); + + $products = $catalogService->getProducts($currentFilters, $sort, $searchQuery); + + $sortingList = [ + 'rating' => 'по популярности', + 'newness' => 'новинки', + 'price-up' => 'по возрастанию цены', + 'price-down' => 'по убыванию цены', + ]; + + $category = end($currentFilters[Category::class])->getFilterModel(); + $badges = $catalogService->getFilterBadges($currentFilters, $searchQuery); + + $gtmService->setForCatalog($products, $category, $searchQuery); + + $data = [ + 'products' => $products, + 'category' => $category, + 'currentFilters' => $currentFilters, + 'badges' => $badges, + 'filters' => app(FilterService::class)->getAll(), + 'sort' => $sort, + 'sortingList' => $sortingList, + 'searchQuery' => $searchQuery, + ]; + + if (!$products->isNotEmpty()) { + $sliderService = new SliderService(); + $data['simpleSliders'] = $sliderService->getSimple(); + } + // $seoService + // ->setCurrentFilters($currentFilters) + // ->setCurrentCity($currentCity) + // ->setProducts($products) + // ->generate(); + + return response()->json($data); + } + + /** + * Display the specified resource. + */ + public function show( + Product $product, + // ProductService $productService, + SliderService $sliderService, + // ProductSeoService $seoService, + FeedbackService $feedbackService, + ): array { + $product->load([ + 'tags', + 'category', + 'countryOfOrigin', + 'availableSizes' => fn ($q) => $q->whereHas('stock', fn ($q) => $q->where('type', StockTypeEnum::SHOP)) + ->with(['stock' => fn ($q) => $q->orderBy('site_sorting', 'asc')->with('city')]), + ]); + // $productService->addToRecent($product->id); + + // $seoService->setProduct($product)->generate(); // !!! + + event(new ProductView($product)); + + return [ + 'product' => $product, + 'feedbacks' => $feedbackService->getForProduct($product->id), + 'similarProducts' => $sliderService->getSimilarProducts($product->id), + 'productGroup' => $sliderService->getProductGroup($product->product_group_id), + // 'recentProductsSlider' => $sliderService->getRecentProducts($productService), + ]; + } +} diff --git a/src/app/Http/Controllers/Api/ProductController.php b/src/app/Http/Controllers/Api/ProductController.php deleted file mode 100644 index 05a1dbe6..00000000 --- a/src/app/Http/Controllers/Api/ProductController.php +++ /dev/null @@ -1,49 +0,0 @@ -load([ - 'tags', - 'category', - 'countryOfOrigin', - 'availableSizes' => fn ($q) => $q->whereHas('stock', fn ($q) => $q->where('type', StockTypeEnum::SHOP)) - ->with(['stock' => fn ($q) => $q->orderBy('site_sorting', 'asc')->with('city')]), - ]); - // $this->productService->addToRecent($product->id); - - // $this->seoService->setProduct($product)->generate(); // !!! - - event(new ProductView($product)); - - return [ - 'product' => $product, - 'feedbacks' => $this->feedbackService->getForProduct($product->id), - 'similarProducts' => $this->sliderService->getSimilarProducts($product->id), - 'productGroup' => $this->sliderService->getProductGroup($product->product_group_id), - // 'recentProductsSlider' => $this->sliderService->getRecentProducts($this->productService), - ]; - } -} diff --git a/src/app/Http/Controllers/Api/TemporaryController.php b/src/app/Http/Controllers/Api/TemporaryController.php deleted file mode 100644 index a891eb92..00000000 --- a/src/app/Http/Controllers/Api/TemporaryController.php +++ /dev/null @@ -1,25 +0,0 @@ -show($request); - - return response()->json([ - 'is_catalog' => true, - 'data' => $view->getData(), - ]); - } -} diff --git a/src/app/Http/Requests/FilterRequest.php b/src/app/Http/Requests/FilterRequest.php index e2c28e29..34eb928c 100644 --- a/src/app/Http/Requests/FilterRequest.php +++ b/src/app/Http/Requests/FilterRequest.php @@ -38,13 +38,16 @@ public function rules() */ public function getSorting(): string { - $session = $this->session(); - $sorting = $this->input('sort') ?? $session->get('sorting', Product::DEFAULT_SORT); - if ($sorting != $session->get('sorting')) { - $session->put('sorting', $sorting); + $sorting = $this->input('sort'); + + if ($this->hasSession()) { + $sessionSorting = $this->session()->get('sorting'); + if ($sorting && $sorting !== $sessionSorting) { + $this->session()->put('sorting', $sorting); + } } - return $sorting; + return $sorting ?? Product::DEFAULT_SORT; } /** @@ -55,7 +58,7 @@ public function getFilters(): array $slugs = array_filter(explode('/', 'catalog/' . $this->path)); $filters = $this->getStaticFilters($slugs); - Url::whereIn('slug', $slugs) + Url::query()->whereIn('slug', $slugs) ->with('filters') ->get(['slug', 'model_type', 'model_id']) ->sortBy(fn (Url $url) => array_search($url->slug, $slugs)) @@ -75,7 +78,7 @@ public function getCity(): ?City { $citySlug = $this->route('city'); - return $citySlug ? City::where('slug', $citySlug)->first() : null; + return $citySlug ? City::query()->where('slug', $citySlug)->first() : null; } /** diff --git a/src/app/Models/Category.php b/src/app/Models/Category.php index 272e8af4..04667a8b 100644 --- a/src/app/Models/Category.php +++ b/src/app/Models/Category.php @@ -262,4 +262,12 @@ public function getNameWithParents(): string return $name; } + + /** + * Mark filter as invisible + */ + public function isInvisible(): bool + { + return $this->isRoot(); + } } diff --git a/src/app/Services/CatalogService.php b/src/app/Services/CatalogService.php index 46e3a6bd..2ba4f5d8 100644 --- a/src/app/Services/CatalogService.php +++ b/src/app/Services/CatalogService.php @@ -55,23 +55,25 @@ public function getProducts(array $filters, string $sort, ?string $search = null return $products; } - public function getFilterBadges(?array $currentFiltersGroups, ?string $searchQuery = null): array + public function getFilterBadges(array $currentFiltersGroups = [], ?string $searchQuery = null): array { $badges = []; - if (!empty($currentFiltersGroups)) { - foreach ($currentFiltersGroups as $currentFiltersGroupKey => $currentFiltersGroup) { - foreach ($currentFiltersGroup as $currentFilterKey => $currentFilter) { - $filterModel = $currentFilter->filters; - if ($filterModel->isInvisible() || $filterModel->slug === 'catalog' || ($currentFiltersGroupKey == Category::class) && ($currentFilterKey != array_key_last($currentFiltersGroup))) { - continue; - } - $badges[] = (object)[ - 'name' => $filterModel->getBadgeName(), - 'url' => UrlHelper::generate([], [$filterModel]), - ]; + foreach ($currentFiltersGroups as $filterModel => $currentFiltersGroup) { + if ($filterModel === Category::class) { + $currentFiltersGroup = [end($currentFiltersGroup)]; + } + foreach ($currentFiltersGroup as $currentFilter) { + $filterModel = $currentFilter->filters; + if ($filterModel->isInvisible()) { + continue; } + $badges[] = (object)[ + 'name' => $filterModel->getBadgeName(), + 'url' => UrlHelper::generate([], [$filterModel]), + ]; } } + if ($searchQuery) { $badges[] = (object)[ 'name' => 'Поиск: ' . mb_strimwidth($searchQuery, 0, 12, '...'), diff --git a/src/routes/api.php b/src/routes/api.php index 5deec654..eebd3437 100644 --- a/src/routes/api.php +++ b/src/routes/api.php @@ -1,15 +1,18 @@ user(); + return [ + 'user' => $request->user(), + 'device' => Device::current(), + ]; })->middleware('auth:sanctum'); Route::get('app-init', [AppController::class, 'init']); -Route::get('catalog/{path?}', [TemporaryController::class, 'catalog'])->where('path', '[a-zA-Z0-9/_-]+'); -Route::get('product/{product:slug}', [ProductController::class, 'show'])->withTrashed()->name('product.show'); // ! test +Route::get('catalog/{path?}', [CatalogController::class, 'index'])->where('path', '[a-zA-Z0-9/_-]+'); +Route::get('product/{product:slug}', [CatalogController::class, 'show'])->withTrashed()->name('product.show');