added collection page
This commit is contained in:
@@ -106,30 +106,61 @@ export default function CategoryPageClient({
|
||||
}
|
||||
}, [selectedCategory?.id]);
|
||||
|
||||
// Update products list
|
||||
// Update products list - BU KISIM ÖNEMLİ!
|
||||
useEffect(() => {
|
||||
if (productsData?.data) {
|
||||
setAllProducts((prev) => {
|
||||
// İlk sayfa ise direkt replace et
|
||||
if (currentPage === 1) {
|
||||
return productsData.data;
|
||||
}
|
||||
|
||||
// Sonraki sayfalar için deduplicate et
|
||||
const existingIds = new Set(prev.map((p) => p.id));
|
||||
const newProducts = productsData.data.filter(
|
||||
(p: Product) => !existingIds.has(p.id)
|
||||
);
|
||||
|
||||
// Eğer yeni ürün yoksa, return prev (gereksiz re-render önlenir)
|
||||
if (newProducts.length === 0) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
return [...prev, ...newProducts];
|
||||
});
|
||||
}
|
||||
}, [productsData, currentPage]);
|
||||
}, [productsData?.data, currentPage]); // productsData yerine productsData.data
|
||||
|
||||
// hasMore hesaplama - BU KISIM DA ÖNEMLİ!
|
||||
const hasMore = useMemo(() => {
|
||||
return !!productsData?.pagination?.next_page_url;
|
||||
}, [productsData]);
|
||||
if (!productsData?.pagination) return false;
|
||||
|
||||
// pagination.next_page_url varsa devam et
|
||||
if (productsData.pagination.next_page_url) return true;
|
||||
|
||||
// Alternatif olarak: current_page < last_page kontrolü
|
||||
if (
|
||||
productsData.pagination.current_page &&
|
||||
productsData.pagination.last_page
|
||||
) {
|
||||
return (
|
||||
productsData.pagination.current_page < productsData.pagination.last_page
|
||||
);
|
||||
}
|
||||
|
||||
// Alternatif 2: hasMorePages flag'i varsa
|
||||
if (productsData.pagination.hasMorePages !== undefined) {
|
||||
return productsData.pagination.hasMorePages;
|
||||
}
|
||||
|
||||
return false;
|
||||
}, [productsData?.pagination]);
|
||||
|
||||
const loadMoreData = useCallback(() => {
|
||||
if (!hasMore || isFetching) return;
|
||||
console.log("Loading page:", currentPage + 1); // Debug için
|
||||
setCurrentPage((prev) => prev + 1);
|
||||
}, [hasMore, isFetching]);
|
||||
}, [hasMore, isFetching, currentPage]);
|
||||
|
||||
const sortedProducts = useMemo(() => {
|
||||
const products = [...allProducts];
|
||||
@@ -245,6 +276,7 @@ export default function CategoryPageClient({
|
||||
products={sortedProducts}
|
||||
hasMore={hasMore}
|
||||
onLoadMore={loadMoreData}
|
||||
isFetching={isFetching}
|
||||
translations={{
|
||||
loading: t("common.loading"),
|
||||
no_results: t("no_results"),
|
||||
@@ -276,4 +308,4 @@ export default function CategoryPageClient({
|
||||
</CategoryFiltersSheet>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ interface CategoryProductsGridProps {
|
||||
products: Product[];
|
||||
hasMore: boolean;
|
||||
onLoadMore: () => void;
|
||||
isFetching?: boolean; // Yeni prop - loading durumu için
|
||||
translations: {
|
||||
loading: string;
|
||||
no_results: string;
|
||||
@@ -16,9 +17,10 @@ export default function CategoryProductsGrid({
|
||||
products,
|
||||
hasMore,
|
||||
onLoadMore,
|
||||
isFetching = false,
|
||||
translations,
|
||||
}: CategoryProductsGridProps) {
|
||||
if (products.length === 0) {
|
||||
if (products.length === 0 && !isFetching) {
|
||||
return (
|
||||
<div className="text-center py-8 text-gray-500">
|
||||
{translations.no_results}
|
||||
@@ -35,9 +37,19 @@ export default function CategoryProductsGrid({
|
||||
style={{ overflow: "visible" }}
|
||||
loader={
|
||||
<div className="flex justify-center py-4">
|
||||
<div>{translations.loading}</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-5 h-5 border-2 border-gray-300 border-t-blue-500 rounded-full animate-spin" />
|
||||
<span>{translations.loading}</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
endMessage={
|
||||
products.length > 0 && !hasMore ? (
|
||||
<div className="text-center py-4 text-gray-500 text-sm">
|
||||
{/* Opsiyonel: "Tüm ürünler yüklendi" mesajı */}
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
>
|
||||
<div className="bg-white rounded-lg grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-3">
|
||||
{products.map((product) => (
|
||||
@@ -55,6 +67,19 @@ export default function CategoryProductsGrid({
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* İlk yükleme için skeleton göster */}
|
||||
{isFetching && products.length === 0 && (
|
||||
<div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-3 mt-3">
|
||||
{Array.from({ length: 6 }).map((_, i) => (
|
||||
<div key={i} className="animate-pulse">
|
||||
<div className="bg-gray-200 h-48 rounded-lg mb-2" />
|
||||
<div className="bg-gray-200 h-4 rounded w-3/4 mb-2" />
|
||||
<div className="bg-gray-200 h-4 rounded w-1/2" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</InfiniteScroll>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user