Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
95.83% covered (success)
95.83%
23 / 24
83.33% covered (warning)
83.33%
5 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
ProductCarousel
95.83% covered (success)
95.83%
23 / 24
83.33% covered (warning)
83.33%
5 / 6
9
0.00% covered (danger)
0.00%
0 / 1
 key
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 label
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 icon
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 description
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 fields
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
1
 products
90.00% covered (success)
90.00%
9 / 10
0.00% covered (danger)
0.00%
0 / 1
4.02
1<?php
2
3namespace App\Widgets\Types;
4
5use App\Models\admin\Product;
6use App\Models\Category;
7use App\Models\ProductCollection;
8use App\Widgets\AbstractWidget;
9use Illuminate\Support\Collection;
10
11class ProductCarousel extends AbstractWidget
12{
13    protected string $view = 'widgets.product-carousel';
14
15    public function key(): string
16    {
17        return 'product_carousel';
18    }
19
20    public function label(): string
21    {
22        return 'Product row';
23    }
24
25    public function icon(): string
26    {
27        return 'fas fa-boxes-stacked';
28    }
29
30    public function description(): string
31    {
32        return 'A row of products — newest, featured, or from a category.';
33    }
34
35    public function fields(): array
36    {
37        return [
38            'title' => ['type' => 'text', 'label' => 'Heading', 'default' => "What's new"],
39            'layout' => ['type' => 'select', 'label' => 'Layout', 'default' => 'carousel',
40                'options' => ['carousel' => 'Sliding carousel', 'grid' => 'Static grid']],
41            'source' => ['type' => 'select', 'label' => 'Show', 'default' => 'newest',
42                'options' => ['newest' => 'Newest products', 'featured' => 'Featured products', 'category' => 'From a category', 'collection'=>'From a collection']],
43            'category_id' => ['type' => 'select', 'label' => 'Category', 'default' => '', 'options' => [''=>'Choose category'] + Category::orderBy('name')->pluck('name','id')->all()],
44            'collection_id' => ['type' => 'select', 'label' => 'Collection', 'default' => '', 'options' => [''=>'Choose collection'] + ProductCollection::where('is_active',true)->orderBy('name')->pluck('name','id')->all()],
45            'limit' => ['type' => 'number', 'label' => 'How many', 'default' => 8],
46        ];
47    }
48
49    /** @return Collection<int,Product> */
50    public function products(array $s)
51    {
52        $limit = max(1, min(48, (int) ($s['limit'] ?? 8)));
53
54        if (($s['source'] ?? '') === 'collection' && ! empty($s['collection_id'])) {
55            return ProductCollection::find($s['collection_id'])?->products()->limit($limit)->get() ?? collect();
56        }
57
58        return Product::query()
59            ->when(($s['source'] ?? '') === 'featured', fn ($q) => $q->where('is_featured', true))
60            ->when(($s['source'] ?? '') === 'category' && ! empty($s['category_id']),
61                fn ($q) => $q->where('category_id', $s['category_id']))
62            ->latest()
63            ->limit($limit)
64            ->get();
65    }
66}