pravkiend cart
This commit is contained in:
@ -11,6 +11,7 @@ const CartInfo: React.FC = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="section-info">
|
||||
<div className="w-layout-blockcontainer container info w-container">
|
||||
<div className="w-layout-vflex flex-block-9">
|
||||
<div className="w-layout-hflex flex-block-7">
|
||||
@ -44,6 +45,7 @@ const CartInfo: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -80,14 +80,49 @@ const CartItem: React.FC<CartItemProps> = ({
|
||||
<div className="text-block-21-copy-copy">{deliveryDate}</div>
|
||||
</div>
|
||||
<div className="w-layout-hflex pcs-cart-s1">
|
||||
<div className="minus-plus" onClick={() => onCountChange && onCountChange(count - 1)} style={{ cursor: 'pointer' }}>
|
||||
<img loading="lazy" src="/images/minus_icon.svg" alt="-" />
|
||||
<div
|
||||
className="minus-plus"
|
||||
onClick={() => onCountChange && onCountChange(count - 1)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
aria-label="Уменьшить количество"
|
||||
tabIndex={0}
|
||||
onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && onCountChange && onCountChange(count - 1)}
|
||||
role="button"
|
||||
>
|
||||
<div className="pluspcs w-embed">
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 10.5V9.5H14V10.5H6Z" fill="currentColor"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div className="input-pcs">
|
||||
<div className="text-block-26">{count}</div>
|
||||
<input
|
||||
type="number"
|
||||
min={1}
|
||||
value={count}
|
||||
onChange={e => {
|
||||
const value = Math.max(1, parseInt(e.target.value, 10) || 1);
|
||||
onCountChange && onCountChange(value);
|
||||
}}
|
||||
className="text-block-26 w-full text-center outline-none"
|
||||
aria-label="Количество"
|
||||
style={{ width: 40 }}
|
||||
/>
|
||||
</div>
|
||||
<div className="minus-plus" onClick={() => onCountChange && onCountChange(count + 1)} style={{ cursor: 'pointer' }}>
|
||||
<img loading="lazy" src="/images/plus_icon.svg" alt="+" />
|
||||
<div
|
||||
className="minus-plus"
|
||||
onClick={() => onCountChange && onCountChange(count + 1)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
aria-label="Увеличить количество"
|
||||
tabIndex={0}
|
||||
onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && onCountChange && onCountChange(count + 1)}
|
||||
role="button"
|
||||
>
|
||||
<div className="pluspcs w-embed">
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 10.5V9.5H14V10.5H6ZM9.5 6H10.5V14H9.5V6Z" fill="currentColor"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-layout-hflex flex-block-39-copy-copy">
|
||||
@ -100,7 +135,31 @@ const CartItem: React.FC<CartItemProps> = ({
|
||||
<path d="M9 16.5L7.84 15.4929C3.72 11.93 1 9.57248 1 6.69619C1 4.33869 2.936 2.5 5.4 2.5C6.792 2.5 8.128 3.11798 9 4.08692C9.872 3.11798 11.208 2.5 12.6 2.5C15.064 2.5 17 4.33869 17 6.69619C17 9.57248 14.28 11.93 10.16 15.4929L9 16.5Z" fill={favorite ? "#e53935" : "currentColor"} />
|
||||
</svg>
|
||||
</div>
|
||||
<img src="/images/delete.svg" loading="lazy" alt="" className="image-13" style={{ cursor: 'pointer' }} onClick={onRemove} />
|
||||
<div
|
||||
className="bdel"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
aria-label="Удалить из корзины"
|
||||
onClick={onRemove}
|
||||
onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && onRemove && onRemove()}
|
||||
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');
|
||||
}}
|
||||
>
|
||||
<svg width="18" height="19" 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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -90,9 +90,24 @@ const CartList: React.FC = () => {
|
||||
</div>
|
||||
<div className="text-block-30">Выделить всё</div>
|
||||
</div>
|
||||
<div className="w-layout-hflex select-all-block" onClick={handleRemoveSelected} style={{ cursor: 'pointer' }}>
|
||||
<div className="w-layout-hflex select-all-block" onClick={handleRemoveSelected} style={{ cursor: 'pointer' }}
|
||||
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="text-block-30">Удалить выбранные</div>
|
||||
<img src="/images/delete.svg" loading="lazy" alt="" className="image-13" />
|
||||
<svg width="18" height="19" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg" className="image-13">
|
||||
<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>
|
||||
</div>
|
||||
{items.length === 0 ? (
|
||||
|
@ -667,10 +667,10 @@ const CartSummary: React.FC = () => {
|
||||
<button
|
||||
className="submit-button fill w-button"
|
||||
onClick={handleProceedToStep2}
|
||||
disabled={summary.totalItems === 0}
|
||||
disabled={summary.totalItems === 0 || !consent}
|
||||
style={{
|
||||
opacity: summary.totalItems === 0 ? 0.5 : 1,
|
||||
cursor: summary.totalItems === 0 ? 'not-allowed' : 'pointer'
|
||||
opacity: summary.totalItems === 0 || !consent ? 0.5 : 1,
|
||||
cursor: summary.totalItems === 0 || !consent ? 'not-allowed' : 'pointer'
|
||||
}}
|
||||
>
|
||||
Оформить заказ
|
||||
@ -722,10 +722,9 @@ const CartSummary: React.FC = () => {
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '8px 12px',
|
||||
border: '1px solid #D0D0D0',
|
||||
borderRadius: '4px',
|
||||
fontSize: '14px',
|
||||
fontFamily: 'inherit'
|
||||
border: 'none',
|
||||
outline: 'none',
|
||||
boxShadow: 'none',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@ -738,10 +737,9 @@ const CartSummary: React.FC = () => {
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '8px 12px',
|
||||
border: '1px solid #D0D0D0',
|
||||
borderRadius: '4px',
|
||||
fontSize: '14px',
|
||||
fontFamily: 'inherit'
|
||||
border: 'none',
|
||||
outline: 'none',
|
||||
boxShadow: 'none',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@ -882,10 +880,10 @@ const CartSummary: React.FC = () => {
|
||||
<button
|
||||
className="submit-button fill w-button"
|
||||
onClick={handleSubmit}
|
||||
disabled={summary.totalItems === 0 || isProcessing || !recipientName.trim() || !recipientPhone.trim()}
|
||||
disabled={summary.totalItems === 0 || isProcessing || !recipientName.trim() || !recipientPhone.trim() || !consent}
|
||||
style={{
|
||||
opacity: (summary.totalItems === 0 || isProcessing || !recipientName.trim() || !recipientPhone.trim()) ? 0.5 : 1,
|
||||
cursor: (summary.totalItems === 0 || isProcessing || !recipientName.trim() || !recipientPhone.trim()) ? 'not-allowed' : 'pointer'
|
||||
opacity: (summary.totalItems === 0 || isProcessing || !recipientName.trim() || !recipientPhone.trim() || !consent) ? 0.5 : 1,
|
||||
cursor: (summary.totalItems === 0 || isProcessing || !recipientName.trim() || !recipientPhone.trim() || !consent) ? 'not-allowed' : 'pointer'
|
||||
}}
|
||||
>
|
||||
{isProcessing ? 'Оформляем заказ...' :
|
||||
@ -896,7 +894,7 @@ const CartSummary: React.FC = () => {
|
||||
{error && <div style={{ color: 'red', marginTop: 10 }}>{error}</div>}
|
||||
|
||||
{/* Кнопка "Назад" */}
|
||||
<button
|
||||
{/* <button
|
||||
onClick={handleBackToStep1}
|
||||
style={{
|
||||
background: 'none',
|
||||
@ -910,7 +908,7 @@ const CartSummary: React.FC = () => {
|
||||
}}
|
||||
>
|
||||
← Назад к настройкам доставки
|
||||
</button>
|
||||
</button> */}
|
||||
|
||||
<div className="w-layout-hflex privacy-consent" style={{ cursor: 'pointer' }} onClick={() => setConsent((v) => !v)}>
|
||||
<div
|
||||
|
@ -171,9 +171,9 @@ const FavoriteList: React.FC<FavoriteListProps> = ({
|
||||
</div>
|
||||
<div className="sort-item-comments">Комментарий</div>
|
||||
</div>
|
||||
<div className="w-layout-hflex add-to-cart-block-copy">
|
||||
{/* <div className="w-layout-hflex add-to-cart-block-copy">
|
||||
<div className="text-sm font-medium text-gray-600">Действия</div>
|
||||
</div>
|
||||
</div> */}
|
||||
{favorites.length > 0 && (
|
||||
<div
|
||||
className="w-layout-hflex select-all-block"
|
||||
@ -233,8 +233,10 @@ const FavoriteList: React.FC<FavoriteListProps> = ({
|
||||
<div className="w-layout-hflex add-to-cart-block-copy">
|
||||
<button
|
||||
onClick={() => handleSearchItem(item)}
|
||||
className="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors duration-200 flex items-center gap-2 text-sm font-medium"
|
||||
>
|
||||
className="px-4 py-2 bg-red-600 hover:bg-red-700 text-white rounded-lg transition-colors duration-200 flex items-center gap-2 text-sm font-medium"
|
||||
style={{color: '#fff'}}
|
||||
>
|
||||
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
|
@ -2,53 +2,55 @@ import React from "react";
|
||||
import Link from "next/link";
|
||||
|
||||
const AvailableParts = () => (
|
||||
<section>
|
||||
<div className="w-layout-blockcontainer container w-container">
|
||||
<div className="w-layout-vflex flex-block-5">
|
||||
<div className="w-layout-hflex flex-block-31">
|
||||
<h2 className="heading-4">Автозапчасти в наличии</h2>
|
||||
<div className="w-layout-hflex flex-block-29">
|
||||
<Link href="/catalog" className="text-block-18">
|
||||
Ко всем автозапчастям
|
||||
</Link>
|
||||
<img src="/images/Arrow_right.svg" loading="lazy" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-layout-hflex flex-block-6">
|
||||
<Link href="/catalog" className="div-block-12" id="w-node-bc394713-4b8e-44e3-8ddf-3edc1c31a743-3b3232bc">
|
||||
<h1 className="heading-7">Аксессуары</h1>
|
||||
<img src="/images/IMG_1.png" loading="lazy" alt="" className="image-22" />
|
||||
<section>
|
||||
<div className="w-layout-blockcontainer container w-container">
|
||||
<div className="w-layout-vflex flex-block-5">
|
||||
<div className="w-layout-hflex flex-block-31">
|
||||
<h2 className="heading-4">Автозапчасти в наличии</h2>
|
||||
<div className="w-layout-hflex flex-block-29">
|
||||
<Link href="/catalog" className="text-block-18">
|
||||
Ко всем автозапчастям
|
||||
</Link>
|
||||
<Link href="/catalog" className="div-block-12-copy">
|
||||
<h1 className="heading-7">Воздушные фильтры</h1>
|
||||
<img src="/images/IMG_2.png" loading="lazy" alt="" className="image-22" />
|
||||
</Link>
|
||||
<Link href="/catalog" className="div-block-12">
|
||||
<h1 className="heading-7">Шины</h1>
|
||||
<img src="/images/IMG_3.png" loading="lazy" alt="" className="image-22" />
|
||||
</Link>
|
||||
<Link href="/catalog" className="div-block-123">
|
||||
<h1 className="heading-7-white">Аккумуляторы</h1>
|
||||
<img src="/images/IMG_4.png" loading="lazy" alt="" className="image-22" />
|
||||
</Link>
|
||||
<div className="w-layout-hflex flex-block-35" id="w-node-_8908a890-8c8f-e12c-999f-08d5da3bcc01-3b3232bc">
|
||||
<Link href="/catalog" className="div-block-12 small">
|
||||
<h1 className="heading-7">Диски</h1>
|
||||
<img src="/images/IMG_5.png" loading="lazy" alt="" className="image-22" />
|
||||
</Link>
|
||||
<Link href="/catalog" className="div-block-12 small">
|
||||
<h1 className="heading-7">Свечи</h1>
|
||||
<img src="/images/IMG_6.png" loading="lazy" alt="" className="image-22" />
|
||||
</Link>
|
||||
<Link href="/catalog" className="div-block-red small">
|
||||
<h1 className="heading-7-white">Масла</h1>
|
||||
<img src="/images/IMG_7.png" loading="lazy" alt="" className="image-22" />
|
||||
</Link>
|
||||
</div>
|
||||
<img src="/images/Arrow_right.svg" loading="lazy" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-layout-hflex flex-block-6">
|
||||
<Link href="/catalog" className="div-block-12">
|
||||
<h1 className="heading-7">Аксессуары</h1>
|
||||
<img src="/images/IMG_1.png" loading="lazy" alt="" className="image-22" />
|
||||
</Link>
|
||||
<Link href="/catalog" className="div-block-12-copy">
|
||||
<h1 className="heading-7">Воздушные фильтры</h1>
|
||||
<img src="/images/IMG_2.png" loading="lazy" alt="" className="image-22" />
|
||||
</Link>
|
||||
<Link href="/catalog" className="div-block-12">
|
||||
<h1 className="heading-7">Шины</h1>
|
||||
<img src="/images/IMG_3.png" loading="lazy" alt="" className="image-22" />
|
||||
</Link>
|
||||
<Link href="/catalog" className="div-block-123">
|
||||
<h1 className="heading-7-white">Аккумуляторы</h1>
|
||||
<img src="/images/IMG_4.png" loading="lazy" alt="" className="image-22" />
|
||||
</Link>
|
||||
<Link href="/catalog" className="div-block-12 small">
|
||||
<h1 className="heading-7">Диски</h1>
|
||||
<img src="/images/IMG_5.png" loading="lazy" alt="" className="image-22" />
|
||||
</Link>
|
||||
<Link href="/catalog" className="div-block-12 small">
|
||||
<h1 className="heading-7">Свечи</h1>
|
||||
<img src="/images/IMG_6.png" loading="lazy" alt="" className="image-22" />
|
||||
</Link>
|
||||
<Link href="/catalog" className="div-block-red small">
|
||||
<h1 className="heading-7-white">Масла</h1>
|
||||
<img src="/images/IMG_7.png" loading="lazy" alt="" className="image-22" />
|
||||
</Link>
|
||||
<Link href="/catalog" className="div-block-12 small">
|
||||
<h1 className="heading-7">Диски</h1>
|
||||
<img src="/images/IMG_5.png" loading="lazy" alt="" className="image-22" />
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
export default AvailableParts;
|
@ -1,17 +1,23 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useLazyQuery, useQuery } from '@apollo/client';
|
||||
import { SEARCH_LAXIMO_FULLTEXT, GET_LAXIMO_CATEGORIES, GET_LAXIMO_UNITS } from '@/lib/graphql/laximo';
|
||||
import { SEARCH_LAXIMO_FULLTEXT, GET_LAXIMO_CATEGORIES, GET_LAXIMO_UNITS, GET_LAXIMO_QUICK_GROUPS, GET_LAXIMO_QUICK_DETAIL } from '@/lib/graphql/laximo';
|
||||
import VinPartCard from './VinPartCard';
|
||||
|
||||
interface VinLeftbarProps {
|
||||
catalogCode?: string;
|
||||
vehicleId?: string;
|
||||
ssd?: string;
|
||||
vehicleInfo: {
|
||||
catalog: string;
|
||||
vehicleid: string;
|
||||
ssd: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
onSearchResults?: (results: any[]) => void;
|
||||
onNodeSelect?: (node: any) => void;
|
||||
}
|
||||
|
||||
const VinLeftbar: React.FC<VinLeftbarProps> = ({ catalogCode, vehicleId, ssd, onSearchResults, onNodeSelect }) => {
|
||||
const VinLeftbar: React.FC<VinLeftbarProps> = ({ vehicleInfo, onSearchResults, onNodeSelect }) => {
|
||||
const catalogCode = vehicleInfo.catalog;
|
||||
const vehicleId = vehicleInfo.vehicleid;
|
||||
const ssd = vehicleInfo.ssd;
|
||||
const [openIndex, setOpenIndex] = useState<number | null>(null);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [activeTab, setActiveTab] = useState<'uzly' | 'manufacturer'>('uzly');
|
||||
@ -88,6 +94,92 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ catalogCode, vehicleId, ssd, on
|
||||
const showNotFound = isSearchAvailable && searchQuery.trim() && !loading && data && searchResults && searchResults.details && searchResults.details.length === 0;
|
||||
const showTips = isSearchAvailable && !searchQuery.trim() && !loading;
|
||||
|
||||
// --- QuickGroups (от производителя) ---
|
||||
const [selectedQuickGroup, setSelectedQuickGroup] = useState<any | null>(null);
|
||||
const { data: quickGroupsData, loading: quickGroupsLoading, error: quickGroupsError } = useQuery(GET_LAXIMO_QUICK_GROUPS, {
|
||||
variables: { catalogCode, vehicleId, ssd },
|
||||
skip: !catalogCode || !vehicleId || activeTab !== 'manufacturer',
|
||||
errorPolicy: 'all'
|
||||
});
|
||||
const quickGroups = quickGroupsData?.laximoQuickGroups || [];
|
||||
|
||||
const [expandedQuickGroups, setExpandedQuickGroups] = useState<Set<string>>(new Set());
|
||||
|
||||
const handleQuickGroupToggle = (groupId: string) => {
|
||||
setExpandedQuickGroups(prev => {
|
||||
const newSet = new Set(prev);
|
||||
if (newSet.has(groupId)) {
|
||||
newSet.delete(groupId);
|
||||
} else {
|
||||
newSet.add(groupId);
|
||||
}
|
||||
return newSet;
|
||||
});
|
||||
};
|
||||
|
||||
const handleQuickGroupClick = (group: any) => {
|
||||
if (group.link) {
|
||||
setSelectedQuickGroup(group);
|
||||
} else {
|
||||
handleQuickGroupToggle(group.quickgroupid);
|
||||
}
|
||||
};
|
||||
|
||||
// Детали выбранной группы (если link: true)
|
||||
console.log('QuickDetail QUERY VARS', {
|
||||
catalogCode,
|
||||
vehicleId,
|
||||
quickGroupId: selectedQuickGroup?.quickgroupid,
|
||||
ssd
|
||||
});
|
||||
|
||||
const skipQuickDetail =
|
||||
!selectedQuickGroup ||
|
||||
!catalogCode ||
|
||||
!vehicleId ||
|
||||
!selectedQuickGroup.quickgroupid ||
|
||||
!ssd;
|
||||
|
||||
const { data: quickDetailData, loading: quickDetailLoading, error: quickDetailError } = useQuery(GET_LAXIMO_QUICK_DETAIL, {
|
||||
variables: selectedQuickGroup ? {
|
||||
catalogCode,
|
||||
vehicleId,
|
||||
quickGroupId: selectedQuickGroup.quickgroupid,
|
||||
ssd
|
||||
} : undefined,
|
||||
skip: skipQuickDetail,
|
||||
errorPolicy: 'all'
|
||||
});
|
||||
const quickDetail = quickDetailData?.laximoQuickDetail;
|
||||
|
||||
const renderQuickGroupTree = (groups: any[], level = 0): React.ReactNode => (
|
||||
<div>
|
||||
{groups.map(group => (
|
||||
<div key={group.quickgroupid} style={{ marginLeft: level * 16, marginBottom: 8 }}>
|
||||
<div
|
||||
className={`flex items-center p-2 rounded cursor-pointer border ${group.link ? 'bg-white hover:bg-red-50 border-gray-200 hover:border-red-300' : 'bg-gray-50 hover:bg-gray-100 border-gray-200'}`}
|
||||
onClick={() => handleQuickGroupClick(group)}
|
||||
>
|
||||
{group.children && group.children.length > 0 && (
|
||||
<svg className={`w-4 h-4 text-gray-400 mr-2 transition-transform ${expandedQuickGroups.has(group.quickgroupid) ? 'rotate-90' : ''}`} fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
||||
</svg>
|
||||
)}
|
||||
<span className={`font-medium ${group.link ? 'text-gray-900' : 'text-gray-600'}`}>{group.name}</span>
|
||||
{group.link && (
|
||||
<span className="ml-2 inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-green-100 text-green-800">Доступен поиск</span>
|
||||
)}
|
||||
</div>
|
||||
{group.children && group.children.length > 0 && expandedQuickGroups.has(group.quickgroupid) && (
|
||||
<div className="mt-1">
|
||||
{renderQuickGroupTree(group.children, level + 1)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="w-layout-vflex vinleftbar">
|
||||
<div className="div-block-2">
|
||||
@ -217,8 +309,47 @@ const VinLeftbar: React.FC<VinLeftbarProps> = ({ catalogCode, vehicleId, ssd, on
|
||||
</>
|
||||
)
|
||||
) : (
|
||||
// Manufacturer tab content (заглушка)
|
||||
<div style={{ padding: '16px', color: '#888' }}>Здесь будет контент "От производителя"</div>
|
||||
// Manufacturer tab content (QuickGroups)
|
||||
<div style={{ padding: '16px' }}>
|
||||
{quickGroupsLoading ? (
|
||||
<div style={{ textAlign: 'center' }}>Загружаем группы быстрого поиска...</div>
|
||||
) : quickGroupsError ? (
|
||||
<div style={{ color: 'red' }}>Ошибка загрузки групп: {quickGroupsError.message}</div>
|
||||
) : selectedQuickGroup ? (
|
||||
<div>
|
||||
<button onClick={() => setSelectedQuickGroup(null)} className="mb-4 px-3 py-1 bg-gray-200 rounded">Назад к группам</button>
|
||||
<h3 className="text-lg font-semibold mb-2">{selectedQuickGroup.name}</h3>
|
||||
{quickDetailLoading ? (
|
||||
<div>Загружаем детали...</div>
|
||||
) : quickDetailError ? (
|
||||
<div style={{ color: 'red' }}>Ошибка загрузки деталей: {quickDetailError.message}</div>
|
||||
) : quickDetail && quickDetail.units && quickDetail.units.length > 0 ? (
|
||||
<div className="space-y-3">
|
||||
{quickDetail.units.map((unit: any) => (
|
||||
<div key={unit.unitid} className="p-3 bg-gray-50 rounded border border-gray-200">
|
||||
<div className="font-medium text-gray-900">{unit.name}</div>
|
||||
{unit.details && unit.details.length > 0 && (
|
||||
<ul className="mt-2 text-sm text-gray-700 list-disc pl-5">
|
||||
{unit.details.map((detail: any) => (
|
||||
<li key={detail.detailid}>
|
||||
<span className="font-medium">{detail.name}</span> <span className="ml-2 text-xs bg-blue-100 text-blue-800 px-2 py-0.5 rounded">OEM: {detail.oem}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div>Нет деталей для этой группы</div>
|
||||
)}
|
||||
</div>
|
||||
) : quickGroups.length > 0 ? (
|
||||
renderQuickGroupTree(quickGroups)
|
||||
) : (
|
||||
<div>Нет доступных групп быстрого поиска</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{/* Tab content end */}
|
||||
</div>
|
||||
|
@ -424,12 +424,12 @@ export default function SearchResult() {
|
||||
<title>Поиск предложений {searchQuery} - Protek</title>
|
||||
</Head>
|
||||
|
||||
<main className="min-h-screen bg-gray-50 flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<div className="animate-spin rounded-full h-32 w-32 border-b-2 border-red-600 mx-auto"></div>
|
||||
<p className="mt-4 text-lg text-gray-600">Поиск предложений...</p>
|
||||
<div className="fixed inset-0 z-50 bg-gray-50 bg-opacity-90 flex items-center justify-center min-h-screen" aria-live="polite">
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<div className="animate-spin rounded-full h-32 w-32 border-b-2 border-red-600 mb-4"></div>
|
||||
<p className="text-lg text-gray-600">Поиск предложений...</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
|
@ -269,13 +269,13 @@ const VehicleDetailsPage = () => {
|
||||
<div className="w-layout-blockcontainer container-vin w-container">
|
||||
{!selectedNode ? (
|
||||
<div className="w-layout-hflex flex-block-13">
|
||||
<VinLeftbar
|
||||
catalogCode={vehicleInfo.catalog}
|
||||
vehicleId={vehicleInfo.vehicleid}
|
||||
ssd={vehicleInfo.ssd}
|
||||
onSearchResults={setFoundParts}
|
||||
onNodeSelect={setSelectedNode}
|
||||
/>
|
||||
{vehicleInfo && vehicleInfo.catalog && vehicleInfo.vehicleid && vehicleInfo.ssd && (
|
||||
<VinLeftbar
|
||||
vehicleInfo={vehicleInfo}
|
||||
onSearchResults={setFoundParts}
|
||||
onNodeSelect={setSelectedNode}
|
||||
/>
|
||||
)}
|
||||
{/* Категории или Knot или карточки */}
|
||||
{foundParts.length > 0 ? (
|
||||
<div className="knot-parts">
|
||||
|
Reference in New Issue
Block a user