feat(layouts): add 'Single' layout option to GroupLayout and update related functionality
This commit is contained in:
@@ -8,6 +8,7 @@ enum GroupLayout: string
|
||||
case Simple = 'simple';
|
||||
case SimpleVertical = 'simple_vertical';
|
||||
case Carousel = 'carousel';
|
||||
case Single = 'single';
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
|
||||
@@ -7,6 +7,7 @@ enum ProductLayout: string
|
||||
case Row = 'row';
|
||||
case ColumnWithImage = 'column_with_image';
|
||||
case ColumnWithCart = 'column_with_cart';
|
||||
case TicketSelector = 'ticket_selector';
|
||||
|
||||
/**
|
||||
* @return list<string>
|
||||
|
||||
@@ -25,7 +25,7 @@ class CatalogFeaturedItemResource extends JsonResource
|
||||
return $this->columnWithImageData($catalogItem);
|
||||
}
|
||||
|
||||
return [
|
||||
$data = [
|
||||
'id' => $catalogItem->id,
|
||||
'type' => $catalogItem->type->value,
|
||||
'nombre' => $catalogItem->nombre,
|
||||
@@ -51,16 +51,17 @@ class CatalogFeaturedItemResource extends JsonResource
|
||||
])
|
||||
->values(),
|
||||
];
|
||||
|
||||
if ($featuredGroup->product_layout === ProductLayout::TicketSelector) {
|
||||
$data['image'] = $this->firstImageUrl($catalogItem);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
private function columnWithImageData(CatalogItem $catalogItem): array
|
||||
{
|
||||
$attachment = $catalogItem->attachments->first()
|
||||
?? $catalogItem->variants
|
||||
->flatMap(fn (Variant $variant) => $variant->attachments)
|
||||
->first();
|
||||
|
||||
return [
|
||||
'id' => $catalogItem->id,
|
||||
'type' => $catalogItem->type->value,
|
||||
@@ -69,7 +70,17 @@ class CatalogFeaturedItemResource extends JsonResource
|
||||
'ticket_generation_policy' => $catalogItem->ticket_generation_policy->value,
|
||||
'validity_time_id' => $catalogItem->validity_time_id,
|
||||
'validity_time' => ValidityTimeResource::make($catalogItem->validityTime),
|
||||
'image' => $attachment?->getTemporaryUrl(1440),
|
||||
'image' => $this->firstImageUrl($catalogItem),
|
||||
];
|
||||
}
|
||||
|
||||
private function firstImageUrl(CatalogItem $catalogItem): ?string
|
||||
{
|
||||
$attachment = $catalogItem->attachments->first()
|
||||
?? $catalogItem->variants
|
||||
->flatMap(fn (Variant $variant) => $variant->attachments)
|
||||
->first();
|
||||
|
||||
return $attachment?->getTemporaryUrl(1440);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,13 @@ class FeaturedGroupService
|
||||
public function itemsResponse(FeaturedGroup $featuredGroup, int $page): array
|
||||
{
|
||||
if ($featuredGroup->group_layout !== GroupLayout::Paginated) {
|
||||
$items = $this->itemsQuery($featuredGroup)->get();
|
||||
$query = $this->itemsQuery($featuredGroup);
|
||||
|
||||
if ($featuredGroup->group_layout === GroupLayout::Single) {
|
||||
$query->limit(1);
|
||||
}
|
||||
|
||||
$items = $query->get();
|
||||
$this->attachGroup($items, $featuredGroup);
|
||||
|
||||
return CatalogFeaturedItemResource::collection($items)->resolve();
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
use App\Domains\Catalog\Enums\GroupLayout;
|
||||
use App\Domains\Catalog\Enums\ProductLayout;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
if (! in_array(DB::getDriverName(), ['mysql', 'mariadb'], true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->alterEnums(ProductLayout::values(), GroupLayout::values());
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
if (! in_array(DB::getDriverName(), ['mysql', 'mariadb'], true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->alterEnums(
|
||||
['row', 'column_with_image', 'column_with_cart'],
|
||||
['paginated', 'simple', 'simple_vertical', 'carousel'],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<string> $productLayouts
|
||||
* @param list<string> $groupLayouts
|
||||
*/
|
||||
private function alterEnums(array $productLayouts, array $groupLayouts): void
|
||||
{
|
||||
$products = $this->enumValues($productLayouts);
|
||||
$groups = $this->enumValues($groupLayouts);
|
||||
|
||||
DB::statement("ALTER TABLE featured_groups MODIFY product_layout ENUM({$products}) NOT NULL");
|
||||
DB::statement("ALTER TABLE featured_groups MODIFY group_layout ENUM({$groups}) NOT NULL DEFAULT 'paginated'");
|
||||
DB::statement("ALTER TABLE tenants MODIFY search_product_layout ENUM({$products}) NOT NULL DEFAULT 'column_with_image'");
|
||||
DB::statement("ALTER TABLE tenants MODIFY search_group_layout ENUM({$groups}) NOT NULL DEFAULT 'paginated'");
|
||||
}
|
||||
|
||||
/** @param list<string> $values */
|
||||
private function enumValues(array $values): string
|
||||
{
|
||||
return collect($values)
|
||||
->map(fn (string $value): string => DB::getPdo()->quote($value))
|
||||
->implode(',');
|
||||
}
|
||||
};
|
||||
@@ -241,6 +241,32 @@ class CatalogControllerTest extends TestCase
|
||||
->assertJsonPath('0.nombre', 'carousel Item 1');
|
||||
}
|
||||
|
||||
public function test_single_group_layout_returns_only_its_first_available_item(): void
|
||||
{
|
||||
$tenant = $this->createTenant('catalog-single-layout');
|
||||
$group = $this->createGroup(
|
||||
$tenant,
|
||||
ProductLayout::TicketSelector,
|
||||
'Entradas',
|
||||
groupLayout: GroupLayout::Single,
|
||||
);
|
||||
|
||||
foreach (['Primera entrada', 'Segunda entrada'] as $order => $name) {
|
||||
$item = $this->createItem($tenant, $name);
|
||||
$group->featuredItems()->create([
|
||||
'catalog_item_id' => $item->id,
|
||||
'order' => $order,
|
||||
]);
|
||||
}
|
||||
|
||||
$this->getJson("/api/tenants/{$tenant->codigo}/catalog")
|
||||
->assertOk()
|
||||
->assertJsonPath('0.layout', ProductLayout::TicketSelector->value)
|
||||
->assertJsonPath('0.group_layout', GroupLayout::Single->value)
|
||||
->assertJsonCount(1, '0.items')
|
||||
->assertJsonPath('0.items.0.nombre', 'Primera entrada');
|
||||
}
|
||||
|
||||
public function test_groups_can_source_items_from_a_category_or_the_entire_catalog(): void
|
||||
{
|
||||
$tenant = $this->createTenant('catalog-sources');
|
||||
|
||||
@@ -36,9 +36,20 @@ class CatalogModelsTest extends TestCase
|
||||
'simple',
|
||||
'simple_vertical',
|
||||
'carousel',
|
||||
'single',
|
||||
], GroupLayout::values());
|
||||
}
|
||||
|
||||
public function test_product_layout_has_all_supported_values(): void
|
||||
{
|
||||
$this->assertSame([
|
||||
'row',
|
||||
'column_with_image',
|
||||
'column_with_cart',
|
||||
'ticket_selector',
|
||||
], ProductLayout::values());
|
||||
}
|
||||
|
||||
public function test_attribute_maps_its_values_and_relations(): void
|
||||
{
|
||||
$attribute = new Attribute;
|
||||
|
||||
Reference in New Issue
Block a user