Files

97 lines
4.1 KiB
PHP

{{--
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)
--}}
<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">
<x-shop.result-count :paginator="$products" />
<x-shop.sort :options="$sortOptions" id="shop-sort" />
</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>
{{-- Sidebar — sort, price and in-stock are wired to the back-end; product
search lives in the nav overlay, not here. --}}
<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"
action="{{ $listingAction }}"
data-controller="auto-submit"
data-action="change->auto-submit#submit range-slider:change->auto-submit#submit"
class="contents"
>
@if ($listing->sort)
<input type="hidden" name="sort" value="{{ $listing->sort->value }}" />
@endif
@if ($priceFloor !== null && $priceCeil !== null && $priceCeil > $priceFloor)
<div class="flex flex-col gap-4 -mt-2">
<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')"
>
@if ($clearPriceUrl)
<a
href="{{ $clearPriceUrl }}"
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>