diff --git a/app/components/product/ProductDetailView.tsx b/app/components/product/ProductDetailView.tsx index 25fa53c..b2fbf04 100644 --- a/app/components/product/ProductDetailView.tsx +++ b/app/components/product/ProductDetailView.tsx @@ -11,12 +11,37 @@ import { BottomBar, } from "./index"; import { ProductDetail as ProductDetailType } from "../../../src/api/types"; -import { Eye, EyeOff } from "lucide-react"; +import { + Eye, + EyeOff, + Heart, + Sparkles, + Star, + ShoppingCart, + Truck, + RotateCcw, + ShieldCheck, + MessageCircle, +} from "lucide-react"; import { Button } from "../ui/button"; import { useNavigate, Link } from "@remix-run/react"; import { useSimilarProductsInfinite } from "~/requestHandler/use-product-hooks"; import MondrianProductList from "../MondrianProductList"; import SellerLogo from "../SellerLogo"; +import { + useServiceGetProductRating, + useServiceGetComments, + useServiceCheckBookmark, + useServiceBookmarkProduct, + useServiceDeleteBookmark, +} from "~/utils/RequestHandler"; +import { useAddToCart } from "~/requestHandler/use-cart-hooks"; +import { useCreateChatThread } from "~/requestHandler/use-chat-hooks"; +import { findVariantId, formatPrice } from "~/utils/helpers"; +import { useToast } from "~/hooks/use-toast"; +import { useRootData } from "~/hooks/use-root-data"; +import { LoginRequiredDialog } from "../LoginRequiredDialog"; +import AIPromoteModal from "../AIPromoteModal"; interface ProductDetailViewProps { product: ProductDetailType; @@ -194,6 +219,83 @@ export const ProductDetailView = memo(function ProductDetailView({ ]); const navigate = useNavigate(); + + // --- Desktop buy/actions state & data (overlays + info column) --- + const { user } = useRootData(); + const { toast } = useToast(); + const [qty, setQty] = useState(1); + const [isAIOpen, setIsAIOpen] = useState(false); + const [isLoginOpen, setIsLoginOpen] = useState(false); + + const { data: ratingData } = useServiceGetProductRating(product.id || ""); + const { data: commentsData } = useServiceGetComments(1, product.id || ""); + const { data: bookmarkData } = useServiceCheckBookmark(product.id || ""); + const { mutate: bookmarkProduct } = useServiceBookmarkProduct(); + const { mutate: deleteBookmark } = useServiceDeleteBookmark(); + const addToCartMutation = useAddToCart(); + const { mutate: createChatThread } = useCreateChatThread(); + + const isBookmarked = bookmarkData?.bookmarked === true; + const avgRating = ratingData?.averageRating || 0; + const reviewCount = commentsData?.count || 0; + const isOutOfStock = currentStock === null || currentStock <= 0; + + const selectedColorValue = + inStockColors.find( + (color) => + (color.info as unknown as { detail: string })?.detail === selectedColor + )?.value || null; + + const handleToggleBookmark = () => { + if (!user?.access_token) { + setIsLoginOpen(true); + return; + } + if (isBookmarked) deleteBookmark(product.id || ""); + else bookmarkProduct(product.id || ""); + }; + + const handleDesktopAddToCart = async () => { + if (!user?.access_token) { + setIsLoginOpen(true); + return; + } + if (isOutOfStock) return; + const variantId = findVariantId(product, selectedColorValue, selectedSize); + if (!variantId) { + toast({ + title: "خطا", + description: "محصول با ویژگی‌های انتخابی شما یافت نشد", + variant: "destructive", + }); + return; + } + try { + await addToCartMutation.mutateAsync({ variantId, quantity: qty }); + toast({ + title: "سبد خرید", + description: "محصول با موفقیت به سبد خرید اضافه شد", + }); + } catch (e) { + toast({ + title: "خطا", + description: "افزودن به سبد خرید با مشکل مواجه شد", + variant: "destructive", + }); + } + }; + + const handleChat = () => { + if (!user?.access_token) { + setIsLoginOpen(true); + return; + } + if (!product.seller?.id) return; + createChatThread(product.seller.id, { + onSuccess: (t) => navigate(`/profile/threads/${t.id}`), + }); + }; + return (
{!isOwner && ( @@ -227,7 +329,7 @@ export const ProductDetailView = memo(function ProductDetailView({ {/* Top section: gallery | info (two columns on desktop) */}
{/* Gallery */} -
+
+ {!isOwner && ( + <> + {/* Save (desktop overlay) */} + + {/* AI try-on (desktop overlay) */} + + + )}
{/* Info */} @@ -279,22 +406,66 @@ export const ProductDetailView = memo(function ProductDetailView({
) : !isOwner ? ( - +
+ +
) : null} - + + {/* Desktop: title + rating + price */} +
+

+ {product.title} +

+
+ + {[1, 2, 3, 4, 5].map((i) => ( + + ))} + + {avgRating > 0 ? ( + {avgRating.toFixed(1)} + ) : null} + + {reviewCount} دیدگاه +
+
+ + {formatPrice(currentDiscountPrice || currentPrice)} + تومان + + {currentDiscountPrice ? ( + + {formatPrice(currentPrice)} + + ) : null} +
+
+ + {/* Mobile: title + description */} +
+ +
{hasAnyStock ? ( <> @@ -338,22 +509,104 @@ export const ProductDetailView = memo(function ProductDetailView({
)} - {/* Buy box (fixed bottom bar on mobile, inline on desktop) */} + {/* Desktop buy row + assurances */} {!isOwner && ( - - (color.info as unknown as { detail: string })?.detail === - selectedColor - )?.value || null - } - selectedSize={selectedSize} - /> +
+
+ + +
+ + {qty} + +
+
+
+
+ +
+ ارسال سریع + + ۲ تا ۴ روز کاری + +
+
+
+ +
+ ۷ روز بازگشت + + ضمانت تعویض کالا + +
+
+
+ +
+ پرداخت امن + + تضمین اصالت کالا + +
+
+
+
+ )} + + {/* Buy box (fixed bottom bar — mobile only) */} + {!isOwner && ( +
+ + (color.info as unknown as { detail: string })?.detail === + selectedColor + )?.value || null + } + selectedSize={selectedSize} + /> +
)}
@@ -361,7 +614,11 @@ export const ProductDetailView = memo(function ProductDetailView({ {/* Full-width below the fold: contact, reviews, similar */} {productActiveStatus && ( <> - {!isOwner && } + {!isOwner && ( +
+ +
+ )} {/* Similar Products Section */} {!isOwner && ( @@ -402,6 +659,18 @@ export const ProductDetailView = memo(function ProductDetailView({ )} )} + + {/* Desktop overlay/buy modals */} + + setIsAIOpen(false)} + productId={product.id || ""} + /> ); }); diff --git a/app/components/product/ProductImageCarousel.tsx b/app/components/product/ProductImageCarousel.tsx index e1528e9..f53972f 100644 --- a/app/components/product/ProductImageCarousel.tsx +++ b/app/components/product/ProductImageCarousel.tsx @@ -25,6 +25,8 @@ import { EyeOff, Eye, ArrowRight, + ChevronLeft, + ChevronRight, } from "lucide-react"; import { useDeleteProduct, @@ -274,6 +276,28 @@ export const ProductImageCarousel = ({ )} + {/* Prev / next arrows (desktop) */} + {images.length > 1 && ( + <> + + + + )} + {/* Settings Drawer */}