categories page has pagination now
This commit is contained in:
parent
bf384c1d67
commit
fe6344ece5
BIN
public/images/no-data-founded/1.jpg
Normal file
BIN
public/images/no-data-founded/1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 156 KiB |
BIN
public/images/no-data-founded/2.jpg
Normal file
BIN
public/images/no-data-founded/2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 91 KiB |
BIN
public/images/no-data-founded/3.jpg
Normal file
BIN
public/images/no-data-founded/3.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 172 KiB |
BIN
public/images/no-data-founded/4.jpg
Normal file
BIN
public/images/no-data-founded/4.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 84 KiB |
BIN
public/images/no-data-founded/5.jpg
Normal file
BIN
public/images/no-data-founded/5.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 400 KiB |
BIN
public/images/no-data-founded/6.jpg
Normal file
BIN
public/images/no-data-founded/6.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 159 KiB |
@ -11,7 +11,7 @@ export default function NotFound({ params }: PropsType) {
|
|||||||
const imageUrl = `/images/404/${Math.floor(Math.random() * 5) + 1}.jpg`;
|
const imageUrl = `/images/404/${Math.floor(Math.random() * 5) + 1}.jpg`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center justify-center gap-3 mb-10 sm:mb-0">
|
<div className="mb-10 flex flex-col items-center justify-center gap-3 sm:mb-0">
|
||||||
<Image
|
<Image
|
||||||
src={imageUrl}
|
src={imageUrl}
|
||||||
width={500}
|
width={500}
|
||||||
|
|||||||
@ -1,10 +1,19 @@
|
|||||||
import { CategoriesListType, CategoryType } from "@/app/types/types";
|
import {
|
||||||
|
CategoriesListType,
|
||||||
|
categoryPropsType,
|
||||||
|
CategoryType,
|
||||||
|
} from "@/app/types/types";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
import Pagination from "../components/pagination/pagination";
|
||||||
|
import NoDataFounded from "../components/no-data-founded/noDataFounded";
|
||||||
|
|
||||||
export default async function Categories() {
|
export default async function Categories({
|
||||||
|
params,
|
||||||
|
searchParams,
|
||||||
|
}: categoryPropsType) {
|
||||||
const CategoriesData: CategoriesListType = await fetch(
|
const CategoriesData: CategoriesListType = await fetch(
|
||||||
`${process.env.NEXT_PUBLIC_API_URL}/blog/categories`,
|
`${process.env.NEXT_PUBLIC_API_URL}/blog/categories?per_page=${searchParams.per_page ? searchParams.per_page : process.env.NEXT_PUBLIC_CATEGORIES_PER_CATEGORY_PAGE}${searchParams.page ? `&page=${searchParams.page}` : ""}`,
|
||||||
{
|
{
|
||||||
cache: "no-store",
|
cache: "no-store",
|
||||||
},
|
},
|
||||||
@ -43,8 +52,9 @@ export default async function Categories() {
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div className="flex w-full flex-wrap justify-center gap-10">
|
<div className="mb-10 flex w-full flex-wrap justify-center gap-10">
|
||||||
{CategoriesData.data.map((category: CategoryType) => (
|
{CategoriesData.data.length > 0 ? (
|
||||||
|
CategoriesData.data.map((category: CategoryType) => (
|
||||||
<div
|
<div
|
||||||
key={category.id}
|
key={category.id}
|
||||||
className="flex w-full items-start gap-5 md:w-[45%]"
|
className="flex w-full items-start gap-5 md:w-[45%]"
|
||||||
@ -69,8 +79,15 @@ export default async function Categories() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))
|
||||||
|
) : (
|
||||||
|
<NoDataFounded />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{CategoriesData.data.length > 0 &&
|
||||||
|
CategoriesData.meta.last_page > 1 && (
|
||||||
|
<Pagination meta={CategoriesData.meta} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -0,0 +1,19 @@
|
|||||||
|
import Image from "next/image";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
export default function NoDataFounded() {
|
||||||
|
const imageUrl = `/images/no-data-founded/${Math.floor(Math.random() * 6) + 1}.jpg`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mb-10 flex flex-col items-center justify-center gap-3 sm:mb-0">
|
||||||
|
<Image
|
||||||
|
src={imageUrl}
|
||||||
|
width={500}
|
||||||
|
height={500}
|
||||||
|
alt="no data founded illustration"
|
||||||
|
className="teste"
|
||||||
|
/>
|
||||||
|
<h2 className="text-[30px] font-[800]">No Data founded!</h2>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
140
src/app/(routes)/blog/components/pagination/pagination.tsx
Normal file
140
src/app/(routes)/blog/components/pagination/pagination.tsx
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
// components/Pagination.tsx
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import Link from "next/link";
|
||||||
|
import { useSearchParams } from "next/navigation";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
interface Meta {
|
||||||
|
current_page: number;
|
||||||
|
last_page: number;
|
||||||
|
total: number; // اضافه کردن total برای بررسی وجود داده
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PaginationProps {
|
||||||
|
meta: Meta;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Pagination: React.FC<PaginationProps> = ({ meta }) => {
|
||||||
|
const { current_page, last_page, total } = meta;
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
|
||||||
|
// اگر هیچ دادهای وجود نداشته باشد یا تنها یک صفحه باشد، کامپوننت را رندر نکن
|
||||||
|
if (total === 0 || last_page <= 1) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const generatePageLink = (page: number): string => {
|
||||||
|
const params = new URLSearchParams(searchParams.toString());
|
||||||
|
params.set("page", page.toString());
|
||||||
|
return `/blog/categories?${params.toString()}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderPageNumbers = (): (JSX.Element | string)[] => {
|
||||||
|
const pages: JSX.Element[] = [];
|
||||||
|
const delta = 1; // تعداد صفحات اطراف صفحه فعلی که نمایش داده شوند
|
||||||
|
const range: number[] = [];
|
||||||
|
const rangeWithDots: (number | string)[] = [];
|
||||||
|
let previous: number | undefined;
|
||||||
|
|
||||||
|
for (let i = 1; i <= last_page; i++) {
|
||||||
|
if (
|
||||||
|
i === 1 ||
|
||||||
|
i === last_page ||
|
||||||
|
(i >= current_page - delta && i <= current_page + delta)
|
||||||
|
) {
|
||||||
|
range.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i of range) {
|
||||||
|
if (previous) {
|
||||||
|
if (i - previous === 2) {
|
||||||
|
rangeWithDots.push(previous + 1);
|
||||||
|
} else if (i - previous > 2) {
|
||||||
|
rangeWithDots.push("...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rangeWithDots.push(i);
|
||||||
|
previous = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rangeWithDots.map((page, index) => {
|
||||||
|
if (page === "...") {
|
||||||
|
return (
|
||||||
|
<span key={`ellipsis-${index}`} className="px-3 py-1">
|
||||||
|
...
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
key={page}
|
||||||
|
href={generatePageLink(Number(page))}
|
||||||
|
className={`rounded-full border px-3 py-1 ${
|
||||||
|
page === current_page
|
||||||
|
? "bg-blog-red text-white"
|
||||||
|
: "bg-[#EAEAEA] text-blog-text-default hover:bg-[#d6d6d6]"
|
||||||
|
}`}
|
||||||
|
aria-current={page === current_page ? "page" : undefined}
|
||||||
|
>
|
||||||
|
{page}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mt-4 flex items-center justify-center gap-2">
|
||||||
|
{/* First Page */}
|
||||||
|
{current_page > 1 && (
|
||||||
|
<Link
|
||||||
|
href={generatePageLink(1)}
|
||||||
|
className="rounded-full border bg-[#EAEAEA] px-3 py-1 text-blog-text-default hover:bg-[#d6d6d6]"
|
||||||
|
aria-label="First Page"
|
||||||
|
>
|
||||||
|
First
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Previous Page */}
|
||||||
|
{current_page > 1 && (
|
||||||
|
<Link
|
||||||
|
href={generatePageLink(current_page - 1)}
|
||||||
|
className="rounded-full border bg-[#EAEAEA] px-4 py-0 text-[24px] text-blog-text-default hover:bg-[#d6d6d6]"
|
||||||
|
aria-label="Previous Page"
|
||||||
|
>
|
||||||
|
{"<"}
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Page Numbers */}
|
||||||
|
{renderPageNumbers()}
|
||||||
|
|
||||||
|
{/* Next Page */}
|
||||||
|
{current_page < last_page && (
|
||||||
|
<Link
|
||||||
|
href={generatePageLink(current_page + 1)}
|
||||||
|
className="rounded-full border bg-[#EAEAEA] px-4 py-0 text-[24px] text-blog-text-default hover:bg-[#d6d6d6]"
|
||||||
|
aria-label="Next Page"
|
||||||
|
>
|
||||||
|
{">"}
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Last Page */}
|
||||||
|
{current_page < last_page && (
|
||||||
|
<Link
|
||||||
|
href={generatePageLink(last_page)}
|
||||||
|
className="rounded-full border bg-[#EAEAEA] px-3 py-1 text-blog-text-default hover:bg-[#d6d6d6]"
|
||||||
|
aria-label="Last Page"
|
||||||
|
>
|
||||||
|
Last
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Pagination;
|
||||||
@ -19,7 +19,11 @@ export type CategoryType = {
|
|||||||
updated_at: string;
|
updated_at: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CategoriesListType = { data: CategoryType[] };
|
export type CategoriesListType = {
|
||||||
|
data: CategoryType[];
|
||||||
|
meta: any;
|
||||||
|
links: any;
|
||||||
|
};
|
||||||
|
|
||||||
// تعریف نوع Tag
|
// تعریف نوع Tag
|
||||||
export type TagType = {
|
export type TagType = {
|
||||||
@ -52,6 +56,11 @@ export type categorySlugPropsType = {
|
|||||||
params: { categorySlug: string };
|
params: { categorySlug: string };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type categoryPropsType = {
|
||||||
|
params: { categorySlug: string };
|
||||||
|
searchParams: any;
|
||||||
|
};
|
||||||
|
|
||||||
export type PaginationType = {
|
export type PaginationType = {
|
||||||
total: number;
|
total: number;
|
||||||
per_page: number;
|
per_page: number;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user