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

337 lines
12 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 {
BookmarkMinus,
Bookmark,
MessageSquare,
Send,
Share2,
Star,
X,
Loader2,
Copy,
Layers,
Sparkles,
} from "lucide-react";
import { useState, useEffect } from "react";
import {
Drawer,
DrawerContent,
DrawerHeader,
DrawerTitle,
} from "~/components/ui/drawer";
import { Skeleton } from "~/components/ui/skeleton";
import {
useServiceGetProductRating,
useServiceGetComments,
useServiceBookmarkProduct,
useServiceDeleteBookmark,
useServiceCheckBookmark,
} from "~/utils/RequestHandler";
import { useToast } from "~/hooks/use-toast";
import { useRootData } from "~/hooks/use-root-data";
import { LoginRequiredDialog } from "../LoginRequiredDialog";
import { AddToSetDrawer } from "../sets";
import AIPromoteModal from "../AIPromoteModal";
export const ProductActions = ({ productId }: { productId: string }) => {
const [isShareDrawerOpen, setIsShareDrawerOpen] = useState(false);
const [isLoginModalOpen, setIsLoginModalOpen] = useState(false);
const [isAddToSetDrawerOpen, setIsAddToSetDrawerOpen] = useState(false);
const [isAITryOnModalOpen, setIsAITryOnModalOpen] = useState(false);
const [showAIFeatureTooltip, setShowAIFeatureTooltip] = useState(false);
// Show AI feature tooltip on first visit
useEffect(() => {
const hasSeenAIFeature = localStorage.getItem("hasSeenAITryOnFeature");
if (!hasSeenAIFeature) {
setShowAIFeatureTooltip(true);
}
}, []);
const handleDismissAITooltip = () => {
setShowAIFeatureTooltip(false);
localStorage.setItem("hasSeenAITryOnFeature", "true");
};
const handleOpenAIModal = () => {
handleDismissAITooltip();
setIsAITryOnModalOpen(true);
};
const [loginDialogMessage, setLoginDialogMessage] = useState(
"برای افزودن محصول به علاقه‌مندی‌ها ابتدا باید وارد حساب کاربری خود شوید."
);
const { toast } = useToast();
const { user } = useRootData();
const { data: ratingData, isLoading: ratingLoading } =
useServiceGetProductRating(productId || "");
const { data: commentsData } = useServiceGetComments(1, productId || "");
const { data: bookmarkData, isLoading: isCheckingBookmark } =
useServiceCheckBookmark(productId || "");
const { mutate: bookmarkProduct, isPending: isBookmarking } =
useServiceBookmarkProduct();
const { mutate: deleteBookmark, isPending: isDeletingBookmark } =
useServiceDeleteBookmark();
const isBookmarked = bookmarkData?.bookmarked === true;
const averageRating = ratingData?.averageRating || 0;
const commentCount = commentsData?.count || 0;
const handleBookmark = () => {
// Check if user is logged in
if (!user?.access_token) {
setIsLoginModalOpen(true);
return;
}
if (isBookmarked) {
deleteBookmark(productId, {
onSuccess: () => {
toast({
title: "محصول از علاقه‌مندی‌ها حذف شد",
variant: "default",
duration: 3000,
});
},
onError: () => {
toast({
title: "خطا",
description: "عملیات با خطا مواجه شد. لطفا دوباره تلاش کنید.",
variant: "destructive",
duration: 3000,
});
},
});
} else {
bookmarkProduct(productId, {
onSuccess: () => {
toast({
title: "محصول به علاقه‌مندی‌ها اضافه شد",
variant: "default",
duration: 3000,
});
},
onError: () => {
toast({
title: "خطا",
description: "عملیات با خطا مواجه شد. لطفا دوباره تلاش کنید.",
variant: "destructive",
duration: 3000,
});
},
});
}
};
const handleAddToSet = () => {
// Check if user is logged in
if (!user?.access_token) {
setLoginDialogMessage(
"برای افزودن محصول به ست ابتدا باید وارد حساب کاربری خود شوید."
);
setIsLoginModalOpen(true);
return;
}
setIsAddToSetDrawerOpen(true);
};
const handleShare = (platform: string) => {
const url = window.location.href;
let shareUrl = "";
if (platform === "telegram") {
shareUrl = `https://t.me/share/url?url=${encodeURIComponent(url)}`;
} else if (platform === "whatsapp") {
shareUrl = `https://api.whatsapp.com/send?text=${encodeURIComponent(url)}`;
} else if (platform === "copy") {
navigator.clipboard.writeText(url);
toast({
title: "لینک کپی شد",
description: "لینک محصول در کلیپ‌بورد کپی شد.",
variant: "default",
duration: 2000,
});
setIsShareDrawerOpen(false);
return;
}
if (shareUrl) {
window.open(shareUrl, "_blank");
setIsShareDrawerOpen(false);
}
};
return (
<>
<div className="flex w-full mt-4 px-4 justify-between">
<div className="flex gap-8">
{isCheckingBookmark ? (
<Skeleton className="h-6 w-6 rounded-full" />
) : isBookmarked ? (
<>
{isDeletingBookmark ? (
<Loader2 className="h-5 w-5 animate-spin" />
) : (
<Bookmark
size={20}
className="text-PRIMARY fill-current cursor-pointer"
onClick={handleBookmark}
/>
)}
</>
) : (
<>
{isBookmarking ? (
<Loader2 className="h-5 w-5 animate-spin" />
) : (
<BookmarkMinus
size={20}
className="cursor-pointer"
onClick={handleBookmark}
/>
)}
</>
)}
<Share2
size={20}
className="cursor-pointer"
onClick={() => setIsShareDrawerOpen(true)}
/>
<Layers
size={20}
className="cursor-pointer"
onClick={handleAddToSet}
/>
<div className="relative">
<Sparkles
size={20}
className="cursor-pointer animate-pulse text-PRIMARY"
onClick={handleOpenAIModal}
/>
{showAIFeatureTooltip && (
<div className="absolute bottom-full right-0 mb-2 z-50 animate-bounce">
<div className="relative bg-gradient-to-r from-purple-600 to-pink-500 text-WHITE px-3 py-2 rounded-lg shadow-xl whitespace-nowrap border border-white/20">
<button
onClick={handleDismissAITooltip}
className="absolute -top-1 -right-1 bg-WHITE text-black rounded-full w-4 h-4 flex items-center justify-center text-xs font-bold shadow-md"
>
×
</button>
<div className="flex items-center gap-2">
<Sparkles size={14} />
<span className="text-R12 font-bold">
پرو با هوش مصنوعی!
</span>
</div>
<p className="text-R10 opacity-90 mt-0.5">
این محصول رو تو تن خودت ببین
</p>
{/* Arrow */}
<div className="absolute top-full right-1 w-0 h-0 border-l-[6px] border-l-transparent border-r-[6px] border-r-transparent border-t-[6px] border-t-pink-500" />
</div>
</div>
)}
</div>
</div>
<div className="flex gap-3 items-center">
<div className="flex gap-1 items-center">
{!ratingLoading && averageRating > 0 && (
<>
<p className="text-B12 font-bold text-GRAY">({commentCount})</p>
<p className="text-B12 font-bold">{averageRating.toFixed(1)}</p>
<Star className="text-BLACK fill-current" size={20} />
</>
)}
</div>
</div>
</div>
<Drawer open={isShareDrawerOpen} onOpenChange={setIsShareDrawerOpen}>
<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={() => setIsShareDrawerOpen(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">
<p className="text-R12 text-GRAY text-center mb-2">
این محصول را با دوستان خود به اشتراک بگذارید
</p>
<button
className="flex items-center gap-4 p-4 rounded-xl bg-[#0088cc]/10 hover:bg-[#0088cc]/20 transition-colors"
onClick={() => handleShare("telegram")}
>
<div className="w-12 h-12 rounded-full bg-[#0088cc] flex items-center justify-center">
<Send size={20} className="text-WHITE" />
</div>
<div className="flex flex-col items-start flex-1">
<span className="text-B14 font-bold text-BLACK">تلگرام</span>
<span className="text-R12 text-GRAY">
ارسال به مخاطبین تلگرام
</span>
</div>
</button>
<button
className="flex items-center gap-4 p-4 rounded-xl bg-[#25D366]/10 hover:bg-[#25D366]/20 transition-colors"
onClick={() => handleShare("whatsapp")}
>
<div className="w-12 h-12 rounded-full bg-[#25D366] flex items-center justify-center">
<MessageSquare size={20} className="text-WHITE" />
</div>
<div className="flex flex-col items-start flex-1">
<span className="text-B14 font-bold text-BLACK">واتساپ</span>
<span className="text-R12 text-GRAY">
ارسال به مخاطبین واتساپ
</span>
</div>
</button>
<button
className="flex items-center gap-4 p-4 rounded-xl bg-BLACK/5 hover:bg-BLACK/10 transition-colors"
onClick={() => handleShare("copy")}
>
<div className="w-12 h-12 rounded-full bg-BLACK flex items-center justify-center">
<Copy size={20} className="text-WHITE" />
</div>
<div className="flex flex-col items-start flex-1">
<span className="text-B14 font-bold text-BLACK">کپی لینک</span>
<span className="text-R12 text-GRAY">
کپی لینک در کلیپبورد
</span>
</div>
</button>
</div>
</DrawerContent>
</Drawer>
<LoginRequiredDialog
loginTitle={loginDialogMessage}
isOpen={isLoginModalOpen}
onOpenChange={setIsLoginModalOpen}
/>
<AddToSetDrawer
isOpen={isAddToSetDrawerOpen}
onOpenChange={setIsAddToSetDrawerOpen}
productId={productId}
/>
<AIPromoteModal
isOpen={isAITryOnModalOpen}
onClose={() => setIsAITryOnModalOpen(false)}
productId={productId}
/>
</>
);
};