@if($product->featuredImage?->url) @push('head') @endpush @endif {{-- Schema.org Product + BreadcrumbList --}} @php $productSchema = [ '@context' => 'https://schema.org', '@type' => 'Product', 'name' => $product->name, 'description' => strip_tags($product->short_description ?? $product->description ?? ''), 'image' => $product->featuredImage?->url ? [url($product->featuredImage->url)] : [], 'sku' => $product->sku ?: 'prod-' . $product->id, 'brand' => [ '@type' => 'Brand', 'name' => "Atelier d'Aubin", ], 'offers' => [ '@type' => 'Offer', 'url' => url()->current(), 'priceCurrency' => 'EUR', 'price' => number_format($product->effective_price, 2, '.', ''), 'availability' => !$product->isInStock() ? 'https://schema.org/OutOfStock' : 'https://schema.org/InStock', ], ]; if ($reviews->count() > 0) { $avgRating = round($reviews->avg('rating'), 1); $productSchema['aggregateRating'] = [ '@type' => 'AggregateRating', 'ratingValue' => $avgRating, 'reviewCount' => $reviews->count(), 'bestRating' => 5, 'worstRating' => 1, ]; $productSchema['review'] = $reviews->map(fn($r) => [ '@type' => 'Review', 'reviewBody' => $r->content, 'datePublished' => $r->created_at->toDateString(), 'author' => ['@type' => 'Person', 'name' => $r->author_name], 'reviewRating' => [ '@type' => 'Rating', 'ratingValue' => $r->rating, 'bestRating' => 5, 'worstRating' => 1, ], ])->values()->all(); } $productJsonLd = json_encode($productSchema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); $breadcrumbItems = [ ['@type' => 'ListItem', 'position' => 1, 'name' => 'Boutique', 'item' => route('shop.index')], ]; $pos = 2; if ($product->category?->parent) { $breadcrumbItems[] = ['@type' => 'ListItem', 'position' => $pos++, 'name' => $product->category->parent->name, 'item' => $product->category->parent->url()]; } if ($product->category) { $breadcrumbItems[] = ['@type' => 'ListItem', 'position' => $pos++, 'name' => $product->category->name, 'item' => $product->category->url()]; } $breadcrumbItems[] = ['@type' => 'ListItem', 'position' => $pos, 'name' => $product->name]; $breadcrumbJsonLd = json_encode([ '@context' => 'https://schema.org', '@type' => 'BreadcrumbList', 'itemListElement' => $breadcrumbItems, ], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); @endphp @if(!$product->is_active && auth()->user()?->is_admin)
Ce produit est masque — visible uniquement par les administrateurs
@endif
{{-- Fil d'ariane --}}
{{-- Galerie --}} @php $allImages = collect(); if ($product->featuredImage) $allImages->push($product->featuredImage); $allImages = $allImages->merge($galleryImages); @endphp
{{-- Image principale --}}
@if($allImages->isNotEmpty()) @foreach($allImages as $i => $img) {{ $img->alt ?: $product->name }}width && $img->height) width="{{ $img->width }}" height="{{ $img->height }}" @endif x-show="active === {{ $i }}" @if($i === 0) fetchpriority="high" style="display: block" @else loading="lazy" @endif class="w-full h-full object-cover cursor-zoom-in" @click="lightbox = true"> @endforeach
@else
@endif
{{-- Miniatures --}} @if($allImages->count() > 1)
@foreach($allImages as $i => $img) @endforeach
@endif {{-- Lightbox --}} @if($allImages->isNotEmpty())
{{-- Fleche gauche --}} {{ $product->name }} {{-- Fleche droite --}} {{-- Compteur --}}
@endif
{{-- Infos produit --}} @php $hasSyncQty = $addonGroups->flatMap->addons->contains(fn($a) => $a->sync_qty); @endphp

{{ $product->category?->name }}

{{ $product->name }}

{{-- Etoiles --}}
@if($reviews->isNotEmpty()) @php $avgRating = round($reviews->avg('rating'), 1); @endphp
@for($i = 1; $i <= 5; $i++) @endfor
{{ $reviews->count() }} avis @else
@for($i = 1; $i <= 5; $i++) @endfor
Donner mon avis @endif
{{-- Prix --}}
@if($product->sale_price) {{ number_format($product->sale_price, 2, ',', ' ') }} € {{ number_format($product->price, 2, ',', ' ') }} € @else {{ number_format($product->price, 2, ',', ' ') }} € @endif
{{-- Description courte --}} @if($product->short_description)
{!! $product->short_description !!}
@endif {{-- Stock epuise --}} @if(!$product->isInStock())

Produit epuise

@endif {{-- Formulaire ajout panier --}}
@csrf {{-- Addons --}} @if($addonGroups->isNotEmpty()) @php $allAddons = $addonGroups->flatMap->addons; $hasSyncQty = $allAddons->contains(fn($a) => $a->sync_qty); $prenomAddon = $allAddons->first(fn($a) => $a->label === 'Prénom' && $a->type === 'text'); $prenomMotAddon = $allAddons->first(fn($a) => $a->label === 'Prénom ou mot' && $a->type === 'text'); $typoAddon = $allAddons->first(fn($a) => $a->label === 'Typographie' && $a->type === 'select'); $tailleAddon = $allAddons->first(fn($a) => $a->label === 'Taille des lettres' && $a->type === 'select'); $prixLettresAddon = $allAddons->first(fn($a) => $a->label === 'Prix des lettres' && $a->type === 'select'); @endphp
@foreach($addonGroups as $group) @if($group->description)

{{ $group->description }}

@endif
@foreach($group->addons as $addon) @endforeach
@endforeach
@if($prenomAddon && $typoAddon) @endif @if($prenomMotAddon && $tailleAddon && $prixLettresAddon) @endif @endif {{-- Quantite + bouton --}}
{{-- Informations livraison --}} @if($product->isInStock())
Livraison en point relais — 5,00 €
Livraison a domicile (Colissimo) — 7,90 €
@endif
{{-- Description complete --}} @if($product->description)

Tout savoir

Description

{!! $product->description !!}
@endif {{-- Avis clients --}}
@php $starPath = 'M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z'; @endphp

Retours d'experience

Avis clients @if($reviews->isNotEmpty()) ({{ $reviews->count() }}) @endif

@if($reviews->isNotEmpty()) @php $avgRating = round($reviews->avg('rating'), 1); $distrib = []; for ($s = 5; $s >= 1; $s--) { $distrib[$s] = $reviews->where('rating', $s)->count(); } @endphp
{{ number_format($avgRating, 1, ',', '') }}
@for($i = 1; $i <= 5; $i++) @endfor
sur 5
@foreach($distrib as $stars => $count) @php $pct = $reviews->count() > 0 ? round($count / $reviews->count() * 100) : 0; @endphp
{{ $stars }}
{{ $pct }}%
@endforeach
@endif
{{-- Liste des avis --}} @if($reviews->isNotEmpty())
@foreach($reviews as $review)
@for($i = 1; $i <= 5; $i++) @endfor
{{ $review->author_name }}
{{ $review->created_at->format('d/m/Y') }}

{{ $review->content }}

@endforeach
@endif {{-- Formulaire d'avis --}}

Laisser un avis

@if(session('review_success'))
{{ session('review_success') }}
@endif @if(session('review_error'))
{{ session('review_error') }}
@endif
@csrf
@error('author_name')

{{ $message }}

@enderror
@error('author_email')

{{ $message }}

@enderror
@for($i = 1; $i <= 5; $i++) @endfor
@error('rating')

{{ $message }}

@enderror
@error('content')

{{ $message }}

@enderror
{{-- Produits similaires --}} @if($related->isNotEmpty())

Produits similaires

@foreach($related as $relProduct) @endforeach
@endif