base logig pages cart shipping and payment

This commit is contained in:
hamid zarghami
2025-09-14 12:47:51 +03:30
parent 7b05f96576
commit 6d52d1e91a
13 changed files with 663 additions and 82 deletions
+128 -15
View File
@@ -1,43 +1,156 @@
'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 } 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 [selectedPaymentMethod, setSelectedPaymentMethod] = useState<string>('')
const [discountCode, setDiscountCode] = useState<string>('')
const [isApplyingDiscount, setIsApplyingDiscount] = useState(false)
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>
)
}
// محاسبه هزینه ارسال
const totalShippingCost = shippingData?.results?.shipping?.reduce((total, shop) => {
return total + (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
}
setIsApplyingDiscount(true)
try {
// TODO: پیاده‌سازی API اعمال کد تخفیف
// await applyDiscountCode(discountCode)
toast('کد تخفیف با موفقیت اعمال شد', 'success')
} catch {
toast('کد تخفیف نامعتبر است', 'error')
} finally {
setIsApplyingDiscount(false)
}
}
const handlePayment = async () => {
if (!selectedPaymentMethod) {
toast('لطفاً روش پرداخت را انتخاب کنید', 'error')
return
}
if (!profile?.userAddress) {
toast('لطفاً ابتدا آدرس خود را تکمیل کنید', 'error')
return
}
try {
// TODO: پیاده‌سازی API پرداخت نهایی
// await processPayment({
// paymentMethodId: selectedPaymentMethod,
// discountCode: discountCode || null,
// shippingAddress: profile.userAddress
// })
toast('پرداخت با موفقیت انجام شد', 'success')
} catch {
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={isApplyingDiscount}
/>
<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 defaultValue="option-one">
<div className="flex items-center gap-2">
<RadioGroupItem value="option-one" id="option-one" />
<div className='text-sm'>زین پال</div>
</div>
<div className="flex items-center gap-2">
<RadioGroupItem value="option-one" id="option-one" />
<div className='text-sm'>زین پال</div>
</div>
<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={3}
itemsPrice={580000}
discount={580000}
total={80580000}
confirmHref="/cart/payment"
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"
/>