Skip to content

Commit

Permalink
added pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
Iamsheye committed Oct 25, 2024
1 parent 6483577 commit 64a4282
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 29 deletions.
Binary file modified bun.lockb
Binary file not shown.
4 changes: 4 additions & 0 deletions src/assets/left-boxed.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/assets/right-boxed.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
103 changes: 103 additions & 0 deletions src/components/pagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import ChevronLeft from "@/assets/left-boxed.svg?react";
import ChevronRight from "@/assets/right-boxed.svg?react";

interface PaginationProps {
currentPage: number;
totalPages: number;
onPageChange: (page: number) => void;
}

const Pagination = ({
totalPages,
currentPage,
onPageChange,
}: PaginationProps) => {
const getPageNumbers = () => {
const pages: (string | number)[] = [1];

if (currentPage > 3) {
pages.push("ellipsis");
}

// Add pages around current page
for (
let i = Math.max(2, currentPage - 1);
i <= Math.min(totalPages - 1, currentPage + 1);
i++
) {
pages.push(i);
}

if (currentPage < totalPages - 2) {
pages.push("ellipsis");
}

if (totalPages > 1) {
pages.push(totalPages);
}

return pages;
};

return (
<nav className="flex items-center justify-center gap-4 lg:justify-end lg:gap-6">
<button
aria-label="Previous page"
disabled={currentPage === 1}
className="disabled:cursor-not-allowed disabled:opacity-50"
onClick={() => currentPage > 1 && onPageChange(currentPage - 1)}
>
<ChevronLeft className="h-8 w-8" />
</button>

<div className="flex items-center gap-1">
{getPageNumbers().map((pageNum, idx) =>
pageNum === "ellipsis" ? (
<svg
key={`ellipsis-${idx}`}
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
className="mx-1 h-4 w-4 text-form_text"
>
<circle cx="12" cy="12" r="1"></circle>
<circle cx="19" cy="12" r="1"></circle>
<circle cx="5" cy="12" r="1"></circle>
</svg>
) : (
<button
key={pageNum}
onClick={() => onPageChange(pageNum as number)}
className={`px-1 text-[1.5rem] ${
currentPage === pageNum
? "font-bold text-primary"
: "font-medium text-form_text"
}`}
>
{pageNum}
</button>
),
)}
</div>

<button
aria-label="Next page"
disabled={currentPage === totalPages}
className="disabled:cursor-not-allowed disabled:opacity-50"
onClick={() =>
currentPage < totalPages && onPageChange(currentPage + 1)
}
>
<ChevronRight className="h-8 w-8" />
</button>
</nav>
);
};

export default Pagination;
72 changes: 43 additions & 29 deletions src/routes/_auth_routes/jobs.$id.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useDebounceValue } from "usehooks-ts";
import { getJobAlert, getJobAlertJobs } from "@/network/jobs";
import { formatDate } from "@/utils";
import EmptyJobAlertIcon from "@/assets/empty-job-alert.svg?react";
import Pagination from "@/components/pagination";

const JobsParamsSchema = z.object({
page: z.number().catch(1),
Expand Down Expand Up @@ -46,7 +47,7 @@ function Jobs() {
useEffect(() => {
navigate({
// @ts-ignore
search: (prev) => ({ ...prev, search: debouncedValue }),
search: (prev) => ({ page: 1, search: debouncedValue }),
replace: true,
});
}, [debouncedValue]);
Expand Down Expand Up @@ -98,36 +99,49 @@ function Jobs() {
</div>
</section>
) : (
<section className="my-8 flex flex-wrap gap-2 lg:gap-4">
{jobs.map((job) => (
<div
key={job.id}
className="flex w-[calc(50%_-_4px)] flex-col justify-between rounded-[32px] bg-form p-6 lg:w-[calc(33%_-_8px)] lg:rounded-[40px] lg:p-8"
>
<div className="flex flex-col items-start gap-2">
<h2
className="text-[1rem] font-semibold text-primary lg:text-[1.25rem]"
style={{ overflowWrap: "anywhere" }}
<>
<section className="my-8 flex flex-wrap gap-2 lg:gap-4">
{jobs.map((job) => (
<div
key={job.id}
className="flex w-[calc(50%_-_4px)] flex-col justify-between rounded-[32px] bg-form p-6 lg:w-[calc(33%_-_8px)] lg:rounded-[40px] lg:p-8"
>
<div className="flex flex-col items-start gap-2">
<h2
className="text-[1rem] font-semibold text-primary lg:text-[1.25rem]"
style={{ overflowWrap: "anywhere" }}
>
{job.title}
</h2>
<p className="inline-block rounded-[40px] border border-primary p-1 text-[0.75rem] lg:p-1.5 lg:text-[0.875rem]">
{job.hostSite}
</p>
<p className="text-[0.75rem] text-form_text lg:text-[0.875rem]">
{formatDate(job.createdAt)}
</p>
</div>

<a
href={job.link}
className="mt-8 text-[0.875rem] text-primary underline lg:mt-4 lg:text-[1.25rem]"
>
{job.title}
</h2>
<p className="inline-block rounded-[40px] border border-primary p-1 text-[0.75rem] lg:p-1.5 lg:text-[0.875rem]">
{job.hostSite}
</p>
<p className="text-[0.75rem] text-form_text lg:text-[0.875rem]">
{formatDate(job.createdAt)}
</p>
link to job
</a>
</div>

<a
href={job.link}
className="mt-8 text-[0.875rem] text-primary underline lg:mt-4 lg:text-[1.25rem]"
>
link to job
</a>
</div>
))}
</section>
))}
</section>
<Pagination
currentPage={page}
totalPages={metadata.totalPages}
onPageChange={(page) =>
navigate({
// @ts-ignore
search: (prev) => ({ ...prev, page }),
replace: true,
})
}
/>
</>
)}
</>
);
Expand Down

0 comments on commit 64a4282

Please sign in to comment.