Initial commit
Some checks failed
Deploy / deploy (push) Has been cancelled

This commit is contained in:
ssww23
2026-03-10 00:55:37 +03:00
parent fc0f28d830
commit 93a655235a
155 changed files with 24768 additions and 0 deletions

View File

@@ -0,0 +1,221 @@
@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