Bring the home product tile to search and explore: seller brand chip (SellerChip) plus price/discount overlay, instead of a bare image. - search: map discountPercent/discountPrice/basePrice + sellerName from ProductSearchResult (sellerName is already returned, so the chip shows now with the initial-letter fallback). - explore: map sellerName/sellerLogo/sellerUsername (and add them to the Product type); these populate once the backend ProductSerializer change ships. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
130 lines
4.7 KiB
TypeScript
130 lines
4.7 KiB
TypeScript
import { useState } from "react";
|
||
import { useProductsInfiniteQuery } from "../../requestHandler/use-explore-hooks";
|
||
import { useGetHomeCategories } from "../../requestHandler/use-home-hooks";
|
||
import TabContainer from "./TabContainer";
|
||
import { Link } from "@remix-run/react";
|
||
import { Telescope } from "lucide-react";
|
||
import MondrianProductList from "../MondrianProductList";
|
||
import { Skeleton } from "../ui/skeleton";
|
||
|
||
const MainSection = () => {
|
||
const tabs = ["دسته بندی ها", "همه"];
|
||
const [activeTab, setActiveTab] = useState(0);
|
||
|
||
// Use our custom infinite query hook
|
||
const {
|
||
data,
|
||
fetchNextPage,
|
||
hasNextPage,
|
||
isFetchingNextPage,
|
||
status,
|
||
refetch,
|
||
} = useProductsInfiniteQuery();
|
||
|
||
// Use the new categories hook
|
||
const {
|
||
data: categories,
|
||
isLoading: categoriesLoading,
|
||
isError: categoriesError,
|
||
} = useGetHomeCategories();
|
||
|
||
// Flatten all products from all pages
|
||
const allProducts = data?.pages.flatMap((page) => page.results) || [];
|
||
|
||
// Loading skeleton for categories
|
||
const CategorySkeleton = () => (
|
||
<div className="px-4 flex flex-col gap-6 w-full">
|
||
<div className="grid grid-cols-2 gap-4 w-full">
|
||
{Array.from({ length: 6 }).map((_, index) => (
|
||
<div key={index} className="relative">
|
||
<Skeleton className="w-full h-[120px] rounded-[15px]" />
|
||
<Skeleton className="absolute bottom-2 left-2/4 -translate-x-1/2 w-20 h-4" />
|
||
</div>
|
||
))}
|
||
</div>
|
||
<Skeleton className="w-full h-16" />
|
||
</div>
|
||
);
|
||
|
||
return (
|
||
<div className="flex flex-col gap-6 w-full pb-20 lg:max-w-[1320px] lg:mx-auto lg:px-8 lg:pt-6">
|
||
<TabContainer
|
||
activeTab={activeTab}
|
||
setActiveTab={setActiveTab}
|
||
tabs={tabs}
|
||
/>
|
||
{activeTab === 0 ? (
|
||
categoriesLoading ? (
|
||
<CategorySkeleton />
|
||
) : categoriesError ? (
|
||
<div className="px-4 flex flex-col items-center gap-4 py-8">
|
||
<Telescope size={80} className="text-GRAY" />
|
||
<p className="text-R14 text-GRAY text-center">
|
||
خطا در بارگذاری دسته بندی ها
|
||
</p>
|
||
</div>
|
||
) : (
|
||
<div className="px-4 lg:px-0 flex flex-col gap-6 w-full">
|
||
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4 w-full">
|
||
{categories?.map((category, index) => {
|
||
return (
|
||
<Link
|
||
className="flex relative w-full cursor-pointer items-center gap-2"
|
||
key={category.id || index}
|
||
to={`/search/${category.categoryName}`}
|
||
>
|
||
<img
|
||
src={category.imageUrl}
|
||
className="w-full h-[120px] lg:h-[180px] object-cover rounded-[15px]"
|
||
alt={category.categoryName}
|
||
/>
|
||
<p className="text-B16 text-center line-clamp-1 w-full font-bold text-white absolute bottom-2 left-2/4 -translate-x-1/2">
|
||
{category.categoryName}
|
||
</p>
|
||
</Link>
|
||
);
|
||
})}
|
||
</div>
|
||
<p className="text-R14 text-GRAY">
|
||
در ویترون، پوشاک تنها یک انتخاب نیست، بلکه تجربه ای از سبک و کیفیت
|
||
است. هر دسته بندی با دقت طراحی شده تا شما را در مسیر ساخت استایل
|
||
شخصی و متمایزتان همراهی کند.
|
||
</p>
|
||
</div>
|
||
)
|
||
) : (
|
||
<MondrianProductList
|
||
products={allProducts.map((product) => {
|
||
return {
|
||
id: product.id,
|
||
title: product.title,
|
||
images: product.imageUrls || [],
|
||
discountPercent: product.discountPercent || 0,
|
||
discountPrice: product.discountPrice || 0,
|
||
basePrice: product.basePrice
|
||
? parseInt(product.basePrice)
|
||
: undefined,
|
||
sellerName: product.sellerName,
|
||
sellerLogo: product.sellerLogo,
|
||
sellerUsername: product.sellerUsername,
|
||
};
|
||
})}
|
||
fetchNextPage={fetchNextPage}
|
||
hasNextPage={hasNextPage}
|
||
isFetchingNextPage={isFetchingNextPage}
|
||
isLoading={status === "pending"}
|
||
isError={status === "error"}
|
||
refetch={refetch}
|
||
emptyState={{
|
||
image: <Telescope size={80} />,
|
||
title: "محصولی در اکسپلور یافت نشد",
|
||
description:
|
||
"فکر میکنم بهتر باشه یه وقت دیگه تست کنید یا اینکه چیزی جدید بیاید.",
|
||
}}
|
||
/>
|
||
)}
|
||
</div>
|
||
);
|
||
};
|
||
export default MainSection;
|