222 lines
11 KiB
PHP
222 lines
11 KiB
PHP
@extends('layouts.shop')
|
||
|
||
@php
|
||
$productGallery = $product->gallery_urls;
|
||
$productImage = $productGallery[0] ?? ($product->image_url ?: config('seo.default_image'));
|
||
$productImageUrl = str_starts_with($productImage, 'http://') || str_starts_with($productImage, 'https://')
|
||
? $productImage
|
||
: url($productImage);
|
||
$productSchemaImages = array_map(
|
||
fn (string $image) => str_starts_with($image, 'http://') || str_starts_with($image, 'https://')
|
||
? $image
|
||
: url($image),
|
||
$productGallery !== [] ? array_values($productGallery) : [$productImageUrl]
|
||
);
|
||
|
||
$manufacturer = trim((string) ($product->specs['manufacturer'] ?? ''));
|
||
$conditionRaw = mb_strtolower(trim((string) ($product->specs['condition'] ?? '')));
|
||
$itemCondition = str_contains($conditionRaw, 'б/у') || str_contains($conditionRaw, 'used')
|
||
? 'https://schema.org/UsedCondition'
|
||
: 'https://schema.org/NewCondition';
|
||
|
||
$productSchema = [
|
||
'@context' => 'https://schema.org',
|
||
'@type' => 'Product',
|
||
'name' => $product->name,
|
||
'description' => $product->short_description ?: ($product->description ?: "Купить {$product->name} по выгодной цене."),
|
||
'sku' => $product->sku ?: null,
|
||
'category' => $product->category?->name,
|
||
'image' => $productSchemaImages,
|
||
'url' => route('products.show', $product),
|
||
'offers' => [
|
||
'@type' => 'Offer',
|
||
'priceCurrency' => config('shop.currency_code', 'RUB'),
|
||
'price' => (string) $product->price,
|
||
'availability' => $product->stock > 0 ? 'https://schema.org/InStock' : 'https://schema.org/OutOfStock',
|
||
'itemCondition' => $itemCondition,
|
||
'url' => route('products.show', $product),
|
||
],
|
||
];
|
||
|
||
if ($manufacturer !== '') {
|
||
$productSchema['brand'] = [
|
||
'@type' => 'Brand',
|
||
'name' => $manufacturer,
|
||
];
|
||
}
|
||
@endphp
|
||
|
||
@section('meta_title', $product->name)
|
||
@section('meta_description', \Illuminate\Support\Str::limit(strip_tags($product->short_description ?: ($product->description ?: "Купить {$product->name} по выгодной цене.")), 160))
|
||
@section('meta_keywords', $product->name . ', ' . ($product->category?->name ?? 'товар') . ', купить')
|
||
@section('meta_canonical', route('products.show', $product))
|
||
@section('meta_image', $productImageUrl)
|
||
@section('meta_image_alt', $product->name)
|
||
@section('meta_og_type', 'product')
|
||
|
||
@push('structured_data')
|
||
<script type="application/ld+json">
|
||
@json($productSchema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
|
||
</script>
|
||
@endpush
|
||
|
||
@section('content')
|
||
@php
|
||
$favoriteIds = array_map('intval', (array) session('favorites', []));
|
||
$compareIds = array_map('intval', (array) session('compare', []));
|
||
$isFavorite = in_array($product->id, $favoriteIds, true);
|
||
$isCompared = in_array($product->id, $compareIds, true);
|
||
$cartItems = (array) session('cart', []);
|
||
$isInCart = isset($cartItems[$product->id]);
|
||
@endphp
|
||
|
||
@include('partials.breadcrumbs', [
|
||
'items' => [
|
||
['label' => 'Главная', 'url' => route('home')],
|
||
['label' => 'Каталог', 'url' => route('catalog.index')],
|
||
['label' => $product->category?->name ?? 'Категория', 'url' => $product->category ? route('catalog.category', $product->category) : null],
|
||
['label' => $product->name, 'url' => null],
|
||
],
|
||
])
|
||
|
||
<section class="pc-section pc-product-page">
|
||
<div class="pc-product-hero">
|
||
<div class="pc-product-gallery" data-product-gallery>
|
||
@if ($productGallery !== [])
|
||
<img
|
||
class="pc-product-image-lg"
|
||
src="{{ $productGallery[0] }}"
|
||
alt="{{ $product->name }}"
|
||
loading="eager"
|
||
decoding="async"
|
||
data-product-gallery-main
|
||
>
|
||
@else
|
||
<div class="pc-product-image-lg" role="img" aria-label="{{ $product->name }}"></div>
|
||
@endif
|
||
|
||
@if (count($productGallery) > 1)
|
||
<div class="pc-product-thumbs" aria-label="Дополнительные изображения товара">
|
||
@foreach ($productGallery as $imageUrl)
|
||
<button
|
||
class="pc-product-thumb {{ $loop->first ? 'is-active' : '' }}"
|
||
type="button"
|
||
data-product-gallery-thumb
|
||
data-image-src="{{ $imageUrl }}"
|
||
data-image-alt="{{ $product->name }} - фото {{ $loop->iteration }}"
|
||
aria-label="Показать фото {{ $loop->iteration }}"
|
||
aria-pressed="{{ $loop->first ? 'true' : 'false' }}"
|
||
>
|
||
<img
|
||
src="{{ $imageUrl }}"
|
||
alt="{{ $product->name }} - миниатюра {{ $loop->iteration }}"
|
||
loading="lazy"
|
||
decoding="async"
|
||
>
|
||
</button>
|
||
@endforeach
|
||
</div>
|
||
@endif
|
||
</div>
|
||
<div class="pc-product-info">
|
||
<h1>{{ $product->name }}</h1>
|
||
<p class="pc-muted">{{ $product->short_description }}</p>
|
||
<div class="pc-product-badges">
|
||
@if ($product->sku)
|
||
<span class="pc-sku">Артикул: {{ $product->sku }}</span>
|
||
@endif
|
||
</div>
|
||
<div class="pc-product-price">
|
||
<strong>{{ number_format($product->price, 0, '.', ' ') }} {{ config('shop.currency_symbol', '₽') }}</strong>
|
||
@if (!empty($product->old_price))
|
||
<span class="pc-product-old">{{ number_format($product->old_price, 0, '.', ' ') }} {{ config('shop.currency_symbol', '₽') }}</span>
|
||
@endif
|
||
</div>
|
||
<div class="pc-product-actions">
|
||
@if ($product->stock > 0)
|
||
<form method="post" action="{{ route('cart.add', $product) }}" data-preserve-scroll="true">
|
||
@csrf
|
||
<button class="pc-btn primary {{ $isInCart ? 'is-active' : '' }}" type="submit">
|
||
{{ $isInCart ? 'В корзине' : 'В корзину' }}
|
||
</button>
|
||
</form>
|
||
@else
|
||
<button class="pc-btn primary" type="button" disabled>Нет в наличии</button>
|
||
@endif
|
||
<form method="post" action="{{ route('favorites.toggle', $product) }}" data-preserve-scroll="true">
|
||
@csrf
|
||
<button class="pc-btn ghost {{ $isFavorite ? 'is-active' : '' }}" type="submit">
|
||
{{ $isFavorite ? 'Убрать из избранного' : 'В избранное' }}
|
||
</button>
|
||
</form>
|
||
<form method="post" action="{{ route('compare.toggle', $product) }}" data-preserve-scroll="true">
|
||
@csrf
|
||
<button class="pc-btn ghost {{ $isCompared ? 'is-active' : '' }}" type="submit">
|
||
{{ $isCompared ? 'Убрать из сравнения' : 'В сравнение' }}
|
||
</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="pc-tabs">
|
||
<input type="radio" name="product-tabs" id="tab-specs" checked>
|
||
<input type="radio" name="product-tabs" id="tab-desc">
|
||
<input type="radio" name="product-tabs" id="tab-shipping">
|
||
<input type="radio" name="product-tabs" id="tab-payment">
|
||
|
||
<div class="pc-tab-labels">
|
||
<label for="tab-specs">Характеристики</label>
|
||
<label for="tab-desc">Описание</label>
|
||
<label for="tab-shipping">Доставка</label>
|
||
<label for="tab-payment">Оплата</label>
|
||
</div>
|
||
|
||
<div class="pc-tab-content">
|
||
<section class="pc-tab-panel pc-tab-specs">
|
||
<div class="pc-specs-grid">
|
||
@forelse (($product->specs ?? []) as $key => $value)
|
||
<div class="pc-spec-row">
|
||
<span>{{ $specLabels[$key] ?? str_replace('_', ' ', $key) }}</span>
|
||
<strong>{{ $value }}</strong>
|
||
</div>
|
||
@empty
|
||
<p class="pc-muted">Характеристики еще не добавлены.</p>
|
||
@endforelse
|
||
</div>
|
||
</section>
|
||
<section class="pc-tab-panel pc-tab-desc">
|
||
<p class="pc-muted">{{ $product->description ?? 'Описание товара будет добавлено позже.' }}</p>
|
||
</section>
|
||
<section class="pc-tab-panel pc-tab-shipping">
|
||
<ul class="pc-list">
|
||
<li>Доставка курьером по городу</li>
|
||
<li>Самовывоз из пункта выдачи</li>
|
||
<li>Отправка по стране 1-3 дня</li>
|
||
</ul>
|
||
</section>
|
||
<section class="pc-tab-panel pc-tab-payment">
|
||
<ul class="pc-list">
|
||
<li>Оплата картой онлайн</li>
|
||
<li>Банковский перевод</li>
|
||
<li>Рассрочка на крупные заказы</li>
|
||
</ul>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
@if ($related->isNotEmpty())
|
||
<section class="pc-section">
|
||
<div class="pc-section-title">
|
||
<h2>Что еще посмотреть в этой категории</h2>
|
||
</div>
|
||
<div class="pc-products-grid">
|
||
@foreach ($related as $item)
|
||
@include('partials.product-card', ['product' => $item])
|
||
@endforeach
|
||
</div>
|
||
</section>
|
||
@endif
|
||
@endsection
|