@extends('layouts.app') @section('title', $article->title) {{-- Story 5.5: Article JSON-LD structured data (only for published articles) --}} @if($article->status === \App\Enums\ArticleStatus::Published) @section('json-ld') @endsection @endif @section('content') {{-- Preview banner — visible only when previewing unpublished content (Story 5.7) --}} @if(isset($preview) && $preview)
⚠️ PREVIEW — Cet article n'est pas publié
@endif {{-- Breadcrumb --}} @php $locale = app()->getLocale(); @endphp {{-- Article layout: content + sticky TOC sidebar --}}
{{-- Main article content --}}
{{-- Article header --}}

{{ $article->title }}

@if($article->published_at || $article->read_time)
@if($article->published_at) @endif @if($article->read_time) {{ $article->read_time }} min de lecture @endif
@endif @if($article->tags->isNotEmpty())
@foreach($article->tags as $tag) {{ $tag->name }} @endforeach
@endif
{{-- Block rendering engine (Story 5.9) --}}
@if(!empty($article->blocks)) @php // Pre-compute heading slugs to handle duplicates (matching controller logic) $headingSlugs = []; $slugCounts = []; foreach ($article->blocks as $i => $b) { if (($b['type'] ?? '') === 'heading') { $text = $b['data']['text'] ?? $b['data']['content'] ?? ''; $baseSlug = \Illuminate\Support\Str::slug($text); if (isset($slugCounts[$baseSlug])) { $slugCounts[$baseSlug]++; $headingSlugs[$i] = $baseSlug . '-' . $slugCounts[$baseSlug]; } else { $slugCounts[$baseSlug] = 1; $headingSlugs[$i] = $baseSlug; } } } @endphp @foreach($article->blocks as $blockIndex => $block) @php $blockType = $block['type'] ?? ''; @endphp @switch($blockType) @case('paragraph') @break @case('heading') @php $headingData = $block['data'] ?? []; $headingData['slug'] = $headingSlugs[$blockIndex] ?? \Illuminate\Support\Str::slug($headingData['text'] ?? $headingData['content'] ?? ''); @endphp @break @case('image') @break @case('kpi') @break @case('quote') @break @case('banner') @break @case('button') @break @case('video') @break @case('list') @break @case('classic') @break @case('gallery') @break @case('iframe') @break @default {{-- Unknown block type — graceful fallback --}} @if(isset($preview) && $preview)
Block type inconnu : {{ $blockType ?: 'N/A' }}
@else @endif @endswitch @endforeach @else

Aucun contenu de bloc disponible.

@endif
{{-- "See also" section — single related article --}} @if(isset($relatedArticles) && $relatedArticles->isNotEmpty()) @php $seeAlso = $relatedArticles->first(); @endphp

{{ __('blog.see_also') }}

{{ $seeAlso->title }}
@endif
@endsection