главная добита по визуалу

This commit is contained in:
Alisa
2026-06-07 23:13:03 +03:00
parent 66e931e0d6
commit 3a065b34d6
12 changed files with 196 additions and 104 deletions
-38
View File
@@ -47,44 +47,6 @@ final class HomeController
'kind' => 'new',
'products' => $productRepository->newPreview(10),
];
foreach ([
['slugs' => ['ikra'], 'title' => 'Икра'],
['slugs' => ['ryba'], 'title' => 'Рыба'],
['slugs' => ['moreprodukty'], 'title' => 'Морепродукты'],
['slugs' => ['myaso'], 'title' => 'Мясо'],
['slugs' => ['polufabrikaty'], 'title' => 'Полуфабрикаты'],
['slugs' => ['syry'], 'title' => 'Сыры'],
['slugs' => ['frukty-ovoschi-yagody-griby'], 'title' => 'Фрукты, овощи, ягоды, грибы'],
['slugs' => ['mramornaya-govyadina'], 'title' => 'Мраморная говядина'],
['slugs' => ['kopchenaya-ryba', 'kopchenaya-riba-1'], 'title' => 'Копченая рыба'],
['slugs' => ['vyalenaya-ryba', 'vylaenaya-riba'], 'title' => 'Вяленая рыба'],
['slugs' => ['malosolnaya-ryba', 'malosolnaya-riba'], 'title' => 'Малосольная рыба'],
] as $sectionConfig) {
$categoryMatch = $this->homeCategoryShowcase(
$categoryRepository,
$productRepository,
$categories,
$sectionConfig['slugs'],
$sectionConfig['title']
);
if ($categoryMatch === null) {
continue;
}
$category = $categoryMatch['category'];
$showcase = $categoryMatch['showcase'];
$slug = (string) ($sectionConfig['slugs'][0] ?? $category['slug']);
$homeCatalogSections[] = [
'key' => $slug,
'title' => $sectionConfig['title'],
'url' => '/catalog/' . $category['slug'],
'count' => $showcase['total'],
'kind' => 'category',
'products' => $showcase['products'],
];
}
$settings = (new SettingRepository())->allKeyed();
} catch (Throwable $exception) {
$dbStatus = app_env('APP_DEBUG', 'false') === 'true'
+185 -22
View File
@@ -1662,8 +1662,8 @@ a:hover {
.home-catalog-showcase {
display: grid;
gap: 18px;
margin-top: 26px;
gap: 16px;
margin-top: 24px;
}
.home-catalog-heading,
@@ -1674,37 +1674,89 @@ a:hover {
justify-content: space-between;
}
.home-catalog-heading {
border: 1px solid rgba(13, 93, 128, 0.12);
border-radius: 16px;
padding: clamp(16px, 2vw, 24px);
background:
linear-gradient(135deg, rgba(13, 93, 128, 0.08), rgba(255, 255, 255, 0.78) 58%),
#fffefa;
box-shadow: 0 14px 36px rgba(22, 60, 43, 0.06);
}
.home-catalog-heading h2 {
font-size: clamp(26px, 3vw, 40px);
margin: 0;
font-size: clamp(26px, 2.45vw, 36px);
line-height: 1.05;
}
.home-catalog-main-link {
display: inline-flex;
flex: 0 0 auto;
align-items: center;
justify-content: center;
min-height: 46px;
border-radius: 999px;
padding: 0 22px;
color: #fff;
font-size: 15px;
font-weight: 900;
text-decoration: none;
background:
linear-gradient(135deg, #0d5d80, #173d2c 74%);
box-shadow: 0 14px 32px rgba(13, 93, 128, 0.2);
transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.home-catalog-main-link:hover,
.home-catalog-main-link:focus-visible {
transform: translateY(-1px);
box-shadow: 0 18px 40px rgba(13, 93, 128, 0.26);
}
.home-product-section {
position: relative;
display: grid;
gap: 12px;
padding: 14px;
border: 1px solid var(--line);
border-radius: 10px;
background: rgba(255, 255, 255, 0.78);
box-shadow: 0 12px 30px rgba(22, 60, 43, 0.055);
gap: 14px;
overflow: hidden;
padding: clamp(14px, 1.8vw, 22px);
border: 1px solid rgba(19, 66, 45, 0.12);
border-radius: 14px;
background:
linear-gradient(180deg, rgba(255, 255, 255, 0.88), rgba(255, 254, 250, 0.96)),
#fff;
box-shadow: 0 16px 44px rgba(22, 60, 43, 0.08);
}
.home-product-section::after {
content: "";
position: absolute;
inset: 0 0 0 auto;
width: 76px;
pointer-events: none;
background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 254, 250, 0.92));
}
.home-product-section.is-promo {
border-color: rgba(196, 57, 47, 0.28);
border-color: rgba(196, 57, 47, 0.2);
background:
linear-gradient(135deg, rgba(196, 57, 47, 0.12), rgba(255, 255, 255, 0.9) 44%),
radial-gradient(circle at top left, rgba(196, 57, 47, 0.1), transparent 32%),
linear-gradient(180deg, rgba(255, 255, 255, 0.92), rgba(255, 250, 248, 0.96)),
#fff;
}
.home-product-section.is-new {
border-color: rgba(19, 66, 45, 0.26);
border-color: rgba(13, 93, 128, 0.2);
background:
linear-gradient(135deg, rgba(19, 66, 45, 0.12), rgba(255, 255, 255, 0.92) 46%),
radial-gradient(circle at top left, rgba(13, 93, 128, 0.12), transparent 34%),
linear-gradient(180deg, rgba(255, 255, 255, 0.92), rgba(246, 251, 250, 0.96)),
#fff;
}
.home-product-section-head h3 {
margin: 0;
font-size: clamp(20px, 1.9vw, 29px);
font-size: clamp(22px, 2vw, 30px);
line-height: 1.05;
}
.home-product-section-actions {
@@ -1717,8 +1769,8 @@ a:hover {
.home-product-section-head a {
flex: 0 0 auto;
color: var(--brand-green);
font-size: 14px;
color: #0d5d80;
font-size: 13px;
font-weight: 900;
text-decoration: none;
}
@@ -1737,12 +1789,12 @@ a:hover {
height: 34px;
border: 1px solid rgba(19, 66, 45, 0.12);
border-radius: 999px;
color: var(--brand-green);
color: #0d5d80;
font-size: 15px;
font-weight: 900;
line-height: 1;
background: #fff;
box-shadow: 0 8px 18px rgba(19, 66, 45, 0.08);
box-shadow: 0 8px 18px rgba(13, 93, 128, 0.1);
cursor: pointer;
transition: transform 0.18s ease, color 0.18s ease, background 0.18s ease;
}
@@ -1750,31 +1802,142 @@ a:hover {
.home-strip-controls button:hover,
.home-strip-controls button:focus-visible {
color: #fff;
background: var(--brand-green);
background: linear-gradient(135deg, #0d5d80, var(--brand-green));
transform: translateY(-1px);
}
.home-products-strip {
display: grid;
grid-auto-flow: column;
grid-auto-columns: minmax(200px, calc((100% - 42px) / 4));
grid-auto-columns: clamp(250px, 18vw, 286px);
gap: 14px;
overflow-x: auto;
overflow-x: hidden;
overflow-y: visible;
padding: 2px 2px 4px;
margin-inline: -2px;
padding: 2px 2px 6px;
scroll-snap-type: x proximity;
-ms-overflow-style: none;
scrollbar-width: none;
}
.home-products-strip::-webkit-scrollbar {
display: none;
width: 0;
height: 0;
}
.home-products-strip .product-card {
min-width: 0;
padding: 12px;
border-color: rgba(19, 66, 45, 0.1);
box-shadow: 0 12px 26px rgba(22, 60, 43, 0.055);
scroll-snap-align: start;
}
.home-products-strip .product-card-image {
margin: -3px -3px 10px;
}
.home-products-strip .product-card-image img,
.home-products-strip .product-card-image-placeholder {
aspect-ratio: 4 / 3;
}
.home-products-strip .product-card .product-category {
height: 26px;
margin-bottom: 6px;
font-size: 10px;
}
.home-products-strip .product-card h3 {
height: 54px;
margin-bottom: 10px;
font-size: 15px;
line-height: 1.18;
}
.home-products-strip .variant-choice {
height: 64px;
grid-template-rows: auto 30px;
gap: 5px;
margin-bottom: 8px;
padding-bottom: 8px;
}
.home-products-strip .variant-choice > span,
.home-products-strip .price-line,
.home-products-strip .package-price-line {
font-size: 12px;
}
.home-products-strip .package-price-note {
font-size: 11px;
}
.home-products-strip .price-line {
grid-template-columns: 1fr;
gap: 2px;
align-items: start;
min-height: 42px;
margin-bottom: 5px;
}
.home-products-strip .package-price-line {
grid-template-columns: 1fr;
gap: 2px;
align-items: start;
min-height: 50px;
padding-top: 8px;
}
.home-products-strip .price-unit-label,
.home-products-strip .package-price-label {
overflow: visible;
color: #546251;
font-size: 11px;
line-height: 1.2;
text-overflow: clip;
white-space: normal;
}
.home-products-strip .price-unit-values,
.home-products-strip .package-price-values {
justify-content: flex-start;
font-size: 13px;
line-height: 1.2;
}
.home-products-strip .old-price {
font-size: 11px;
}
.home-products-strip .quantity-stepper {
min-width: 82px;
}
.home-products-strip .quantity-stepper button,
.home-products-strip .quantity-stepper input {
width: 28px;
height: 36px;
font-size: 13px;
}
.home-products-strip .add-to-cart-button {
min-height: 36px;
padding-inline: 10px;
font-size: 12px;
white-space: nowrap;
}
.home-products-strip .product-card-actions {
grid-template-columns: 84px minmax(104px, 1fr);
min-height: 38px;
}
.home-products-strip .price-tier-trigger {
flex: 0 0 auto;
}
.home-delivery-separator {
display: grid;
grid-template-columns: minmax(0, 1.25fr) minmax(280px, 0.75fr);
Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

+7 -7
View File
@@ -77,13 +77,13 @@ $faviconSvg = <<<'SVG'
SVG;
$faviconHref = 'data:image/svg+xml,' . rawurlencode($faviconSvg);
$homeEmbeddedImages = [
'home-hero-picnic' => '/assets/images/home/hero-picnic-sunset.png',
'home-warehouse-fish' => '/assets/images/home/warehouse-fish.jpg',
'home-banner-meat' => '/assets/images/home/banner-meat-grill.png',
'home-banner-seafood' => '/assets/images/home/banner-seafood-fresh.png',
'home-warehouse-main' => '/assets/images/home/warehouse-main.jpg',
'home-warehouse-arrival' => '/assets/images/home/warehouse-arrival.jpg',
'home-warehouse-cold' => '/assets/images/home/warehouse-cold.jpg',
'home-hero-picnic' => '/assets/images/home/hero-picnic-sunset.webp',
'home-warehouse-fish' => '/assets/images/home/warehouse-fish.webp',
'home-banner-meat' => '/assets/images/home/banner-meat-grill.webp',
'home-banner-seafood' => '/assets/images/home/banner-seafood-fresh.webp',
'home-warehouse-main' => '/assets/images/home/warehouse-main.webp',
'home-warehouse-arrival' => '/assets/images/home/warehouse-arrival.webp',
'home-warehouse-cold' => '/assets/images/home/warehouse-cold.webp',
];
try {
$megaCategories = (new \App\Repositories\CategoryRepository())->tree();
+2 -35
View File
@@ -235,9 +235,9 @@ $arrivalDate = $lastArrival->format('j') . ' ' . $months[(int) $lastArrival->for
<div class="home-catalog-heading">
<div>
<p class="eyebrow">Каталог продукции</p>
<h2>Подборки по категориям</h2>
<h2>Акции и новые поступления</h2>
</div>
<a class="subtle-link" href="/catalog">Весь каталог</a>
<a class="home-catalog-main-link" href="/catalog">Перейти во весь каталог</a>
</div>
<?php if (($homeCatalogSections ?? []) === []): ?>
@@ -245,7 +245,6 @@ $arrivalDate = $lastArrival->format('j') . ' ' . $months[(int) $lastArrival->for
<p class="muted">После наполнения каталога товары появятся здесь по категориям.</p>
</div>
<?php else: ?>
<?php $wishlistRequestRendered = false; ?>
<?php foreach ($homeCatalogSections as $section): ?>
<?php
$sectionProducts = $section['products'] ?? [];
@@ -254,10 +253,6 @@ $arrivalDate = $lastArrival->format('j') . ' ' . $months[(int) $lastArrival->for
}
$sectionKind = (string) ($section['kind'] ?? 'category');
?>
<?php if (!$wishlistRequestRendered && ($section['key'] ?? '') === 'myaso'): ?>
<?php require base_path('views/partials/wishlist-request-panel.php'); ?>
<?php $wishlistRequestRendered = true; ?>
<?php endif; ?>
<section class="home-product-section is-<?= e($sectionKind) ?>" id="home-<?= e((string) ($section['key'] ?? 'section')) ?>">
<div class="home-product-section-head">
<h3><?= e((string) ($section['title'] ?? 'Категория')) ?></h3>
@@ -277,35 +272,7 @@ $arrivalDate = $lastArrival->format('j') . ' ' . $months[(int) $lastArrival->for
<?php endforeach; ?>
</div>
</section>
<?php if (($section['key'] ?? '') === 'frukty-ovoschi-yagody-griby'): ?>
<section class="home-delivery-separator" aria-label="Расчет доставки">
<div>
<p class="eyebrow">Доставка и самовывоз</p>
<h3>Рассчитаем доставку до подъезда и подъем отдельно</h3>
<p>Внутри МКАД бесплатно от <?= e((string) ($settings['inside_mkad_free_from'] ?? '5000')) ?> руб. За МКАД бесплатная доставка от 10000 руб. до 10 км, дальше сумма бесплатной доставки зависит от расстояния.</p>
</div>
<form class="home-delivery-mini" action="/delivery" method="get">
<label>
<span>Сумма заказа</span>
<input type="number" name="amount" min="0" step="100" value="5000">
</label>
<label>
<span>Получение</span>
<select name="method">
<option value="pickup">Самовывоз</option>
<option value="inside" selected>Доставка внутри МКАД</option>
<option value="outside">Доставка за МКАД</option>
</select>
</label>
<button class="primary-button" type="submit">Открыть расчет</button>
</form>
</section>
<?php endif; ?>
<?php endforeach; ?>
<?php if (!$wishlistRequestRendered): ?>
<?php require base_path('views/partials/wishlist-request-panel.php'); ?>
<?php endif; ?>
<?php endif; ?>
</section>
+2 -2
View File
@@ -79,11 +79,11 @@ $isPurchasable = $isPublished && $isAvailable && $activePackagePrice > 0;
<?php if (!empty($product['main_image_path']) && $isPurchasable): ?>
<a class="product-card-image" href="/product/<?= e($product['slug']) ?>" aria-label="<?= e($product['name']) ?>">
<img src="<?= e((string) $product['main_image_path']) ?>" alt="<?= e((string) $product['name']) ?>">
<img src="<?= e((string) $product['main_image_path']) ?>" alt="<?= e((string) $product['name']) ?>" loading="lazy" decoding="async">
</a>
<?php elseif (!empty($product['main_image_path'])): ?>
<div class="product-card-image" aria-label="<?= e($product['name']) ?>">
<img src="<?= e((string) $product['main_image_path']) ?>" alt="<?= e((string) $product['name']) ?>">
<img src="<?= e((string) $product['main_image_path']) ?>" alt="<?= e((string) $product['name']) ?>" loading="lazy" decoding="async">
</div>
<?php elseif ($isPurchasable): ?>
<a class="product-card-image product-card-image-placeholder" href="/product/<?= e($product['slug']) ?>" aria-label="<?= e($product['name']) ?>">