Merge pull request 'fix1207' (#24) from 1207 into main
Reviewed-on: #24
This commit is contained in:
BIN
public/images/resource2.png
Normal file
BIN
public/images/resource2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
@ -227,33 +227,54 @@ const BottomHead = ({ menuOpen, onClose }: { menuOpen: boolean; onClose: () => v
|
||||
<span>{mobileCategory.label}</span>
|
||||
</div>
|
||||
<div className="mobile-subcategories">
|
||||
{mobileCategory.links.map((link: string, linkIndex: number) => (
|
||||
{mobileCategory.links.length === 1 ? (
|
||||
<div
|
||||
className="mobile-subcategory"
|
||||
onClick={() => {
|
||||
let subcategoryId = `${mobileCategory.catalogId}_0`;
|
||||
if (mobileCategory.groups) {
|
||||
for (const group of mobileCategory.groups) {
|
||||
if (group.subgroups && group.subgroups.length > 0) {
|
||||
const foundSubgroup = group.subgroups.find((subgroup: any) => subgroup.name === mobileCategory.links[0]);
|
||||
if (foundSubgroup) {
|
||||
subcategoryId = foundSubgroup.id;
|
||||
break;
|
||||
}
|
||||
} else if (group.name === mobileCategory.links[0]) {
|
||||
subcategoryId = group.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
const activeCatalog = catalogsData?.partsIndexCategoriesWithGroups?.[tabData.findIndex(tab => tab === mobileCategory)];
|
||||
const catalogId = activeCatalog?.id || 'fallback';
|
||||
handleCategoryClick(catalogId, mobileCategory.links[0], subcategoryId);
|
||||
}}
|
||||
style={{ cursor: "pointer" }}
|
||||
>
|
||||
Показать все
|
||||
</div>
|
||||
) : (
|
||||
mobileCategory.links.map((link: string, linkIndex: number) => (
|
||||
<div
|
||||
className="mobile-subcategory"
|
||||
key={link}
|
||||
onClick={() => {
|
||||
// Ищем соответствующую подгруппу по названию
|
||||
let subcategoryId = `${mobileCategory.catalogId}_${linkIndex}`;
|
||||
|
||||
if (mobileCategory.groups) {
|
||||
for (const group of mobileCategory.groups) {
|
||||
// Проверяем в подгруппах
|
||||
if (group.subgroups && group.subgroups.length > 0) {
|
||||
const foundSubgroup = group.subgroups.find((subgroup: any) => subgroup.name === link);
|
||||
if (foundSubgroup) {
|
||||
subcategoryId = foundSubgroup.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Если нет подгрупп, проверяем саму группу
|
||||
else if (group.name === link) {
|
||||
} else if (group.name === link) {
|
||||
subcategoryId = group.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Получаем catalogId из данных
|
||||
const activeCatalog = catalogsData?.partsIndexCategoriesWithGroups?.[tabData.findIndex(tab => tab === mobileCategory)];
|
||||
const catalogId = activeCatalog?.id || 'fallback';
|
||||
handleCategoryClick(catalogId, link, subcategoryId);
|
||||
@ -261,7 +282,8 @@ const BottomHead = ({ menuOpen, onClose }: { menuOpen: boolean; onClose: () => v
|
||||
>
|
||||
{link}
|
||||
</div>
|
||||
))}
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
@ -443,30 +465,51 @@ const BottomHead = ({ menuOpen, onClose }: { menuOpen: boolean; onClose: () => v
|
||||
<h3 className="heading-16">{tab.heading}</h3>
|
||||
<div className="w-layout-hflex flex-block-92">
|
||||
<div className="w-layout-vflex flex-block-91">
|
||||
{tab.links.map((link, linkIndex) => {
|
||||
{tab.links.length === 1 ? (
|
||||
<div
|
||||
className="link-2"
|
||||
onClick={() => {
|
||||
const catalog = catalogsData?.partsIndexCategoriesWithGroups?.[idx];
|
||||
|
||||
// Ищем соответствующую подгруппу по названию
|
||||
let subcategoryId = `fallback_${idx}_${linkIndex}`;
|
||||
|
||||
let subcategoryId = `fallback_${idx}_0`;
|
||||
if (catalog?.groups) {
|
||||
for (const group of catalog.groups) {
|
||||
if (group.subgroups && group.subgroups.length > 0) {
|
||||
const foundSubgroup = group.subgroups.find((subgroup: any) => subgroup.name === tab.links[0]);
|
||||
if (foundSubgroup) {
|
||||
subcategoryId = foundSubgroup.id;
|
||||
break;
|
||||
}
|
||||
} else if (group.name === tab.links[0]) {
|
||||
subcategoryId = group.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
const catalogId = catalog?.id || 'fallback';
|
||||
handleCategoryClick(catalogId, tab.links[0], subcategoryId);
|
||||
}}
|
||||
style={{ cursor: "pointer" }}
|
||||
>
|
||||
Показать все
|
||||
</div>
|
||||
) : (
|
||||
tab.links.map((link: string, linkIndex: number) => {
|
||||
const catalog = catalogsData?.partsIndexCategoriesWithGroups?.[idx];
|
||||
let subcategoryId = `fallback_${idx}_${linkIndex}`;
|
||||
if (catalog?.groups) {
|
||||
for (const group of catalog.groups) {
|
||||
// Проверяем в подгруппах
|
||||
if (group.subgroups && group.subgroups.length > 0) {
|
||||
const foundSubgroup = group.subgroups.find((subgroup: any) => subgroup.name === link);
|
||||
if (foundSubgroup) {
|
||||
subcategoryId = foundSubgroup.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Если нет подгрупп, проверяем саму группу
|
||||
else if (group.name === link) {
|
||||
} else if (group.name === link) {
|
||||
subcategoryId = group.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="link-2"
|
||||
@ -480,7 +523,8 @@ const BottomHead = ({ menuOpen, onClose }: { menuOpen: boolean; onClose: () => v
|
||||
{link}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
})
|
||||
)}
|
||||
</div>
|
||||
<div className="w-layout-vflex flex-block-91-copy">
|
||||
<img src="https://d3e54v103j8qbb.cloudfront.net/plugins/Basic/assets/placeholder.60f9b1840c.svg" loading="lazy" alt="" className="image-17" />
|
||||
|
@ -1,10 +1,16 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
const CatalogSubscribe: React.FC = () => (
|
||||
<div className="w-layout-blockcontainer container subscribe w-container">
|
||||
<div className="w-layout-hflex flex-block-18">
|
||||
<img
|
||||
src="/images/resource2.png"
|
||||
alt="Ресурс 2"
|
||||
className="mt-[-18px]"
|
||||
/>
|
||||
<div className="div-block-9">
|
||||
<h3 className="heading-3 sub">Подпишитесь на новостную рассылку</h3>
|
||||
{/* <h3 className="heading-3 sub">Подпишитесь на новостную рассылку</h3> */}
|
||||
|
||||
<div className="text-block-14">Оставайтесь в курсе акций, <br />новинок и специальных предложений</div>
|
||||
</div>
|
||||
<div className="form-block-3 w-form">
|
||||
@ -13,6 +19,38 @@ const CatalogSubscribe: React.FC = () => (
|
||||
<input type="submit" className="submit-button-copy w-button" value="Подписаться" />
|
||||
</form>
|
||||
</div>
|
||||
<div className="flex flex-row items-center mt-2">
|
||||
{/* Кастомный чекбокс без input/label */}
|
||||
{(() => {
|
||||
const [checked, setChecked] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={`h-[24px] w-[24px] border border-[#8893A1] rounded-sm mr-4 flex-shrink-0 flex items-center justify-center cursor-pointer transition-colors duration-150 ${checked ? 'bg-[#EC1C24]' : 'bg-transparent'}`}
|
||||
onClick={() => setChecked(v => !v)}
|
||||
role="checkbox"
|
||||
aria-checked={checked}
|
||||
tabIndex={0}
|
||||
onKeyDown={e => { if (e.key === ' ' || e.key === 'Enter') setChecked(v => !v); }}
|
||||
>
|
||||
<svg
|
||||
className={`w-5 h-5 text-white transition-opacity duration-150 ${checked ? 'opacity-100' : 'opacity-0'}`}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M5 13l4 4L19 7" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
</div>
|
||||
<span className="text-[#8893A1] text-[12px] leading-snug select-none">
|
||||
Я даю свое согласие на обработку персональных данных<br />
|
||||
и соглашаюсь с условиями <a href="/privacy-policy" className="underline hover:text-[#6c7684]">Политики конфиденциальности</a>
|
||||
</span>
|
||||
</>
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -385,7 +385,7 @@ const Header: React.FC<HeaderProps> = ({ onOpenAuthModal = () => console.log('Au
|
||||
<section className="bottom_head">
|
||||
<div className="w-layout-blockcontainer container nav w-container">
|
||||
<div className="w-layout-hflex flex-block-93">
|
||||
<Link href="/" className="code-embed-15 w-embed" style={{ display: 'block', cursor: 'pointer' }}>
|
||||
<Link href="/" className="code-embed-15 w-embed protekauto-logo" style={{ display: 'block', cursor: 'pointer'}}>
|
||||
<svg width="190" height="72" viewBox="0 0 190 72" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M138.377 29.5883V23.1172H112.878V29.5883H138.377Z" fill="white"></path>
|
||||
<path d="M107.423 18.1195C109.21 18.1195 110.658 16.6709 110.658 14.884C110.658 13.097 109.21 11.6484 107.423 11.6484L88.395 11.6484C86.6082 11.6484 85.1596 13.097 85.1596 14.884C85.1596 16.6709 86.6082 18.1195 88.395 18.1195H107.423Z" fill="white"></path>
|
||||
|
@ -147,7 +147,7 @@ const BrandSelectionSection: React.FC = () => {
|
||||
</svg>
|
||||
</Combobox.Button>
|
||||
<Combobox.Options
|
||||
className="absolute left-0 top-full z-10 bg-white border-x border-b border-stone-300 rounded-b-lg shadow-lg w-full max-h-60 overflow-auto scrollbar-none"
|
||||
className="absolute left-0 top-full z-100 bg-white border-x border-b border-stone-300 rounded-b-lg shadow-lg w-full max-h-60 overflow-auto scrollbar-none"
|
||||
style={{ scrollbarWidth: 'none' }}
|
||||
data-hide-scrollbar
|
||||
>
|
||||
|
@ -247,63 +247,65 @@ const ProfileGarageMain = () => {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Расширенная информация об автомобиле */}
|
||||
{expandedVehicle === vehicle.id && (
|
||||
<div className="mt-4 px-5 py-4 bg-white rounded-lg border border-gray-200">
|
||||
{/* Расширенная информация об автомобиле — вложена внутрь карточки */}
|
||||
<div
|
||||
className={
|
||||
`overflow-hidden transition-all duration-300 rounded-lg flex flex-col gap-4` +
|
||||
(expandedVehicle === vehicle.id ? ' py-4 max-h-[1000px] opacity-100 mt-4' : ' max-h-0 opacity-0 pointer-events-none')
|
||||
}
|
||||
>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 text-sm">
|
||||
{vehicle.brand && (
|
||||
<div>
|
||||
<span className="font-medium text-gray-700">Бренд:</span>
|
||||
<span className="ml-2 text-gray-900">{vehicle.brand}</span>
|
||||
<div className="font-bold text-gray-950">Бренд</div>
|
||||
<div className="mt-1.5 text-gray-600">{vehicle.brand}</div>
|
||||
</div>
|
||||
)}
|
||||
{vehicle.model && (
|
||||
<div>
|
||||
<span className="font-medium text-gray-700">Модель:</span>
|
||||
<span className="ml-2 text-gray-900">{vehicle.model}</span>
|
||||
<div className="font-bold text-gray-950">Модель</div>
|
||||
<div className="mt-1.5 text-gray-600">{vehicle.model}</div>
|
||||
</div>
|
||||
)}
|
||||
{vehicle.modification && (
|
||||
<div>
|
||||
<span className="font-medium text-gray-700">Модификация:</span>
|
||||
<span className="ml-2 text-gray-900">{vehicle.modification}</span>
|
||||
<div className="font-bold text-gray-950">Модификация</div>
|
||||
<div className="mt-1.5 text-gray-600">{vehicle.modification}</div>
|
||||
</div>
|
||||
)}
|
||||
{vehicle.year && (
|
||||
<div>
|
||||
<span className="font-medium text-gray-700">Год:</span>
|
||||
<span className="ml-2 text-gray-900">{vehicle.year}</span>
|
||||
<div className="font-bold text-gray-950">Год</div>
|
||||
<div className="mt-1.5 text-gray-600">{vehicle.year}</div>
|
||||
</div>
|
||||
)}
|
||||
{vehicle.frame && (
|
||||
<div>
|
||||
<span className="font-medium text-gray-700">Номер кузова:</span>
|
||||
<span className="ml-2 text-gray-900">{vehicle.frame}</span>
|
||||
<div className="font-bold text-gray-950">Номер кузова</div>
|
||||
<div className="mt-1.5 text-gray-600">{vehicle.frame}</div>
|
||||
</div>
|
||||
)}
|
||||
{vehicle.licensePlate && (
|
||||
<div>
|
||||
<span className="font-medium text-gray-700">Госномер:</span>
|
||||
<span className="ml-2 text-gray-900">{vehicle.licensePlate}</span>
|
||||
<div className="font-bold text-gray-950">Госномер</div>
|
||||
<div className="mt-1.5 text-gray-600">{vehicle.licensePlate}</div>
|
||||
</div>
|
||||
)}
|
||||
{vehicle.mileage && (
|
||||
<div>
|
||||
<span className="font-medium text-gray-700">Пробег:</span>
|
||||
<span className="ml-2 text-gray-900">{vehicle.mileage.toLocaleString()} км</span>
|
||||
<div className="font-bold text-gray-950">Пробег</div>
|
||||
<div className="mt-1.5 text-gray-600">{vehicle.mileage.toLocaleString()} км</div>
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<span className="font-medium text-gray-700">Добавлен:</span>
|
||||
<span className="ml-2 text-gray-900">
|
||||
<div className="font-bold text-gray-950">Добавлен</div>
|
||||
<div className="mt-1.5 text-gray-600">
|
||||
{new Date(vehicle.createdAt).toLocaleDateString('ru-RU')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
{!showAddCar && (
|
||||
|
@ -45,6 +45,8 @@ const VinQuick: React.FC<VinQuickProps> = ({ quickGroup, catalogCode, vehicleId,
|
||||
}
|
||||
};
|
||||
|
||||
const [shownCounts, setShownCounts] = useState<{ [unitid: string]: number }>({});
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
{/* <button onClick={onBack} className="mb-4 px-4 py-2 bg-gray-200 rounded self-start">Назад</button> */}
|
||||
@ -71,16 +73,48 @@ const VinQuick: React.FC<VinQuickProps> = ({ quickGroup, catalogCode, vehicleId,
|
||||
</div>
|
||||
<div className="knot-img">
|
||||
<h1 className="heading-19">{unit.name}</h1>
|
||||
|
||||
{unit.details && unit.details.length > 0 && unit.details.map((detail: any, index: number) => (
|
||||
{(() => {
|
||||
const details = unit.details || [];
|
||||
const total = details.length;
|
||||
const shownCount = shownCounts[unit.unitid] ?? 3;
|
||||
return (
|
||||
<>
|
||||
{details.slice(0, shownCount).map((detail: any, index: number) => (
|
||||
<div className="w-layout-hflex flex-block-115" key={`${unit.unitid}-${detail.detailid || index}`}>
|
||||
<div className="oemnuber">{detail.oem}</div>
|
||||
<div className="partsname">{detail.name}</div>
|
||||
<a href="#" className="button-3 w-button" onClick={e => { e.preventDefault(); handleDetailClick(detail); }}>Показать цены</a>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{total > 3 && shownCount < total && (
|
||||
<div className="flex gap-2 mt-2 w-full">
|
||||
{shownCount + 3 < total && (
|
||||
<button
|
||||
className="expand-btn"
|
||||
onClick={() => setShownCounts(prev => ({ ...prev, [unit.unitid]: shownCount + 3 }))}
|
||||
style={{ border: '1px solid #EC1C24', borderRadius: 8, background: '#fff', color: '#222', padding: '6px 18px', minWidth: 180 }}
|
||||
>
|
||||
Развернуть
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" style={{ display: 'inline', verticalAlign: 'middle', marginLeft: 4 }}>
|
||||
<path d="M4 6l4 4 4-4" stroke="#222" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
className="showall-btn"
|
||||
onClick={() => setShownCounts(prev => ({ ...prev, [unit.unitid]: total }))}
|
||||
style={{ background: '#e9eef5', borderRadius: 8, color: '#222', padding: '6px 18px', border: 'none'}}
|
||||
>
|
||||
Показать все
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{shownCount >= total && (
|
||||
<a href="#" className="showallparts w-button" onClick={e => { e.preventDefault(); handleUnitClick(unit); }}>Подробнее</a>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
|
@ -30,7 +30,7 @@
|
||||
}
|
||||
|
||||
.bottom_head{
|
||||
z-index: 60;
|
||||
z-index: 3000;
|
||||
}
|
||||
|
||||
.top_head{
|
||||
@ -618,12 +618,48 @@ body {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.form-block-4,
|
||||
.flex-block-124,
|
||||
.flex-block-6-copy
|
||||
{
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
a.link-block.w-inline-block,
|
||||
a.link-block-2.w-inline-block {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.core-product-search.carousel-scroll {
|
||||
display: flex;
|
||||
flex-wrap: nowrap; /* Не переносить строки */
|
||||
gap: 16px; /* Отступ между карточками, если нужно */
|
||||
}
|
||||
|
||||
.subscribe{
|
||||
padding-top: 10px !important;
|
||||
padding-bottom: 10px !important;
|
||||
|
||||
}
|
||||
|
||||
.text-block-14, .div-block-9{
|
||||
width: 350px !important;
|
||||
max-width: 350px !important;
|
||||
min-width: 350px !important;
|
||||
}
|
||||
@media screen and (max-width: 1920px) {
|
||||
.text-block-14, .div-block-9{
|
||||
width: 350px !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.flex-block-18{
|
||||
row-gap: 40px !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.menu-button.w--open {
|
||||
z-index: 2000;
|
||||
@ -631,10 +667,9 @@ a.link-block-2.w-inline-block {
|
||||
color: var(--white);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 50px;
|
||||
padding-top: 15px;
|
||||
padding-bottom: 15px;
|
||||
left: auto;
|
||||
width: 50px;
|
||||
height: 44px;
|
||||
padding: 13px 12px;
|
||||
}
|
||||
.heading-7 {
|
||||
z-index: 999;
|
||||
@ -671,15 +706,25 @@ a.link-block-2.w-inline-block {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.flex-block-14-copy-copy{
|
||||
|
||||
margin-bottom: 20px !important;
|
||||
}
|
||||
|
||||
.showall-btn {
|
||||
width: 100%;
|
||||
}
|
||||
.showall-btn:hover {
|
||||
background: #ec1c24 !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 991px) {
|
||||
.flex-block-108, .flex-block-14-copy-copy {
|
||||
flex-flow: column;
|
||||
justify-content: space-between;
|
||||
|
||||
}
|
||||
.flex-block-14-copy-copy{
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
}
|
||||
@media screen and (max-width: 991px) {
|
||||
@ -994,3 +1039,7 @@ a.link-block-2.w-inline-block {
|
||||
}
|
||||
}
|
||||
|
||||
.protekauto-logo {
|
||||
position: fixed;
|
||||
z-index: 3000;
|
||||
}
|
@ -1008,10 +1008,9 @@ body {
|
||||
color: var(--white);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 50px;
|
||||
padding-top: 15px;
|
||||
padding-bottom: 15px;
|
||||
left: auto;
|
||||
width: 50px;
|
||||
height: 44px;
|
||||
padding: 13px 12px;
|
||||
}
|
||||
|
||||
.menu-button.w--open:hover {
|
||||
|
Reference in New Issue
Block a user