'use client'; import { useCart } from "@/components/context/cartcontext"; import Link from "next/link"; import { useState, useEffect } from "react"; import { ShoppingBag, ChevronLeft, ChevronRight, Truck, CreditCard, MapPin, User, Lock } from "lucide-react"; import PaymentMethodsSection from "@/components/PaymentMethods"; import { getCartApi } from "@/public/src/services/cart/api"; import { fetchUserAddresses, type Address, addAddressApi, NewAddressData, updateAddressApi, deleteAddressApi } from "@/public/src/services/address/api"; export default function CheckoutPage() { const { cart } = useCart(); const [shippingMethod, setShippingMethod] = useState('post'); const [isAuthenticated, setIsAuthenticated] = useState(false); const [isLoading, setIsLoading] = useState(true); const [serverSummary, setServerSummary] = useState(null); const [addresses, setAddresses] = useState([]); const [selectedAddressId, setSelectedAddressId] = useState(null); const [showNewAddressForm, setShowNewAddressForm] = useState(false); const [isAddressLoading, setIsAddressLoading] = useState(true); const [newAddress, setNewAddress] = useState({ title: 'خانه', recipientName: '', phone: '', province: '', city: '', postalCode: '', addressLine: '', plaque: '', unit: '', isDefault: false }); useEffect(() => { const initializeCheckout = async () => { // توجه: در صفحه Cart از refreshToken استفاده کرده بودید، اگر اینجا accessToken است دقت کنید که یکسان باشند const token = localStorage.getItem('accessToken') || localStorage.getItem('refreshToken'); if (token) { setIsAuthenticated(true); // ۳. دریافت اطلاعات سبد خرید از سرور try { const data = await getCartApi(); if (data && data.summary) { setServerSummary(data.summary); } } catch (error) { console.error("خطا در دریافت اطلاعات سبد خرید:", error); } } setIsLoading(false); }; initializeCheckout(); }, []); useEffect(() => { const initializeCheckout = async () => { const token = localStorage.getItem('accessToken') || localStorage.getItem('refreshToken'); if (token) { setIsAuthenticated(true); try { // دریافت همزمان اطلاعات سبد و آدرس‌ها const [cartData, addressData] = await Promise.all([ getCartApi(), fetchUserAddresses() ]); if (cartData && cartData.summary) { setServerSummary(cartData.summary); } if (addressData && addressData.length > 0) { setAddresses(addressData); // انتخاب آدرس پیش‌فرض یا اولین آدرس به عنوان انتخاب‌شده const defaultAddress = addressData.find(addr => addr.isDefault) || addressData[0]; setSelectedAddressId(defaultAddress.id); } else { // اگر آدرسی وجود نداشت، فرم افزودن آدرس را نمایش بده setShowNewAddressForm(true); } } catch (error) { console.error("خطا در دریافت اطلاعات صفحه پرداخت:", error); } finally { setIsAddressLoading(false); } } else { setIsAuthenticated(false); setIsAddressLoading(false); } setIsLoading(false); }; initializeCheckout(); }, []); const handleAddressInputChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setNewAddress(prev => ({ ...prev, [name]: value })); }; const handleAddNewAddress = async (e: React.FormEvent) => { e.preventDefault(); // اینجا می‌توانید ولیدیشن‌های لازم را اضافه کنید try { const addedAddress = await addAddressApi(newAddress); // آدرس جدید را به لیست اضافه کن و آن را به عنوان انتخاب شده قرار بده setAddresses(prev => [...prev, addedAddress]); setSelectedAddressId(addedAddress.id); setShowNewAddressForm(false); // فرم را مخفی کن // فرم را ریست کن setNewAddress({ title: 'خانه', recipientName: '', phone: '', province: '', city: '', postalCode: '', addressLine: '', plaque: '', unit: '', isDefault: false }); } catch (error) { console.error("خطا در ذخیره آدرس:", error); // اینجا می‌توانید به کاربر خطا را نمایش دهید } }; const [editingAddressId, setEditingAddressId] = useState(null); // 2. تابع کلیک روی دکمه ویرایش const handleEditClick = (address: any, e: any) => { e.preventDefault(); e.stopPropagation(); // برای جلوگیری از انتخاب شدن radio button هنگام کلیک روی ویرایش setEditingAddressId(address.id); // پر کردن مقادیر فرم با دیتای آدرس انتخاب شده (فرض بر این است که استیت شما setNewAddress نام دارد) setNewAddress({ title: address.title || "", recipientName: address.recipientName || "", phone: address.phone || "", province: address.province || "", city: address.city || "", postalCode: address.postalCode || "", addressLine: address.addressLine || "", plaque: address.plaque || "", unit: address.unit || "", isDefault: address.isDefault || false }); setShowNewAddressForm(true); }; // 3. تابع فراخوانی API ویرایش const handleUpdateAddress = async () => { // اضافه کردن این شرط برای جلوگیری از خطای تایپ و توقف اجرا در صورت null بودن ID if (!editingAddressId) return; try { const response = await updateAddressApi(editingAddressId, newAddress); if (response.success) { // آپدیت کردن آدرس ویرایش شده در لیست آدرس‌ها setAddresses(prevAddresses => prevAddresses.map(addr => addr.id === editingAddressId ? response.data : addr) ); // خروج از حالت فرم و ریست کردن مقادیر setShowNewAddressForm(false); setEditingAddressId(null); setNewAddress({ title: "", recipientName: "", phone: "", province: "", city: "", postalCode: "", addressLine: "", plaque: "", unit: "", isDefault: false }); } } catch (error) { // مدیریت خطا (در صورت نیاز آلرت یا توست نمایش دهید) console.error("خطا در به‌روزرسانی آدرس:", error); } }; // 4. تابع انصراف یکپارچه شده const handleCancelForm = () => { setShowNewAddressForm(false); setEditingAddressId(null); setNewAddress({ title: "", recipientName: "", phone: "", province: "", city: "", postalCode: "", addressLine: "", plaque: "", unit: "", isDefault: false }); }; const handleDeleteAddress = async (addressId: string, e: React.MouseEvent) => { e.stopPropagation(); // جلوگیری از انتخاب شدن آدرس هنگام کلیک روی دکمه حذف // گرفتن تاییدیه از کاربر قبل از حذف const confirmDelete = window.confirm("آیا از حذف این آدرس اطمینان دارید؟"); if (!confirmDelete) return; try { const response = await deleteAddressApi(addressId); if (response.success) { // حذف آدرس از لیست موجود در State setAddresses(prevAddresses => prevAddresses.filter(addr => addr.id !== addressId) ); // اگر آدرسی که پاک شد همان آدرس انتخاب‌شده بود، انتخاب را لغو کن if (selectedAddressId === addressId) { setSelectedAddressId(null); } // اگر آدرسی که پاک شد در حال ویرایش بود، فرم ویرایش را ببند if (editingAddressId === addressId) { setShowNewAddressForm(false); setEditingAddressId(null); setNewAddress({ title: "", recipientName: "", phone: "", province: "", city: "", postalCode: "", addressLine: "", plaque: "", unit: "", isDefault: false }); } } } catch (error) { console.error("خطا در حذف آدرس:", error); // اینجا می‌توانید یک Toast یا Alert برای نمایش خطا به کاربر اضافه کنید } }; // محاسبه قیمت کل و تعداد const parsePrice = (priceStr?: number | null | string) => { if (!priceStr) return 0; return Number(priceStr.toString().replace(/,/g, '')); }; // ۴. استفاده از اطلاعات سرور در صورت لاگین بودن، در غیر این صورت استفاده از Context const totalPrice = isAuthenticated && serverSummary ? serverSummary.totalPrice || serverSummary.total || 0 : cart.reduce((total, item) => total + (parsePrice(item.price) * item.quantity), 0); const totalItems = isAuthenticated && serverSummary ? serverSummary.totalQuantity || serverSummary.itemsCount || 0 : cart.reduce((total, item) => total + item.quantity, 0); const shippingCost = shippingMethod === 'post' ? 45000 : 75000; const finalPrice = totalPrice + shippingCost; // حالت در حال بررسی توکن if (isLoading) { return (
); } // اگر کاربر لاگین نبود if (!isAuthenticated) { return (

دسترسی محدود

برای ثبت نهایی سفارش و مشاهده این صفحه، باید ابتدا وارد حساب کاربری خود شوید یا ثبت‌نام کنید.

بازگشت به سبد خرید
); } // رندر اصلی کامپوننت Checkout return (

اطلاعات ارسال

بازگشت به سبد خرید
سبد خرید
اطلاعات ارسال
پرداخت
{/* ... (فرم‌های آدرس گیرنده بدون تغییر) ... */}
{isAddressLoading ? (

در حال بارگذاری آدرس‌ها...

) : ( <> {showNewAddressForm ? (
{addresses.length > 0 && ( )}