Files
shop-front/src/app/cart/payment/page.tsx
T
2025-10-08 09:08:01 +03:30

174 lines
7.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client'
import CartSummary from '@/components/CartSummary'
import Layout from '@/hoc/Layout'
import { NextPage } from 'next'
import TitleBack from '../components/TitleBack'
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
import DiscountCard from '../components/DiscountCard'
import { usePaymentMethods, useGetCart, useShippingCost, useApplyDiscountCode, useCheckoutCart } from '../hooks/useCartData'
import { useState } from 'react'
import { toast } from '@/components/Toast'
import { useGetProfile } from '@/app/profile/hooks/useProfileData'
const CartPayment: NextPage = () => {
const { data: paymentMethodsData, isLoading: paymentMethodsLoading } = usePaymentMethods()
const { data: cartData, isLoading: cartLoading } = useGetCart()
const { data: shippingData, isLoading: shippingLoading } = useShippingCost()
const { data: profileData, isLoading: profileLoading } = useGetProfile()
const applyDiscountMutation = useApplyDiscountCode()
const checkoutMutation = useCheckoutCart()
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState<string>('')
const [discountCode, setDiscountCode] = useState<string>('')
const isLoading = paymentMethodsLoading || cartLoading || shippingLoading || profileLoading
if (isLoading) {
return (
<div className="mt-14 px-4 sm:px-8 lg:px-20">
<div className="flex items-center justify-center h-64">
<div className="text-lg">در حال بارگذاری...</div>
</div>
</div>
)
}
const cart = cartData?.results?.cart
const paymentMethods = paymentMethodsData?.results?.paymentMethods || []
const profile = profileData?.results?.info
if (!cart?.items?.length) {
return (
<div className="mt-14 px-4 sm:px-8 lg:px-20">
<div className="flex items-center justify-center h-64">
<div className="text-lg">سبد خرید شما خالی است</div>
</div>
</div>
)
}
// بارگذاری انتخاب‌های ارسال از localStorage
const savedShipments = typeof window !== 'undefined' ? localStorage.getItem('selectedShipments') : null
const selectedShipments = savedShipments ? JSON.parse(savedShipments) : {}
// محاسبه هزینه ارسال بر اساس انتخاب‌های کاربر
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
const handlePaymentMethodChange = (value: string) => {
setSelectedPaymentMethod(value)
}
const handleDiscountCodeSubmit = async () => {
if (!discountCode.trim()) {
toast('لطفاً کد تخفیف را وارد کنید', 'error')
return
}
try {
await applyDiscountMutation.mutateAsync({ discount_code: discountCode })
toast('کد تخفیف با موفقیت اعمال شد', 'success')
setDiscountCode('')
} catch (error: unknown) {
const errorMessage = (error as { response?: { data?: { message?: string } } })?.response?.data?.message || 'کد تخفیف نامعتبر است'
toast(errorMessage, 'error')
}
}
const handlePayment = async () => {
if (!selectedPaymentMethod) {
toast('لطفاً روش پرداخت را انتخاب کنید', 'error')
return
}
if (!profile?.userAddress) {
toast('لطفاً ابتدا آدرس خود را تکمیل کنید', 'error')
return
}
const response = await checkoutMutation.mutateAsync({
payment_method_id: selectedPaymentMethod
})
if (response?.results?.paymentData?.redirectUrl) {
window.location.href = response.results.paymentData.redirectUrl
} else {
toast('خطا در دریافت لینک پرداخت', 'error')
}
}
return (
<div className="mt-14 px-4 sm:px-8 lg:px-20">
<div className="mt-6 flex flex-col lg:flex-row gap-6">
<div className='flex-1'>
<TitleBack title='پرداخت' />
<DiscountCard
discountCode={discountCode}
setDiscountCode={setDiscountCode}
onSubmit={handleDiscountCodeSubmit}
isLoading={applyDiscountMutation.isPending}
/>
<div className='mt-5 border border-border rounded-2xl p-4 sm:p-6 font-light'>
<div>انتخاب روش پرداخت</div>
<div className='mt-6 sm:mt-10 text-[#333333] font-light'>
<RadioGroup
value={selectedPaymentMethod}
onValueChange={handlePaymentMethodChange}
>
{paymentMethods.map((method) => (
<div key={method._id} className="flex items-center gap-2 mb-3">
<RadioGroupItem
value={method._id}
id={method._id}
disabled={!method.isActive}
/>
<label
htmlFor={method._id}
className={`text-sm ${method.isActive ? 'cursor-pointer' : 'cursor-not-allowed'} ${!method.isActive ? 'text-gray-400' : ''}`}
>
<span className="font-medium">{method.title_fa}</span>
{method.provider && (
<span className="text-xs text-gray-500 mr-2">
({method.provider})
</span>
)}
</label>
</div>
))}
</RadioGroup>
</div>
</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={handlePayment}
confirmLabel="پرداخت"
className="w-full"
isLoading={checkoutMutation.isPending}
/>
</div>
</div>
</div>
)
}
export default function CartPaymentWithLayout() {
return (
<Layout>
<CartPayment />
</Layout>
)
}