210 lines
7.4 KiB
TypeScript
210 lines
7.4 KiB
TypeScript
import { useState } from "react";
|
||
import { useNavigate } from "@remix-run/react";
|
||
import { X, Plus, Check, Loader2, Layers, ChevronLeft } from "lucide-react";
|
||
import {
|
||
Drawer,
|
||
DrawerContent,
|
||
DrawerHeader,
|
||
DrawerTitle,
|
||
} from "~/components/ui/drawer";
|
||
import { Button } from "~/components/ui/button";
|
||
import { Skeleton } from "~/components/ui/skeleton";
|
||
import {
|
||
useUserCollections,
|
||
useAddProductsToCollection,
|
||
} from "../../requestHandler/use-user-collection-hooks";
|
||
import { CreateSetModal } from "./CreateSetModal";
|
||
import { SetSuccessModal } from "./SetSuccessModal";
|
||
import { UserCollection } from "src/api/types";
|
||
|
||
interface AddToSetDrawerProps {
|
||
isOpen: boolean;
|
||
onOpenChange: (open: boolean) => void;
|
||
productId: string;
|
||
}
|
||
|
||
export const AddToSetDrawer = ({
|
||
isOpen,
|
||
onOpenChange,
|
||
productId,
|
||
}: AddToSetDrawerProps) => {
|
||
const navigate = useNavigate();
|
||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||
const [isSuccessModalOpen, setIsSuccessModalOpen] = useState(false);
|
||
const [selectedSet, setSelectedSet] = useState<UserCollection | null>(null);
|
||
const [addingToSetId, setAddingToSetId] = useState<string | null>(null);
|
||
|
||
const { data: collections, isLoading } = useUserCollections();
|
||
|
||
const handleGoToSetDetail = (e: React.MouseEvent, collectionId: string) => {
|
||
e.stopPropagation();
|
||
onOpenChange(false);
|
||
navigate(`/profile/sets/${collectionId}`);
|
||
};
|
||
const { mutate: addToCollection, isPending: isAddingToCollection } =
|
||
useAddProductsToCollection();
|
||
|
||
const handleAddToSet = (collectionId: string) => {
|
||
setAddingToSetId(collectionId);
|
||
|
||
// Find the collection to show in success modal
|
||
const collection = collections?.find((c) => c.id === collectionId);
|
||
|
||
addToCollection(
|
||
{ collectionId, productIds: [productId] },
|
||
{
|
||
onSuccess: () => {
|
||
setAddingToSetId(null);
|
||
onOpenChange(false);
|
||
|
||
// Show success modal with the collection
|
||
if (collection) {
|
||
setSelectedSet(collection);
|
||
setIsSuccessModalOpen(true);
|
||
}
|
||
},
|
||
onError: () => {
|
||
setAddingToSetId(null);
|
||
},
|
||
}
|
||
);
|
||
};
|
||
|
||
const handleCreateSetSuccess = (newSet: UserCollection) => {
|
||
setSelectedSet(newSet);
|
||
setIsCreateModalOpen(false);
|
||
onOpenChange(false);
|
||
setIsSuccessModalOpen(true);
|
||
};
|
||
|
||
const isProductInCollection = (collection: UserCollection) => {
|
||
return collection.products?.includes(productId) || false;
|
||
};
|
||
|
||
return (
|
||
<>
|
||
<Drawer open={isOpen} onOpenChange={onOpenChange}>
|
||
<DrawerContent>
|
||
<DrawerHeader className="flex flex-col">
|
||
<div className="flex relative items-center justify-center w-full">
|
||
<X
|
||
className="absolute right-0 cursor-pointer hover:bg-BLACK/5 rounded-full p-1 transition-colors"
|
||
size={28}
|
||
onClick={() => onOpenChange(false)}
|
||
/>
|
||
<div className="flex flex-col items-center gap-2">
|
||
<DrawerTitle className="text-B16 font-bold">
|
||
افزودن به ست
|
||
</DrawerTitle>
|
||
</div>
|
||
</div>
|
||
</DrawerHeader>
|
||
|
||
<div className="px-4 pb-4 flex flex-col gap-3 max-h-[60vh] overflow-y-auto">
|
||
<p className="text-R12 text-GRAY text-center mb-2">
|
||
این محصول را به یکی از ستهای خود اضافه کنید
|
||
</p>
|
||
|
||
{isLoading ? (
|
||
<div className="flex flex-col gap-3">
|
||
{[1, 2, 3].map((i) => (
|
||
<Skeleton key={i} className="h-16 w-full rounded-xl" />
|
||
))}
|
||
</div>
|
||
) : collections && collections.length > 0 ? (
|
||
<div className="flex flex-col gap-3">
|
||
{collections.map((collection) => {
|
||
const isInCollection = isProductInCollection(collection);
|
||
const isAdding = addingToSetId === collection.id;
|
||
|
||
return (
|
||
<button
|
||
key={collection.id}
|
||
className={`flex items-center gap-4 p-4 rounded-xl transition-colors ${
|
||
isInCollection
|
||
? "bg-GREEN/10 cursor-default"
|
||
: "bg-BLACK/5 hover:bg-BLACK/10"
|
||
}`}
|
||
onClick={() =>
|
||
!isInCollection &&
|
||
!isAdding &&
|
||
handleAddToSet(collection.id!)
|
||
}
|
||
disabled={isInCollection || isAdding}
|
||
>
|
||
<div
|
||
className={`w-12 h-12 rounded-full flex items-center justify-center ${
|
||
isInCollection ? "bg-GREEN" : "bg-PRIMARY"
|
||
}`}
|
||
>
|
||
{isInCollection ? (
|
||
<Check size={24} className="text-BLACK" />
|
||
) : (
|
||
<Layers size={24} className="text-BLACK" />
|
||
)}
|
||
</div>
|
||
<div className="flex flex-col items-start flex-1">
|
||
<span className="text-B14 font-bold text-BLACK">
|
||
{collection.title}
|
||
</span>
|
||
<span className="text-R12 text-GRAY">
|
||
{isInCollection
|
||
? "این محصول از قبل در این ست وجود دارد"
|
||
: `${collection.products?.length || 0} محصول`}
|
||
</span>
|
||
</div>
|
||
{isAdding ? (
|
||
<Loader2 className="h-5 w-5 animate-spin text-PRIMARY" />
|
||
) : (
|
||
<button
|
||
onClick={(e) => handleGoToSetDetail(e, collection.id!)}
|
||
className="p-2 rounded-full hover:bg-BLACK/10 transition-colors"
|
||
title="مشاهده ست"
|
||
>
|
||
<ChevronLeft size={20} className="text-GRAY" />
|
||
</button>
|
||
)}
|
||
</button>
|
||
);
|
||
})}
|
||
</div>
|
||
) : (
|
||
<div className="flex flex-col items-center py-8 text-center">
|
||
<Layers size={48} className="text-GRAY mb-4" />
|
||
<p className="text-B14 text-GRAY">هنوز ستی ایجاد نکردهاید</p>
|
||
<p className="text-R12 text-GRAY mt-1">
|
||
اولین ست خود را بسازید
|
||
</p>
|
||
</div>
|
||
)}
|
||
|
||
{/* Create new set button */}
|
||
<Button
|
||
variant="dark"
|
||
size="xl"
|
||
className="w-full mt-4 gap-2"
|
||
onClick={() => setIsCreateModalOpen(true)}
|
||
>
|
||
<Plus size={18} />
|
||
ایجاد ست جدید
|
||
</Button>
|
||
</div>
|
||
</DrawerContent>
|
||
</Drawer>
|
||
|
||
<CreateSetModal
|
||
isOpen={isCreateModalOpen}
|
||
onOpenChange={setIsCreateModalOpen}
|
||
productId={productId}
|
||
onSuccess={handleCreateSetSuccess}
|
||
/>
|
||
|
||
<SetSuccessModal
|
||
isOpen={isSuccessModalOpen}
|
||
onOpenChange={setIsSuccessModalOpen}
|
||
collection={selectedSet}
|
||
/>
|
||
</>
|
||
);
|
||
};
|