diff --git a/apps/www/app/blog/BlogClient.tsx b/apps/www/app/blog/BlogClient.tsx index 636cefd9ed6..953b2da92c0 100644 --- a/apps/www/app/blog/BlogClient.tsx +++ b/apps/www/app/blog/BlogClient.tsx @@ -1,16 +1,13 @@ 'use client' -import { useState, useCallback } from 'react' -import DefaultLayout from 'components/Layouts/Default' +import { isBrowser, LOCAL_STORAGE_KEYS } from 'common' +import BlogFilters from 'components/Blog/BlogFilters' import BlogGridItem from 'components/Blog/BlogGridItem' import BlogListItem from 'components/Blog/BlogListItem' -import BlogFilters from 'components/Blog/BlogFilters' -import FeaturedThumb from 'components/Blog/FeaturedThumb' -import { cn } from 'ui' -import { LOCAL_STORAGE_KEYS, isBrowser } from 'common' import { useInfiniteScrollWithFetch } from 'hooks/useInfiniteScroll' - +import { useCallback, useState } from 'react' import type PostTypes from 'types/post' +import { cn } from 'ui' export type BlogView = 'list' | 'grid' @@ -74,14 +71,20 @@ export default function BlogClient({ initialBlogs, totalPosts }: BlogClientProps const [filteredTotal, setFilteredTotal] = useState(null) const isList = view === 'list' - // Determine which posts and total to use based on filter state const currentPosts = filteredPosts ?? initialBlogs const currentTotal = filteredTotal ?? totalPosts const fetchMorePosts = useCallback( async (offset: number, limit: number) => { + const isFiltered = + (filterParams.category && filterParams.category !== 'all') || Boolean(filterParams.search) + // The featured post is rendered above the list (not in `items`), so the + // API offset has to skip past it for unfiltered fetches. Filtered + // results come from a separate query and don't share that hero slot. + const apiOffset = isFiltered ? offset : offset + 1 + const params = new URLSearchParams({ - offset: offset.toString(), + offset: apiOffset.toString(), limit: limit.toString(), }) @@ -118,9 +121,7 @@ export default function BlogClient({ initialBlogs, totalPosts }: BlogClientProps rootMargin: '1000px', }) - // Handle filter changes - fetch filtered results from API const handleFilterChange = useCallback(async (category?: string, search?: string) => { - // If no filters, reset to initial state if ((!category || category === 'all') && !search) { setFilterParams({}) setFilteredPosts(null) @@ -159,78 +160,64 @@ export default function BlogClient({ initialBlogs, totalPosts }: BlogClientProps } }, []) - const featuredPost = initialBlogs[0] - return ( <> - -

Supabase blog

-
- {featuredPost && } -
+ -
-
- - -
    - {isFiltering ? ( - // Show skeletons while filtering - isList ? ( - Array.from({ length: SKELETON_COUNT }).map((_, idx) => ( -
    - -
    - )) - ) : ( - Array.from({ length: SKELETON_COUNT }).map((_, idx) => ( -
    - -
    - )) - ) - ) : blogs?.length ? ( - blogs?.map((blog: PostTypes, idx: number) => - isList ? ( -
    - -
    - ) : ( -
    - -
    - ) - ) - ) : ( -

    No results

    - )} -
- - {hasMore && !isFiltering && ( -