232 lines
9.9 KiB
TypeScript
232 lines
9.9 KiB
TypeScript
'use client'
|
||
import CartSummary from '@/components/CartSummary'
|
||
import Layout from '@/hoc/Layout'
|
||
import { NextPage } from 'next'
|
||
// import CartItem from '../components/CartItem'
|
||
import TitleBack from '../components/TitleBack'
|
||
import ShippingMethodSelector from '../components/ShippingMethodSelector'
|
||
import { Location } from 'iconsax-react'
|
||
import { useGetCart, useSaveShipmentCart, useShippingCost } from '../hooks/useCartData'
|
||
// import { CartItemType } from '../types/Types'
|
||
import { useGetProfile } from '@/app/profile/hooks/useProfileData'
|
||
import Link from 'next/link'
|
||
import { useState, useEffect } from 'react'
|
||
import { toast } from '@/components/Toast'
|
||
import { extractErrorMessage } from '@/helpers/errorUtils'
|
||
|
||
const CartShipping: NextPage = () => {
|
||
|
||
const { data: cartData, isLoading: cartLoading, error: cartError } = useGetCart()
|
||
const { data: shippingData, isLoading: shippingLoading, error: shippingError } = useShippingCost()
|
||
const { data: profileData, isLoading: profileLoading, error: profileError } = useGetProfile()
|
||
const { mutate: saveShipmentCart } = useSaveShipmentCart()
|
||
|
||
// State برای ذخیره انتخابهای روش ارسال
|
||
const [selectedShipments, setSelectedShipments] = useState<Record<string, number>>({})
|
||
const [isSavingShipment, setIsSavingShipment] = useState(false)
|
||
|
||
// بارگذاری انتخابهای قبلی از localStorage
|
||
useEffect(() => {
|
||
const savedShipments = localStorage.getItem('selectedShipments')
|
||
if (savedShipments) {
|
||
setSelectedShipments(JSON.parse(savedShipments))
|
||
}
|
||
}, [])
|
||
|
||
// ذخیره انتخابها در localStorage
|
||
useEffect(() => {
|
||
if (Object.keys(selectedShipments).length > 0) {
|
||
localStorage.setItem('selectedShipments', JSON.stringify(selectedShipments))
|
||
}
|
||
}, [selectedShipments])
|
||
|
||
// پاک کردن انتخابهای نامعتبر وقتی shippingData تغییر میکند
|
||
useEffect(() => {
|
||
if (shippingData?.results?.shipping) {
|
||
const validShopIds = new Set(shippingData.results.shipping.map(shop => shop.shopId))
|
||
const filteredShipments = Object.fromEntries(
|
||
Object.entries(selectedShipments).filter(([shopId]) => validShopIds.has(shopId))
|
||
)
|
||
|
||
if (Object.keys(filteredShipments).length !== Object.keys(selectedShipments).length) {
|
||
setSelectedShipments(filteredShipments)
|
||
}
|
||
}
|
||
}, [shippingData, selectedShipments])
|
||
|
||
// هندلر انتخاب روش ارسال
|
||
const handleShipmentSelect = (shopId: string, shipperId: number) => {
|
||
setSelectedShipments(prev => ({
|
||
...prev,
|
||
[shopId]: shipperId
|
||
}))
|
||
}
|
||
|
||
// چک کردن اینکه آیا همه فروشگاهها روش ارسال انتخاب کردهاند
|
||
const allShipmentsSelected = shippingData?.results?.shipping?.every(shop =>
|
||
selectedShipments[shop.shopId] !== undefined
|
||
) || false
|
||
|
||
// هندلر پاک کردن همه انتخابها
|
||
const handleClearSelections = () => {
|
||
setSelectedShipments({})
|
||
localStorage.removeItem('selectedShipments')
|
||
}
|
||
|
||
// هندلر ذخیره انتخابهای ارسال و انتقال به صفحه پرداخت
|
||
const handleProceedToPayment = async () => {
|
||
if (!allShipmentsSelected) return
|
||
|
||
setIsSavingShipment(true)
|
||
|
||
// فیلتر کردن selectedShipments تا فقط shop هایی که در shippingData وجود دارند
|
||
const validShopIds = new Set(shippingData?.results?.shipping?.map(shop => shop.shopId) || [])
|
||
|
||
// تبدیل selectedShipments به فرمت مورد نیاز API
|
||
const shipmentsInfo = Object.entries(selectedShipments)
|
||
.filter(([shopId]) => validShopIds.has(shopId))
|
||
.map(([shopId, shipperId]) => ({
|
||
shopId,
|
||
shipmentId: shipperId
|
||
}))
|
||
|
||
|
||
// ذخیره انتخابها در API
|
||
await new Promise<void>((resolve, reject) => {
|
||
saveShipmentCart({ shipmentsInfo }, {
|
||
onSuccess: () => {
|
||
resolve()
|
||
window.location.href = '/cart/payment'
|
||
},
|
||
onError: (error) => {
|
||
setIsSavingShipment(false)
|
||
toast(extractErrorMessage(error))
|
||
reject(error)
|
||
}
|
||
})
|
||
})
|
||
|
||
}
|
||
|
||
if (cartLoading || shippingLoading || profileLoading) {
|
||
return (
|
||
<div className="mt-14 px-4 sm:px-6 lg:px-20">
|
||
<div className="flex items-center justify-center h-64">
|
||
<div className="text-lg">در حال بارگذاری...</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
if (cartError || shippingError || profileError) {
|
||
return (
|
||
<div className="mt-14 px-4 sm:px-6 lg:px-20">
|
||
<div className="flex items-center justify-center h-64">
|
||
<div className="text-lg text-red-500">خطا در بارگذاری اطلاعات</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
const cart = cartData?.results?.cart
|
||
const items = cart?.items || []
|
||
const profile = profileData?.results?.info
|
||
|
||
if (!items.length) {
|
||
return (
|
||
<div className="mt-14 px-4 sm:px-6 lg:px-20">
|
||
<div className="flex items-center justify-center h-64">
|
||
<div className="text-lg">سبد خرید شما خالی است</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
// محاسبه هزینه ارسال بر اساس انتخابهای کاربر
|
||
const totalShippingCost = shippingData?.results?.shipping?.reduce((total, shop) => {
|
||
const selectedShipperId = selectedShipments[shop.shopId]
|
||
const selectedShipper = shop.shippers?.find(shipper => shipper.shipperId === selectedShipperId)
|
||
return total + (selectedShipper?.totalShippingCost || shop.shippers?.[0]?.totalShippingCost || 0)
|
||
}, 0) || 0
|
||
|
||
// محاسبه قیمت نهایی
|
||
const finalTotal = (cart?.payable_price || 0) + totalShippingCost
|
||
|
||
return (
|
||
<div className="mt-14 px-4 sm:px-6 lg:px-20">
|
||
|
||
<div className="mt-6 flex flex-col lg:flex-row gap-6">
|
||
<div className='flex-1'>
|
||
<TitleBack title='آدرس و تایید جزئیات' />
|
||
<div className='mt-5 border border-border rounded-2xl p-4 sm:p-6 flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4'>
|
||
<div className='flex gap-2 items-start sm:items-center'>
|
||
<Location size={20} color='#333333' className='min-w-5 mt-1 sm:mt-0' />
|
||
<div className='text-xs text-[#7F7F7F]'>
|
||
<div>
|
||
آدرس تحویل سفارش
|
||
</div>
|
||
{profile?.userAddress && (
|
||
<div className='mt-2 text-sm text-black'>
|
||
{profile.userAddress.address}
|
||
{profile.userAddress.city && `، ${profile.userAddress.city.name}`}
|
||
{profile.userAddress.province && `، ${profile.userAddress.province.name}`}
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
<Link href={'/profile'} className='text-primary text-sm self-end sm:self-auto'>ویرایش</Link>
|
||
</div>
|
||
|
||
<ShippingMethodSelector
|
||
shippingData={shippingData?.results?.shipping || []}
|
||
selectedShipments={selectedShipments}
|
||
onShipmentSelect={handleShipmentSelect}
|
||
onClearSelections={handleClearSelections}
|
||
/>
|
||
|
||
{/* <div className="flex-1 mt-5 border border-border p-4 sm:p-5 rounded-2xl">
|
||
{items.map((item: CartItemType, index: number) => {
|
||
if (!item || !item.product || !item.variant) {
|
||
return null
|
||
}
|
||
return (
|
||
<CartItem
|
||
key={`${item.product._id}-${item.variant._id}`}
|
||
item={item}
|
||
noBorder={index === 0}
|
||
/>
|
||
)
|
||
})}
|
||
</div> */}
|
||
</div>
|
||
<div className="w-full lg:w-[360px] lg:flex-shrink-0">
|
||
<CartSummary
|
||
itemsCount={cart?.items_count || 0}
|
||
itemsPrice={cart?.retail_price || 0}
|
||
discount={cart?.total_discount || 0}
|
||
shippingCost={totalShippingCost}
|
||
total={finalTotal}
|
||
onConfirm={handleProceedToPayment}
|
||
confirmLabel="پرداخت"
|
||
className="w-full"
|
||
confirmDisabled={!allShipmentsSelected}
|
||
isLoading={isSavingShipment}
|
||
/>
|
||
{!allShipmentsSelected && (
|
||
<div className="mt-2 text-sm text-red-600 text-center">
|
||
لطفا برای همه فروشگاهها روش ارسال انتخاب کنید
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default function CartShippingWithLayout() {
|
||
return (
|
||
<Layout>
|
||
<CartShipping />
|
||
</Layout>
|
||
)
|
||
} |