This commit is contained in:
50
resources/views/partials/breadcrumbs.blade.php
Normal file
50
resources/views/partials/breadcrumbs.blade.php
Normal file
@@ -0,0 +1,50 @@
|
||||
@if (!empty($items))
|
||||
@php
|
||||
$breadcrumbSchemaItems = collect($items)
|
||||
->values()
|
||||
->map(function ($item, $index) {
|
||||
if (!is_array($item)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$label = trim((string) ($item['label'] ?? ''));
|
||||
if ($label === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
$url = !empty($item['url']) ? (string) $item['url'] : url()->current();
|
||||
|
||||
return [
|
||||
'@type' => 'ListItem',
|
||||
'position' => $index + 1,
|
||||
'name' => $label,
|
||||
'item' => $url,
|
||||
];
|
||||
})
|
||||
->filter()
|
||||
->values()
|
||||
->all();
|
||||
$breadcrumbSchema = [
|
||||
'@context' => 'https://schema.org',
|
||||
'@type' => 'BreadcrumbList',
|
||||
'itemListElement' => $breadcrumbSchemaItems,
|
||||
];
|
||||
@endphp
|
||||
|
||||
<nav class="pc-breadcrumbs" aria-label="Хлебные крошки">
|
||||
@foreach ($items as $item)
|
||||
@if (!$loop->last && !empty($item['url']))
|
||||
<a href="{{ $item['url'] }}">{{ $item['label'] }}</a>
|
||||
<span class="pc-breadcrumbs-sep">/</span>
|
||||
@else
|
||||
<span class="pc-breadcrumbs-current">{{ $item['label'] }}</span>
|
||||
@endif
|
||||
@endforeach
|
||||
</nav>
|
||||
|
||||
@if (!empty($breadcrumbSchemaItems))
|
||||
<script type="application/ld+json">
|
||||
@json($breadcrumbSchema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
|
||||
</script>
|
||||
@endif
|
||||
@endif
|
||||
49
resources/views/partials/home-slider.blade.php
Normal file
49
resources/views/partials/home-slider.blade.php
Normal file
@@ -0,0 +1,49 @@
|
||||
@php
|
||||
$slides = $slides ?? collect();
|
||||
$isSingle = $slides->count() <= 1;
|
||||
@endphp
|
||||
|
||||
<div class="pc-home-slider {{ $sliderClass ?? '' }}" data-home-slider>
|
||||
<div class="pc-home-slider-track">
|
||||
@forelse ($slides as $slide)
|
||||
@php
|
||||
$hasTitle = $slide->show_title && !empty($slide->title);
|
||||
$hasSubtitle = $slide->show_subtitle && !empty($slide->subtitle);
|
||||
$hasButton = $slide->show_button && !empty($slide->button_text) && !empty($slide->button_url);
|
||||
$hasContent = $hasTitle || $hasSubtitle || $hasButton;
|
||||
$altText = $hasTitle ? $slide->title : 'Слайд на главной странице';
|
||||
@endphp
|
||||
<article class="pc-home-slide {{ $loop->first ? 'is-active' : '' }}" data-home-slide>
|
||||
<img src="{{ $slide->image_url }}" alt="{{ $altText }}" loading="{{ $loop->first ? 'eager' : 'lazy' }}">
|
||||
<div class="pc-home-slide-overlay"></div>
|
||||
@if ($hasContent)
|
||||
<div class="pc-home-slide-content">
|
||||
@if ($hasTitle)
|
||||
<h2>{{ $slide->title }}</h2>
|
||||
@endif
|
||||
@if ($hasSubtitle)
|
||||
<p>{{ $slide->subtitle }}</p>
|
||||
@endif
|
||||
@if ($hasButton)
|
||||
<a class="pc-btn primary" href="{{ $slide->button_url }}">{{ $slide->button_text }}</a>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</article>
|
||||
@empty
|
||||
<article class="pc-home-slide is-active is-fallback" data-home-slide>
|
||||
<div class="pc-home-slide-overlay"></div>
|
||||
<div class="pc-home-slide-content">
|
||||
<h2>{{ $fallbackTitle ?? 'Собирайте ПК быстрее' }}</h2>
|
||||
<p>{{ $fallbackText ?? 'Загрузите баннеры в админке, чтобы вывести акции и подборки товаров на главной странице.' }}</p>
|
||||
@if (!empty($fallbackUrl))
|
||||
<a class="pc-btn primary" href="{{ $fallbackUrl }}">{{ $fallbackButton ?? 'Открыть каталог' }}</a>
|
||||
@endif
|
||||
</div>
|
||||
</article>
|
||||
@endforelse
|
||||
</div>
|
||||
|
||||
<button class="pc-home-slider-btn is-prev" type="button" data-home-slider-prev aria-label="Предыдущий слайд" @disabled($isSingle)>‹</button>
|
||||
<button class="pc-home-slider-btn is-next" type="button" data-home-slider-next aria-label="Следующий слайд" @disabled($isSingle)>›</button>
|
||||
</div>
|
||||
41
resources/views/partials/pagination.blade.php
Normal file
41
resources/views/partials/pagination.blade.php
Normal file
@@ -0,0 +1,41 @@
|
||||
@if ($paginator->hasPages())
|
||||
<nav class="pc-pager" role="navigation" aria-label="Пагинация">
|
||||
<ul class="pc-pager-list">
|
||||
<li>
|
||||
@if ($paginator->onFirstPage())
|
||||
<span class="pc-pager-link is-disabled" aria-disabled="true">Назад</span>
|
||||
@else
|
||||
<a class="pc-pager-link" href="{{ $paginator->previousPageUrl() }}" rel="prev">Назад</a>
|
||||
@endif
|
||||
</li>
|
||||
|
||||
@foreach ($elements as $element)
|
||||
@if (is_string($element))
|
||||
<li>
|
||||
<span class="pc-pager-link is-gap">{{ $element }}</span>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
<li>
|
||||
@if ($page == $paginator->currentPage())
|
||||
<span class="pc-pager-link is-active" aria-current="page">{{ $page }}</span>
|
||||
@else
|
||||
<a class="pc-pager-link" href="{{ $url }}">{{ $page }}</a>
|
||||
@endif
|
||||
</li>
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
<li>
|
||||
@if ($paginator->hasMorePages())
|
||||
<a class="pc-pager-link" href="{{ $paginator->nextPageUrl() }}" rel="next">Вперед</a>
|
||||
@else
|
||||
<span class="pc-pager-link is-disabled" aria-disabled="true">Вперед</span>
|
||||
@endif
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
47
resources/views/partials/payment-requisites.blade.php
Normal file
47
resources/views/partials/payment-requisites.blade.php
Normal file
@@ -0,0 +1,47 @@
|
||||
@php
|
||||
$paymentBank = config('shop.payment_bank');
|
||||
$paymentCardHolder = config('shop.payment_card_holder');
|
||||
$paymentCardNumber = config('shop.payment_card_number');
|
||||
$telegram = trim((string) config('shop.contact_telegram'));
|
||||
$telegramUrl = '';
|
||||
|
||||
if ($telegram !== '') {
|
||||
$telegramUrl = str_starts_with($telegram, 'http://') || str_starts_with($telegram, 'https://')
|
||||
? $telegram
|
||||
: 'https://t.me/' . ltrim($telegram, '@/');
|
||||
}
|
||||
@endphp
|
||||
|
||||
<div class="pc-payment-details {{ $class ?? '' }}">
|
||||
<h3>{{ $title ?? 'Оплата по реквизитам' }}</h3>
|
||||
|
||||
@isset($amount)
|
||||
<p class="pc-payment-total">Сумма к оплате: <strong>{{ number_format((float) $amount, 0, '.', ' ') }} {{ config('shop.currency_symbol', '₽') }}</strong></p>
|
||||
@endisset
|
||||
|
||||
<div class="pc-payment-grid">
|
||||
<div class="pc-payment-row">
|
||||
<span class="pc-payment-key">Банк</span>
|
||||
<strong class="pc-payment-value">{{ $paymentBank }}</strong>
|
||||
</div>
|
||||
<div class="pc-payment-row">
|
||||
<span class="pc-payment-key">Получатель</span>
|
||||
<strong class="pc-payment-value">{{ $paymentCardHolder }}</strong>
|
||||
</div>
|
||||
<div class="pc-payment-row">
|
||||
<span class="pc-payment-key">Номер карты</span>
|
||||
<strong class="pc-payment-value">{{ $paymentCardNumber }}</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@isset($purpose)
|
||||
<p class="pc-payment-purpose">Назначение платежа: <strong>{{ $purpose }}</strong></p>
|
||||
@endisset
|
||||
|
||||
@if (!empty($showHelp))
|
||||
<p class="pc-muted">После оплаты отправьте чек в поддержку для подтверждения заказа.</p>
|
||||
@if ($telegramUrl !== '')
|
||||
<p class="pc-muted">Telegram: <a class="pc-contact-link" href="{{ $telegramUrl }}" target="_blank" rel="noopener noreferrer">{{ $telegram }}</a></p>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
60
resources/views/partials/product-card.blade.php
Normal file
60
resources/views/partials/product-card.blade.php
Normal file
@@ -0,0 +1,60 @@
|
||||
@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
|
||||
|
||||
<article class="pc-card pc-product-card">
|
||||
<div class="pc-product-media">
|
||||
<div class="pc-product-tools">
|
||||
<form method="post" action="{{ route('favorites.toggle', $product) }}" class="pc-product-tool-form" data-preserve-scroll="true">
|
||||
@csrf
|
||||
<button class="pc-product-tool {{ $isFavorite ? 'is-active' : '' }}" type="submit" aria-label="Добавить в избранное" title="В избранное">
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M12 20s-7-4.5-9-9c-1.2-2.7.7-6 4.2-6 2 0 3.2 1 3.8 2 0.6-1 1.8-2 3.8-2 3.5 0 5.4 3.3 4.2 6-2 4.5-9 9-9 9z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</form>
|
||||
<form method="post" action="{{ route('compare.toggle', $product) }}" class="pc-product-tool-form" data-preserve-scroll="true">
|
||||
@csrf
|
||||
<button class="pc-product-tool {{ $isCompared ? 'is-active' : '' }}" type="submit" aria-label="Добавить в сравнение" title="Сравнить">
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M5 4h3v16H5zM16 4h3v16h-3zM10.5 8h3v12h-3z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@if (!empty($product->image_url))
|
||||
<img class="pc-product-image" src="{{ $product->image_url }}" alt="{{ $product->name }}" loading="lazy" decoding="async">
|
||||
@else
|
||||
<div class="pc-product-image" role="img" aria-label="{{ $product->name }}"></div>
|
||||
@endif
|
||||
</div>
|
||||
<h3>
|
||||
<a class="pc-product-link" href="{{ route('products.show', $product) }}">{{ $product->name }}</a>
|
||||
</h3>
|
||||
@if (!empty($product->short_description))
|
||||
<p>{{ $product->short_description }}</p>
|
||||
@endif
|
||||
<div class="pc-product-meta">
|
||||
<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 ghost {{ $isInCart ? 'is-active' : '' }}" type="submit">
|
||||
{{ $isInCart ? 'В корзине' : 'В корзину' }}
|
||||
</button>
|
||||
</form>
|
||||
@else
|
||||
<button class="pc-btn ghost" type="button" disabled>Нет в наличии</button>
|
||||
@endif
|
||||
</div>
|
||||
</article>
|
||||
28
resources/views/partials/product-carousel.blade.php
Normal file
28
resources/views/partials/product-carousel.blade.php
Normal file
@@ -0,0 +1,28 @@
|
||||
@php
|
||||
$items = $products ?? collect();
|
||||
@endphp
|
||||
|
||||
<section class="pc-section">
|
||||
<div class="pc-section-title">
|
||||
<h2>{{ $title ?? 'Товары' }}</h2>
|
||||
@if (!empty($description))
|
||||
<p>{{ $description }}</p>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if ($items->isEmpty())
|
||||
<div class="pc-card">{{ $emptyText ?? 'Пока нет товаров.' }}</div>
|
||||
@else
|
||||
<div class="pc-product-carousel" data-product-carousel>
|
||||
<button class="pc-product-carousel-btn is-prev" type="button" data-product-carousel-prev aria-label="Предыдущие товары">‹</button>
|
||||
<div class="pc-product-carousel-track" data-product-carousel-track>
|
||||
@foreach ($items as $product)
|
||||
<div class="pc-product-carousel-item">
|
||||
@include('partials.product-card', ['product' => $product])
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<button class="pc-product-carousel-btn is-next" type="button" data-product-carousel-next aria-label="Следующие товары">›</button>
|
||||
</div>
|
||||
@endif
|
||||
</section>
|
||||
Reference in New Issue
Block a user