2026-08-31 22:56:40 +03:00
|
|
|
{{--
|
2026-09-03 16:28:10 +03:00
|
|
|
Reloadable body of a product listing — result count + sort, product grid +
|
|
|
|
|
pagination, and the filter sidebar. Shared by the category page (scoped to a
|
|
|
|
|
collection) and the all-products page. Rendered on full load and on every
|
|
|
|
|
turbo-frame navigation, straight from the query string.
|
|
|
|
|
|
|
|
|
|
Vars (all from App\Catalog\ProductListingPage::build):
|
|
|
|
|
$products (LengthAwarePaginator), $sortOptions (array),
|
|
|
|
|
$listing (App\Catalog\ProductListing), $listingAction (string, GET form target),
|
|
|
|
|
$clearPriceUrl (?string), $priceFloor / $priceCeil (?int)
|
2026-08-31 22:56:40 +03:00
|
|
|
--}}
|
|
|
|
|
|
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-[1fr_230px] gap-14">
|
|
|
|
|
|
|
|
|
|
<div class="flex items-center justify-between gap-6 flex-wrap mb-7">
|
2026-09-03 16:28:10 +03:00
|
|
|
<x-shop.result-count :paginator="$products" />
|
|
|
|
|
<x-shop.sort :options="$sortOptions" id="shop-sort" />
|
2026-08-31 22:56:40 +03:00
|
|
|
</div>
|
|
|
|
|
<div></div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="grid grid-cols-1 lg:grid-cols-[1fr_230px] gap-14">
|
|
|
|
|
|
|
|
|
|
{{-- Products --}}
|
|
|
|
|
<div>
|
|
|
|
|
@if($products->isEmpty())
|
|
|
|
|
<p class="text-neutral-500">{{ __('storefront.shop.no_products') }}</p>
|
|
|
|
|
@else
|
|
|
|
|
<x-product-grid :products="$products->items()" cols="3" />
|
|
|
|
|
|
|
|
|
|
<div class="mt-12">
|
|
|
|
|
<x-ui.pagination :paginator="$products" />
|
|
|
|
|
</div>
|
|
|
|
|
@endif
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-09-03 16:28:10 +03:00
|
|
|
{{-- Sidebar — sort, price and in-stock are wired to the back-end; product
|
|
|
|
|
search lives in the nav overlay, not here. --}}
|
2026-08-31 22:56:40 +03:00
|
|
|
<aside class="flex flex-col gap-10">
|
|
|
|
|
|
|
|
|
|
{{-- Filter form: a plain GET form whose fields ARE the state. Changing
|
|
|
|
|
any control auto-submits (auto-submit controller); Turbo captures
|
|
|
|
|
the GET, navigates the frame, and advances the URL. `sort` rides
|
|
|
|
|
along as a hidden field so it survives a filter change; `page` is
|
|
|
|
|
deliberately absent, so filtering drops back to page 1. Without JS
|
|
|
|
|
the sr-only submit button applies the range inputs. --}}
|
|
|
|
|
<form
|
|
|
|
|
method="get"
|
2026-09-03 16:28:10 +03:00
|
|
|
action="{{ $listingAction }}"
|
2026-08-31 22:56:40 +03:00
|
|
|
data-controller="auto-submit"
|
|
|
|
|
data-action="change->auto-submit#submit range-slider:change->auto-submit#submit"
|
|
|
|
|
class="contents"
|
|
|
|
|
>
|
|
|
|
|
@if ($listing->sort)
|
2026-09-02 14:05:20 +03:00
|
|
|
<input type="hidden" name="sort" value="{{ $listing->sort->value }}" />
|
2026-08-31 22:56:40 +03:00
|
|
|
@endif
|
|
|
|
|
|
|
|
|
|
@if ($priceFloor !== null && $priceCeil !== null && $priceCeil > $priceFloor)
|
2026-09-03 16:28:10 +03:00
|
|
|
<div class="flex flex-col gap-4 -mt-2">
|
2026-08-31 22:56:40 +03:00
|
|
|
<p class="font-extrabold text-h4">{{ __('storefront.shop.filter_price') }}</p>
|
|
|
|
|
|
|
|
|
|
<x-ui.range-slider
|
|
|
|
|
name="price"
|
|
|
|
|
:min="$priceFloor"
|
|
|
|
|
:max="$priceCeil"
|
|
|
|
|
:min-value="max($priceFloor, $listing->minPrice ?? $priceFloor)"
|
|
|
|
|
:max-value="min($priceCeil, $listing->maxPrice ?? $priceCeil)"
|
|
|
|
|
prefix="€"
|
|
|
|
|
separator=" - "
|
|
|
|
|
:legend="__('storefront.shop.filter_price')"
|
|
|
|
|
:min-label="__('storefront.shop.price_min')"
|
|
|
|
|
:max-label="__('storefront.shop.price_max')"
|
|
|
|
|
>
|
2026-09-03 16:28:10 +03:00
|
|
|
@if ($clearPriceUrl)
|
2026-08-31 22:56:40 +03:00
|
|
|
<a
|
2026-09-03 16:28:10 +03:00
|
|
|
href="{{ $clearPriceUrl }}"
|
2026-08-31 22:56:40 +03:00
|
|
|
class="underline-slide [--slide-h:1px] font-display text-sm font-bold uppercase italic"
|
|
|
|
|
>{{ __('storefront.shop.reset') }}</a>
|
|
|
|
|
@endif
|
|
|
|
|
</x-ui.range-slider>
|
|
|
|
|
</div>
|
|
|
|
|
@endif
|
|
|
|
|
|
|
|
|
|
<div class="flex flex-col gap-4 [&_label]:text-base">
|
|
|
|
|
<p class="font-extrabold text-h4">{{ __('storefront.shop.availability') }}</p>
|
|
|
|
|
<x-ui.checkbox id="shop-in-stock" name="in_stock" :checked="$listing->inStockOnly">
|
|
|
|
|
{{ __('storefront.shop.in_stock_only') }}
|
|
|
|
|
</x-ui.checkbox>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<button type="submit" class="sr-only">{{ __('storefront.shop.apply') }}</button>
|
|
|
|
|
</form>
|
|
|
|
|
|
|
|
|
|
</aside>
|
|
|
|
|
|
|
|
|
|
</div>
|