compare
This commit is contained in:
+154
-3
@@ -6,17 +6,20 @@ import { NextPage } from 'next'
|
||||
import Image from 'next/image'
|
||||
import { useSearchParams } from 'next/navigation'
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useGetCompare } from './hooks/useCompareData'
|
||||
import { useGetCompare, useSearchCompareProduct } from './hooks/useCompareData'
|
||||
import { useLocalCart } from '@/app/product/hooks/useLocalCart'
|
||||
import { toast } from '@/components/Toast'
|
||||
import { CompareProduct } from './types/Types'
|
||||
import { useSharedStore } from '@/share/store/sharedStore'
|
||||
import DefaulModal from '@/components/DefaulModal'
|
||||
|
||||
const ComparePage: NextPage = () => {
|
||||
|
||||
const [productIds, setProductIds] = useState<string[]>([]);
|
||||
const [isCompareModalOpen, setIsCompareModalOpen] = useState(false);
|
||||
const search = useSearchParams()
|
||||
const { data, isLoading } = useGetCompare(productIds)
|
||||
const { data: searchData } = useSearchCompareProduct(productIds[0])
|
||||
const { addToLocalCart } = useLocalCart()
|
||||
const { isLogin } = useSharedStore()
|
||||
|
||||
@@ -34,10 +37,58 @@ const ComparePage: NextPage = () => {
|
||||
toast('محصول به سبد خرید اضافه شد', 'success')
|
||||
}
|
||||
|
||||
const handleProductClick = (productId: number) => {
|
||||
const productIdStr = productId.toString()
|
||||
|
||||
// بررسی اینکه محصول قبلاً اضافه نشده باشد
|
||||
if (productIds.includes(productIdStr)) {
|
||||
toast('این محصول قبلاً در لیست مقایسه اضافه شده است', 'error')
|
||||
return
|
||||
}
|
||||
|
||||
// اضافه کردن محصول به لیست مقایسه
|
||||
const newProductIds = [...productIds, productIdStr]
|
||||
console.log('New product IDs:', newProductIds)
|
||||
setProductIds(newProductIds)
|
||||
|
||||
// بهروزرسانی URL با محصولات جدید
|
||||
const url = new URL(window.location.href)
|
||||
url.searchParams.set('productIds', newProductIds.join(','))
|
||||
url.searchParams.delete('productId') // حذف productId قدیمی
|
||||
window.history.pushState({}, '', url.toString())
|
||||
|
||||
setIsCompareModalOpen(false)
|
||||
toast('محصول به لیست مقایسه اضافه شد', 'success')
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const productId = search.get('productId')
|
||||
const productIdsParam = search.get('productIds')
|
||||
|
||||
console.log('URL params - productId:', productId, 'productIds:', productIdsParam)
|
||||
|
||||
if (productIdsParam) {
|
||||
// اگر productIds در URL موجود است، آن را استفاده کن
|
||||
const ids = productIdsParam.split(',').filter(id => id.trim())
|
||||
console.log('Parsed product IDs:', ids)
|
||||
setProductIds(ids)
|
||||
|
||||
// حذف productId قدیمی از URL
|
||||
if (productId) {
|
||||
setProductIds([productId]);
|
||||
const url = new URL(window.location.href)
|
||||
url.searchParams.delete('productId')
|
||||
window.history.replaceState({}, '', url.toString())
|
||||
}
|
||||
} else if (productId) {
|
||||
// اگر فقط productId موجود است، آن را به productIds تبدیل کن
|
||||
console.log('Single product ID:', productId)
|
||||
setProductIds([productId])
|
||||
|
||||
// URL را به productIds تبدیل کن
|
||||
const url = new URL(window.location.href)
|
||||
url.searchParams.delete('productId')
|
||||
url.searchParams.set('productIds', productId)
|
||||
window.history.replaceState({}, '', url.toString())
|
||||
}
|
||||
}, [search]);
|
||||
|
||||
@@ -74,7 +125,7 @@ const ComparePage: NextPage = () => {
|
||||
return (
|
||||
<Layout>
|
||||
<div className='mt-24 px-20'>
|
||||
<div className='flex border-b border-border'>
|
||||
<div className='flex items-center border-b border-border'>
|
||||
{products.map((product, index) => (
|
||||
<div key={product._id} className={`w-[300px] flex flex-col justify-center items-center ${index < products.length - 1 ? 'border-l border-border' : ''} pb-5`}>
|
||||
<Image
|
||||
@@ -104,6 +155,10 @@ const ComparePage: NextPage = () => {
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<Button variant={'outline'} onClick={() => setIsCompareModalOpen(true)}>
|
||||
افزودن به مقایسه
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className='mt-8'>
|
||||
@@ -127,6 +182,102 @@ const ComparePage: NextPage = () => {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* مودال انتخاب کالا برای مقایسه */}
|
||||
<DefaulModal
|
||||
open={isCompareModalOpen}
|
||||
close={() => setIsCompareModalOpen(false)}
|
||||
isHeader={true}
|
||||
title_header="انتخاب کالا برای مقایسه"
|
||||
width={800}
|
||||
>
|
||||
<div className="space-y-6">
|
||||
{/* نوار جستجو */}
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="text-sm text-gray-600 whitespace-nowrap">
|
||||
759 كالا
|
||||
</div>
|
||||
<div className="flex-1 relative">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="نام یا کد کالا را وارد کنید"
|
||||
className="w-full px-4 py-3 pr-12 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
|
||||
/>
|
||||
<div className="absolute left-3 top-1/2 transform -translate-y-1/2">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||
<circle cx="11" cy="11" r="8" />
|
||||
<path d="m21 21-4.35-4.35" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* عنوان برترین کالاها */}
|
||||
<div className="text-sm font-medium text-gray-800">
|
||||
برترین کالاها برای مقایسه
|
||||
</div>
|
||||
|
||||
{/* لیست محصولات */}
|
||||
<div className="grid grid-cols-3 gap-3 max-h-80 overflow-y-auto">
|
||||
{searchData?.results?.products?.slice(0, 6).map((product: CompareProduct) => (
|
||||
<div
|
||||
key={product._id}
|
||||
className="border border-gray-200 rounded-lg p-3 hover:shadow-md transition-shadow bg-white cursor-pointer"
|
||||
onClick={() => handleProductClick(product._id)}
|
||||
>
|
||||
<div className="flex flex-col items-center text-center space-y-2">
|
||||
{/* تصویر محصول */}
|
||||
<div className="w-full h-24 relative">
|
||||
<Image
|
||||
src={product.imagesUrl.cover}
|
||||
alt={product.title_fa}
|
||||
fill
|
||||
className="object-cover rounded-lg"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* متن ذخیره سازی */}
|
||||
<div className="text-xs text-blue-600 font-medium">
|
||||
ذخیره سازی
|
||||
</div>
|
||||
|
||||
{/* نام محصول */}
|
||||
<h3 className="text-xs font-medium text-gray-900 leading-tight">
|
||||
{product.title_fa}
|
||||
</h3>
|
||||
|
||||
{/* ستارهها */}
|
||||
<div className="flex items-center gap-1">
|
||||
{[...Array(5)].map((_, i) => (
|
||||
<svg key={i} width="10" height="10" viewBox="0 0 24 24" fill={i < 3.5 ? "#FFD700" : "#E5E7EB"} className="w-2.5 h-2.5">
|
||||
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" />
|
||||
</svg>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* قیمت */}
|
||||
<div className="text-xs font-medium text-gray-900">
|
||||
{product.default_variant.price.selling_price.toLocaleString()} <span className="text-[10px]">تومان</span>
|
||||
</div>
|
||||
|
||||
{/* آیکون قلب */}
|
||||
<button
|
||||
className="p-1 hover:bg-gray-100 rounded-full transition-colors"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
// TODO: اضافه کردن به علاقهمندیها
|
||||
}}
|
||||
>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||
<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</DefaulModal>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,18 @@ import { CompareResponse } from "../types/Types";
|
||||
export const getCompare = async (
|
||||
productIds: string[]
|
||||
): Promise<CompareResponse> => {
|
||||
const { data } = await axios.get(`/product/compare?productIds=${productIds}`);
|
||||
console.log("API call - productIds:", productIds);
|
||||
|
||||
// روش اول: ارسال آرایه به صورت جداگانه
|
||||
const params = new URLSearchParams();
|
||||
productIds.forEach((id) => {
|
||||
params.append("productIds", id);
|
||||
});
|
||||
|
||||
console.log("Final URL:", `/product/compare?${params.toString()}`);
|
||||
|
||||
const { data } = await axios.get(`/product/compare?${params.toString()}`);
|
||||
console.log("API response:", data);
|
||||
return data;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import * as api from "../service/Service";
|
||||
import { useSharedStore } from "@/share/store/sharedStore";
|
||||
|
||||
export const useGetDetailProduct = (id: string) => {
|
||||
return useQuery({
|
||||
@@ -26,10 +27,11 @@ export const useAddQuestion = () => {
|
||||
};
|
||||
|
||||
export const useCheckWishProduct = (productId: string, variantId: string) => {
|
||||
const { isLogin } = useSharedStore();
|
||||
return useQuery({
|
||||
queryKey: ["check-wish-product", productId, variantId],
|
||||
queryFn: () => api.checkWishProduct(productId, variantId),
|
||||
enabled: !!productId && !!variantId,
|
||||
enabled: !!productId && !!variantId && isLogin,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -73,7 +73,7 @@ axiosInstance.interceptors.response.use(
|
||||
console.error("Token refresh failed:", refreshError);
|
||||
await removeToken();
|
||||
await removeRefreshToken();
|
||||
window.location.href = `/`;
|
||||
// window.location.href = `/`;
|
||||
return Promise.reject(refreshError);
|
||||
} finally {
|
||||
window.isRefreshingToken = false;
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
export const TOKEN_NAME = "sh_token";
|
||||
export const REFRESH_TOKEN_NAME = "sh_refresh_token";
|
||||
export const BASE_URL = "https://shop-api.dev.danakcorp.com";
|
||||
// export const BASE_URL = "https://api.shinan.ir";
|
||||
// export const BASE_URL = "https://shop-api.dev.danakcorp.com";
|
||||
export const BASE_URL = "http://192.168.1.111:4000";
|
||||
|
||||
export const PRIMARY_COLOR = "#015699";
|
||||
|
||||
Reference in New Issue
Block a user