Удален файл интеграции с Parts Index API и обновлены компоненты для работы с корзиной и избранным. Добавлены функции для обработки добавления товаров в корзину с уведомлениями, улучшена логика работы с избранным, а также добавлены фильтры для истории поиска по производителю.
This commit is contained in:
@ -7,7 +7,6 @@ import CartSummary from "@/components/CartSummary";
|
||||
import CartRecommended from "../components/CartRecommended";
|
||||
import CatalogSubscribe from "@/components/CatalogSubscribe";
|
||||
import MobileMenuBottomSection from "@/components/MobileMenuBottomSection";
|
||||
import CartDebug from "@/components/CartDebug";
|
||||
|
||||
export default function CartPage() {
|
||||
|
||||
@ -39,7 +38,6 @@ export default function CartPage() {
|
||||
</section>
|
||||
<Footer />
|
||||
<MobileMenuBottomSection />
|
||||
<CartDebug />
|
||||
</>
|
||||
);
|
||||
}
|
@ -16,7 +16,7 @@ export default function Favorite() {
|
||||
const [showFiltersMobile, setShowFiltersMobile] = useState(false);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [filterValues, setFilterValues] = useState<{[key: string]: any}>({});
|
||||
const [sortBy, setSortBy] = useState<'name' | 'brand' | 'price' | 'date'>('date');
|
||||
const [sortBy, setSortBy] = useState<'name' | 'brand' | 'date'>('date');
|
||||
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc');
|
||||
|
||||
// Создаем динамические фильтры на основе данных избранного
|
||||
|
@ -1,11 +1,11 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import Head from "next/head";
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
import { useRouter } from "next/router";
|
||||
import { useMutation, ApolloProvider } from "@apollo/client";
|
||||
import { gql } from "@apollo/client";
|
||||
import { apolloClient } from "@/lib/apollo";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
const CONFIRM_PAYMENT = gql`
|
||||
mutation ConfirmPayment($orderId: ID!) {
|
||||
@ -51,8 +51,15 @@ function PaymentSuccessContent() {
|
||||
}
|
||||
}).then(() => {
|
||||
console.log('Оплата заказа подтверждена');
|
||||
toast.success('Оплата успешно подтверждена!', {
|
||||
duration: 3000,
|
||||
icon: '✅',
|
||||
});
|
||||
}).catch((error: any) => {
|
||||
console.error('Ошибка подтверждения оплаты:', error);
|
||||
toast.error('Ошибка подтверждения оплаты: ' + error.message, {
|
||||
duration: 5000,
|
||||
});
|
||||
});
|
||||
}
|
||||
}, [router.query, confirmPayment]);
|
||||
@ -76,7 +83,7 @@ function PaymentSuccessContent() {
|
||||
<link href="/images/webclip.png" rel="apple-touch-icon" />
|
||||
</Head>
|
||||
|
||||
<Header />
|
||||
|
||||
|
||||
<div className="w-layout-blockcontainer container info w-container">
|
||||
<div className="w-layout-vflex flex-block-9">
|
||||
|
@ -1,4 +1,8 @@
|
||||
import * as React from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { GET_CLIENT_ME } from '@/lib/graphql';
|
||||
import Header from '@/components/Header';
|
||||
import Footer from '@/components/Footer';
|
||||
import ProfileSidebar from '@/components/ProfileSidebar';
|
||||
@ -11,6 +15,48 @@ import NotificationMane from "@/components/profile/NotificationMane";
|
||||
import Head from "next/head";
|
||||
|
||||
const ProfileActsPage = () => {
|
||||
const router = useRouter();
|
||||
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);
|
||||
|
||||
const { data: clientData, loading: clientLoading } = useQuery(GET_CLIENT_ME, {
|
||||
skip: !isAuthenticated,
|
||||
onCompleted: (data) => {
|
||||
// Проверяем есть ли у клиента юридические лица
|
||||
if (!data?.clientMe?.legalEntities?.length) {
|
||||
// Если нет юридических лиц, перенаправляем на настройки
|
||||
router.push('/profile-settings?tab=legal');
|
||||
return;
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error('Ошибка загрузки данных клиента:', error);
|
||||
// Если ошибка авторизации, перенаправляем на главную
|
||||
router.push('/');
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// Проверяем авторизацию
|
||||
const token = localStorage.getItem('authToken');
|
||||
if (!token) {
|
||||
router.push('/');
|
||||
return;
|
||||
}
|
||||
setIsAuthenticated(true);
|
||||
}, [router]);
|
||||
|
||||
// Показываем загрузку пока проверяем авторизацию и данные
|
||||
if (!isAuthenticated || clientLoading) {
|
||||
return (
|
||||
<div className="page-wrapper">
|
||||
<div className="flex flex-col justify-center items-center min-h-[400px]">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-red-600"></div>
|
||||
<div className="mt-4 text-gray-600">Загрузка...</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="page-wrapper">
|
||||
<Head>
|
||||
|
@ -1,4 +1,8 @@
|
||||
import * as React from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { GET_CLIENT_ME } from '@/lib/graphql';
|
||||
import Header from '@/components/Header';
|
||||
import Footer from '@/components/Footer';
|
||||
import CatalogSubscribe from '@/components/CatalogSubscribe';
|
||||
@ -8,9 +12,49 @@ import ProfileRequisitiesMain from '@/components/profile/ProfileRequisitiesMain'
|
||||
import ProfileInfo from '@/components/profile/ProfileInfo';
|
||||
import Head from "next/head";
|
||||
|
||||
|
||||
|
||||
const ProfileRequisitiesPage = () => {
|
||||
const router = useRouter();
|
||||
const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);
|
||||
|
||||
const { data: clientData, loading: clientLoading } = useQuery(GET_CLIENT_ME, {
|
||||
skip: !isAuthenticated,
|
||||
onCompleted: (data) => {
|
||||
// Проверяем есть ли у клиента юридические лица
|
||||
if (!data?.clientMe?.legalEntities?.length) {
|
||||
// Если нет юридических лиц, перенаправляем на настройки
|
||||
router.push('/profile-settings?tab=legal');
|
||||
return;
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error('Ошибка загрузки данных клиента:', error);
|
||||
// Если ошибка авторизации, перенаправляем на главную
|
||||
router.push('/');
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// Проверяем авторизацию
|
||||
const token = localStorage.getItem('authToken');
|
||||
if (!token) {
|
||||
router.push('/');
|
||||
return;
|
||||
}
|
||||
setIsAuthenticated(true);
|
||||
}, [router]);
|
||||
|
||||
// Показываем загрузку пока проверяем авторизацию и данные
|
||||
if (!isAuthenticated || clientLoading) {
|
||||
return (
|
||||
<div className="page-wrapper">
|
||||
<div className="flex flex-col justify-center items-center min-h-[400px]">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-red-600"></div>
|
||||
<div className="mt-4 text-gray-600">Загрузка...</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="page-wrapper">
|
||||
<Head>
|
||||
|
@ -502,6 +502,7 @@ export default function SearchResult() {
|
||||
price={`${offer.price.toLocaleString()} ₽`}
|
||||
delivery={`${offer.deliveryDuration} ${offer.deliveryDuration === 1 ? 'день' : 'дней'}`}
|
||||
stock={`${offer.quantity} шт.`}
|
||||
offer={offer}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
@ -105,6 +105,14 @@ const VehicleSearchResultsPage: React.FC<VehicleSearchResultsPageProps> = () =>
|
||||
ssdLength: ssd.length
|
||||
});
|
||||
|
||||
// Создаем базовые параметры URL
|
||||
const urlParams = new URLSearchParams();
|
||||
|
||||
// Добавляем VIN-номер в URL, если он есть
|
||||
if (searchQuery && searchType === 'vin') {
|
||||
urlParams.set('vin', searchQuery);
|
||||
}
|
||||
|
||||
// Если есть SSD, сохраняем его в localStorage для безопасной передачи
|
||||
if (ssd && ssd.trim() !== '') {
|
||||
const vehicleKey = `vehicle_ssd_${catalogCode}_${vehicleId}`;
|
||||
@ -121,25 +129,22 @@ const VehicleSearchResultsPage: React.FC<VehicleSearchResultsPageProps> = () =>
|
||||
|
||||
localStorage.setItem(vehicleKey, ssd);
|
||||
|
||||
// Выбираем URL в зависимости от того, нужно ли пропустить промежуточную страницу
|
||||
const url = skipToCategories
|
||||
? `/vehicle-search/${catalogCode}/${vehicleId}?use_storage=1&ssd_length=${ssd.length}&searchType=categories`
|
||||
: `/vehicle-search/${catalogCode}/${vehicleId}?use_storage=1&ssd_length=${ssd.length}`;
|
||||
|
||||
console.log('🔗 Переходим на URL с localStorage:', url);
|
||||
// Используем replace вместо push для моментального перехода
|
||||
router.replace(url);
|
||||
} else {
|
||||
// Выбираем URL в зависимости от того, нужно ли пропустить промежуточную страницу
|
||||
const url = skipToCategories
|
||||
? `/vehicle-search/${catalogCode}/${vehicleId}?searchType=categories`
|
||||
: `/vehicle-search/${catalogCode}/${vehicleId}`;
|
||||
|
||||
console.log('🔗 Переходим на URL без SSD:', url);
|
||||
// Используем replace вместо push для моментального перехода
|
||||
router.replace(url);
|
||||
urlParams.set('use_storage', '1');
|
||||
urlParams.set('ssd_length', ssd.length.toString());
|
||||
}
|
||||
}, [router]);
|
||||
|
||||
if (skipToCategories) {
|
||||
urlParams.set('searchType', 'categories');
|
||||
}
|
||||
|
||||
// Формируем URL с параметрами
|
||||
const baseUrl = `/vehicle-search/${catalogCode}/${vehicleId}`;
|
||||
const url = urlParams.toString() ? `${baseUrl}?${urlParams.toString()}` : baseUrl;
|
||||
|
||||
console.log('🔗 Переходим на URL:', url);
|
||||
// Используем replace вместо push для моментального перехода
|
||||
router.replace(url);
|
||||
}, [router, searchQuery, searchType]);
|
||||
|
||||
// Предзагрузка и автоматический переход при поиске по VIN, если найден только один автомобиль
|
||||
useEffect(() => {
|
||||
|
Reference in New Issue
Block a user