Compare commits
8 Commits
numbers
...
8cae029d7f
Author | SHA1 | Date | |
---|---|---|---|
8cae029d7f | |||
cbf50691c4 | |||
4a3da4d5c5 | |||
215853e8c7 | |||
f894b7e023 | |||
a879e5e5e7 | |||
85f7634158 | |||
5e454a7367 |
@ -16,6 +16,8 @@ interface CartItemProps {
|
|||||||
onComment: (comment: string) => void;
|
onComment: (comment: string) => void;
|
||||||
onCountChange?: (count: number) => void;
|
onCountChange?: (count: number) => void;
|
||||||
onRemove?: () => void;
|
onRemove?: () => void;
|
||||||
|
isSummaryStep?: boolean;
|
||||||
|
itemNumber?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CartItem: React.FC<CartItemProps> = ({
|
const CartItem: React.FC<CartItemProps> = ({
|
||||||
@ -34,9 +36,14 @@ const CartItem: React.FC<CartItemProps> = ({
|
|||||||
onComment,
|
onComment,
|
||||||
onCountChange,
|
onCountChange,
|
||||||
onRemove,
|
onRemove,
|
||||||
|
isSummaryStep = false,
|
||||||
|
itemNumber,
|
||||||
}) => (
|
}) => (
|
||||||
<div className="w-layout-hflex cart-item">
|
<div className="w-layout-hflex cart-item">
|
||||||
<div className="w-layout-hflex info-block-search-copy">
|
<div className="w-layout-hflex info-block-search-copy">
|
||||||
|
{isSummaryStep ? (
|
||||||
|
<div style={{ marginRight: 12, minWidth: 24, textAlign: 'center', fontWeight: 600, fontSize: 14 }}>{itemNumber}</div>
|
||||||
|
) : (
|
||||||
<div
|
<div
|
||||||
className={"div-block-7" + (selected ? " active" : "")}
|
className={"div-block-7" + (selected ? " active" : "")}
|
||||||
onClick={onSelect}
|
onClick={onSelect}
|
||||||
@ -48,9 +55,22 @@ const CartItem: React.FC<CartItemProps> = ({
|
|||||||
</svg>
|
</svg>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
<div className="w-layout-hflex block-name">
|
<div className="w-layout-hflex block-name">
|
||||||
<h4 className="heading-9-copy">{name}</h4>
|
<h4 className="heading-9-copy">{name}</h4>
|
||||||
<div className="text-block-21-copy">{description}</div>
|
<div
|
||||||
|
className={
|
||||||
|
"text-block-21-copy" +
|
||||||
|
(isSummaryStep && itemNumber === 1 ? " border-t-0" : "")
|
||||||
|
}
|
||||||
|
style={
|
||||||
|
isSummaryStep && itemNumber === 1
|
||||||
|
? { borderTop: 'none' }
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{description}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-block-copy w-form">
|
<div className="form-block-copy w-form">
|
||||||
<form className="form-copy" onSubmit={e => e.preventDefault()}>
|
<form className="form-copy" onSubmit={e => e.preventDefault()}>
|
||||||
@ -64,6 +84,7 @@ const CartItem: React.FC<CartItemProps> = ({
|
|||||||
id="Search-5"
|
id="Search-5"
|
||||||
value={comment}
|
value={comment}
|
||||||
onChange={e => onComment(e.target.value)}
|
onChange={e => onComment(e.target.value)}
|
||||||
|
disabled={isSummaryStep}
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
<div className="success-message w-form-done">
|
<div className="success-message w-form-done">
|
||||||
@ -80,6 +101,10 @@ const CartItem: React.FC<CartItemProps> = ({
|
|||||||
<div className="text-block-21-copy-copy">{deliveryDate}</div>
|
<div className="text-block-21-copy-copy">{deliveryDate}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-layout-hflex pcs-cart-s1">
|
<div className="w-layout-hflex pcs-cart-s1">
|
||||||
|
{isSummaryStep ? (
|
||||||
|
<div className="text-block-26" style={{ fontWeight: 600, fontSize: 14 }}>{count} шт.</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<div
|
<div
|
||||||
className="minus-plus"
|
className="minus-plus"
|
||||||
onClick={() => onCountChange && onCountChange(count - 1)}
|
onClick={() => onCountChange && onCountChange(count - 1)}
|
||||||
@ -124,11 +149,14 @@ const CartItem: React.FC<CartItemProps> = ({
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-layout-hflex flex-block-39-copy-copy">
|
<div className="w-layout-hflex flex-block-39-copy-copy">
|
||||||
<h4 className="price-in-cart-s1">{price}</h4>
|
<h4 className="price-in-cart-s1">{price}</h4>
|
||||||
<div className="price-1-pcs-cart-s1">{pricePerItem}</div>
|
<div className="price-1-pcs-cart-s1">{pricePerItem}</div>
|
||||||
</div>
|
</div>
|
||||||
|
{!isSummaryStep && (
|
||||||
<div className="w-layout-hflex control-element">
|
<div className="w-layout-hflex control-element">
|
||||||
<div className="favorite-icon w-embed" onClick={onFavorite} style={{ cursor: 'pointer', color: favorite ? '#e53935' : undefined }}>
|
<div className="favorite-icon w-embed" onClick={onFavorite} style={{ cursor: 'pointer', color: favorite ? '#e53935' : undefined }}>
|
||||||
<svg width="18" height="19" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="18" height="19" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
@ -161,6 +189,7 @@ const CartItem: React.FC<CartItemProps> = ({
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -3,7 +3,11 @@ import CartItem from "./CartItem";
|
|||||||
import { useCart } from "@/contexts/CartContext";
|
import { useCart } from "@/contexts/CartContext";
|
||||||
import { useFavorites } from "@/contexts/FavoritesContext";
|
import { useFavorites } from "@/contexts/FavoritesContext";
|
||||||
|
|
||||||
const CartList: React.FC = () => {
|
interface CartListProps {
|
||||||
|
isSummaryStep?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CartList: React.FC<CartListProps> = ({ isSummaryStep = false }) => {
|
||||||
const { state, toggleSelect, updateComment, removeItem, selectAll, removeSelected, updateQuantity } = useCart();
|
const { state, toggleSelect, updateComment, removeItem, selectAll, removeSelected, updateQuantity } = useCart();
|
||||||
const { addToFavorites, removeFromFavorites, isFavorite, favorites } = useFavorites();
|
const { addToFavorites, removeFromFavorites, isFavorite, favorites } = useFavorites();
|
||||||
const { items } = state;
|
const { items } = state;
|
||||||
@ -25,24 +29,18 @@ const CartList: React.FC = () => {
|
|||||||
const handleFavorite = (id: string) => {
|
const handleFavorite = (id: string) => {
|
||||||
const item = items.find(item => item.id === id);
|
const item = items.find(item => item.id === id);
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
|
|
||||||
const isInFavorites = isFavorite(item.productId, item.offerKey, item.article, item.brand);
|
const isInFavorites = isFavorite(item.productId, item.offerKey, item.article, item.brand);
|
||||||
|
|
||||||
if (isInFavorites) {
|
if (isInFavorites) {
|
||||||
// Находим товар в избранном по правильному ID
|
|
||||||
const favoriteItem = favorites.find((fav: any) => {
|
const favoriteItem = favorites.find((fav: any) => {
|
||||||
// Проверяем по разным комбинациям идентификаторов
|
|
||||||
if (item.productId && fav.productId === item.productId) return true;
|
if (item.productId && fav.productId === item.productId) return true;
|
||||||
if (item.offerKey && fav.offerKey === item.offerKey) return true;
|
if (item.offerKey && fav.offerKey === item.offerKey) return true;
|
||||||
if (fav.article === item.article && fav.brand === item.brand) return true;
|
if (fav.article === item.article && fav.brand === item.brand) return true;
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (favoriteItem) {
|
if (favoriteItem) {
|
||||||
removeFromFavorites(favoriteItem.id);
|
removeFromFavorites(favoriteItem.id);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Добавляем в избранное
|
|
||||||
addToFavorites({
|
addToFavorites({
|
||||||
productId: item.productId,
|
productId: item.productId,
|
||||||
offerKey: item.offerKey,
|
offerKey: item.offerKey,
|
||||||
@ -68,14 +66,17 @@ const CartList: React.FC = () => {
|
|||||||
updateQuantity(id, count);
|
updateQuantity(id, count);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Функция для форматирования цены
|
|
||||||
const formatPrice = (price: number, currency: string = 'RUB') => {
|
const formatPrice = (price: number, currency: string = 'RUB') => {
|
||||||
return `${price.toLocaleString('ru-RU')} ${currency === 'RUB' ? '₽' : currency}`;
|
return `${price.toLocaleString('ru-RU')} ${currency === 'RUB' ? '₽' : currency}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// На втором шаге показываем только выбранные товары
|
||||||
|
const displayItems = isSummaryStep ? items.filter(item => item.selected) : items;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-layout-vflex flex-block-48">
|
<div className="w-layout-vflex flex-block-48">
|
||||||
<div className="w-layout-vflex product-list-cart">
|
<div className="w-layout-vflex product-list-cart">
|
||||||
|
{!isSummaryStep && (
|
||||||
<div className="w-layout-hflex multi-control">
|
<div className="w-layout-hflex multi-control">
|
||||||
<div className="w-layout-hflex select-all-block" onClick={handleSelectAll} style={{ cursor: 'pointer' }}>
|
<div className="w-layout-hflex select-all-block" onClick={handleSelectAll} style={{ cursor: 'pointer' }}>
|
||||||
<div
|
<div
|
||||||
@ -110,17 +111,28 @@ const CartList: React.FC = () => {
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{items.length === 0 ? (
|
)}
|
||||||
|
{displayItems.length === 0 ? (
|
||||||
<div className="empty-cart-message" style={{ textAlign: 'center', padding: '2rem', color: '#666' }}>
|
<div className="empty-cart-message" style={{ textAlign: 'center', padding: '2rem', color: '#666' }}>
|
||||||
<p>Ваша корзина пуста</p>
|
<p>Ваша корзина пуста</p>
|
||||||
<p>Добавьте товары из каталога</p>
|
<p>Добавьте товары из каталога</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
items.map((item) => {
|
displayItems.map((item, idx) => {
|
||||||
const isInFavorites = isFavorite(item.productId, item.offerKey, item.article, item.brand);
|
const isInFavorites = isFavorite(item.productId, item.offerKey, item.article, item.brand);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="div-block-21" key={item.id}>
|
<div
|
||||||
|
className={
|
||||||
|
"div-block-21" +
|
||||||
|
(isSummaryStep && idx === 0 ? " border-t-0" : "")
|
||||||
|
}
|
||||||
|
style={
|
||||||
|
isSummaryStep && idx === 0
|
||||||
|
? { borderTop: 'none' }
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
key={item.id}
|
||||||
|
>
|
||||||
<CartItem
|
<CartItem
|
||||||
name={item.name}
|
name={item.name}
|
||||||
description={item.description}
|
description={item.description}
|
||||||
@ -137,6 +149,8 @@ const CartList: React.FC = () => {
|
|||||||
onComment={(comment) => handleComment(item.id, comment)}
|
onComment={(comment) => handleComment(item.id, comment)}
|
||||||
onCountChange={(count) => handleCountChange(item.id, count)}
|
onCountChange={(count) => handleCountChange(item.id, count)}
|
||||||
onRemove={() => handleRemove(item.id)}
|
onRemove={() => handleRemove(item.id)}
|
||||||
|
isSummaryStep={isSummaryStep}
|
||||||
|
itemNumber={idx + 1}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -26,8 +26,17 @@ const CartList2: React.FC = () => {
|
|||||||
<p>Вернитесь на предыдущий шаг и выберите товары</p>
|
<p>Вернитесь на предыдущий шаг и выберите товары</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
selectedItems.map((item) => (
|
selectedItems.map((item, index) => (
|
||||||
<div className="div-block-21-copy" key={item.id}>
|
<div
|
||||||
|
className={
|
||||||
|
"div-block-21-copy" +
|
||||||
|
(index === 0 ? " border-t-0" : "")
|
||||||
|
}
|
||||||
|
style={
|
||||||
|
index === 0 ? { borderTop: 'none' } : undefined
|
||||||
|
}
|
||||||
|
key={item.id}
|
||||||
|
>
|
||||||
<div className="w-layout-hflex cart-item-check">
|
<div className="w-layout-hflex cart-item-check">
|
||||||
<div className="w-layout-hflex info-block-search">
|
<div className="w-layout-hflex info-block-search">
|
||||||
<div className="text-block-35">{item.quantity}</div>
|
<div className="text-block-35">{item.quantity}</div>
|
||||||
|
@ -5,7 +5,12 @@ import { useMutation, useQuery } from "@apollo/client";
|
|||||||
import { CREATE_ORDER, CREATE_PAYMENT, GET_CLIENT_ME, GET_CLIENT_DELIVERY_ADDRESSES } from "@/lib/graphql";
|
import { CREATE_ORDER, CREATE_PAYMENT, GET_CLIENT_ME, GET_CLIENT_DELIVERY_ADDRESSES } from "@/lib/graphql";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
|
|
||||||
const CartSummary: React.FC = () => {
|
interface CartSummaryProps {
|
||||||
|
step: number;
|
||||||
|
setStep: (step: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CartSummary: React.FC<CartSummaryProps> = ({ step, setStep }) => {
|
||||||
const { state, updateDelivery, updateOrderComment, clearCart } = useCart();
|
const { state, updateDelivery, updateOrderComment, clearCart } = useCart();
|
||||||
const { summary, delivery, items, orderComment } = state;
|
const { summary, delivery, items, orderComment } = state;
|
||||||
const legalEntityDropdownRef = useRef<HTMLDivElement>(null);
|
const legalEntityDropdownRef = useRef<HTMLDivElement>(null);
|
||||||
@ -16,7 +21,6 @@ const CartSummary: React.FC = () => {
|
|||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
const [isProcessing, setIsProcessing] = useState(false);
|
const [isProcessing, setIsProcessing] = useState(false);
|
||||||
const [showAuthWarning, setShowAuthWarning] = useState(false);
|
const [showAuthWarning, setShowAuthWarning] = useState(false);
|
||||||
const [step, setStep] = useState(1);
|
|
||||||
|
|
||||||
// Новые состояния для первого шага
|
// Новые состояния для первого шага
|
||||||
const [selectedLegalEntity, setSelectedLegalEntity] = useState<string>("");
|
const [selectedLegalEntity, setSelectedLegalEntity] = useState<string>("");
|
||||||
@ -135,25 +139,20 @@ const CartSummary: React.FC = () => {
|
|||||||
toast.error('Пожалуйста, введите имя получателя');
|
toast.error('Пожалуйста, введите имя получателя');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!recipientPhone.trim()) {
|
if (!recipientPhone.trim()) {
|
||||||
toast.error('Пожалуйста, введите телефон получателя');
|
toast.error('Пожалуйста, введите телефон получателя');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!selectedDeliveryAddress.trim()) {
|
if (!selectedDeliveryAddress.trim()) {
|
||||||
toast.error('Пожалуйста, выберите адрес доставки');
|
toast.error('Пожалуйста, выберите адрес доставки');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обновляем данные доставки без стоимости
|
|
||||||
updateDelivery({
|
updateDelivery({
|
||||||
address: selectedDeliveryAddress,
|
address: selectedDeliveryAddress,
|
||||||
cost: 0, // Стоимость включена в товары
|
cost: 0,
|
||||||
date: 'Включена в стоимость товаров',
|
date: 'Включена в стоимость товаров',
|
||||||
time: 'Способ доставки указан в адресе'
|
time: 'Способ доставки указан в адресе'
|
||||||
});
|
});
|
||||||
|
|
||||||
setStep(2);
|
setStep(2);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -894,7 +893,7 @@ const CartSummary: React.FC = () => {
|
|||||||
{error && <div style={{ color: 'red', marginTop: 10 }}>{error}</div>}
|
{error && <div style={{ color: 'red', marginTop: 10 }}>{error}</div>}
|
||||||
|
|
||||||
{/* Кнопка "Назад" */}
|
{/* Кнопка "Назад" */}
|
||||||
{/* <button
|
<button
|
||||||
onClick={handleBackToStep1}
|
onClick={handleBackToStep1}
|
||||||
style={{
|
style={{
|
||||||
background: 'none',
|
background: 'none',
|
||||||
@ -908,7 +907,7 @@ const CartSummary: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
← Назад к настройкам доставки
|
← Назад к настройкам доставки
|
||||||
</button> */}
|
</button>
|
||||||
|
|
||||||
<div className="w-layout-hflex privacy-consent" style={{ cursor: 'pointer' }} onClick={() => setConsent((v) => !v)}>
|
<div className="w-layout-hflex privacy-consent" style={{ cursor: 'pointer' }} onClick={() => setConsent((v) => !v)}>
|
||||||
<div
|
<div
|
||||||
|
@ -208,7 +208,7 @@ const CatalogGroupsSection: React.FC<CatalogGroupsSectionProps> = ({
|
|||||||
vehicleId,
|
vehicleId,
|
||||||
...(ssd && ssd.trim() !== '' && { ssd })
|
...(ssd && ssd.trim() !== '' && { ssd })
|
||||||
},
|
},
|
||||||
skip: !catalogCode || !vehicleId || catalogType !== 'quickGroups',
|
skip: !catalogCode || vehicleId === undefined || vehicleId === null || catalogType !== 'quickGroups',
|
||||||
errorPolicy: 'all'
|
errorPolicy: 'all'
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -33,7 +33,7 @@ const CategoriesSection: React.FC<CategoriesSectionProps> = ({
|
|||||||
vehicleId,
|
vehicleId,
|
||||||
...(ssd && ssd.trim() !== '' && { ssd })
|
...(ssd && ssd.trim() !== '' && { ssd })
|
||||||
},
|
},
|
||||||
skip: !catalogCode || !vehicleId,
|
skip: !catalogCode || vehicleId === undefined || vehicleId === null,
|
||||||
errorPolicy: 'all'
|
errorPolicy: 'all'
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useLazyQuery } from '@apollo/client';
|
import { useLazyQuery } from '@apollo/client';
|
||||||
import { LaximoFulltextSearchResult, LaximoFulltextDetail, LaximoOEMResult } from '@/types/laximo';
|
import { LaximoFulltextSearchResult, LaximoFulltextDetail, LaximoOEMResult } from '@/types/laximo';
|
||||||
import { SEARCH_LAXIMO_FULLTEXT, SEARCH_LAXIMO_OEM } from '@/lib/graphql';
|
import { GET_LAXIMO_FULLTEXT_SEARCH, SEARCH_LAXIMO_OEM } from '@/lib/graphql/laximo';
|
||||||
import PartDetailCard from './PartDetailCard';
|
import PartDetailCard from './PartDetailCard';
|
||||||
|
|
||||||
interface FulltextSearchSectionProps {
|
interface FulltextSearchSectionProps {
|
||||||
@ -17,7 +17,7 @@ const FulltextSearchSection: React.FC<FulltextSearchSectionProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
|
|
||||||
const [executeSearch, { data, loading, error }] = useLazyQuery(SEARCH_LAXIMO_FULLTEXT, {
|
const [executeSearch, { data, loading, error }] = useLazyQuery(GET_LAXIMO_FULLTEXT_SEARCH, {
|
||||||
errorPolicy: 'all'
|
errorPolicy: 'all'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -187,13 +187,13 @@ const GroupDetailsSection: React.FC<GroupDetailsSectionProps> = ({
|
|||||||
const { data, loading, error } = useQuery<{ laximoQuickDetail: LaximoQuickDetail }>(
|
const { data, loading, error } = useQuery<{ laximoQuickDetail: LaximoQuickDetail }>(
|
||||||
GET_LAXIMO_QUICK_DETAIL,
|
GET_LAXIMO_QUICK_DETAIL,
|
||||||
{
|
{
|
||||||
variables: {
|
variables: quickGroupId ? {
|
||||||
catalogCode,
|
catalogCode,
|
||||||
vehicleId,
|
vehicleId,
|
||||||
quickGroupId,
|
quickGroupId,
|
||||||
ssd
|
ssd
|
||||||
},
|
} : undefined,
|
||||||
skip: !catalogCode || !vehicleId || !quickGroupId || !ssd,
|
skip: !catalogCode || vehicleId === undefined || vehicleId === null || !quickGroupId || !ssd || ssd.trim() === '',
|
||||||
errorPolicy: 'all'
|
errorPolicy: 'all'
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -30,7 +30,7 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
|
|||||||
onSuccess={handleAuthSuccess}
|
onSuccess={handleAuthSuccess}
|
||||||
/>
|
/>
|
||||||
</header>
|
</header>
|
||||||
<main className="pt-[132px]">{children}</main>
|
<main className="pt-[108px] md:pt-[131px]">{children}</main>
|
||||||
<MobileMenuBottomSection onOpenAuthModal={() => setAuthModalOpen(true)} />
|
<MobileMenuBottomSection onOpenAuthModal={() => setAuthModalOpen(true)} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -154,13 +154,13 @@ const QuickDetailSection: React.FC<QuickDetailSectionProps> = ({
|
|||||||
const { data: quickDetailData, loading: quickDetailLoading, error: quickDetailError } = useQuery<{ laximoQuickDetail: LaximoQuickDetail }>(
|
const { data: quickDetailData, loading: quickDetailLoading, error: quickDetailError } = useQuery<{ laximoQuickDetail: LaximoQuickDetail }>(
|
||||||
GET_LAXIMO_QUICK_DETAIL,
|
GET_LAXIMO_QUICK_DETAIL,
|
||||||
{
|
{
|
||||||
variables: {
|
variables: selectedGroup?.quickgroupid ? {
|
||||||
catalogCode,
|
catalogCode,
|
||||||
vehicleId,
|
vehicleId,
|
||||||
quickGroupId: selectedGroup.quickgroupid,
|
quickGroupId: selectedGroup.quickgroupid,
|
||||||
ssd
|
ssd
|
||||||
},
|
} : undefined,
|
||||||
skip: !catalogCode || !vehicleId || !selectedGroup.quickgroupid || !ssd,
|
skip: !catalogCode || vehicleId === undefined || vehicleId === null || !selectedGroup?.quickgroupid || !ssd || ssd.trim() === '',
|
||||||
errorPolicy: 'all',
|
errorPolicy: 'all',
|
||||||
fetchPolicy: 'cache-and-network' // Принудительно запрашиваем данные
|
fetchPolicy: 'cache-and-network' // Принудительно запрашиваем данные
|
||||||
}
|
}
|
||||||
@ -169,11 +169,28 @@ const QuickDetailSection: React.FC<QuickDetailSectionProps> = ({
|
|||||||
const quickDetail = quickDetailData?.laximoQuickDetail;
|
const quickDetail = quickDetailData?.laximoQuickDetail;
|
||||||
|
|
||||||
// Добавляем отладочную информацию
|
// Добавляем отладочную информацию
|
||||||
console.log('🔍 QuickDetailSection Debug:');
|
console.log('🔍 QuickDetailSection Debug:', {
|
||||||
console.log('📊 quickDetailData:', quickDetailData);
|
catalogCode,
|
||||||
console.log('📋 quickDetail:', quickDetail);
|
vehicleId,
|
||||||
console.log('🏗️ quickDetail.units:', quickDetail?.units);
|
vehicleIdType: typeof vehicleId,
|
||||||
console.log('⚙️ Variables:', { catalogCode, vehicleId, quickGroupId: selectedGroup.quickgroupid, ssd });
|
quickGroupId: selectedGroup?.quickgroupid,
|
||||||
|
quickGroupIdType: typeof selectedGroup?.quickgroupid,
|
||||||
|
ssd: ssd ? `${ssd.substring(0, 30)}...` : 'отсутствует',
|
||||||
|
ssdType: typeof ssd,
|
||||||
|
ssdLength: ssd?.length,
|
||||||
|
hasData: !!quickDetailData,
|
||||||
|
hasQuickDetail: !!quickDetail,
|
||||||
|
unitsCount: quickDetail?.units?.length || 0,
|
||||||
|
loading: quickDetailLoading,
|
||||||
|
error: quickDetailError?.message,
|
||||||
|
skipCondition: !catalogCode || vehicleId === undefined || vehicleId === null || !selectedGroup?.quickgroupid || !ssd,
|
||||||
|
skipDetails: {
|
||||||
|
noCatalogCode: !catalogCode,
|
||||||
|
noVehicleId: vehicleId === undefined || vehicleId === null,
|
||||||
|
noQuickGroupId: !selectedGroup?.quickgroupid,
|
||||||
|
noSsd: !ssd
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Если выбран узел для детального просмотра, показываем UnitDetailsSection
|
// Если выбран узел для детального просмотра, показываем UnitDetailsSection
|
||||||
if (selectedUnit) {
|
if (selectedUnit) {
|
||||||
@ -213,6 +230,20 @@ const QuickDetailSection: React.FC<QuickDetailSectionProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (quickDetailError) {
|
if (quickDetailError) {
|
||||||
|
console.error('🚨 QuickDetailSection Error Details:', {
|
||||||
|
message: quickDetailError.message,
|
||||||
|
graphQLErrors: quickDetailError.graphQLErrors,
|
||||||
|
networkError: quickDetailError.networkError,
|
||||||
|
extraInfo: quickDetailError.extraInfo,
|
||||||
|
selectedGroup: selectedGroup,
|
||||||
|
variables: selectedGroup?.quickgroupid ? {
|
||||||
|
catalogCode,
|
||||||
|
vehicleId,
|
||||||
|
quickGroupId: selectedGroup.quickgroupid,
|
||||||
|
ssd
|
||||||
|
} : 'undefined (no variables sent)'
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
@ -231,6 +262,33 @@ const QuickDetailSection: React.FC<QuickDetailSectionProps> = ({
|
|||||||
<h3 className="text-lg font-medium text-red-600 mb-2">Ошибка загрузки деталей</h3>
|
<h3 className="text-lg font-medium text-red-600 mb-2">Ошибка загрузки деталей</h3>
|
||||||
<p className="text-red-700">Не удалось загрузить детали для группы "{selectedGroup.name}"</p>
|
<p className="text-red-700">Не удалось загрузить детали для группы "{selectedGroup.name}"</p>
|
||||||
<p className="text-sm text-red-600 mt-2">Ошибка: {quickDetailError.message}</p>
|
<p className="text-sm text-red-600 mt-2">Ошибка: {quickDetailError.message}</p>
|
||||||
|
|
||||||
|
{/* Отладочная информация */}
|
||||||
|
<details className="mt-4">
|
||||||
|
<summary className="text-sm text-red-700 cursor-pointer hover:text-red-800">
|
||||||
|
🔧 Показать отладочную информацию
|
||||||
|
</summary>
|
||||||
|
<div className="mt-2 p-3 bg-red-100 rounded text-xs">
|
||||||
|
<div><strong>Catalog Code:</strong> {catalogCode}</div>
|
||||||
|
<div><strong>Vehicle ID:</strong> {vehicleId} (type: {typeof vehicleId})</div>
|
||||||
|
<div><strong>Quick Group ID:</strong> {selectedGroup?.quickgroupid} (type: {typeof selectedGroup?.quickgroupid})</div>
|
||||||
|
<div><strong>SSD:</strong> {ssd ? `${ssd.substring(0, 100)}...` : 'отсутствует'} (length: {ssd?.length})</div>
|
||||||
|
<div className="mt-2">
|
||||||
|
<strong>GraphQL Errors:</strong>
|
||||||
|
<pre className="mt-1 text-xs overflow-auto">
|
||||||
|
{JSON.stringify(quickDetailError.graphQLErrors, null, 2)}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
{quickDetailError.networkError && (
|
||||||
|
<div className="mt-2">
|
||||||
|
<strong>Network Error:</strong>
|
||||||
|
<pre className="mt-1 text-xs overflow-auto">
|
||||||
|
{JSON.stringify(quickDetailError.networkError, null, 2)}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -464,7 +522,7 @@ const QuickGroupsSection: React.FC<QuickGroupsSectionProps> = ({
|
|||||||
vehicleId,
|
vehicleId,
|
||||||
...(ssd && ssd.trim() !== '' && { ssd })
|
...(ssd && ssd.trim() !== '' && { ssd })
|
||||||
},
|
},
|
||||||
skip: !catalogCode || !vehicleId,
|
skip: !catalogCode || vehicleId === undefined || vehicleId === null,
|
||||||
errorPolicy: 'all'
|
errorPolicy: 'all'
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -39,7 +39,7 @@ const UnitDetailsSection: React.FC<UnitDetailsSectionProps> = ({
|
|||||||
unitId,
|
unitId,
|
||||||
ssd: ssd || ''
|
ssd: ssd || ''
|
||||||
},
|
},
|
||||||
skip: !catalogCode || !vehicleId || !unitId,
|
skip: !catalogCode || vehicleId === undefined || vehicleId === null || !unitId,
|
||||||
errorPolicy: 'all'
|
errorPolicy: 'all'
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -54,7 +54,7 @@ const UnitDetailsSection: React.FC<UnitDetailsSectionProps> = ({
|
|||||||
unitId,
|
unitId,
|
||||||
ssd: ssd || ''
|
ssd: ssd || ''
|
||||||
},
|
},
|
||||||
skip: !catalogCode || !vehicleId || !unitId,
|
skip: !catalogCode || vehicleId === undefined || vehicleId === null || !unitId,
|
||||||
errorPolicy: 'all'
|
errorPolicy: 'all'
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -69,7 +69,7 @@ const UnitDetailsSection: React.FC<UnitDetailsSectionProps> = ({
|
|||||||
unitId,
|
unitId,
|
||||||
ssd: ssd || ''
|
ssd: ssd || ''
|
||||||
},
|
},
|
||||||
skip: !catalogCode || !vehicleId || !unitId,
|
skip: !catalogCode || vehicleId === undefined || vehicleId === null || !unitId,
|
||||||
errorPolicy: 'all'
|
errorPolicy: 'all'
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -59,7 +59,7 @@ const UnitsSection: React.FC<UnitsSectionProps> = ({
|
|||||||
categoryId,
|
categoryId,
|
||||||
...(ssd && ssd.trim() !== '' && { ssd })
|
...(ssd && ssd.trim() !== '' && { ssd })
|
||||||
},
|
},
|
||||||
skip: !catalogCode || !vehicleId || !categoryId,
|
skip: !catalogCode || vehicleId === undefined || vehicleId === null || !categoryId,
|
||||||
errorPolicy: 'all',
|
errorPolicy: 'all',
|
||||||
fetchPolicy: 'no-cache', // Полностью отключаем кэширование для гарантии свежих данных
|
fetchPolicy: 'no-cache', // Полностью отключаем кэширование для гарантии свежих данных
|
||||||
notifyOnNetworkStatusChange: true
|
notifyOnNetworkStatusChange: true
|
||||||
|
@ -110,7 +110,7 @@ const LegalEntityListBlock: React.FC<LegalEntityListBlockProps> = ({ legalEntiti
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
layer-name="link_control_element"
|
layer-name="link_control_element"
|
||||||
className="flex relative gap-1.5 items-center cursor-pointer hover:text-red-600"
|
className="flex relative gap-1.5 items-center cursor-pointer group"
|
||||||
role="button"
|
role="button"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
onClick={() => router.push('/profile-requisites')}
|
onClick={() => router.push('/profile-requisites')}
|
||||||
@ -130,7 +130,7 @@ const LegalEntityListBlock: React.FC<LegalEntityListBlockProps> = ({ legalEntiti
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
layer-name="Редактировать"
|
layer-name="Редактировать"
|
||||||
className="text-sm leading-5 text-gray-600"
|
className="text-sm leading-5 text-gray-600 group-hover:text-red-600"
|
||||||
>
|
>
|
||||||
Реквизиты компании
|
Реквизиты компании
|
||||||
</div>
|
</div>
|
||||||
@ -141,8 +141,9 @@ const LegalEntityListBlock: React.FC<LegalEntityListBlockProps> = ({ legalEntiti
|
|||||||
<div
|
<div
|
||||||
role="button"
|
role="button"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
className="flex relative gap-1.5 items-center cursor-pointer hover:text-red-600"
|
className="flex relative gap-1.5 items-center cursor-pointer group"
|
||||||
onClick={() => onEdit && onEdit(entity)}
|
onClick={() => onEdit && onEdit(entity)}
|
||||||
|
aria-label="Редактировать юридическое лицо"
|
||||||
>
|
>
|
||||||
<div className="relative h-4 w-[18px]">
|
<div className="relative h-4 w-[18px]">
|
||||||
<Image
|
<Image
|
||||||
@ -153,26 +154,37 @@ const LegalEntityListBlock: React.FC<LegalEntityListBlockProps> = ({ legalEntiti
|
|||||||
className="absolute left-0.5 top-0"
|
className="absolute left-0.5 top-0"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm leading-5 text-gray-600">
|
<div className="text-sm leading-5 text-gray-600 group-hover:text-red-600">
|
||||||
Редактировать
|
Редактировать
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
role="button"
|
role="button"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
className="flex relative gap-1.5 items-center cursor-pointer hover:text-red-600"
|
className="flex relative gap-1.5 items-center cursor-pointer group"
|
||||||
|
aria-label="Удалить юридическое лицо"
|
||||||
onClick={() => handleDelete(entity.id, entity.shortName)}
|
onClick={() => handleDelete(entity.id, entity.shortName)}
|
||||||
|
onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && handleDelete(entity.id, entity.shortName)}
|
||||||
|
style={{ display: 'inline-flex', cursor: 'pointer', transition: 'color 0.2s' }}
|
||||||
|
onMouseEnter={e => {
|
||||||
|
const path = e.currentTarget.querySelector('path');
|
||||||
|
if (path) path.setAttribute('fill', '#ec1c24');
|
||||||
|
}}
|
||||||
|
onMouseLeave={e => {
|
||||||
|
const path = e.currentTarget.querySelector('path');
|
||||||
|
if (path) path.setAttribute('fill', '#D0D0D0');
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div className="relative h-4 w-[18px]">
|
<div className="relative h-4 w-4">
|
||||||
<Image
|
<svg width="16" height="16" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
src="/images/delete.svg"
|
<path
|
||||||
alt="Удалить"
|
d="M4.625 17.5C4.14375 17.5 3.73192 17.3261 3.3895 16.9782C3.04708 16.6304 2.87558 16.2117 2.875 15.7222V4.16667H2V2.38889H6.375V1.5H11.625V2.38889H16V4.16667H15.125V15.7222C15.125 16.2111 14.9538 16.6298 14.6114 16.9782C14.269 17.3267 13.8568 17.5006 13.375 17.5H4.625ZM6.375 13.9444H8.125V5.94444H6.375V13.9444ZM9.875 13.9444H11.625V5.94444H9.875V13.9444Z"
|
||||||
width={16}
|
fill="#D0D0D0"
|
||||||
height={16}
|
style={{ transition: 'fill 0.2s' }}
|
||||||
className="absolute left-0.5 top-0"
|
|
||||||
/>
|
/>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm leading-5 text-gray-600">
|
<div className="text-sm leading-5 text-gray-600 group-hover:text-red-600">
|
||||||
Удалить
|
Удалить
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -52,14 +52,50 @@ const ProfileAddressCard: React.FC<ProfileAddressCardProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="flex justify-between items-start self-stretch">
|
<div className="flex justify-between items-start self-stretch max-sm:flex-row max-sm:gap-4 max-sm:justify-start max-sm:items-center">
|
||||||
<div className="flex gap-1.5 items-center cursor-pointer group" onClick={onEdit}>
|
<div
|
||||||
<img src="/images/edit.svg" alt="edit" width={18} height={18} className="mr-1.5 group-hover:filter-red" />
|
className="flex gap-1.5 items-center cursor-pointer group"
|
||||||
<div className="relative text-sm leading-5 text-gray-600">Редактировать</div>
|
onClick={onEdit}
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
aria-label="Редактировать адрес"
|
||||||
|
onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && onEdit && onEdit()}
|
||||||
|
onMouseEnter={e => {
|
||||||
|
const svg = (e.currentTarget as HTMLElement).querySelector('img');
|
||||||
|
if (svg) (svg as HTMLImageElement).style.filter = 'invert(32%) sepia(97%) saturate(7490%) hue-rotate(355deg) brightness(97%) contrast(108%)';
|
||||||
|
}}
|
||||||
|
onMouseLeave={e => {
|
||||||
|
const svg = (e.currentTarget as HTMLElement).querySelector('img');
|
||||||
|
if (svg) (svg as HTMLImageElement).style.filter = '';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img src="/images/edit.svg" alt="edit" width={18} height={18} className="mr-1.5" />
|
||||||
|
<div className="relative text-sm leading-5 text-gray-600 group-hover:text-red-600 max-sm:hidden">Редактировать</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-1.5 items-center cursor-pointer group" onClick={onDelete}>
|
<div
|
||||||
<img src="/images/delete.svg" alt="delete" width={18} height={18} className="mr-1.5 group-hover:filter-red" />
|
className="flex gap-1.5 items-center cursor-pointer group"
|
||||||
<div className="relative text-sm leading-5 text-gray-600">Удалить</div>
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
aria-label="Удалить адрес"
|
||||||
|
onClick={onDelete}
|
||||||
|
onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && onDelete && onDelete()}
|
||||||
|
onMouseEnter={e => {
|
||||||
|
const path = e.currentTarget.querySelector('path');
|
||||||
|
if (path) path.setAttribute('fill', '#ec1c24');
|
||||||
|
}}
|
||||||
|
onMouseLeave={e => {
|
||||||
|
const path = e.currentTarget.querySelector('path');
|
||||||
|
if (path) path.setAttribute('fill', '#D0D0D0');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg width="18" height="18" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path
|
||||||
|
d="M4.625 17.5C4.14375 17.5 3.73192 17.3261 3.3895 16.9782C3.04708 16.6304 2.87558 16.2117 2.875 15.7222V4.16667H2V2.38889H6.375V1.5H11.625V2.38889H16V4.16667H15.125V15.7222C15.125 16.2111 14.9538 16.6298 14.6114 16.9782C14.269 17.3267 13.8568 17.5006 13.375 17.5H4.625ZM6.375 13.9444H8.125V5.94444H6.375V13.9444ZM9.875 13.9444H11.625V5.94444H9.875V13.9444Z"
|
||||||
|
fill="#D0D0D0"
|
||||||
|
style={{ transition: 'fill 0.2s' }}
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<div className="relative text-sm leading-5 text-gray-600 group-hover:text-red-600 max-sm:hidden">Удалить</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{onSelectMain && (
|
{onSelectMain && (
|
||||||
|
@ -89,11 +89,11 @@ const ProfileBalanceCard: React.FC<ProfileBalanceCardProps> = ({
|
|||||||
{balance}
|
{balance}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row gap-5 items-end mt-5 w-full max-sm:flex-col">
|
<div className="flex flex-row gap-5 items-end mt-5 w-full max-sm:flex-col max-sm:items-start">
|
||||||
<div className="flex flex-col flex-1 shrink basis-0">
|
<div className="flex flex-col flex-1 shrink basis-0">
|
||||||
<div className="flex flex-col min-w-[160px]">
|
<div className="flex flex-col min-w-[160px]">
|
||||||
<div className="text-sm leading-snug text-gray-600">Лимит отсрочки</div>
|
<div className="text-sm leading-snug text-gray-600">Лимит отсрочки</div>
|
||||||
<div className="flex flex-col self-start mt-2">
|
<div className="flex flex-col mt-2">
|
||||||
<div className="text-lg font-medium leading-none text-gray-950">{limit}</div>
|
<div className="text-lg font-medium leading-none text-gray-950">{limit}</div>
|
||||||
<div className={`text-sm leading-snug ${isOverLimit ? 'text-red-600' : 'text-gray-600'}`}>
|
<div className={`text-sm leading-snug ${isOverLimit ? 'text-red-600' : 'text-gray-600'}`}>
|
||||||
{limitLeft.includes('Не установлен') ? limitLeft : `Осталось ${limitLeft}`}
|
{limitLeft.includes('Не установлен') ? limitLeft : `Осталось ${limitLeft}`}
|
||||||
|
@ -179,7 +179,7 @@ const ProfileGarageMain = () => {
|
|||||||
|
|
||||||
{!vehiclesLoading && filteredVehicles.map((vehicle) => (
|
{!vehiclesLoading && filteredVehicles.map((vehicle) => (
|
||||||
<div key={vehicle.id} className="mt-8">
|
<div key={vehicle.id} className="mt-8">
|
||||||
<div className="flex flex-col justify-center pr-5 py-3 w-full rounded-lg bg-slate-50 max-md:max-w-full">
|
<div className="flex flex-col justify-center px-5 py-3 w-full rounded-lg bg-slate-50 max-md:max-w-full">
|
||||||
<div className="flex flex-wrap gap-8 items-center w-full max-md:max-w-full">
|
<div className="flex flex-wrap gap-8 items-center w-full max-md:max-w-full">
|
||||||
<div className="flex gap-8 items-center self-stretch my-auto min-w-[240px] max-md:flex-col max-md:min-w-0 max-md:gap-2">
|
<div className="flex gap-8 items-center self-stretch my-auto min-w-[240px] max-md:flex-col max-md:min-w-0 max-md:gap-2">
|
||||||
<div className="self-stretch my-auto text-xl font-bold leading-none text-gray-950">
|
<div className="self-stretch my-auto text-xl font-bold leading-none text-gray-950">
|
||||||
@ -203,15 +203,29 @@ const ProfileGarageMain = () => {
|
|||||||
<div className="flex gap-5 items-center self-stretch pr-2.5 my-auto text-sm leading-snug text-gray-600 whitespace-nowrap">
|
<div className="flex gap-5 items-center self-stretch pr-2.5 my-auto text-sm leading-snug text-gray-600 whitespace-nowrap">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="flex gap-1.5 items-center self-stretch my-auto cursor-pointer text-sm leading-snug text-gray-600 hover:text-red-600 transition-colors"
|
className="flex gap-1.5 items-center self-stretch my-auto text-sm leading-snug text-gray-600 cursor-pointer bg-transparent group"
|
||||||
|
style={{ outline: 'none' }}
|
||||||
|
aria-label="Удалить автомобиль"
|
||||||
|
tabIndex={0}
|
||||||
onClick={() => handleDeleteVehicle(vehicle.id)}
|
onClick={() => handleDeleteVehicle(vehicle.id)}
|
||||||
|
onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && handleDeleteVehicle(vehicle.id)}
|
||||||
|
onMouseEnter={e => {
|
||||||
|
const path = e.currentTarget.querySelector('path');
|
||||||
|
if (path) path.setAttribute('fill', '#ec1c24');
|
||||||
|
}}
|
||||||
|
onMouseLeave={e => {
|
||||||
|
const path = e.currentTarget.querySelector('path');
|
||||||
|
if (path) path.setAttribute('fill', '#D0D0D0');
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<img
|
<svg width="16" height="16" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
loading="lazy"
|
<path
|
||||||
src="/images/delete.svg"
|
d="M4.625 17.5C4.14375 17.5 3.73192 17.3261 3.3895 16.9782C3.04708 16.6304 2.87558 16.2117 2.875 15.7222V4.16667H2V2.38889H6.375V1.5H11.625V2.38889H16V4.16667H15.125V15.7222C15.125 16.2111 14.9538 16.6298 14.6114 16.9782C14.269 17.3267 13.8568 17.5006 13.375 17.5H4.625ZM6.375 13.9444H8.125V5.94444H6.375V13.9444ZM9.875 13.9444H11.625V5.94444H9.875V13.9444Z"
|
||||||
className="object-contain shrink-0 self-stretch my-auto aspect-[1.12] w-[18px]"
|
fill="#D0D0D0"
|
||||||
|
style={{ transition: 'fill 0.2s' }}
|
||||||
/>
|
/>
|
||||||
<span className="self-stretch my-auto text-gray-600">
|
</svg>
|
||||||
|
<span className="self-stretch my-auto text-gray-600 group-hover:text-red-600">
|
||||||
Удалить
|
Удалить
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
@ -418,15 +432,29 @@ const ProfileGarageMain = () => {
|
|||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="flex gap-1.5 items-center self-stretch my-auto text-sm leading-snug text-gray-600 cursor-pointer bg-transparent hover:text-red-600 transition-colors"
|
className="flex gap-1.5 items-center self-stretch my-auto text-sm leading-snug text-gray-600 cursor-pointer bg-transparent group"
|
||||||
|
style={{ outline: 'none' }}
|
||||||
|
aria-label="Удалить из истории поиска"
|
||||||
|
tabIndex={0}
|
||||||
onClick={() => handleDeleteFromHistory(historyItem.id)}
|
onClick={() => handleDeleteFromHistory(historyItem.id)}
|
||||||
|
onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && handleDeleteFromHistory(historyItem.id)}
|
||||||
|
onMouseEnter={e => {
|
||||||
|
const path = e.currentTarget.querySelector('path');
|
||||||
|
if (path) path.setAttribute('fill', '#ec1c24');
|
||||||
|
}}
|
||||||
|
onMouseLeave={e => {
|
||||||
|
const path = e.currentTarget.querySelector('path');
|
||||||
|
if (path) path.setAttribute('fill', '#D0D0D0');
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<img
|
<svg width="16" height="16" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
loading="lazy"
|
<path
|
||||||
src="/images/delete.svg"
|
d="M4.625 17.5C4.14375 17.5 3.73192 17.3261 3.3895 16.9782C3.04708 16.6304 2.87558 16.2117 2.875 15.7222V4.16667H2V2.38889H6.375V1.5H11.625V2.38889H16V4.16667H15.125V15.7222C15.125 16.2111 14.9538 16.6298 14.6114 16.9782C14.269 17.3267 13.8568 17.5006 13.375 17.5H4.625ZM6.375 13.9444H8.125V5.94444H6.375V13.9444ZM9.875 13.9444H11.625V5.94444H9.875V13.9444Z"
|
||||||
className="object-contain shrink-0 self-stretch my-auto aspect-[1.12] w-[18px]"
|
fill="#D0D0D0"
|
||||||
|
style={{ transition: 'fill 0.2s' }}
|
||||||
/>
|
/>
|
||||||
<span className="self-stretch my-auto text-gray-600">
|
</svg>
|
||||||
|
<span className="self-stretch my-auto text-gray-600 group-hover:text-red-600">
|
||||||
Удалить
|
Удалить
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -80,24 +80,25 @@ const ProfileHistoryItem: React.FC<ProfileHistoryItemProps> = ({
|
|||||||
<div className="w-16 text-center max-md:w-full">
|
<div className="w-16 text-center max-md:w-full">
|
||||||
<button
|
<button
|
||||||
onClick={handleDeleteClick}
|
onClick={handleDeleteClick}
|
||||||
className="p-2 text-red-500 hover:text-red-700 hover:bg-red-50 rounded-lg transition-colors group"
|
className="flex items-center p-2 group"
|
||||||
title="Удалить из истории"
|
title="Удалить из истории"
|
||||||
aria-label="Удалить из истории"
|
aria-label="Удалить из истории"
|
||||||
|
tabIndex={0}
|
||||||
|
onMouseEnter={e => {
|
||||||
|
const path = e.currentTarget.querySelector('path');
|
||||||
|
if (path) path.setAttribute('fill', '#ec1c24');
|
||||||
|
}}
|
||||||
|
onMouseLeave={e => {
|
||||||
|
const path = e.currentTarget.querySelector('path');
|
||||||
|
if (path) path.setAttribute('fill', '#D0D0D0');
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<svg
|
<svg width="16" height="16" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
width="16"
|
<path
|
||||||
height="16"
|
d="M4.625 17.5C4.14375 17.5 3.73192 17.3261 3.3895 16.9782C3.04708 16.6304 2.87558 16.2117 2.875 15.7222V4.16667H2V2.38889H6.375V1.5H11.625V2.38889H16V4.16667H15.125V15.7222C15.125 16.2111 14.9538 16.6298 14.6114 16.9782C14.269 17.3267 13.8568 17.5006 13.375 17.5H4.625ZM6.375 13.9444H8.125V5.94444H6.375V13.9444ZM9.875 13.9444H11.625V5.94444H9.875V13.9444Z"
|
||||||
viewBox="0 0 24 24"
|
fill="#D0D0D0"
|
||||||
fill="none"
|
style={{ transition: 'fill 0.2s' }}
|
||||||
stroke="currentColor"
|
/>
|
||||||
strokeWidth="2"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
className="transition-colors"
|
|
||||||
>
|
|
||||||
<path d="M3 6h18" className="group-hover:stroke-[#ec1c24]" />
|
|
||||||
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" className="group-hover:stroke-[#ec1c24]" />
|
|
||||||
<path d="M8 6V4c0-1 1-2 2-2h4c-1 0 2 1 2 2v2" className="group-hover:stroke-[#ec1c24]" />
|
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -272,7 +272,7 @@ const ProfileHistoryMain = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col min-h-[526px]">
|
<div className="flex flex-col min-h-[526px]">
|
||||||
<div className="flex flex-wrap gap-5 items-center px-8 py-3 w-full leading-snug text-gray-400 whitespace-nowrap bg-white rounded-lg max-md:px-5 max-md:max-w-full max-md:flex-col">
|
<div className="flex gap-5 items-center px-8 py-3 w-full leading-snug text-gray-400 whitespace-nowrap bg-white rounded-lg max-md:px-5 max-md:max-w-full">
|
||||||
<div className="flex-1 shrink self-stretch my-auto text-gray-400 basis-0 text-ellipsis max-md:max-w-full max-md:w-full">
|
<div className="flex-1 shrink self-stretch my-auto text-gray-400 basis-0 text-ellipsis max-md:max-w-full max-md:w-full">
|
||||||
<SearchInput
|
<SearchInput
|
||||||
value={search}
|
value={search}
|
||||||
@ -280,7 +280,7 @@ const ProfileHistoryMain = () => {
|
|||||||
placeholder="Поиск в истории..."
|
placeholder="Поиск в истории..."
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2 max-sm:hidden">
|
||||||
{(selectedManufacturer !== "Все" || search.trim() || activeTab !== "Все") && (
|
{(selectedManufacturer !== "Все" || search.trim() || activeTab !== "Все") && (
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -89,7 +89,7 @@ const ProfileHistoryTabs: React.FC<ProfileHistoryTabsProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
<div
|
<div
|
||||||
className="relative w-[240px] max-w-full"
|
className="relative w-[240px] max-w-full max-sm:w-full"
|
||||||
ref={dropdownRef}
|
ref={dropdownRef}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>
|
>
|
||||||
|
@ -10,7 +10,7 @@ const ProfileSettingsActionsBlock: React.FC<ProfileSettingsActionsBlockProps> =
|
|||||||
Сохранить изменения
|
Сохранить изменения
|
||||||
</div>
|
</div>
|
||||||
<div className="gap-2.5 self-stretch px-5 py-4 my-auto rounded-xl border border-red-600 min-h-[50px] min-w-[240px] cursor-pointer bg-white text-gray-950" onClick={onAddLegalEntity}>
|
<div className="gap-2.5 self-stretch px-5 py-4 my-auto rounded-xl border border-red-600 min-h-[50px] min-w-[240px] cursor-pointer bg-white text-gray-950" onClick={onAddLegalEntity}>
|
||||||
Добавить юридическое лицо
|
Добавить юр лицо
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -47,7 +47,7 @@ const KnotIn: React.FC<KnotInProps> = ({ catalogCode, vehicleId, ssd, unitId, un
|
|||||||
GET_LAXIMO_UNIT_INFO,
|
GET_LAXIMO_UNIT_INFO,
|
||||||
{
|
{
|
||||||
variables: { catalogCode, vehicleId, unitId, ssd: ssd || '' },
|
variables: { catalogCode, vehicleId, unitId, ssd: ssd || '' },
|
||||||
skip: !catalogCode || !vehicleId || !unitId,
|
skip: !catalogCode || vehicleId === undefined || vehicleId === null || !unitId,
|
||||||
errorPolicy: 'all',
|
errorPolicy: 'all',
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -56,7 +56,7 @@ const KnotIn: React.FC<KnotInProps> = ({ catalogCode, vehicleId, ssd, unitId, un
|
|||||||
GET_LAXIMO_UNIT_IMAGE_MAP,
|
GET_LAXIMO_UNIT_IMAGE_MAP,
|
||||||
{
|
{
|
||||||
variables: { catalogCode, vehicleId, unitId, ssd: ssd || '' },
|
variables: { catalogCode, vehicleId, unitId, ssd: ssd || '' },
|
||||||
skip: !catalogCode || !vehicleId || !unitId,
|
skip: !catalogCode || vehicleId === undefined || vehicleId === null || !unitId,
|
||||||
errorPolicy: 'all',
|
errorPolicy: 'all',
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -12,7 +12,7 @@ interface VinCategoryProps {
|
|||||||
const VinCategory: React.FC<VinCategoryProps> = ({ catalogCode, vehicleId, ssd, onNodeSelect }) => {
|
const VinCategory: React.FC<VinCategoryProps> = ({ catalogCode, vehicleId, ssd, onNodeSelect }) => {
|
||||||
const { data: categoriesData, loading: categoriesLoading, error: categoriesError } = useQuery(GET_LAXIMO_CATEGORIES, {
|
const { data: categoriesData, loading: categoriesLoading, error: categoriesError } = useQuery(GET_LAXIMO_CATEGORIES, {
|
||||||
variables: { catalogCode, vehicleId, ssd },
|
variables: { catalogCode, vehicleId, ssd },
|
||||||
skip: !catalogCode || !vehicleId,
|
skip: !catalogCode || vehicleId === undefined || vehicleId === null,
|
||||||
errorPolicy: "all",
|
errorPolicy: "all",
|
||||||
});
|
});
|
||||||
const categories = categoriesData?.laximoCategories || [];
|
const categories = categoriesData?.laximoCategories || [];
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { useLazyQuery, useQuery } from '@apollo/client';
|
import { useLazyQuery, useQuery } from '@apollo/client';
|
||||||
import { SEARCH_LAXIMO_FULLTEXT, GET_LAXIMO_CATEGORIES, GET_LAXIMO_UNITS, GET_LAXIMO_QUICK_GROUPS, GET_LAXIMO_QUICK_DETAIL } from '@/lib/graphql/laximo';
|
import { GET_LAXIMO_FULLTEXT_SEARCH, GET_LAXIMO_CATEGORIES, GET_LAXIMO_UNITS, GET_LAXIMO_QUICK_GROUPS, GET_LAXIMO_QUICK_DETAIL } from '@/lib/graphql/laximo';
|
||||||
import VinPartCard from './VinPartCard';
|
import VinPartCard from './VinPartCard';
|
||||||
|
|
||||||
interface VinLeftbarProps {
|
interface VinLeftbarProps {
|
||||||
@ -21,11 +21,11 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
const [openIndex, setOpenIndex] = useState<number | null>(null);
|
const [openIndex, setOpenIndex] = useState<number | null>(null);
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
const [activeTab, setActiveTab] = useState<'uzly' | 'manufacturer'>('uzly');
|
const [activeTab, setActiveTab] = useState<'uzly' | 'manufacturer'>('uzly');
|
||||||
const [executeSearch, { data, loading, error }] = useLazyQuery(SEARCH_LAXIMO_FULLTEXT, { errorPolicy: 'all' });
|
const [executeSearch, { data, loading, error }] = useLazyQuery(GET_LAXIMO_FULLTEXT_SEARCH, { errorPolicy: 'all' });
|
||||||
|
|
||||||
const { data: categoriesData, loading: categoriesLoading, error: categoriesError } = useQuery(GET_LAXIMO_CATEGORIES, {
|
const { data: categoriesData, loading: categoriesLoading, error: categoriesError } = useQuery(GET_LAXIMO_CATEGORIES, {
|
||||||
variables: { catalogCode, vehicleId, ssd },
|
variables: { catalogCode, vehicleId, ssd },
|
||||||
skip: !catalogCode || !vehicleId,
|
skip: !catalogCode || vehicleId === undefined || vehicleId === null,
|
||||||
errorPolicy: 'all'
|
errorPolicy: 'all'
|
||||||
});
|
});
|
||||||
const categories = categoriesData?.laximoCategories || [];
|
const categories = categoriesData?.laximoCategories || [];
|
||||||
@ -88,7 +88,7 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
}, [searchResults, searchQuery, onSearchResults]);
|
}, [searchResults, searchQuery, onSearchResults]);
|
||||||
|
|
||||||
// --- Новый блок: вычисляем доступность поиска ---
|
// --- Новый блок: вычисляем доступность поиска ---
|
||||||
const isSearchAvailable = !!catalogCode && !!vehicleId && !!ssd && ssd.trim() !== '';
|
const isSearchAvailable = !!catalogCode && vehicleId !== undefined && vehicleId !== null && !!ssd && ssd.trim() !== '';
|
||||||
const showWarning = !isSearchAvailable;
|
const showWarning = !isSearchAvailable;
|
||||||
const showError = !!error && isSearchAvailable && searchQuery.trim();
|
const showError = !!error && isSearchAvailable && searchQuery.trim();
|
||||||
const showNotFound = isSearchAvailable && searchQuery.trim() && !loading && data && searchResults && searchResults.details && searchResults.details.length === 0;
|
const showNotFound = isSearchAvailable && searchQuery.trim() && !loading && data && searchResults && searchResults.details && searchResults.details.length === 0;
|
||||||
@ -98,7 +98,7 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
const [selectedQuickGroup, setSelectedQuickGroup] = useState<any | null>(null);
|
const [selectedQuickGroup, setSelectedQuickGroup] = useState<any | null>(null);
|
||||||
const { data: quickGroupsData, loading: quickGroupsLoading, error: quickGroupsError } = useQuery(GET_LAXIMO_QUICK_GROUPS, {
|
const { data: quickGroupsData, loading: quickGroupsLoading, error: quickGroupsError } = useQuery(GET_LAXIMO_QUICK_GROUPS, {
|
||||||
variables: { catalogCode, vehicleId, ssd },
|
variables: { catalogCode, vehicleId, ssd },
|
||||||
skip: !catalogCode || !vehicleId || activeTab !== 'manufacturer',
|
skip: !catalogCode || vehicleId === undefined || vehicleId === null || activeTab !== 'manufacturer',
|
||||||
errorPolicy: 'all'
|
errorPolicy: 'all'
|
||||||
});
|
});
|
||||||
const quickGroups = quickGroupsData?.laximoQuickGroups || [];
|
const quickGroups = quickGroupsData?.laximoQuickGroups || [];
|
||||||
@ -136,12 +136,30 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
const skipQuickDetail =
|
const skipQuickDetail =
|
||||||
!selectedQuickGroup ||
|
!selectedQuickGroup ||
|
||||||
!catalogCode ||
|
!catalogCode ||
|
||||||
!vehicleId ||
|
vehicleId === undefined ||
|
||||||
!selectedQuickGroup.quickgroupid ||
|
vehicleId === null ||
|
||||||
!ssd;
|
!selectedQuickGroup?.quickgroupid ||
|
||||||
|
!ssd ||
|
||||||
|
ssd.trim() === '';
|
||||||
|
|
||||||
|
console.log('QuickDetail QUERY VARS', {
|
||||||
|
catalogCode,
|
||||||
|
vehicleId,
|
||||||
|
quickGroupId: selectedQuickGroup?.quickgroupid,
|
||||||
|
ssd: ssd ? `${ssd.substring(0, 30)}...` : 'отсутствует'
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('QuickDetail SKIP CONDITIONS', {
|
||||||
|
hasSelectedQuickGroup: !!selectedQuickGroup,
|
||||||
|
hasCatalogCode: !!catalogCode,
|
||||||
|
hasVehicleId: vehicleId !== undefined && vehicleId !== null,
|
||||||
|
hasQuickGroupId: !!selectedQuickGroup?.quickgroupid,
|
||||||
|
hasSsd: !!ssd && ssd.trim() !== '',
|
||||||
|
skipQuickDetail
|
||||||
|
});
|
||||||
|
|
||||||
const { data: quickDetailData, loading: quickDetailLoading, error: quickDetailError } = useQuery(GET_LAXIMO_QUICK_DETAIL, {
|
const { data: quickDetailData, loading: quickDetailLoading, error: quickDetailError } = useQuery(GET_LAXIMO_QUICK_DETAIL, {
|
||||||
variables: selectedQuickGroup ? {
|
variables: selectedQuickGroup?.quickgroupid && !skipQuickDetail ? {
|
||||||
catalogCode,
|
catalogCode,
|
||||||
vehicleId,
|
vehicleId,
|
||||||
quickGroupId: selectedQuickGroup.quickgroupid,
|
quickGroupId: selectedQuickGroup.quickgroupid,
|
||||||
@ -180,12 +198,42 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// === Полнотекстовый поиск деталей (аналогично FulltextSearchSection) ===
|
||||||
|
const [fulltextQuery, setFulltextQuery] = useState('');
|
||||||
|
const [executeFulltextSearch, { data: fulltextData, loading: fulltextLoading, error: fulltextError }] = useLazyQuery(SEARCH_LAXIMO_FULLTEXT, { errorPolicy: 'all' });
|
||||||
|
|
||||||
|
const handleFulltextSearch = () => {
|
||||||
|
if (!fulltextQuery.trim()) return;
|
||||||
|
if (!ssd || ssd.trim() === '') {
|
||||||
|
console.error('SSD обязателен для поиска по названию');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
executeFulltextSearch({
|
||||||
|
variables: {
|
||||||
|
catalogCode,
|
||||||
|
vehicleId,
|
||||||
|
searchText: fulltextQuery.trim(),
|
||||||
|
ssd
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFulltextKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
handleFulltextSearch();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const fulltextResults = fulltextData?.laximoFulltextSearch?.details || [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-layout-vflex vinleftbar">
|
<div className="w-layout-vflex vinleftbar">
|
||||||
|
{/* === Форма полнотекстового поиска === */}
|
||||||
<div className="div-block-2">
|
<div className="div-block-2">
|
||||||
<div className="form-block w-form">
|
<div className="form-block w-form">
|
||||||
<form id="vin-form-search" name="vin-form-search" data-name="vin-form-search" action="#" method="post" className="form">
|
<form id="vin-form-search" name="vin-form-search" data-name="vin-form-search" action="#" method="post" className="form" onSubmit={e => { e.preventDefault(); handleFulltextSearch(); }}>
|
||||||
<a href="#" className="link-block-3 w-inline-block" onClick={e => { e.preventDefault(); if (!ssd || ssd.trim() === '') { return; } handleSearch(); }}>
|
<a href="#" className="link-block-3 w-inline-block" onClick={e => { e.preventDefault(); if (!ssd || ssd.trim() === '') { return; } handleFulltextSearch(); }}>
|
||||||
<div className="code-embed-6 w-embed">
|
<div className="code-embed-6 w-embed">
|
||||||
{/* SVG */}
|
{/* SVG */}
|
||||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
@ -203,14 +251,95 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, o
|
|||||||
type="text"
|
type="text"
|
||||||
id="VinSearchInput"
|
id="VinSearchInput"
|
||||||
required
|
required
|
||||||
value={searchQuery}
|
value={fulltextQuery}
|
||||||
onChange={e => setSearchQuery(e.target.value)}
|
onChange={e => setFulltextQuery(e.target.value)}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleFulltextKeyDown}
|
||||||
disabled={loading}
|
disabled={fulltextLoading}
|
||||||
/>
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleFulltextSearch}
|
||||||
|
disabled={!fulltextQuery.trim() || fulltextLoading || !ssd || ssd.trim() === ''}
|
||||||
|
className="px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-700 disabled:bg-gray-400 disabled:cursor-not-allowed transition-colors ml-2"
|
||||||
|
>
|
||||||
|
{fulltextLoading ? 'Поиск...' : 'Найти'}
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
{/* Варианты отображения: предупреждение, ошибка, подсказки, результаты */}
|
{(!ssd || ssd.trim() === '') && (
|
||||||
|
<div className="mt-3 p-3 bg-yellow-50 border border-yellow-200 rounded-lg">
|
||||||
|
<div className="flex">
|
||||||
|
<svg className="h-5 w-5 text-yellow-400 flex-shrink-0" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
<path fillRule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
<div className="ml-3">
|
||||||
|
<h3 className="text-sm font-medium text-yellow-800">
|
||||||
|
Полнотекстовый поиск недоступен
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-yellow-700 mt-1">
|
||||||
|
Для поиска по названию деталей необходимо сначала выбрать конкретный автомобиль через поиск по VIN или мастер подбора.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{fulltextError && (
|
||||||
|
<div className="bg-red-50 border border-red-200 rounded-lg p-4 mt-3">
|
||||||
|
<div className="flex">
|
||||||
|
<div className="flex-shrink-0">
|
||||||
|
<svg className="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div className="ml-3">
|
||||||
|
<h3 className="text-sm font-medium text-red-800">
|
||||||
|
Ошибка поиска
|
||||||
|
</h3>
|
||||||
|
<div className="mt-2 text-sm text-red-700">
|
||||||
|
<p>{fulltextError.message}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{fulltextResults && (
|
||||||
|
<div className="bg-white border border-gray-200 rounded-lg overflow-hidden mt-3">
|
||||||
|
<div className="px-6 py-4 bg-gray-50 border-b border-gray-200">
|
||||||
|
<h3 className="text-lg font-medium text-gray-900">
|
||||||
|
Результаты поиска: "{fulltextQuery}"
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-600 mt-1">
|
||||||
|
Найдено {fulltextResults.length} деталей
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{fulltextResults.length > 0 ? (
|
||||||
|
<div className="space-y-4 p-6">
|
||||||
|
<div className="text-sm text-blue-700 bg-blue-50 border border-blue-200 rounded-lg p-3">
|
||||||
|
💡 Нажмите на карточку детали для поиска предложений и цен. Используйте кнопку "Показать применимость" для просмотра применения в автомобиле.
|
||||||
|
</div>
|
||||||
|
{fulltextResults.map((detail: any, index: number) => (
|
||||||
|
<VinPartCard
|
||||||
|
key={`${detail.oem}-${index}`}
|
||||||
|
n={index + 1}
|
||||||
|
name={detail.name}
|
||||||
|
oem={detail.oem}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="px-6 py-8 text-center">
|
||||||
|
<svg className="w-12 h-12 mx-auto text-gray-400 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9.172 16.172a4 4 0 015.656 0M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||||
|
</svg>
|
||||||
|
<p className="text-gray-600">
|
||||||
|
По запросу "{fulltextQuery}" ничего не найдено
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-gray-500 mt-1">
|
||||||
|
Попробуйте изменить поисковый запрос
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-layout-vflex flex-block-113">
|
<div className="w-layout-vflex flex-block-113">
|
||||||
|
@ -180,23 +180,6 @@ export const SEARCH_LAXIMO_OEM = gql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const SEARCH_LAXIMO_FULLTEXT = gql`
|
|
||||||
query SearchLaximoFulltext($catalogCode: String!, $vehicleId: String!, $searchText: String!, $ssd: String!) {
|
|
||||||
laximoFulltextSearch(catalogCode: $catalogCode, vehicleId: $vehicleId, searchText: $searchText, ssd: $ssd) {
|
|
||||||
details {
|
|
||||||
codeonimage
|
|
||||||
code
|
|
||||||
name
|
|
||||||
note
|
|
||||||
filter
|
|
||||||
oem
|
|
||||||
price
|
|
||||||
availability
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const GET_LAXIMO_FULLTEXT_SEARCH = gql`
|
export const GET_LAXIMO_FULLTEXT_SEARCH = gql`
|
||||||
query GetLaximoFulltextSearch($catalogCode: String!, $vehicleId: String!, $searchQuery: String!, $ssd: String!) {
|
query GetLaximoFulltextSearch($catalogCode: String!, $vehicleId: String!, $searchQuery: String!, $ssd: String!) {
|
||||||
laximoFulltextSearch(catalogCode: $catalogCode, vehicleId: $vehicleId, searchQuery: $searchQuery, ssd: $ssd) {
|
laximoFulltextSearch(catalogCode: $catalogCode, vehicleId: $vehicleId, searchQuery: $searchQuery, ssd: $ssd) {
|
||||||
@ -208,6 +191,10 @@ export const GET_LAXIMO_FULLTEXT_SEARCH = gql`
|
|||||||
parttype
|
parttype
|
||||||
filter
|
filter
|
||||||
note
|
note
|
||||||
|
codeonimage
|
||||||
|
code
|
||||||
|
price
|
||||||
|
availability
|
||||||
attributes {
|
attributes {
|
||||||
key
|
key
|
||||||
name
|
name
|
||||||
|
@ -7,8 +7,10 @@ import CartSummary from "@/components/CartSummary";
|
|||||||
import CartRecommended from "../components/CartRecommended";
|
import CartRecommended from "../components/CartRecommended";
|
||||||
import CatalogSubscribe from "@/components/CatalogSubscribe";
|
import CatalogSubscribe from "@/components/CatalogSubscribe";
|
||||||
import MobileMenuBottomSection from "@/components/MobileMenuBottomSection";
|
import MobileMenuBottomSection from "@/components/MobileMenuBottomSection";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
|
||||||
export default function CartPage() {
|
export default function CartPage() {
|
||||||
|
const [step, setStep] = useState(1);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<><Head>
|
<><Head>
|
||||||
@ -26,8 +28,8 @@ export default function CartPage() {
|
|||||||
<div className="w-layout-blockcontainer container w-container">
|
<div className="w-layout-blockcontainer container w-container">
|
||||||
<div className="w-layout-vflex cart-list">
|
<div className="w-layout-vflex cart-list">
|
||||||
<div className="w-layout-hflex core-product-card">
|
<div className="w-layout-hflex core-product-card">
|
||||||
<CartList />
|
<CartList isSummaryStep={step === 2} />
|
||||||
<CartSummary />
|
<CartSummary step={step} setStep={setStep} />
|
||||||
</div>
|
</div>
|
||||||
<CartRecommended />
|
<CartRecommended />
|
||||||
</div>
|
</div>
|
||||||
|
@ -58,7 +58,7 @@ const ProfileActsPage = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div className="page-wrapper">
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
<title>ProfileActs</title>
|
<title>ProfileActs</title>
|
||||||
<meta content="ProfileActs" property="og:title" />
|
<meta content="ProfileActs" property="og:title" />
|
||||||
@ -78,7 +78,7 @@ const ProfileActsPage = () => {
|
|||||||
</section>
|
</section>
|
||||||
<MobileMenuBottomSection />
|
<MobileMenuBottomSection />
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ const VehicleDetailsPage = () => {
|
|||||||
...(finalSsd && { ssd: finalSsd }),
|
...(finalSsd && { ssd: finalSsd }),
|
||||||
localized: true
|
localized: true
|
||||||
},
|
},
|
||||||
skip: !brand || !vehicleId,
|
skip: !brand || vehicleId === undefined || vehicleId === null,
|
||||||
errorPolicy: 'all'
|
errorPolicy: 'all'
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -194,8 +194,9 @@ const VehicleDetailsPage = () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Если vehicleId невалидный (например, '0'), показываем предупреждение и не рендерим поиск
|
// Если vehicleId отсутствует или пустой, показываем предупреждение
|
||||||
if (!vehicleId || vehicleId === '0') {
|
// Важно: vehicleId может быть '0' для некоторых автомобилей, найденных по VIN
|
||||||
|
if (!vehicleId || vehicleId === '') {
|
||||||
return (
|
return (
|
||||||
<main className="min-h-screen bg-yellow-50 flex items-center justify-center">
|
<main className="min-h-screen bg-yellow-50 flex items-center justify-center">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
@ -214,7 +215,8 @@ const VehicleDetailsPage = () => {
|
|||||||
|
|
||||||
// Гарантируем, что vehicleId — строка
|
// Гарантируем, что vehicleId — строка
|
||||||
const vehicleIdStr = Array.isArray(vehicleId) ? (vehicleId[0] || '') : (vehicleId || '');
|
const vehicleIdStr = Array.isArray(vehicleId) ? (vehicleId[0] || '') : (vehicleId || '');
|
||||||
const fallbackVehicleId = (vehicleIdStr !== '0' ? vehicleIdStr : '');
|
// Для Laximo API vehicleId может быть '0' для автомобилей, найденных по VIN
|
||||||
|
const fallbackVehicleId = vehicleIdStr;
|
||||||
|
|
||||||
let vehicleInfo = vehicleData?.laximoVehicleInfo || {
|
let vehicleInfo = vehicleData?.laximoVehicleInfo || {
|
||||||
vehicleid: fallbackVehicleId,
|
vehicleid: fallbackVehicleId,
|
||||||
@ -225,8 +227,8 @@ const VehicleDetailsPage = () => {
|
|||||||
attributes: [] as never[]
|
attributes: [] as never[]
|
||||||
};
|
};
|
||||||
|
|
||||||
// Если вдруг с сервера пришёл vehicleid: '0', подменяем на корректный
|
// Убеждаемся, что vehicleid соответствует параметру из URL
|
||||||
if (vehicleInfo.vehicleid === '0' && fallbackVehicleId) {
|
if (vehicleInfo.vehicleid !== fallbackVehicleId && fallbackVehicleId) {
|
||||||
vehicleInfo = { ...vehicleInfo, vehicleid: fallbackVehicleId };
|
vehicleInfo = { ...vehicleInfo, vehicleid: fallbackVehicleId };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,12 +74,12 @@ const PartDetailPage = () => {
|
|||||||
oemNumber: oemNumber,
|
oemNumber: oemNumber,
|
||||||
ssd: finalSsd
|
ssd: finalSsd
|
||||||
},
|
},
|
||||||
skip: !brand || !vehicleId || !oemNumber || !finalSsd,
|
skip: !brand || vehicleId === undefined || vehicleId === null || !oemNumber || !finalSsd,
|
||||||
errorPolicy: 'all'
|
errorPolicy: 'all'
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!brand || !vehicleId || !oemNumber) {
|
if (!brand || vehicleId === undefined || vehicleId === null || !oemNumber) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
|
@ -431,3 +431,38 @@ input#VinSearchInput {
|
|||||||
max-height: 2.8em;
|
max-height: 2.8em;
|
||||||
line-height: 1.4em;
|
line-height: 1.4em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.heading-9-copy,
|
||||||
|
.text-block-21-copy {
|
||||||
|
width: 250px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.w-layout-hflex.flex-block-6 {
|
||||||
|
flex-direction: column !important;
|
||||||
|
}
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.div-block-12,
|
||||||
|
.div-block-12.small,
|
||||||
|
.div-block-12-copy,
|
||||||
|
.div-block-12-copy.small,
|
||||||
|
.div-block-123,
|
||||||
|
.div-block-123.small,
|
||||||
|
.div-block-red,
|
||||||
|
.div-block-red.small {
|
||||||
|
width: 100% !important;
|
||||||
|
max-width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.flex-block-6 {
|
||||||
|
grid-template-columns: 1fr !important;
|
||||||
|
grid-template-rows: none !important;
|
||||||
|
grid-template-areas: none !important;
|
||||||
|
grid-auto-flow: row !important; /* <--- ВАЖНО! */
|
||||||
|
}
|
||||||
|
}
|
@ -787,6 +787,8 @@
|
|||||||
.w-layout-blockcontainer {
|
.w-layout-blockcontainer {
|
||||||
max-width: 728px;
|
max-width: 728px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 767px) {
|
@media screen and (max-width: 767px) {
|
||||||
@ -794,6 +796,8 @@
|
|||||||
max-width: none;
|
max-width: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.w-commerce-commercelayoutcontainer {
|
.w-commerce-commercelayoutcontainer {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
@ -2844,6 +2848,7 @@ body {
|
|||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-field-copy {
|
.text-field-copy {
|
||||||
@ -3110,6 +3115,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.block-name {
|
.block-name {
|
||||||
|
max-width: 300px;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -3908,6 +3914,7 @@ body {
|
|||||||
font-size: var(--_fonts---font-size--small-font-size);
|
font-size: var(--_fonts---font-size--small-font-size);
|
||||||
height: 20px;
|
height: 20px;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
|
max-width: 100%;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
@ -4024,6 +4031,7 @@ body {
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.button-for-mobile-menu-block:hover {
|
.button-for-mobile-menu-block:hover {
|
||||||
background-color: var(--_button---hover-dark_blue);
|
background-color: var(--_button---hover-dark_blue);
|
||||||
}
|
}
|
||||||
@ -4329,7 +4337,7 @@ body {
|
|||||||
color: var(--_fonts---color--black);
|
color: var(--_fonts---color--black);
|
||||||
font-size: var(--_fonts---font-size--bigger);
|
font-size: var(--_fonts---font-size--bigger);
|
||||||
text-align: right;
|
text-align: right;
|
||||||
max-width: 100px;
|
max-width: 200px;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@ -5426,10 +5434,10 @@ body {
|
|||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
.topmenuh {
|
.bottom_head {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
} */
|
||||||
|
|
||||||
.flex-block-4 {
|
.flex-block-4 {
|
||||||
grid-column-gap: 40px;
|
grid-column-gap: 40px;
|
||||||
@ -5519,7 +5527,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.flex-block-39-copy {
|
.flex-block-39-copy {
|
||||||
width: 200px;
|
width: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cart-ditail {
|
.cart-ditail {
|
||||||
@ -5579,6 +5587,8 @@ body {
|
|||||||
background-color: var(--white);
|
background-color: var(--white);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.button-for-mobile-menu-block {
|
.button-for-mobile-menu-block {
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
@ -5680,9 +5690,9 @@ body {
|
|||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topmenub {
|
/* .bottom_head {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
} */
|
||||||
|
|
||||||
.vinleftbar {
|
.vinleftbar {
|
||||||
width: 320px;
|
width: 320px;
|
||||||
@ -6082,7 +6092,7 @@ body {
|
|||||||
padding-bottom: 40px;
|
padding-bottom: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top_head, .topmenuh {
|
.top_head, .bottom_head {
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
padding-right: 30px;
|
padding-right: 30px;
|
||||||
}
|
}
|
||||||
@ -6882,7 +6892,7 @@ body {
|
|||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topmenub {
|
.bottom_head {
|
||||||
padding-left: 30px;
|
padding-left: 30px;
|
||||||
padding-right: 30px;
|
padding-right: 30px;
|
||||||
}
|
}
|
||||||
@ -7329,7 +7339,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.flex-block-39-copy {
|
.flex-block-39-copy {
|
||||||
width: 200px;
|
width: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.heading-9-copy-copy {
|
.heading-9-copy-copy {
|
||||||
@ -7543,8 +7553,9 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.flex-block-18-copy-copy {
|
.flex-block-18-copy-copy {
|
||||||
grid-column-gap: 10px;
|
grid-column-gap: 40px;
|
||||||
grid-row-gap: 10px;
|
grid-row-gap: 40px;
|
||||||
|
flex-flow: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.link-block-4-copy {
|
.link-block-4-copy {
|
||||||
@ -7602,8 +7613,9 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.flex-block-87 {
|
.flex-block-87 {
|
||||||
grid-column-gap: 0px;
|
grid-column-gap: 10px;
|
||||||
grid-row-gap: 0px;
|
grid-row-gap: 10px;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mobile-menu-bottom {
|
.mobile-menu-bottom {
|
||||||
@ -7627,10 +7639,16 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.button-for-mobile-menu-block {
|
.button-for-mobile-menu-block {
|
||||||
grid-column-gap: 0px;
|
grid-column-gap: 2px;
|
||||||
grid-row-gap: 0px;
|
grid-row-gap: 2px;
|
||||||
width: 60px;
|
background-color: var(--_fonts---color--white);
|
||||||
padding-bottom: 5px;
|
color: var(--_button---light-blue-grey);
|
||||||
|
flex-flow: column;
|
||||||
|
width: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-for-mobile-menu-block:hover {
|
||||||
|
background-color: var(--_button---light-blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-3 {
|
.section-3 {
|
||||||
@ -7643,7 +7661,8 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.flex-block-93 {
|
.flex-block-93 {
|
||||||
margin-left: 0;
|
align-self: auto;
|
||||||
|
min-height: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sort-list-card {
|
.sort-list-card {
|
||||||
@ -7882,6 +7901,10 @@ body {
|
|||||||
.container-copy.footer {
|
.container-copy.footer {
|
||||||
padding-bottom: 90px;
|
padding-bottom: 90px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mobile-menu-buttom-section {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 479px) {
|
@media screen and (max-width: 479px) {
|
||||||
@ -7951,7 +7974,7 @@ body {
|
|||||||
grid-row-gap: 15px;
|
grid-row-gap: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top_head, .topmenuh {
|
.top_head, .bottom_head {
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
}
|
}
|
||||||
@ -9132,7 +9155,7 @@ body {
|
|||||||
top: 58px;
|
top: 58px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topmenub {
|
.bottom_head {
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
}
|
}
|
||||||
@ -9400,6 +9423,12 @@ body {
|
|||||||
#w-node-_35f55517-cbe0-9ee3-13bb-a3ed00029bba-00029ba8, #w-node-_35f55517-cbe0-9ee3-13bb-a3ed00029bc7-00029ba8 {
|
#w-node-_35f55517-cbe0-9ee3-13bb-a3ed00029bba-00029ba8, #w-node-_35f55517-cbe0-9ee3-13bb-a3ed00029bc7-00029ba8 {
|
||||||
justify-self: stretch;
|
justify-self: stretch;
|
||||||
}
|
}
|
||||||
|
.button-for-mobile-menu-block {
|
||||||
|
grid-column-gap: 0px;
|
||||||
|
grid-row-gap: 0px;
|
||||||
|
width: 60px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.flex-block-113 {
|
.flex-block-113 {
|
||||||
|
Reference in New Issue
Block a user