Skip to content
Open
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 62 additions & 41 deletions pages/blog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { useRouter } from 'next/router';
import React, { useContext, useEffect, useState } from 'react';
import React, { useContext, useState } from 'react';

import Empty from '@/components/illustrations/Empty';
import GenericLayout from '@/components/layout/GenericLayout';
import Loader from '@/components/Loader';
import BlogPostItem from '@/components/navigation/BlogPostItem';
import Filter from '@/components/navigation/Filter';
import Heading from '@/components/typography/Heading';
Expand All @@ -14,13 +13,11 @@ import type { IBlogPost } from '@/types/post';
import { HeadingLevel, HeadingTypeStyle } from '@/types/typography/Heading';
import { ParagraphTypeStyle } from '@/types/typography/Paragraph';

/**
* @description The BlogIndexPage is the blog index page of the website.
*/
export default function BlogIndexPage() {
const router = useRouter();
const { navItems } = useContext(BlogContext);

// Sorting featured + date
const [posts, setPosts] = useState<IBlogPost[]>(
navItems
? navItems.sort((i1: IBlogPost, i2: IBlogPost) => {
Expand All @@ -34,41 +31,39 @@ export default function BlogIndexPage() {
})
: []
);
const [isClient, setIsClient] = useState(false);

const onFilter = (data: IBlogPost[]) => setPosts(data);
const toFilter = [
{
name: 'type'
},
{
name: 'authors',
unique: 'name'
},
{
name: 'tags'
}
];

const [currentPage, setCurrentPage] = useState(1);
const postsPerPage = 6;

const indexOfLastPost = currentPage * postsPerPage;
const indexOfFirstPost = indexOfLastPost - postsPerPage;
const currentPosts = posts.slice(indexOfFirstPost, indexOfLastPost);

const totalPages = Math.ceil(posts.length / postsPerPage);

const onFilter = (data: IBlogPost[]) => {
setPosts(data);
setCurrentPage(1);
};

const toFilter = [{ name: 'type' }, { name: 'authors', unique: 'name' }, { name: 'tags' }];

const clearFilters = () => {
router.push(`${router.pathname}`, undefined, {
shallow: true
});
router.push(`${router.pathname}`, undefined, { shallow: true });
};

const showClearFilters = Object.keys(router.query).length > 0;

const description = 'Find the latest and greatest stories from our community';
const image = '/img/social/blog.webp';

useEffect(() => {
setIsClient(true);
}, []);

return (
<GenericLayout title='Blog' description={description} image={image} wide>
<div className='relative px-4 pb-20 pt-8 sm:px-6 lg:px-8 lg:pb-28 lg:pt-12' id='main-content'>
<div className='absolute inset-0'>
<div className='h-1/3 bg-white sm:h-2/3'></div>
</div>

<div className='relative mx-auto max-w-7xl'>
<div className='text-center'>
<Heading level={HeadingLevel.h1} typeStyle={HeadingTypeStyle.lg}>
Expand Down Expand Up @@ -96,6 +91,8 @@ export default function BlogIndexPage() {
<TextLink href='/rss.xml'> RSS Feed</TextLink>, too!
</Paragraph>
</div>

{/* Filter Controls */}
<div className='mx:64 mt-12 md:flex md:justify-center lg:justify-center'>
<Filter
data={navItems || []}
Expand All @@ -106,31 +103,55 @@ export default function BlogIndexPage() {
{showClearFilters && (
<button
type='button'
className='bg-none text-md mt-1 rounded-md border border-gray-200 px-4 py-2 font-semibold tracking-heading text-gray-800 shadow-none transition-all duration-500 ease-in-out hover:text-gray-700 md:mt-0 md:py-0'
className='bg-none text-md mt-1 rounded-md border border-gray-200 px-4 py-2
font-semibold tracking-heading text-gray-800 shadow-none transition-all
duration-500 ease-in-out hover:text-gray-700 md:mt-0 md:py-0'
onClick={clearFilters}
>
<span className='inline-block'>Clear filters</span>
</button>
)}
</div>

{/* Blog List and Pagination */}
<div>
{Object.keys(posts).length === 0 && (
{posts.length === 0 ? (
<div className='mt-16 flex flex-col items-center justify-center'>
<Empty />
<p className='mx-auto mt-3 max-w-2xl text-xl leading-7 text-gray-500'>No post matches your filter</p>
</div>
)}
{Object.keys(posts).length > 0 && isClient && (
<ul className='mx-auto mt-12 grid max-w-lg gap-5 lg:max-w-none lg:grid-cols-3'>
{posts.map((post, index) => (
<BlogPostItem key={index} post={post} />
))}
</ul>
)}
{Object.keys(posts).length > 0 && !isClient && (
<div className='h-screen w-full'>
<Loader loaderText='Loading Blogs' className='mx-auto my-60' pulsating />
</div>
) : (
<>
<ul className='mx-auto mt-12 grid max-w-lg gap-5 lg:max-w-none lg:grid-cols-3'>
{currentPosts.map((post) => (
<BlogPostItem key={post.slug || post.id || post.title} post={post} />
))}
</ul>

{totalPages > 1 && (
<div className='mt-10 flex justify-center items-center space-x-4'>
<button
onClick={() => setCurrentPage((prev) => Math.max(prev - 1, 1))}
disabled={currentPage === 1}
className='rounded-md border border-gray-300 px-3 py-1 text-gray-700 hover:bg-gray-100 disabled:opacity-50'
>
Previous
</button>

<span className='text-gray-700'>
Page {currentPage} of {totalPages}
</span>

<button
onClick={() => setCurrentPage((prev) => Math.min(prev + 1, totalPages))}
disabled={currentPage === totalPages}
className='rounded-md border border-gray-300 px-3 py-1 text-gray-700 hover:bg-gray-100 disabled:opacity-50'
>
Next
</button>
</div>
)}
</>
)}
</div>
</div>
Expand Down
Loading