feat(categories): add category retrieval and pagination for tenant-specific products
This commit is contained in:
@@ -4,9 +4,11 @@ namespace App\Domains\Catalog\Controllers;
|
||||
|
||||
use App\Domains\Catalog\Enums\GroupLayout;
|
||||
use App\Domains\Catalog\Models\CatalogItem;
|
||||
use App\Domains\Catalog\Models\Category;
|
||||
use App\Domains\Catalog\Models\FeaturedGroup;
|
||||
use App\Domains\Catalog\Models\FeaturedItem;
|
||||
use App\Domains\Catalog\Requests\CatalogItemDetailRequest;
|
||||
use App\Domains\Catalog\Requests\CategoryPageRequest;
|
||||
use App\Domains\Catalog\Requests\FeaturedGroupPageRequest;
|
||||
use App\Domains\Catalog\Requests\SearchCatalogItemsRequest;
|
||||
use App\Domains\Catalog\Requests\StoreCatalogItemRequest;
|
||||
@@ -57,6 +59,32 @@ class CatalogController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
public function category(
|
||||
CategoryPageRequest $request,
|
||||
Tenant $tenant,
|
||||
Category $category,
|
||||
CatalogService $catalogService,
|
||||
): AnonymousResourceCollection {
|
||||
abort_unless($category->tenant_code === $tenant->codigo, 404);
|
||||
|
||||
return CatalogSearchItemResource::collection(
|
||||
$catalogService->categoryItems(
|
||||
$tenant,
|
||||
$category,
|
||||
$tenant->search_items_per_page,
|
||||
(int) $request->validated('page', 1),
|
||||
)
|
||||
)->additional([
|
||||
'category' => [
|
||||
'id' => $category->id,
|
||||
'nombre' => $category->nombre,
|
||||
'categoria_id' => $category->categoria_id,
|
||||
],
|
||||
'layout' => $tenant->search_product_layout->value,
|
||||
'group_layout' => $tenant->search_group_layout->value,
|
||||
]);
|
||||
}
|
||||
|
||||
public function featuredGroupItems(
|
||||
FeaturedGroupPageRequest $request,
|
||||
Tenant $tenant,
|
||||
|
||||
21
app/Domains/Catalog/Requests/CategoryPageRequest.php
Normal file
21
app/Domains/Catalog/Requests/CategoryPageRequest.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\Catalog\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class CategoryPageRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @return array<string, list<string>> */
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'page' => ['sometimes', 'integer', 'min:1'],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ use App\Domains\Attachable\Services\AttachmentService;
|
||||
use App\Domains\Catalog\Enums\CatalogItemType;
|
||||
use App\Domains\Catalog\Models\Attribute;
|
||||
use App\Domains\Catalog\Models\CatalogItem;
|
||||
use App\Domains\Catalog\Models\Category;
|
||||
use App\Domains\Catalog\Models\Inventory;
|
||||
use App\Domains\Catalog\Models\ItemAttribute;
|
||||
use App\Domains\Catalog\Models\Variant;
|
||||
@@ -210,6 +211,29 @@ class CatalogService
|
||||
]));
|
||||
}
|
||||
|
||||
/** @return LengthAwarePaginator<CatalogItem> */
|
||||
public function categoryItems(
|
||||
Tenant $tenant,
|
||||
Category $category,
|
||||
int $perPage,
|
||||
int $page,
|
||||
): LengthAwarePaginator {
|
||||
return CatalogItem::query()
|
||||
->where('tenant_code', $tenant->codigo)
|
||||
->where('category_id', $category->id)
|
||||
->with([
|
||||
'attachments',
|
||||
'inventory',
|
||||
'variants.inventory',
|
||||
'variants.attachments',
|
||||
'variants.definitions.itemAttribute.attribute',
|
||||
'bundleComponents.catalogItem',
|
||||
'bundleComponents.variant.catalogItem',
|
||||
])
|
||||
->orderBy('nombre')
|
||||
->paginate(perPage: $perPage, pageName: 'page', page: $page);
|
||||
}
|
||||
|
||||
public function delete(CatalogItem $catalogItem): void
|
||||
{
|
||||
DB::transaction(function () use ($catalogItem): void {
|
||||
|
||||
@@ -9,6 +9,8 @@ Route::prefix('tenants/{tenant:codigo}')->group(function (): void {
|
||||
->name('catalog.featured-groups.items.index');
|
||||
Route::get('catalog-items', [CatalogController::class, 'search'])
|
||||
->name('catalog-items.index');
|
||||
Route::get('categories/{category}', [CatalogController::class, 'category'])
|
||||
->name('categories.show');
|
||||
Route::get('catalog-items/{catalogItem}', [CatalogController::class, 'show']);
|
||||
Route::post('catalog-items', [CatalogController::class, 'store']);
|
||||
});
|
||||
|
||||
@@ -16,7 +16,14 @@ class BootstrapTenantController extends Controller
|
||||
|
||||
return TenantResource::make(
|
||||
Tenant::query()
|
||||
->with(['headerLogo', 'footerLogo', 'mainCarouselImages', 'menues', 'socialMedia'])
|
||||
->with([
|
||||
'headerLogo',
|
||||
'footerLogo',
|
||||
'mainCarouselImages',
|
||||
'menues',
|
||||
'socialMedia',
|
||||
'categories' => fn ($query) => $query->orderBy('nombre'),
|
||||
])
|
||||
->where('dominio', $dominio)
|
||||
->firstOrFail()
|
||||
);
|
||||
|
||||
@@ -6,6 +6,7 @@ use App\Domains\Attachable\Models\Attachment;
|
||||
use App\Domains\Catalog\Enums\GroupLayout;
|
||||
use App\Domains\Catalog\Enums\ProductLayout;
|
||||
use App\Domains\Catalog\Models\CatalogItem;
|
||||
use App\Domains\Catalog\Models\Category;
|
||||
use App\Domains\Menu\Models\Menu;
|
||||
use App\Domains\Menu\Models\TenantMenu;
|
||||
use Illuminate\Database\Eloquent\Attributes\Fillable;
|
||||
@@ -109,6 +110,14 @@ class Tenant extends Model
|
||||
return $this->hasMany(CatalogItem::class, 'tenant_code', 'codigo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Category, $this>
|
||||
*/
|
||||
public function categories(): HasMany
|
||||
{
|
||||
return $this->hasMany(Category::class, 'tenant_code', 'codigo');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<SocialMedia, $this>
|
||||
*/
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Domains\Tenant\Resources;
|
||||
|
||||
use App\Domains\Catalog\Models\Category;
|
||||
use App\Domains\Menu\Models\Menu;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -64,9 +65,43 @@ class TenantResource extends JsonResource
|
||||
'menues',
|
||||
fn () => $this->menuTree($this->menues)
|
||||
),
|
||||
'categories' => $this->whenLoaded(
|
||||
'categories',
|
||||
fn () => $this->categoryTree($this->categories)
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection<int, Category> $categories
|
||||
* @return Collection<int, array<string, mixed>>
|
||||
*/
|
||||
private function categoryTree(Collection $categories): Collection
|
||||
{
|
||||
$categoryIds = $categories->pluck('id')->flip();
|
||||
$childrenByParent = $categories
|
||||
->filter(fn (Category $category) => $category->categoria_id !== null
|
||||
&& $categoryIds->has($category->categoria_id))
|
||||
->groupBy('categoria_id');
|
||||
|
||||
$formatCategory = function (Category $category) use (&$formatCategory, $childrenByParent): array {
|
||||
return [
|
||||
'id' => $category->id,
|
||||
'nombre' => $category->nombre,
|
||||
'subcategories' => $childrenByParent
|
||||
->get($category->id, collect())
|
||||
->map($formatCategory)
|
||||
->values(),
|
||||
];
|
||||
};
|
||||
|
||||
return $categories
|
||||
->filter(fn (Category $category) => $category->categoria_id === null
|
||||
|| ! $categoryIds->has($category->categoria_id))
|
||||
->map($formatCategory)
|
||||
->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection<int, Menu> $menus
|
||||
* @return Collection<int, array<string, mixed>>
|
||||
|
||||
Reference in New Issue
Block a user