import { useState, useRef, useEffect } from "react"; import { ChevronDown, ChevronUp, Edit } from "lucide-react"; import { useNavigate, useParams } from "@remix-run/react"; import { useGetSellerProductsList, useUpdateVariantStock, useUpdateProductBasePrice, useUpdateVariantPrice, } from "../requestHandler/use-product-hooks"; import { cn } from "../lib/utils"; import { SellerProductListItem } from "../../src/api/types"; import placeholderImage from "~/assets/icons/product.png"; import placeholderImageDark from "~/assets/icons/product-dark.png"; import { useRootData } from "~/hooks/use-root-data"; import { ThrottledQuantityControl } from "../components/cart/ThrottledQuantityControl"; import { InlinePriceEditor } from "../components/seller/InlinePriceEditor"; /** Format a raw decimal price string to Persian digits ("120000.00" -> "۱۲۰٬۰۰۰"). */ function faPrice(raw: string | null | undefined): string { if (raw === null || raw === undefined || raw === "") return ""; const n = parseFloat(raw); if (!isFinite(n)) return ""; return Math.round(n).toLocaleString("fa-IR"); } function ProductAccordionItem({ product, isOpen, onToggle, isSticky, storeId, }: { product: SellerProductListItem; isOpen: boolean; onToggle: () => void; isSticky: boolean; storeId: string; }) { const navigate = useNavigate(); const { theme } = useRootData(); const updateVariantStock = useUpdateVariantStock(); const updateBasePrice = useUpdateProductBasePrice(); const updateVariantPrice = useUpdateVariantPrice(); const [updatingVariantId, setUpdatingVariantId] = useState( null ); const [pricingVariantId, setPricingVariantId] = useState(null); // Use real variants from API const variants = product.variants || []; const productId = product.id || ""; const faBase = faPrice(product.basePrice); const handleEditProduct = (e: React.MouseEvent) => { e.stopPropagation(); navigate(`/store/${storeId}/product/${product.id}`); }; return (
{/* Image toggles the accordion */} {/* Title toggles; price editor sits under it on mobile (not inside a button) */}
{ if (v) updateBasePrice.mutate({ productId, basePrice: v }); }} isPending={updateBasePrice.isPending} size="sm" align="start" ariaLabel="ویرایش قیمت محصول" className="-mr-2" />
{/* Desktop price column */}
{ if (v) updateBasePrice.mutate({ productId, basePrice: v }); }} isPending={updateBasePrice.isPending} ariaLabel="ویرایش قیمت محصول" />
{/* Desktop variants column */} {variants && variants.length > 0 ? ( {variants.length} نوع ) : ( )}
{variants && variants.length > 0 && ( {variants.length} نوع )}
{isOpen && variants && variants.length > 0 && (
{variants.map((variant, index) => { const color = variant.attributes?.find( (attribute) => attribute.name === "COLOR" ); const size = variant.attributes?.find( (attribute) => attribute.name === "SIZE" ); const variantId = variant.id || ""; return (
{color && (
)} {size && (
{size.value}
)}
{/* Per-variant price (overrides base price for this variant) */}
قیمت { setPricingVariantId(variantId); updateVariantPrice.mutate( { variantId, price: v }, { onSettled: () => setPricingVariantId(null) } ); }} isPending={pricingVariantId === variantId} allowEmpty placeholder={ faBase ? `پیش‌فرض: ${faBase}` : "پیش‌فرض" } size="sm" align="start" ariaLabel="ویرایش قیمت این تنوع" className="-mr-2" />
{/* Stock */}
موجودی { setUpdatingVariantId(variantId); updateVariantStock.mutate( { variantId, stock: newQuantity, }, { onSettled: () => { setUpdatingVariantId(null); }, } ); }} isPending={updatingVariantId === variant.id} allowManualEdit={true} throttleDelay={1000} />
); })}
)}
); } function StoreProductsContent() { const { storeId } = useParams(); const navigate = useNavigate(); const [openProductId, setOpenProductId] = useState(null); const [stickyProductId, setStickyProductId] = useState(null); const containerRef = useRef(null); const { data: products = [], isLoading, isError, } = useGetSellerProductsList(); useEffect(() => { const handleScroll = () => { if (openProductId) { setStickyProductId(openProductId); } }; window.addEventListener("scroll", handleScroll); return () => window.removeEventListener("scroll", handleScroll); }, [openProductId]); const handleToggleAccordion = (productId: string) => { if (openProductId === productId) { setOpenProductId(null); setStickyProductId(null); } else { setOpenProductId(productId); setStickyProductId(productId); } }; if (isLoading) { return (
در حال بارگذاری محصولات...
); } if (isError) { return (
خطا در بارگذاری محصولات
); } if (products.length === 0) { return (
محصولی یافت نشد
); } return (

محصولات فروشگاه

{products.length} محصول

{/* Desktop table-style header */}
محصول قیمت تنوع عملیات
{products.map((product) => product.id ? ( handleToggleAccordion(product.id || "")} isSticky={stickyProductId === product.id} storeId={storeId || ""} /> ) : null )}
); } export default function StoreProducts() { return ; }