превью относительно готово
This commit is contained in:
@@ -47,6 +47,9 @@ final class ProductRepository extends BaseRepository
|
|||||||
{
|
{
|
||||||
$limit = max(1, min($limit, 96));
|
$limit = max(1, min($limit, 96));
|
||||||
$categoryIds = (new CategoryRepository())->descendantIds($categoryId);
|
$categoryIds = (new CategoryRepository())->descendantIds($categoryId);
|
||||||
|
$categoryParents = $this->categoryParentMap();
|
||||||
|
$requestedRootId = $this->rootCategoryId($categoryId, $categoryParents);
|
||||||
|
$isRootCategory = ($categoryParents[$categoryId] ?? null) === null;
|
||||||
$placeholders = implode(',', array_fill(0, count($categoryIds), '?'));
|
$placeholders = implode(',', array_fill(0, count($categoryIds), '?'));
|
||||||
$sql = $this->previewSelectSql(
|
$sql = $this->previewSelectSql(
|
||||||
'AND (
|
'AND (
|
||||||
@@ -67,13 +70,37 @@ final class ProductRepository extends BaseRepository
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
ORDER BY p.sort_order, p.name',
|
ORDER BY p.sort_order, p.name',
|
||||||
$limit
|
5000
|
||||||
);
|
);
|
||||||
|
|
||||||
$statement = $this->pdo()->prepare($sql);
|
$statement = $this->pdo()->prepare($sql);
|
||||||
$statement->execute(array_merge($categoryIds, $categoryIds));
|
$statement->execute(array_merge($categoryIds, $categoryIds));
|
||||||
|
|
||||||
return $this->preparePreviewProducts($statement->fetchAll());
|
$categoryLookup = array_flip($categoryIds);
|
||||||
|
$products = $this->preparePreviewProducts($statement->fetchAll());
|
||||||
|
$filtered = [];
|
||||||
|
|
||||||
|
foreach ($products as $product) {
|
||||||
|
$leafCategoryIds = $product['category_display_ids'] ?? [];
|
||||||
|
$leafRootIds = $product['category_display_root_ids'] ?? [];
|
||||||
|
|
||||||
|
if ($leafCategoryIds === []) {
|
||||||
|
if (isset($categoryLookup[(int) ($product['category_id'] ?? 0)])) {
|
||||||
|
$filtered[] = $product;
|
||||||
|
}
|
||||||
|
} elseif (
|
||||||
|
array_intersect($leafCategoryIds, $categoryIds) !== []
|
||||||
|
&& (!$isRootCategory || array_values(array_unique($leafRootIds)) === [$requestedRootId])
|
||||||
|
) {
|
||||||
|
$filtered[] = $product;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($filtered) >= $limit) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -236,6 +263,7 @@ final class ProductRepository extends BaseRepository
|
|||||||
p.seo_title,
|
p.seo_title,
|
||||||
p.seo_description,
|
p.seo_description,
|
||||||
p.seo_keywords,
|
p.seo_keywords,
|
||||||
|
p.category_id,
|
||||||
c.name AS category_name,
|
c.name AS category_name,
|
||||||
c.slug AS category_slug,
|
c.slug AS category_slug,
|
||||||
p.main_image_path,
|
p.main_image_path,
|
||||||
@@ -351,6 +379,7 @@ final class ProductRepository extends BaseRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
$categoryParents = $this->categoryParentMap();
|
$categoryParents = $this->categoryParentMap();
|
||||||
|
$categoryRoots = $this->categoryRootMap($categoryParents);
|
||||||
|
|
||||||
foreach ($products as &$product) {
|
foreach ($products as &$product) {
|
||||||
$linkedCategories = $categoriesByProduct[(int) $product['id']] ?? [];
|
$linkedCategories = $categoriesByProduct[(int) $product['id']] ?? [];
|
||||||
@@ -373,6 +402,11 @@ final class ProductRepository extends BaseRepository
|
|||||||
});
|
});
|
||||||
|
|
||||||
$names = array_values(array_unique(array_map(static fn (array $category): string => $category['name'], $leafCategories)));
|
$names = array_values(array_unique(array_map(static fn (array $category): string => $category['name'], $leafCategories)));
|
||||||
|
$product['category_display_ids'] = array_values(array_map(static fn (array $category): int => (int) $category['id'], $leafCategories));
|
||||||
|
$product['category_display_root_ids'] = array_values(array_unique(array_map(
|
||||||
|
static fn (array $category): int => (int) ($categoryRoots[(int) $category['id']] ?? $category['id']),
|
||||||
|
$leafCategories
|
||||||
|
)));
|
||||||
$product['category_display_name'] = $names === []
|
$product['category_display_name'] = $names === []
|
||||||
? ($product['category_name'] ?? 'Каталог')
|
? ($product['category_name'] ?? 'Каталог')
|
||||||
: implode(' / ', $names);
|
: implode(' / ', $names);
|
||||||
@@ -398,6 +432,37 @@ final class ProductRepository extends BaseRepository
|
|||||||
return $parents;
|
return $parents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, int|null> $categoryParents
|
||||||
|
* @return array<int, int>
|
||||||
|
*/
|
||||||
|
private function categoryRootMap(array $categoryParents): array
|
||||||
|
{
|
||||||
|
$roots = [];
|
||||||
|
|
||||||
|
foreach (array_keys($categoryParents) as $categoryId) {
|
||||||
|
$roots[$categoryId] = $this->rootCategoryId((int) $categoryId, $categoryParents);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $roots;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<int, int|null> $categoryParents
|
||||||
|
*/
|
||||||
|
private function rootCategoryId(int $categoryId, array $categoryParents): int
|
||||||
|
{
|
||||||
|
$currentId = $categoryId;
|
||||||
|
$parentId = $categoryParents[$currentId] ?? null;
|
||||||
|
|
||||||
|
while ($parentId !== null) {
|
||||||
|
$currentId = $parentId;
|
||||||
|
$parentId = $categoryParents[$currentId] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $currentId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<int, int> $linkedCategoryIds
|
* @param array<int, int> $linkedCategoryIds
|
||||||
* @param array<int, int|null> $categoryParents
|
* @param array<int, int|null> $categoryParents
|
||||||
|
|||||||
+124
-35
@@ -247,6 +247,15 @@ body {
|
|||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mega-item::after {
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
right: -12px;
|
||||||
|
left: -12px;
|
||||||
|
height: 14px;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
.mega-root {
|
.mega-root {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -274,30 +283,31 @@ body {
|
|||||||
|
|
||||||
.mega-submenu {
|
.mega-submenu {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 100%;
|
top: calc(100% + 8px);
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 30;
|
z-index: 30;
|
||||||
width: 300px;
|
width: min(760px, calc(100vw - 32px));
|
||||||
max-height: 72vh;
|
max-height: min(74vh, 680px);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 12px 10px 10px;
|
padding: 14px;
|
||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line);
|
||||||
border-radius: 8px;
|
border-radius: 10px;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
background: var(--paper);
|
background: var(--paper);
|
||||||
box-shadow: 0 22px 60px rgba(23, 61, 44, 0.14);
|
box-shadow: 0 26px 70px rgba(23, 61, 44, 0.18);
|
||||||
overflow: visible;
|
overflow: auto;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
transform: translateY(6px);
|
transform: translateY(6px);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
transition: opacity 0.16s ease, transform 0.16s ease, visibility 0.16s ease;
|
transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mega-item:hover > .mega-submenu,
|
.mega-item:hover > .mega-submenu,
|
||||||
.mega-item:focus-within > .mega-submenu {
|
.mega-item:focus-within > .mega-submenu {
|
||||||
display: grid;
|
display: block;
|
||||||
gap: 4px;
|
columns: 3 190px;
|
||||||
|
column-gap: 14px;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
@@ -306,11 +316,16 @@ body {
|
|||||||
|
|
||||||
.mega-submenu li {
|
.mega-submenu li {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
break-inside: avoid;
|
||||||
|
margin: 0 0 4px;
|
||||||
|
border-bottom: 1px solid #edf1e9;
|
||||||
|
padding-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mega-submenu a {
|
.mega-submenu a {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
min-height: 32px;
|
min-height: 32px;
|
||||||
border-radius: 7px;
|
border-radius: 7px;
|
||||||
padding: 7px 9px;
|
padding: 7px 9px;
|
||||||
@@ -327,11 +342,29 @@ body {
|
|||||||
|
|
||||||
.mega-submenu.depth-2,
|
.mega-submenu.depth-2,
|
||||||
.mega-submenu.depth-3 {
|
.mega-submenu.depth-3 {
|
||||||
top: -10px;
|
top: 0;
|
||||||
|
left: calc(100% + 8px);
|
||||||
|
width: min(620px, calc(100vw - 32px));
|
||||||
|
max-height: min(70vh, 560px);
|
||||||
|
overflow: auto;
|
||||||
|
columns: 2 180px;
|
||||||
|
transform: translateX(8px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mega-submenu li:has(> .mega-submenu) > a::after {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin-left: 10px;
|
||||||
|
color: #9aa894;
|
||||||
|
content: "›";
|
||||||
|
}
|
||||||
|
|
||||||
|
.mega-submenu li:has(> .mega-submenu)::after {
|
||||||
|
position: absolute;
|
||||||
|
top: -8px;
|
||||||
|
bottom: -8px;
|
||||||
left: 100%;
|
left: 100%;
|
||||||
max-height: min(70vh, 520px);
|
width: 14px;
|
||||||
overflow: visible;
|
content: "";
|
||||||
transform: translateX(6px);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mega-item:nth-last-child(-n+3) > .mega-submenu {
|
.mega-item:nth-last-child(-n+3) > .mega-submenu {
|
||||||
@@ -348,8 +381,7 @@ body {
|
|||||||
|
|
||||||
.mega-submenu li:hover > .mega-submenu,
|
.mega-submenu li:hover > .mega-submenu,
|
||||||
.mega-submenu li:focus-within > .mega-submenu {
|
.mega-submenu li:focus-within > .mega-submenu {
|
||||||
display: grid;
|
display: block;
|
||||||
gap: 4px;
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
transform: translateX(0);
|
transform: translateX(0);
|
||||||
@@ -1081,21 +1113,23 @@ a:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.product-card .product-category {
|
.product-card .product-category {
|
||||||
display: flex;
|
display: -webkit-box;
|
||||||
align-items: flex-start;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
height: 32px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: #7a856f;
|
color: #7a856f;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
.product-card h3 {
|
.product-card h3 {
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-height: 50px;
|
height: 58px;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
line-height: 1.22;
|
line-height: 1.22;
|
||||||
-webkit-line-clamp: 3;
|
-webkit-line-clamp: 3;
|
||||||
@@ -1103,31 +1137,51 @@ a:hover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.price-line {
|
.price-line {
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 4px 6px;
|
|
||||||
align-items: baseline;
|
|
||||||
min-height: 22px;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #2d372f;
|
|
||||||
}
|
|
||||||
|
|
||||||
.package-price-line {
|
|
||||||
position: relative;
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(0, 1fr) auto 22px;
|
grid-template-columns: minmax(0, 1fr) auto 22px;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
min-height: 30px;
|
min-height: 30px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #2d372f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-unit-label {
|
||||||
|
overflow: hidden;
|
||||||
|
min-width: 0;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.price-unit-values {
|
||||||
|
display: inline-flex;
|
||||||
|
gap: 6px;
|
||||||
|
align-items: baseline;
|
||||||
|
justify-content: flex-end;
|
||||||
|
min-width: 0;
|
||||||
|
color: var(--brand-green);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.package-price-line {
|
||||||
|
position: relative;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr) auto;
|
||||||
|
gap: 6px;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 36px;
|
||||||
border-top: 1px solid #e3e8de;
|
border-top: 1px solid #e3e8de;
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.package-price-label {
|
.package-price-label {
|
||||||
|
overflow: hidden;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
color: #2d372f;
|
color: #2d372f;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.package-price-values {
|
.package-price-values {
|
||||||
@@ -1160,9 +1214,10 @@ a:hover {
|
|||||||
|
|
||||||
.variant-choice {
|
.variant-choice {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
grid-template-rows: auto 34px;
|
||||||
align-self: start;
|
align-self: start;
|
||||||
gap: 7px;
|
gap: 7px;
|
||||||
min-height: 76px;
|
height: 76px;
|
||||||
margin: 0 0 12px;
|
margin: 0 0 12px;
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
border-bottom: 1px solid #edf1e9;
|
border-bottom: 1px solid #edf1e9;
|
||||||
@@ -1177,14 +1232,19 @@ a:hover {
|
|||||||
|
|
||||||
.variant-choice-list {
|
.variant-choice-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: nowrap;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
min-height: 32px;
|
min-width: 0;
|
||||||
|
min-height: 34px;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
scrollbar-width: thin;
|
||||||
}
|
}
|
||||||
|
|
||||||
.variant-choice-button {
|
.variant-choice-button {
|
||||||
appearance: none;
|
appearance: none;
|
||||||
|
flex: 0 0 auto;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
min-height: 30px;
|
min-height: 30px;
|
||||||
@@ -1230,6 +1290,13 @@ a:hover {
|
|||||||
background: #102f21;
|
background: #102f21;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.add-to-cart-button.is-added {
|
||||||
|
color: #102f21;
|
||||||
|
background: #dcebd3;
|
||||||
|
box-shadow: inset 0 0 0 2px var(--brand-green), 0 0 0 4px rgba(23, 61, 44, 0.12);
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
.product-card-actions {
|
.product-card-actions {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(96px, 0.44fr) minmax(0, 1fr);
|
grid-template-columns: minmax(96px, 0.44fr) minmax(0, 1fr);
|
||||||
@@ -1334,7 +1401,7 @@ body[data-payment-mode="cash"] .price-tier-trigger {
|
|||||||
transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s ease;
|
transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
body[data-payment-mode="cash"] .package-price-line:has(.price-tier-trigger:hover) + .price-tier-popover,
|
body[data-payment-mode="cash"] .price-line:has(.price-tier-trigger:hover) ~ .price-tier-popover,
|
||||||
body[data-payment-mode="cash"] .price-tier-popover:hover {
|
body[data-payment-mode="cash"] .price-tier-popover:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
@@ -1628,6 +1695,26 @@ body[data-payment-mode="cash"] .price-tier-popover:hover {
|
|||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cart-summary-saving {
|
||||||
|
border: 1px solid rgba(23, 61, 44, 0.16);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 12px;
|
||||||
|
color: var(--brand-green);
|
||||||
|
background: #eef6e9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-summary-saving dt {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 900;
|
||||||
|
color: var(--brand-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-summary-saving dd {
|
||||||
|
font-size: 26px;
|
||||||
|
line-height: 1;
|
||||||
|
color: var(--brand-red);
|
||||||
|
}
|
||||||
|
|
||||||
.cart-summary p {
|
.cart-summary p {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
@@ -2381,6 +2468,7 @@ body[data-payment-mode="cash"] .price-tier-popover:hover {
|
|||||||
|
|
||||||
.mega-submenu {
|
.mega-submenu {
|
||||||
width: min(320px, calc(100vw - 32px));
|
width: min(320px, calc(100vw - 32px));
|
||||||
|
columns: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mega-submenu.depth-2,
|
.mega-submenu.depth-2,
|
||||||
@@ -2389,6 +2477,7 @@ body[data-payment-mode="cash"] .price-tier-popover:hover {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: none;
|
max-height: none;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
|
columns: 1;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-2
@@ -287,19 +287,24 @@ try {
|
|||||||
|
|
||||||
const updateCardPrices = (card) => {
|
const updateCardPrices = (card) => {
|
||||||
const packageNode = card.querySelector('[data-dynamic-package-price]');
|
const packageNode = card.querySelector('[data-dynamic-package-price]');
|
||||||
|
const unitNode = card.querySelector('[data-dynamic-unit-price]');
|
||||||
updateDynamicPrices(card);
|
updateDynamicPrices(card);
|
||||||
|
|
||||||
if (packageNode) {
|
if (unitNode || packageNode) {
|
||||||
const base = Number(packageNode.dataset.basePackagePrice || 0);
|
const unitBase = Number(unitNode?.dataset.baseUnitPrice || 0);
|
||||||
|
const packageBase = Number(packageNode?.dataset.basePackagePrice || 0);
|
||||||
|
const base = unitBase > 0 ? unitBase : packageBase;
|
||||||
|
|
||||||
const tiers = tierValues(base);
|
const tiers = tierValues(base);
|
||||||
const tierBase = card.querySelector('[data-tier-base]');
|
const tierBase = card.querySelector('[data-tier-base]');
|
||||||
const tierCash20 = card.querySelector('[data-tier-cash-20]');
|
const tierCash20 = card.querySelector('[data-tier-cash-20]');
|
||||||
const tierCash50 = card.querySelector('[data-tier-cash-50]');
|
const tierCash50 = card.querySelector('[data-tier-cash-50]');
|
||||||
|
const tierUnitLabel = card.querySelector('[data-tier-unit-label]');
|
||||||
|
|
||||||
if (tierBase) tierBase.textContent = formatRub(tiers.base);
|
if (tierBase) tierBase.textContent = formatRub(tiers.base);
|
||||||
if (tierCash20) tierCash20.textContent = formatRub(tiers.cash20);
|
if (tierCash20) tierCash20.textContent = formatRub(tiers.cash20);
|
||||||
if (tierCash50) tierCash50.textContent = formatRub(tiers.cash50);
|
if (tierCash50) tierCash50.textContent = formatRub(tiers.cash50);
|
||||||
|
if (tierUnitLabel) tierUnitLabel.textContent = card.querySelector('[data-unit-label]')?.textContent || 'шт.';
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -327,9 +332,12 @@ try {
|
|||||||
const baseTotalNode = cartPage.querySelector('[data-cart-base-total]');
|
const baseTotalNode = cartPage.querySelector('[data-cart-base-total]');
|
||||||
const totalNode = cartPage.querySelector('[data-cart-current-total]');
|
const totalNode = cartPage.querySelector('[data-cart-current-total]');
|
||||||
const modeNode = cartPage.querySelector('[data-cart-current-mode]');
|
const modeNode = cartPage.querySelector('[data-cart-current-mode]');
|
||||||
|
const savingRow = cartPage.querySelector('[data-cart-saving-row]');
|
||||||
|
const savingNode = cartPage.querySelector('[data-cart-saving-total]');
|
||||||
const items = getCartItems();
|
const items = getCartItems();
|
||||||
const baseTotal = cartBaseTotal(items);
|
const baseTotal = cartBaseTotal(items);
|
||||||
const currentTotal = Math.floor(baseTotal * priceMode().multiplier);
|
const currentTotal = Math.floor(baseTotal * priceMode().multiplier);
|
||||||
|
const savingTotal = Math.max(0, baseTotal - currentTotal);
|
||||||
|
|
||||||
if (emptyNode) {
|
if (emptyNode) {
|
||||||
emptyNode.hidden = items.length !== 0;
|
emptyNode.hidden = items.length !== 0;
|
||||||
@@ -371,6 +379,14 @@ try {
|
|||||||
if (modeNode) {
|
if (modeNode) {
|
||||||
modeNode.textContent = priceMode().label;
|
modeNode.textContent = priceMode().label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (savingRow) {
|
||||||
|
savingRow.hidden = savingTotal <= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (savingNode) {
|
||||||
|
savingNode.textContent = formatRub(savingTotal);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateModeButtons = () => {
|
const updateModeButtons = () => {
|
||||||
@@ -497,8 +513,10 @@ try {
|
|||||||
|
|
||||||
saveCartItems(items);
|
saveCartItems(items);
|
||||||
updateAllPrices();
|
updateAllPrices();
|
||||||
|
addButton.classList.add('is-added');
|
||||||
addButton.textContent = 'Добавлено';
|
addButton.textContent = 'Добавлено';
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
|
addButton.classList.remove('is-added');
|
||||||
addButton.textContent = 'В корзину';
|
addButton.textContent = 'В корзину';
|
||||||
}, 1200);
|
}, 1200);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -31,6 +31,10 @@
|
|||||||
<dt>Текущий режим</dt>
|
<dt>Текущий режим</dt>
|
||||||
<dd data-cart-current-mode>Наличные</dd>
|
<dd data-cart-current-mode>Наличные</dd>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="cart-summary-saving" data-cart-saving-row hidden>
|
||||||
|
<dt>Ваша выгода</dt>
|
||||||
|
<dd data-cart-saving-total>0 руб.</dd>
|
||||||
|
</div>
|
||||||
<div class="cart-summary-total">
|
<div class="cart-summary-total">
|
||||||
<dt>Сумма к расчету</dt>
|
<dt>Сумма к расчету</dt>
|
||||||
<dd data-cart-current-total>0 руб.</dd>
|
<dd data-cart-current-total>0 руб.</dd>
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ $activeOldUnitPrice = ($activeOldPackagePrice !== null && $activePackageQuantity
|
|||||||
if ($activeOldUnitPrice !== null && $activeOldUnitPrice <= $activeUnitPrice) {
|
if ($activeOldUnitPrice !== null && $activeOldUnitPrice <= $activeUnitPrice) {
|
||||||
$activeOldUnitPrice = null;
|
$activeOldUnitPrice = null;
|
||||||
}
|
}
|
||||||
|
$activeTierBase = $activeUnitPrice ?? $activePackagePrice;
|
||||||
|
$activeTierUnit = unit_label((string) ($activeVariant['unit'] ?? '')) ?: 'шт.';
|
||||||
?>
|
?>
|
||||||
<article
|
<article
|
||||||
class="product-card price-aware"
|
class="product-card price-aware"
|
||||||
@@ -97,9 +99,12 @@ if ($activeOldUnitPrice !== null && $activeOldUnitPrice <= $activeUnitPrice) {
|
|||||||
|
|
||||||
<?php if ($activeVariant['price_per_unit'] !== null): ?>
|
<?php if ($activeVariant['price_per_unit'] !== null): ?>
|
||||||
<span class="price-line">
|
<span class="price-line">
|
||||||
Цена за <span data-unit-label><?= e(unit_label((string) $activeVariant['unit'])) ?></span>:
|
<span class="price-unit-label">Цена за <span data-unit-label><?= e(unit_label((string) $activeVariant['unit'])) ?></span>:</span>
|
||||||
<span class="old-price" data-old-unit-price-display<?= $activeOldUnitPrice === null ? ' hidden' : '' ?>><?= e(money_label($activeOldUnitPrice)) ?></span>
|
<span class="price-unit-values">
|
||||||
<b data-price-unit data-dynamic-unit-price data-base-unit-price="<?= e((string) $activeUnitPrice) ?>"><?= e(money_label($activeVariant['price_per_unit'])) ?></b>
|
<span class="old-price" data-old-unit-price-display<?= $activeOldUnitPrice === null ? ' hidden' : '' ?>><?= e(money_label($activeOldUnitPrice)) ?></span>
|
||||||
|
<b data-price-unit data-dynamic-unit-price data-base-unit-price="<?= e((string) $activeUnitPrice) ?>"><?= e(money_label($activeVariant['price_per_unit'])) ?></b>
|
||||||
|
</span>
|
||||||
|
<button class="price-tier-trigger" type="button" aria-label="Показать градацию цены">?</button>
|
||||||
</span>
|
</span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
@@ -110,7 +115,6 @@ if ($activeOldUnitPrice !== null && $activeOldUnitPrice <= $activeUnitPrice) {
|
|||||||
<span class="old-price" data-old-package-price-display<?= $activeOldPackagePrice === null ? ' hidden' : '' ?>><?= e(money_label($activeOldPackagePrice)) ?></span>
|
<span class="old-price" data-old-package-price-display<?= $activeOldPackagePrice === null ? ' hidden' : '' ?>><?= e(money_label($activeOldPackagePrice)) ?></span>
|
||||||
<span data-package-price data-dynamic-package-price data-base-package-price="<?= e((string) $activePackagePrice) ?>"><?= e(money_label($activeVariant['package_price'])) ?></span>
|
<span data-package-price data-dynamic-package-price data-base-package-price="<?= e((string) $activePackagePrice) ?>"><?= e(money_label($activeVariant['package_price'])) ?></span>
|
||||||
</span>
|
</span>
|
||||||
<button class="price-tier-trigger" type="button" aria-label="Показать градацию цены">?</button>
|
|
||||||
</strong>
|
</strong>
|
||||||
<?php if ($activeVariant['price_per_unit'] !== null): ?>
|
<?php if ($activeVariant['price_per_unit'] !== null): ?>
|
||||||
<span class="package-price-note">Цена за <span data-unit-label-note><?= e(unit_label((string) $activeVariant['unit'])) ?></span> × <span data-package-label-note><?= e((string) $activeVariant['name']) ?></span></span>
|
<span class="package-price-note">Цена за <span data-unit-label-note><?= e(unit_label((string) $activeVariant['unit'])) ?></span> × <span data-package-label-note><?= e((string) $activeVariant['name']) ?></span></span>
|
||||||
@@ -118,11 +122,11 @@ if ($activeOldUnitPrice !== null && $activeOldUnitPrice <= $activeUnitPrice) {
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<div class="price-tier-popover" role="tooltip">
|
<div class="price-tier-popover" role="tooltip">
|
||||||
<strong>Варианты цены за наличный расчет:</strong>
|
<strong>Варианты цены за <span data-tier-unit-label><?= e($activeTierUnit) ?></span> при наличном расчете:</strong>
|
||||||
<dl>
|
<dl>
|
||||||
<div><dt>Базовая цена</dt><dd data-tier-base><?= e(money_label($activePackagePrice)) ?></dd></div>
|
<div><dt>Базовая цена</dt><dd data-tier-base><?= e(money_label($activeTierBase)) ?></dd></div>
|
||||||
<div><dt>При заказе от 20 000р.</dt><dd data-tier-cash-20><?= e(money_label(floor($activePackagePrice * 0.95))) ?></dd></div>
|
<div><dt>При заказе от 20 000р.</dt><dd data-tier-cash-20><?= e(money_label(floor($activeTierBase * 0.95))) ?></dd></div>
|
||||||
<div><dt>При заказе от 50 000р.</dt><dd data-tier-cash-50><?= e(money_label(floor($activePackagePrice * 0.93))) ?></dd></div>
|
<div><dt>При заказе от 50 000р.</dt><dd data-tier-cash-50><?= e(money_label(floor($activeTierBase * 0.93))) ?></dd></div>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user