Vitron-Front/app/components/product/BottomBar.tsx
2026-04-29 01:44:16 +03:30

224 lines
6.6 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.

import { ShoppingCart, X, Check } from "lucide-react";
import { Button } from "~/components/ui/button";
import discountRed from "~/assets/icons/product/discount-red.svg";
import { useState } from "react";
import { useToast } from "~/hooks/use-toast";
import {
Drawer,
DrawerContent,
DrawerHeader,
DrawerTitle,
} from "~/components/ui/drawer";
import { Link } from "@remix-run/react";
import { useAddToCart } from "../../requestHandler/use-cart-hooks";
import { findVariantId, formatPrice } from "../../utils/helpers";
import { ProductDetail } from "src/api/types";
import { useRootData } from "~/hooks/use-root-data";
import { LoginRequiredDialog } from "../LoginRequiredDialog";
interface BottomBarProps {
product: ProductDetail;
selectedColor: string | null;
selectedSize: string | null;
currentPrice: string;
currentDiscountPrice: string | null;
currentStock: number | null;
}
interface PriceDisplayProps {
currentPrice: string;
currentDiscountPrice: string | null;
}
const PriceDisplay = ({
currentPrice,
currentDiscountPrice,
}: PriceDisplayProps) => {
return (
<div className="flex flex-col gap-1">
{currentDiscountPrice && (
<div className="flex items-center gap-3">
<p className="text-GRAY line-through decoration-RED decoration-2 text-B14">
{formatPrice(currentPrice)}
</p>
<img src={discountRed} alt="discount-red" className="w-6 h-6" />
</div>
)}
<div className="flex items-center gap-3">
<p className="text-B14 font-bold">
{formatPrice(currentDiscountPrice || currentPrice)}
</p>
<p className="text-B14 font-bold">تومان</p>
</div>
</div>
);
};
interface AddToCartButtonProps {
isOutOfStock: boolean;
onClick: () => void;
}
const AddToCartButton = ({ isOutOfStock, onClick }: AddToCartButtonProps) => (
<Button
variant="dark"
size="lg"
className="font-bold flex items-center gap-2 bg-VITROWN_BLUE text-white"
disabled={isOutOfStock}
onClick={onClick}
>
{isOutOfStock ? (
<span className="text-B14 font-bold">ناموجود</span>
) : (
<>
<ShoppingCart size={24} />
افزودن به سبد خرید
</>
)}
</Button>
);
interface CartDrawerProps {
isOpen: boolean;
onOpenChange: (open: boolean) => void;
}
const CartDrawer = ({ isOpen, onOpenChange }: CartDrawerProps) => (
<Drawer open={isOpen} onOpenChange={onOpenChange}>
<DrawerContent>
<DrawerHeader className="flex flex-col py-3">
<div className="flex relative pt-2 text-B12 font-bold items-center justify-center w-full">
<X
className="absolute right-2 cursor-pointer"
size={24}
onClick={() => onOpenChange(false)}
/>
<DrawerTitle className="text-B12 font-bold">سبد خرید</DrawerTitle>
</div>
</DrawerHeader>
<div className="p-4 flex flex-col gap-4">
<div className="flex flex-col gap-10 w-full">
<div className="flex items-center justify-center w-full">
<Check className="text-green-500" size={48} />
<p className="text-B14 font-bold mr-2">
محصول به سبد خرید اضافه شد!
</p>
</div>
<div className="flex flex-col w-full gap-1">
<Link to="/cart" className="w-full">
<Button
variant="dark"
size="lg"
className="w-full font-bold"
onClick={() => onOpenChange(false)}
>
مشاهده سبد خرید
</Button>
</Link>
<Button
variant="outline"
size="lg"
className="w-full font-bold"
onClick={() => onOpenChange(false)}
>
ادامه خرید
</Button>
</div>
</div>
</div>
</DrawerContent>
</Drawer>
);
export const BottomBar = ({
product,
selectedColor,
selectedSize,
currentPrice,
currentDiscountPrice,
currentStock,
}: BottomBarProps) => {
const { toast } = useToast();
const { user } = useRootData();
const [isCartDrawerOpen, setIsCartDrawerOpen] = useState(false);
const [isLoginModalOpen, setIsLoginModalOpen] = useState(false);
// Use the addToCart mutation hook
const addToCartMutation = useAddToCart();
const isOutOfStock = currentStock === null || currentStock <= 0;
const handleAddToCart = async () => {
// Check if user is logged in
if (!user?.access_token) {
setIsLoginModalOpen(true);
return;
}
if (currentStock !== null && currentStock > 0) {
// Find the variant ID based on selected color and size
const variantId = findVariantId(product, selectedColor, selectedSize);
if (!variantId) {
toast({
title: "خطا",
description: "محصول با ویژگی‌های انتخابی شما یافت نشد",
variant: "destructive",
});
return;
}
try {
// Add to cart using React Query mutation
await addToCartMutation.mutateAsync({
variantId,
quantity: 1,
});
toast({
title: "سبد خرید",
description: "محصول با موفقیت به سبد خرید اضافه شد",
variant: "default",
});
setIsCartDrawerOpen(true);
} catch (error) {
console.error("Error adding to cart:", error);
toast({
title: "خطا",
description: "افزودن محصول به سبد خرید با مشکل مواجه شد",
variant: "destructive",
});
}
}
};
return (
<>
<div className="max-w-md mx-auto fixed gap-2 bottom-[calc(50px+env(safe-area-inset-bottom))] left-0 right-0 border-t border-inner-border bg-WHITE p-4 z-50 flex flex-row">
<div className="flex w-full items-center justify-between">
<div className="flex flex-col gap-1">
<AddToCartButton
isOutOfStock={isOutOfStock}
onClick={handleAddToCart}
/>
</div>
<PriceDisplay
currentPrice={currentPrice}
currentDiscountPrice={currentDiscountPrice}
/>
</div>
</div>
<CartDrawer
isOpen={isCartDrawerOpen}
onOpenChange={setIsCartDrawerOpen}
/>
<LoginRequiredDialog
loginTitle="برای افزودن محصول به سبد خرید ابتدا باید وارد حساب کاربری خود شوید."
isOpen={isLoginModalOpen}
onOpenChange={setIsLoginModalOpen}
/>
</>
);
};