@extends('layouts.store') @section('content') @php $currency = $s->currency_code ?? '$'; $total = $products->total(); $hasFilters = filled($q ?? null) || filled($cat ?? null) || filled($collection ?? null) || filled($min ?? null) || filled($max ?? null); @endphp {{-- ===== Top bar ===== --}}

{{ __('messages.Shop') }}

{{ trans_choice('messages.products', $total, ['count' => $total]) }} @if($hasFilters) • {{ __('messages.FiltersApplied') }} @endif
{{-- keep other query params when changing sort --}} @foreach(request()->except(['sort','page']) as $k => $v) @if(is_array($v)) @foreach($v as $vv)@endforeach @else @endif @endforeach
{{-- ===== Sidebar filters (desktop) ===== --}} {{-- ===== Main content ===== --}}
{{-- Applied filter chips --}} @if($hasFilters)
@if(filled($q)) “{{ $q }}” × @endif @if(filled($cat)) @php $catName = optional($categories->firstWhere('id', $cat))->name ?? $cat; @endphp {{ $catName }} × @endif @if(filled($collection)) @php $coObj = $collections->first(fn($c) => (string)$c->slug === (string)$collection || (string)$c->id === (string)$collection); $coName = $coObj->title ?? $collection; @endphp {{ $coName }} × @endif @if(filled($min)) {{ __('messages.Min') }}: {{ $currency }}{{ number_format((float)$min, 2) }} × @endif @if(filled($max)) {{ __('messages.Max') }}: {{ $currency }}{{ number_format((float)$max, 2) }} × @endif {{ __('messages.ResetAll') }}
@endif {{-- Products grid --}} @if($products->count())
@foreach($products as $p) @php // Media & description $imgUrl = $p->image ? asset('images/products/'.$p->image) : asset('images/products/no-image.png'); $descShort = \Illuminate\Support\Str::limit(strip_tags($p->note ?? ''), 600); // FINAL product price from controller (already discount+tax). Fallback to model helper if needed. $taxRate = isset($p->TaxNet) ? (float)$p->TaxNet : (float)($s->default_tax_rate ?? 0); $finalPrice = (float)($p->display_price ?? (method_exists($p,'minDisplayPrice') ? $p->minDisplayPrice($taxRate) : ($p->price ?? 0))); // Variants payload with FINAL price for each (display_price) $hasVariants = $p->variants && $p->variants->count() > 0; $variantsPayload = $hasVariants ? $p->variants->map(function($v) use ($p, $imgUrl, $taxRate, $currency) { $base = (float)($v->price ?? 0); $calc = method_exists($p,'computeFinalPrice') ? $p->computeFinalPrice($taxRate, $base) : ['final' => $base]; return [ 'id' => (int)$v->id, 'name' => (string)($v->name ?? ''), 'price' => (float)$base, 'display_price' => (float)$calc['final'], 'display_price_formatted' => $currency . number_format($calc['final'], 2), 'image' => $v->image ? asset('images/products/'.$v->image) : $imgUrl, ]; })->values() : collect([]); @endphp
{{ $p->name }} {{-- Quick View (uses FINAL price) --}}
{{ $p->name }}
{{ $currency }}{{ number_format($finalPrice, 2) }}
@endforeach
{{-- Pagination --}} @php $products->appends(request()->except('page')); @endphp @if ($products->hasPages())
@if($products->total() > 0) {{ __('messages.Showing') }} {{ $products->firstItem() }}{{ $products->lastItem() }} {{ __('messages.of') }} {{ $products->total() }} {{ __('messages.productsLower') }} @else {{ __('messages.NoProductsFound') }} @endif
@endif @else {{-- Empty state --}}
😕
{{ __('messages.NoProductsFound') }}

{{ __('messages.TryAdjustingFiltersOrBrowseAll') }}

{{ __('messages.ClearFilters') }}
@endif
{{-- ===== Offcanvas Filters (mobile) ===== --}}
{{ __('messages.Filters') }}
@include('store.partials.filters-card', [ 'q' => $q, 'cat' => $cat, 'collection' => $collection, 'min' => $min, 'max' => $max, 'sort' => $sort, 'categories' => $categories, 'collections' => $collections, 'isOffcanvas' => true ])
{{-- ===== Quick View Modal (image + description + VARIANTS) ===== --}} {{-- ===== Variant Picker Modal (for card Add-to-cart) ===== --}} {{-- ===== Styles ===== --}} {{-- ===== Quick View + Variant Picker + Capture-phase Add-to-cart (same logic as your base) ===== --}} @endsection