Skip to content

Commit a200ae0

Browse files
committed
Made Pagination feature more accessible and optimized
1 parent 0538fbe commit a200ae0

File tree

13 files changed

+55
-24
lines changed

13 files changed

+55
-24
lines changed

src/app/tags/[tag]/page.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,15 @@ export default async function TagsPage({params, searchParams}: PageProps){
7979
const currentPage = page ? parseInt(page) : 1;
8080
const postsPerPage = pageSize ? parseInt(pageSize) : POSTS_IN_SEARCH;
8181
const tagDecoded = decodeURIComponent(tag)
82-
const results = await getPostsByTag(tagDecoded)
83-
const totalPages = Math.ceil(results.length / postsPerPage)
82+
const results = await getPostsByTag(tagDecoded);
8483
return (
8584
<PageLayout>
8685
<Search
8786
mode="tag"
8887
pageSize={postsPerPage}
8988
tag={tagDecoded}
9089
results={results}
91-
totalPages={totalPages}
90+
totalPages={results.length}
9291
currentPage={currentPage}
9392
/>
9493
</PageLayout>

src/components/pages/landing.tsx

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import { PaginationWithLinks } from "@/components/pagination-with-links"
1818
import CollapsibleFilters from "../blog/widget/filters"
1919
import NoSearchResults from "../shrug"
2020
import { InputGroup, InputGroupAddon, InputGroupInput } from "@/components/ui/input-group"
21+
import usePaginatedData from "@/hooks/use-pagination";
22+
import { getRangeAsText } from "@/lib/helpers/seo";
2123

2224
interface LandingPageProps{
2325
posts: IBlogPostBase[],
@@ -39,7 +41,7 @@ function BlogPosts(props: BlogPostsProps) {
3941
return <Inner {...props} />
4042
}
4143

42-
export default function LandingPage({posts, totalPages, currentPage, categories,pageSize, query}: LandingPageProps){
44+
export default function LandingPage({posts, totalPages, currentPage, categories, pageSize, query}: LandingPageProps){
4345
const [search, setSearch] = useState(query)
4446
const [selected, setSelected] = useState<string[]>([])
4547
const filteredPosts = useMemo(()=>{
@@ -56,10 +58,7 @@ export default function LandingPage({posts, totalPages, currentPage, categories,
5658
): currPosts;
5759
return flairFilters;
5860
},[search,posts,selected])
59-
const entries = filteredPosts.slice(
60-
(currentPage - 1) * pageSize,
61-
currentPage * pageSize
62-
)
61+
const entries = usePaginatedData(filteredPosts,currentPage,pageSize);
6362
const featured = posts.filter(post=>post.featured).slice(0,MAX_FEATURED_POSTS);
6463
const toggleCategory = (category: string) => setSelected(prev=>prev?.includes(category) ? prev.filter(val=>val!==category) : [...(prev||[]),category])
6564
return (
@@ -79,7 +78,17 @@ export default function LandingPage({posts, totalPages, currentPage, categories,
7978
{posts.length!==0 ? (
8079
<SiteSection id="blog" innerWidthClass="space-y-4 grid grid-cols-1 lg:grid-cols-[3fr_1fr] gap-4">
8180
<div className="space-y-5">
82-
<h3 className="scroll-m-20 text-xl md:text-2xl lg:text-3xl font-semibold tracking-tight border-b border-primary pb-2">{search==="" ? "Latest Posts" : "Search Results"}</h3>
81+
<div className="flex flex-col md:flex-row justify-center md:justify-between items-center gap-2.5">
82+
<h3 className="scroll-m-20 text-xl md:text-2xl lg:text-3xl font-semibold tracking-tight border-b border-primary pb-2">{search==="" ? "Latest Posts" : "Search Results"}</h3>
83+
<p className="text-sm text-muted-foreground">
84+
{getRangeAsText(
85+
currentPage,
86+
pageSize,
87+
search==="" ? totalPages : entries.length,
88+
"post"
89+
)}
90+
</p>
91+
</div>
8392
{entries.length<=0 ? (
8493
<div className="flex !mt-0 flex-col items-center justify-center gap-3 h-full w-full">
8594
<NoSearchResults tag={search}/>

src/components/pages/search.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import NoSearchResults from "../shrug"
1616
import { InputGroup, InputGroupAddon, InputGroupInput } from "@/components/ui/input-group"
1717
import { BlogPostsProps } from "../blog-posts"
1818
import PostsLoader from "../loaders/posts"
19+
import { getRangeAsText } from "@/lib/helpers/seo"
20+
import usePaginatedData from "@/hooks/use-pagination"
1921

2022
export const searchSchema = z.object({
2123
query: z.string().trim()
@@ -52,11 +54,8 @@ export default function Search(props: SearchProps){
5254
)
5355
: results.filter(val=>val.categories.some(c=>c.toLowerCase().includes(keyword.toLowerCase())))
5456
,[results, keyword, mode])
55-
const router = useRouter()
56-
const entries = filteredPosts.slice(
57-
(currentPage - 1) * pageSize,
58-
currentPage + pageSize
59-
)
57+
const router = useRouter();
58+
const entries = usePaginatedData(filteredPosts,currentPage,pageSize);
6059
const form = useForm<z.infer<typeof searchSchema>>({
6160
resolver: zodResolver(searchSchema),
6261
defaultValues: { query: keyword }
@@ -90,7 +89,13 @@ export default function Search(props: SearchProps){
9089
<InputGroupAddon>
9190
<SearchIcon/>
9291
</InputGroupAddon>
93-
<InputGroupAddon align="inline-end">{entries.length} {entries.length<=1 ? "result" : "results"}</InputGroupAddon>
92+
<InputGroupAddon align="inline-end">
93+
{getRangeAsText(
94+
currentPage,
95+
pageSize,
96+
totalPages
97+
)}
98+
</InputGroupAddon>
9499
</InputGroup>
95100
</FormItem>
96101
)}

src/hooks/use-pagination.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default function usePaginatedData<T>(items: T[], page: number, pageSize: number){
2+
const endIndex = page * pageSize;
3+
const startIndex = endIndex - pageSize;
4+
return items.slice(startIndex,endIndex)
5+
}

src/lib/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const SOCIAL_MEDIA_LINKS = [
1818
export const POSTS_PER_PAGE = 8
1919
export const POSTS_IN_SEARCH = 5
2020
export const MAX_RELATED_POSTS = 3
21-
export const MAX_FEATURED_POSTS = 5
21+
export const MAX_FEATURED_POSTS = 6
2222
export const SITE_URL = process.env.NODE_ENV==="production" ? "https://arsentech-blog.vercel.app" : "http://localhost:3000"
2323

2424
export const KEYWORDS = ["arsentech", "arsentech youtube", "arsentech github", "malware", "malware testing", "windows", "windows experiments", "tech tutorials", "technology", "tech", "arsen tech", "coding", "programming", "coding with arsentech", "arsentech shorts", "remove memz", "remove 000.exe", "avast vs noescape", "antivirus", "linux", "virus testing", "antimalware", "ransomware", "trojan", "trojan malware", "techonologies", "html", "css", "js", "coding languages", "computer", "computer virus", "computer malware", "software", "more arsentech", "chrome", "tech tips", "tech youtuber", "programmer", "coder", "coding tips", "freeware", "software engineer", "software coding", "ms dos", "operating system", "normal people vs coder", "normal people vs programmer", "coding tutorials", "pc", "blog", "arsentech blog", "tech blog", "coding blog"]

src/lib/helpers/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ export const getAllTags = cache(async(limit?: number) => {
9393

9494
export const getPostsByTag = cache(async(tag: string) => {
9595
const posts = await getAllPosts();
96-
return posts.filter(post =>post.tags.some(t => t.toLowerCase() === tag.toLowerCase()));
96+
return posts.filter(post =>post.tags.some(t => t.toLowerCase().includes(tag.toLowerCase())));
9797
});
9898

9999
export const getAllSlugs = cache(async(limit?: number) => {

src/lib/helpers/seo.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,17 @@ export function getValueFromKey(searchParams: URLSearchParams, key: string, fall
44
const hasKey = searchParams.has(key);
55
return hasKey ? searchParams.get(key)?.slice(0,100) ?? fallbackValue : fallbackValue
66
}
7-
export const absoluteURL = (path: string) => `${SITE_URL}${path}`
7+
export const absoluteURL = (path: string) => `${SITE_URL}${path}`
8+
9+
export function getRangeAsText(page: number, pageSize: number, totalResults: number, itemName = 'result'): string {
10+
if (totalResults === 0)
11+
return `Showing 0 ${itemName}s on this page`;
12+
13+
const start = (page - 1) * pageSize + 1;
14+
const end = Math.min(page * pageSize, totalResults);
15+
16+
if (start >= totalResults)
17+
return `Showing ${totalResults} of ${totalResults} ${itemName}s`;
18+
19+
return `Showing ${start} - ${end} of ${totalResults} ${totalResults <= 1 ? itemName : `${itemName}s`}`;
20+
}

src/posts/remove-000-exe.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: "How to Remove The 000.exe Virus"
33
description: "This guide will help you remove the 000.exe virus without any antivirus software or any help on your infected Windows PC. You'll learn to fix MBR corruptions after reading the post"
44
date: "2025-11-26"
5-
tags: ["000.exe", "malware", "remove 000.exe", "delete 000.exe", "computer virus", "000.exe removal", "000.exe malware", "how to remove the 000.exe", "how to delete the 000.exe"]
5+
tags: ["000.exe", "malware", "remove 000.exe", "delete 000.exe", "computer virus", "000.exe removal", "000.exe malware", "how to remove 000.exe", "troubleshooting", "windows"]
66
published: true
77
featured: false
88
categories: ["Malware Removal", "Windows", "Cybersecurity", "Troubleshooting", "Bootable USB"]

src/posts/remove-ios-calendar-virus.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: "How to Remove the Dangerous Calendar Spam from Your iPhone"
33
description: "This guide will help you remove the dangerous calendar virus (that keeps poping up) on your iOS device"
44
date: "2025-11-25"
5-
tags: ["iphone", "ios", "calendar", "iphone spam", "calendar spam", "calendar virus", "calendar spam ios", "calendar virus ios", "ios calendar virus", "iphone calendar spam", "iphone calendar virus"]
5+
tags: ["iphone", "ios", "calendar", "iphone spam", "calendar spam", "calendar virus", "calendar spam ios", "calendar virus ios", "ios calendar virus", "iphone calendar spam", "iphone calendar virus", "troubleshooting"]
66
published: true
77
featured: false
88
categories: ["Malware Removal", "iOS", "Cybersecurity", "Troubleshooting"]

src/posts/remove-memz.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: "How to Remove The MEMZ Trojan"
33
description: "This guide will help you remove the MEMZ trojan without any antivirus software or any help on your infected Windows PC. You'll learn to fix MBR corruptions after reading the post"
44
date: "2025-11-26"
5-
tags: ["memz trojan", "malware", "memz", "remove memz trojan", "delete memz trojan", "memz trojan removal", "memz trojan malware", "remove memz", "delete memz", "memz removal", "computer virus", "how to remove the memz trojan", "how to delete the memz trojan"]
5+
tags: ["memz trojan", "malware", "memz", "remove memz trojan", "delete memz trojan", "memz trojan removal", "memz trojan malware", "remove memz", "delete memz", "memz removal", "computer virus", "how to remove memz", "troubleshooting", "windows"]
66
published: true
77
featured: false
88
categories: ["Malware Removal", "Windows", "Cybersecurity", "Troubleshooting", "Bootable USB"]

0 commit comments

Comments
 (0)