import { json, type LoaderFunctionArgs, type MetaFunction, } from "@remix-run/node"; import { useParams, useSearchParams } from "@remix-run/react"; import { useToast } from "../hooks/use-toast"; import { useGetCartDetails, useUpdateCartItemQuantity, useRemoveFromCart, } from "../requestHandler/use-cart-hooks"; import { useCreateShippingInfo } from "../requestHandler/use-shipping-hooks"; import { useCallback, useEffect, useState } from "react"; import { CartHeader } from "../components/cart/CartHeader"; import { CartItem } from "../components/cart/CartItem"; import { CartSummary } from "../components/cart/CartSummary"; import { ShippingInformation } from "../components/cart/ShippingInformation"; import { ReceiverInformation } from "../components/cart/ReceiverInformation"; import { useCashOutCart } from "../requestHandler/use-order-hooks"; import { Address, CartDetail as CartDetailType, CartItem as CartItemType, SellerCourierList, } from "src/api/types"; import UiProvider from "~/components/UiProvider"; export const meta: MetaFunction = () => { return [ { title: "سبد خرید - ویترون" }, { name: "description", content: "مدیریت سبد خرید شما در ویترون. بررسی محصولات، انتخاب روش ارسال و تکمیل فرآیند خرید.", }, { name: "keywords", content: "سبد خرید، خرید آنلاین، پرداخت، ارسال، ویترون", }, { name: "robots", content: "noindex, follow" }, { property: "og:title", content: "سبد خرید - ویترون" }, { property: "og:description", content: "مدیریت سبد خرید شما در ویترون. بررسی محصولات، انتخاب روش ارسال و تکمیل فرآیند خرید.", }, { property: "og:type", content: "website" }, { name: "twitter:card", content: "summary" }, { name: "twitter:title", content: "سبد خرید - ویترون" }, { name: "twitter:description", content: "مدیریت سبد خرید شما در ویترون. بررسی محصولات، انتخاب روش ارسال و تکمیل فرآیند خرید.", }, ]; }; // Server-side loader to fetch initial cart data export async function loader({ params }: LoaderFunctionArgs) { const { cartId } = params; if (!cartId) { throw new Response("Missing cart ID", { status: 400 }); } return json({ cartId }); } // Main Cart Component export default function CartDetail() { const { cartId } = useParams(); const [searchParams, setSearchParams] = useSearchParams(); const { data: cart, isLoading: isLoadingCart, refetch, isError, } = useGetCartDetails(cartId || ""); const updateMutation = useUpdateCartItemQuantity(); const removeMutation = useRemoveFromCart(); const { toast } = useToast(); const [step, setStep] = useState(0); const createShippingInfo = useCreateShippingInfo(); const cashOutMutation = useCashOutCart(cartId || ""); // Calculate total price of all items in the cart const calculateTotal = useCallback( ( cart: CartDetailType | null | undefined, deliveryPrice?: number | null, discountValue?: number | null ) => { if (!cart || !cart.items || cart.items.length === 0) return "0"; let total = cart.items.reduce((sum: number, item: CartItemType) => { if (item.productVariant?.stock && item.productVariant?.stock > 0) { const price = Number( item.productVariant?.discountPrice || item.productVariant?.price ) * item.quantity; return sum + price; } return sum; }, 0); if (deliveryPrice) { total += deliveryPrice; } if (discountValue) { total -= discountValue; } return total.toString(); }, [] ); // Handle quantity change const handleQuantityChange = async (itemId: string, newQuantity: number) => { if (newQuantity < 1) return; try { await updateMutation.mutateAsync({ itemId, quantity: newQuantity }); } catch (error) { console.error("Error updating item quantity:", error); toast({ title: "خطا", description: "بروزرسانی تعداد محصول با مشکل مواجه شد", variant: "destructive", }); } }; // Handle item removal const handleRemoveItem = async (itemId: string) => { try { await removeMutation.mutateAsync(itemId); toast({ title: "سبد خرید", description: "محصول با موفقیت از سبد خرید حذف شد", variant: "default", }); } catch (error) { console.error("Error removing item:", error); toast({ title: "خطا", description: "حذف محصول از سبد خرید با مشکل مواجه شد", variant: "destructive", }); } }; const [selectedAddressInfo, setSelectedAddressInfo] = useState
(null); const [selectedCourierInfo, setSelectedCourierInfo] = useState(null); const [shippingInfoId, setShippingInfoId] = useState(""); const [isCreatingOrder, setIsCreatingOrder] = useState(false); const [shippingInfoIsLoading, setShippingInfoIsLoading] = useState(false); // Initialize step from URL query parameter when component mounts useEffect(() => { const stepParam = searchParams.get("step"); if (stepParam) { const newStep = parseInt(stepParam, 10); if (!isNaN(newStep) && newStep >= 0 && newStep <= 2) { setStep(newStep); } // Clean up the URL by removing the step parameter const newSearchParams = new URLSearchParams(searchParams); newSearchParams.delete("step"); setSearchParams(newSearchParams, { replace: true }); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // Only run once on mount useEffect(() => { console.log("selectedCourierInfo", selectedCourierInfo); }, [selectedCourierInfo]); const continueHandler = async () => { if (step === 0) { setStep(1); } else if (step === 1) { const isFaceToFace = selectedCourierInfo?.courierIsFaceToFace; if (!isFaceToFace && (!selectedAddressInfo || !selectedAddressInfo?.id)) { toast({ title: "خطا", description: "لطفا آدرس را انتخاب کنید", variant: "destructive", }); return; } if (!selectedCourierInfo || !selectedCourierInfo?.id) { toast({ title: "خطا", description: "لطفا روش ارسال را انتخاب کنید", variant: "destructive", }); return; } try { const response = await createShippingInfo.mutateAsync({ address: isFaceToFace ? undefined : selectedAddressInfo?.id, sellerCourier: selectedCourierInfo.id, }); setShippingInfoId(response.id || ""); setStep(2); } catch (error) { console.error("Error creating shipping info:", error); toast({ title: "خطا", description: "ثبت اطلاعات ارسال با مشکل مواجه شد", variant: "destructive", }); } } else if (step === 2) { if (!shippingInfoId) { toast({ title: "Error", description: "Shipping information ID is missing.", variant: "destructive", }); return; } setIsCreatingOrder(true); try { console.log( `Initiating cash out for cart ${cartId} with shipping info ID: ${shippingInfoId}` ); const response = await cashOutMutation.mutateAsync({ shippingInfoId: shippingInfoId, }); console.log("Cash out mutation initiated."); window.location.href = response.redirect; } catch (error) { console.error( "Error caught in continueHandler during cash out:", error ); toast({ title: "عدم وجود محصول", description: "موجودی این محصول کمتر از تعداد درخواستی شما است. لطفا تعداد محصولات موجود را چک کنید.", variant: "destructive", }); } finally { setIsCreatingOrder(false); } } }; return (
{/* Cart Content */}
{step === 0 && (
{cart?.items?.map((item, index) => ( ))}
)} {step === 1 && ( )} {step === 2 && ( )}
continueHandler()} step={step} isLoading={ isCreatingOrder || cashOutMutation.isPending || shippingInfoIsLoading } />
); }