-
-
Notifications
You must be signed in to change notification settings - Fork 755
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: added pagination in blog page #3591
base: master
Are you sure you want to change the base?
Changes from 1 commit
5fee8c9
396a102
9d57d6c
e78abef
e260c39
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,101 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import React from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { useRouter } from 'next/router'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { useState, useEffect } from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import IconArrowRight from '../icons/ArrowRight'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import IconArrowLeft from '../icons/ArrowLeft'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import Button from '../buttons/Button'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { ButtonIconPosition } from '@/types/components/buttons/ButtonPropsType'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
interface BlogPaginationProps { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
blogsPerPage: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
totalBlogs: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
paginate: (pageNumber: number) => void; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export default function BlogPagination({ blogsPerPage, totalBlogs, paginate }: BlogPaginationProps) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const router = useRouter(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { page } = router.query; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const currentPage: number = parseInt(page as string); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const totalPages: number = Math.ceil(totalBlogs / blogsPerPage); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const pagesToShow: number = 6; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const [pageNumbers, setPageNumbers] = useState<(number | string)[]>([]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const calculatePageNumbers = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const pageNumbers: (number | string)[] = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (totalPages <= pagesToShow) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for (let i = 1; i <= totalPages; i++) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push(i); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (currentPage <= 2) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for (let i = 1; i <= 3; i++) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push(i); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push('...'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push(totalPages - 2); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push(totalPages - 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push(totalPages); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (currentPage >= totalPages - 1) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push(1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push(2); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push(3); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push('...'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for (let i = totalPages - 2; i <= totalPages; i++) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push(i); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push(1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push('...'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push(currentPage - 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push(currentPage); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push(currentPage + 1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push('...'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
pageNumbers.push(totalPages); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return pageNumbers; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve pagination calculation robustness.
const calculatePageNumbers = () => {
- const pageNumbers: (number | string)[] = [];
+ const numbers: (number | string)[] = [];
+ if (totalPages < 1) return [];
if (totalPages <= pagesToShow) {
for (let i = 1; i <= totalPages; i++) {
- pageNumbers.push(i);
+ numbers.push(i);
}
} else {
// ... rest of the logic, replace pageNumbers with numbers
}
- return pageNumbers;
+ return numbers;
};
🧰 Tools🪛 eslint[error] 21-21: Delete (prettier/prettier) [error] 22-22: Replace (prettier/prettier) [error] 22-22: Expected blank line after variable declarations. (newline-after-var) [error] 22-22: 'pageNumbers' is already declared in the upper scope on line 19 column 12. (@typescript-eslint/no-shadow) [error] 23-23: Delete (prettier/prettier) [error] 23-53: Expected blank line before this statement. (padding-line-between-statements) [error] 24-24: Replace (prettier/prettier) [error] 25-25: Replace (prettier/prettier) [error] 26-26: Delete (prettier/prettier) [error] 27-27: Replace (prettier/prettier) [error] 28-28: Delete (prettier/prettier) [error] 28-52: Unexpected if as the only statement in an else block. (no-lonely-if) [error] 29-29: Replace (prettier/prettier) [error] 30-30: Delete (prettier/prettier) [error] 31-31: Replace (prettier/prettier) [error] 32-32: Delete (prettier/prettier) [error] 33-33: Replace (prettier/prettier) [error] 34-34: Replace (prettier/prettier) [error] 35-35: Replace (prettier/prettier) [error] 36-36: Delete (prettier/prettier) [error] 37-37: Replace (prettier/prettier) [error] 38-38: Replace (prettier/prettier) [error] 39-39: Replace (prettier/prettier) [error] 40-40: Replace (prettier/prettier) [error] 41-41: Delete (prettier/prettier) [error] 42-42: Replace (prettier/prettier) [error] 43-43: Replace (prettier/prettier) [error] 44-44: Delete (prettier/prettier) [error] 45-45: Replace (prettier/prettier) [error] 46-46: Replace (prettier/prettier) [error] 47-47: Replace (prettier/prettier) [error] 48-48: Replace (prettier/prettier) [error] 49-49: Replace (prettier/prettier) [error] 50-50: Replace (prettier/prettier) [error] 51-51: Delete (prettier/prettier) [error] 52-52: Delete (prettier/prettier) [error] 53-53: Replace (prettier/prettier) [error] 54-54: Delete (prettier/prettier) [error] 54-54: Expected blank line before this statement. (padding-line-between-statements) [error] 55-55: Delete (prettier/prettier) 🪛 GitHub Actions: PR testing - if Node project[error] 22-22: Variable 'pageNumbers' is already declared in the upper scope |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
setPageNumbers(calculatePageNumbers()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, [currentPage, totalBlogs]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<div className='flex justify-center items-center p-4 gap-2 mt-8'> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Button | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
className={`${currentPage === 1 && 'opacity-50 cursor-not-allowed'} w-[120px] h-[35px] py-2 px-4 rounded-l-md`} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bgClassName='bg-white' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
textClassName='text-[#212525] font-inter text-[14px] font-normal' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
text='Previous' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
disabled={currentPage === 1} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onClick={() => paginate(currentPage - 1)} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
icon={<IconArrowLeft className='w-4 h-4 inline-block' />} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
iconPosition={ButtonIconPosition.LEFT} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<div className='flex justify-center gap-3 w-[35vw]'> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{pageNumbers.map((number, index) => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<button | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
key={index} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
className={`w-[40px] h-[40px] ${number === currentPage ? 'border rounded bg-[#6200EE] text-white' : 'text-[#6B6B6B'}`} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix className syntax error. There's a missing closing bracket in the className string. -className={`w-[40px] h-[40px] ${number === currentPage ? 'border rounded bg-[#6200EE] text-white' : 'text-[#6B6B6B'}`}
+className={`w-[40px] h-[40px] ${number === currentPage ? 'border rounded bg-[#6200EE] text-white' : 'text-[#6B6B6B]'}`} 📝 Committable suggestion
Suggested change
🧰 Tools🪛 eslint[error] 78-78: Replace (prettier/prettier) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onClick={() => typeof number === 'number' && paginate(number)} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
disabled={number === '...'} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{number} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</button> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
))} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Button | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
className={`${currentPage === totalPages && 'opacity-50 cursor-not-allowed'} w-[120px] h-[35px] py-2 px-4 rounded-l-md`} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bgClassName='bg-white' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
textClassName='text-[#212525] font-inter text-[14px] font-normal' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
text='Next' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
disabled={currentPage === totalPages} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onClick={() => paginate(currentPage + 1)} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
icon={<IconArrowRight className='w-4 h-4 inline-block' />} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
iconPosition={ButtonIconPosition.RIGHT} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Optimize Tailwind classes and improve accessibility.
- <div className='flex justify-center items-center p-4 gap-2 mt-8'>
+ <nav aria-label="Blog pagination" className='flex justify-center items-center p-4 gap-2 mt-8'>
<Button
- className={`${currentPage === 1 && 'opacity-50 cursor-not-allowed'} w-[120px] h-[35px] py-2 px-4 rounded-l-md`}
+ className={`${currentPage === 1 ? 'opacity-50 cursor-not-allowed' : ''} size-[120px] py-2 px-4 rounded-l-md`}
+ aria-label="Previous page"
// ... rest of the props
/>
<div className='flex justify-center gap-3 w-[35vw]'>
{pageNumbers.map((number, index) => (
<button
key={index}
+ aria-label={`${typeof number === 'number' ? `Go to page ${number}` : 'More pages'}`}
+ aria-current={number === currentPage ? 'page' : undefined}
// ... rest of the props
> 📝 Committable suggestion
Suggested change
🧰 Tools🪛 eslint[error] 65-65: Delete (prettier/prettier) [error] 66-66: Replace (prettier/prettier) [error] 67-67: Delete (prettier/prettier) [error] 68-68: Replace (prettier/prettier) [error] 69-69: Delete (prettier/prettier) [error] 70-70: Replace (prettier/prettier) [error] 71-71: Delete (prettier/prettier) [error] 72-72: Delete (prettier/prettier) [error] 73-73: Delete (prettier/prettier) [error] 74-74: Delete (prettier/prettier) [error] 75-75: Replace (prettier/prettier) [error] 76-76: Delete (prettier/prettier) [error] 77-77: Replace (prettier/prettier) [error] 78-78: Delete (prettier/prettier) [error] 79-79: Replace (prettier/prettier) [error] 80-80: Delete (prettier/prettier) [error] 81-81: Delete (prettier/prettier) [error] 82-82: Replace (prettier/prettier) [error] 83-83: Delete (prettier/prettier) [error] 84-84: Delete (prettier/prettier) [error] 85-85: Replace (prettier/prettier) [error] 86-86: Replace (prettier/prettier) [error] 87-87: Replace (prettier/prettier) [error] 88-88: Delete (prettier/prettier) [error] 89-89: Delete (prettier/prettier) [error] 90-90: Replace (prettier/prettier) [error] 91-91: Delete (prettier/prettier) [error] 92-92: Replace (prettier/prettier) [error] 93-93: Delete (prettier/prettier) [error] 94-94: Replace (prettier/prettier) [error] 95-95: Delete (prettier/prettier) [error] 96-96: Replace (prettier/prettier) [error] 97-97: Delete (prettier/prettier) [error] 98-98: Replace (prettier/prettier) 🪛 GitHub Actions: PR testing - if Node project[warning] 65-95: Multiple Tailwind CSS issues: invalid classname order and non-usage of available shorthand properties (e.g., 'size-4' instead of 'w-4, h-4') |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,5 +1,5 @@ | ||||||
import { useRouter } from 'next/router'; | ||||||
import React, { useContext, useEffect, useState } from 'react'; | ||||||
import React, { useContext, useEffect, useState, useRef } from 'react'; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Remove unused useRef import. The useRef hook is imported but never used in the component. -import React, { useContext, useEffect, useState, useRef } from 'react';
+import React, { useContext, useEffect, useState } from 'react'; 📝 Committable suggestion
Suggested change
🧰 Tools🪛 eslint[error] 2-2: 'useRef' is defined but never used. (unused-imports/no-unused-imports) [error] 2-2: 'useRef' is defined but never used. (no-unused-vars) 🪛 GitHub Actions: PR testing - if Node project[error] 2-2: Unused import: 'useRef' is defined but never used |
||||||
|
||||||
import Empty from '@/components/illustrations/Empty'; | ||||||
import GenericLayout from '@/components/layout/GenericLayout'; | ||||||
|
@@ -13,7 +13,7 @@ import BlogContext from '@/context/BlogContext'; | |||||
import type { IBlogPost } from '@/types/post'; | ||||||
import { HeadingLevel, HeadingTypeStyle } from '@/types/typography/Heading'; | ||||||
import { ParagraphTypeStyle } from '@/types/typography/Paragraph'; | ||||||
|
||||||
import BlogPagination from '@/components/navigation/BlogPagination'; | ||||||
/** | ||||||
* @description The BlogIndexPage is the blog index page of the website. | ||||||
*/ | ||||||
|
@@ -24,19 +24,21 @@ export default function BlogIndexPage() { | |||||
const [posts, setPosts] = useState<IBlogPost[]>( | ||||||
navItems | ||||||
? navItems.sort((i1: IBlogPost, i2: IBlogPost) => { | ||||||
const i1Date = new Date(i1.date); | ||||||
const i2Date = new Date(i2.date); | ||||||
const i1Date = new Date(i1.date); | ||||||
const i2Date = new Date(i2.date); | ||||||
|
||||||
if (i1.featured && !i2.featured) return -1; | ||||||
if (!i1.featured && i2.featured) return 1; | ||||||
if (i1.featured && !i2.featured) return -1; | ||||||
if (!i1.featured && i2.featured) return 1; | ||||||
|
||||||
return i2Date.getTime() - i1Date.getTime(); | ||||||
}) | ||||||
return i2Date.getTime() - i1Date.getTime(); | ||||||
}) | ||||||
: [] | ||||||
); | ||||||
const [isClient, setIsClient] = useState(false); | ||||||
|
||||||
const onFilter = (data: IBlogPost[]) => setPosts(data); | ||||||
const onFilter = (data: IBlogPost[]) => { | ||||||
setPosts(data); | ||||||
}; | ||||||
const toFilter = [ | ||||||
{ | ||||||
name: 'type' | ||||||
|
@@ -50,14 +52,61 @@ export default function BlogIndexPage() { | |||||
} | ||||||
]; | ||||||
const clearFilters = () => { | ||||||
router.push(`${router.pathname}`, undefined, { | ||||||
shallow: true | ||||||
}); | ||||||
const { page } = router.query; | ||||||
router.push( | ||||||
{ | ||||||
pathname: router.pathname, | ||||||
query: { ...(page && { page }) }, | ||||||
}, | ||||||
undefined, | ||||||
{ | ||||||
shallow: true, | ||||||
} | ||||||
); | ||||||
}; | ||||||
const showClearFilters = Object.keys(router.query).length > 0; | ||||||
const showClearFilters = Object.keys(router.query).length > 1; | ||||||
|
||||||
const description = 'Find the latest and greatest stories from our community'; | ||||||
const image = '/img/social/blog.webp'; | ||||||
const blogsPerPage = 9; | ||||||
|
||||||
const [currentPosts, setCurrentPosts] = useState<IBlogPost[]>([]); | ||||||
|
||||||
const paginate = (pageNumber: number) => { | ||||||
const { query } = router; | ||||||
const newQuery = { | ||||||
...query, | ||||||
page: pageNumber | ||||||
}; | ||||||
router.push( | ||||||
{ | ||||||
pathname: router.pathname, | ||||||
query: newQuery | ||||||
}, | ||||||
undefined, | ||||||
{ | ||||||
shallow: true | ||||||
} | ||||||
); | ||||||
}; | ||||||
useEffect(() => { | ||||||
if(router.isReady){ | ||||||
const pageFromQuery = parseInt(router.query.page as string); | ||||||
if(!pageFromQuery){ | ||||||
router.replace( | ||||||
{ | ||||||
pathname: router.pathname, | ||||||
query: { ...router.query, page: '1' }, | ||||||
}, | ||||||
undefined, | ||||||
{ shallow: true } | ||||||
); | ||||||
} | ||||||
const indexOfLastPost = pageFromQuery * blogsPerPage; | ||||||
const indexOfFirstPost = indexOfLastPost - blogsPerPage; | ||||||
setCurrentPosts(posts.slice(indexOfFirstPost, indexOfLastPost)); | ||||||
} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve pagination state management and performance.
Consider using a custom hook to manage pagination state: function usePagination<T>(items: T[], itemsPerPage: number) {
const [currentPage, setCurrentPage] = useState(1);
const maxPage = Math.ceil(items.length / itemsPerPage);
const currentItems = useMemo(() => {
const start = (currentPage - 1) * itemsPerPage;
return items.slice(start, start + itemsPerPage);
}, [items, currentPage, itemsPerPage]);
return {
currentPage,
setCurrentPage,
currentItems,
maxPage
};
} 🧰 Tools🪛 eslint[error] 75-91: Expected blank line after variable declarations. (newline-after-var) [error] 77-80: Expected blank line after variable declarations. (newline-after-var) [error] 81-90: Expected blank line before this statement. (padding-line-between-statements) [error] 86-86: Trailing spaces not allowed. (no-trailing-spaces) [error] 86-86: Delete (prettier/prettier) [error] 93-93: Expected space(s) after "if". (keyword-spacing) [error] 93-93: Replace (prettier/prettier) [error] 93-108: Missing space before opening brace. (space-before-blocks) [error] 94-94: Expected blank line after variable declarations. (newline-after-var) [error] 94-94: Missing radix parameter. (radix) [error] 95-104: Expected blank line before this statement. (padding-line-between-statements) [error] 95-95: Expected space(s) after "if". (keyword-spacing) [error] 95-95: Replace (prettier/prettier) [error] 95-104: Missing space before opening brace. (space-before-blocks) [error] 99-99: Delete (prettier/prettier) [error] 99-99: Unexpected trailing comma. (comma-dangle) [error] 106-106: Expected blank line after variable declarations. (newline-after-var) [error] 107-107: Expected blank line before this statement. (padding-line-between-statements) |
||||||
}, [router.isReady, router.query.page, posts]); | ||||||
|
||||||
useEffect(() => { | ||||||
setIsClient(true); | ||||||
|
@@ -114,15 +163,15 @@ export default function BlogIndexPage() { | |||||
)} | ||||||
</div> | ||||||
<div> | ||||||
{Object.keys(posts).length === 0 && ( | ||||||
{(Object.keys(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) => ( | ||||||
{currentPosts.map((post, index) => ( | ||||||
<BlogPostItem key={index} post={post} /> | ||||||
))} | ||||||
</ul> | ||||||
|
@@ -132,6 +181,11 @@ export default function BlogIndexPage() { | |||||
<Loader loaderText='Loading Blogs' className='mx-auto my-60' pulsating /> | ||||||
</div> | ||||||
)} | ||||||
<BlogPagination | ||||||
blogsPerPage={blogsPerPage} | ||||||
totalBlogs={posts.length} | ||||||
paginate={paginate} | ||||||
/> | ||||||
</div> | ||||||
</div> | ||||||
</div> | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add input validation for currentPage.
The
parseInt
call is missing a radix parameter and there's no validation for NaN values.📝 Committable suggestion
🧰 Tools
🪛 eslint
[error] 19-19: Delete
··
(prettier/prettier)
[error] 19-19: Missing radix parameter.
(radix)
[error] 20-20: Replace
····
with··
(prettier/prettier)