diff --git a/app/app/(dashboard)/links/page.tsx b/app/app/(dashboard)/links/page.tsx
index 5010874..76b173a 100644
--- a/app/app/(dashboard)/links/page.tsx
+++ b/app/app/(dashboard)/links/page.tsx
@@ -1,58 +1,193 @@
-"use client"
+"use client";
import { DatePickerWithRange } from "@/components/DialogComponents/DatePickerWithRange";
-import React, { useEffect, useState } from 'react'
+import React, { useEffect, useState } from "react";
import { FilterDialog } from "@/components/DialogComponents/FilterDialog";
import { LinkCard } from "@/components/CardComponents/LinkCard";
import { getLinks } from "@/lib/actions/getLinksAction";
import { DateRange } from "react-day-picker";
import Loading from "./loading";
-import { linkType } from "@/interfaces/types";
+import { linkType, paginationType } from "@/interfaces/types";
+import {
+ Pagination,
+ PaginationContent,
+ PaginationEllipsis,
+ PaginationItem,
+ PaginationLink,
+ PaginationNext,
+ PaginationPrevious,
+} from "@/components/ui/pagination";
+import { toast } from "@/components/ui/use-toast";
+import { pageOrder, paginateOperation } from "@/lib/constants";
+export default function Page() {
+ const [filteredLinks, setFilteredLinks] = useState
(
+ []
+ );
+ const [loading, setLoading] = useState(true);
+ const current_date = new Date();
+ const [date, setDate] = React.useState({
+ to: new Date(
+ current_date.getFullYear(),
+ current_date.getMonth(),
+ current_date.getDate() + 1
+ ),
+ from: new Date(2024, 4, 18),
+ });
+ const [totalPages, setTotalPages] = useState(0);
-export default function Page() {
+ const [paginator, setPaginator] = useState({
+ value: 1,
+ pageActive: pageOrder.ONE,
+ });
+
+ const pagination = (page: pageOrder, action: paginateOperation) => {
+ if (
+ (page + paginator.value > totalPages && page + paginator.value != 1) ||
+ (paginator.pageActive + paginator.value + 1 > totalPages &&
+ action == paginateOperation.NEXT)
+ ) {
+ toast({
+ title: "End of the links",
+ description: "That's all we have",
+ });
+ return;
+ }
+
+ if (paginateOperation.NEXT == action) {
+ if (paginator.pageActive == pageOrder.ONE) {
+ setPaginator((c) => {
+ return { ...c, pageActive: pageOrder.TWO };
+ });
+ } else if (paginator.pageActive == pageOrder.TWO) {
+ setPaginator((c) => {
+ return { ...c, pageActive: pageOrder.THREE };
+ });
+ } else {
+ setPaginator((c) => {
+ return { value: c.value + 1, pageActive: pageOrder.THREE };
+ });
+ }
+ } else if (paginateOperation.PREV == action) {
+ if (paginator.pageActive == pageOrder.THREE) {
+ setPaginator((c) => {
+ return { ...c, pageActive: pageOrder.TWO };
+ });
+ } else if (paginator.pageActive == pageOrder.TWO) {
+ setPaginator((c) => {
+ return { ...c, pageActive: pageOrder.ONE };
+ });
+ } else {
+ setPaginator((c) => {
+ return {
+ value: c.value - Number(c.value != 1),
+ pageActive: pageOrder.ONE,
+ };
+ });
+ }
+ } else {
+ setPaginator((c) => {
+ return { ...c, pageActive: page };
+ });
+ }
+ };
+
+ useEffect(() => {
+ setLoading(true);
+ getLinks((paginator.value + paginator.pageActive).toString()).then(
+ (res) => {
+ const linkList: linkType[] | undefined = res.links;
+ setTotalPages(res.total_pages || 0);
+ const from: Date | undefined = date?.from;
+ const to: Date | undefined = date?.to;
+ const filterLinks: linkType[] | undefined = linkList?.filter((link) => {
+ return (
+ (!from || link.created_at >= from) && (!to || link.created_at <= to)
+ );
+ });
+
+ setFilteredLinks(filterLinks);
+ setLoading(false);
+ }
+ );
+ }, [date, paginator]);
- const [filteredLinks,setFilteredLinks] = useState([])
- const [loading,setLoading] = useState(true)
- const current_date = new Date()
- const [date, setDate] = React.useState({
- to: new Date(current_date.getFullYear(), current_date.getMonth(), current_date.getDate()+1),
- from: new Date(2024, 4, 18),
- })
-
- useEffect(()=>{
- setLoading(true)
- getLinks().then((res)=>{
- const linkList:linkType[] | undefined = res.links;
- const from: Date | undefined = date?.from;
- const to: Date | undefined = date?.to;
- const filterLinks: linkType[] | undefined = linkList?.filter((link)=>{
- return (!from || link.created_at >=from) && (!to || link.created_at <= to)
- })
- setFilteredLinks(filterLinks)
- setLoading(false)
- })
-
- },[date])
-
return (
Links
- {loading?
:
{filteredLinks?.map((link) => (
-
- ))}
}
+ {loading ? (
+
+ ) : (
+
+ {filteredLinks?.map((link) => (
+
+ ))}
+
+ )}
+
+
+
+ pagination(0, paginateOperation.PREV)}
+ href="#"
+ />
+
+
+ pagination(pageOrder.ONE, paginateOperation.CLICK)}
+ isActive={paginator.pageActive == pageOrder.ONE}
+ href="#"
+ >
+ {paginator.value}
+
+
+
+ pagination(pageOrder.TWO, paginateOperation.CLICK)}
+ isActive={paginator.pageActive == pageOrder.TWO}
+ href="#"
+ >
+ {paginator.value + 1}
+
+
+
+
+ pagination(pageOrder.THREE, paginateOperation.CLICK)
+ }
+ isActive={paginator.pageActive == pageOrder.THREE}
+ href="#"
+ >
+ {paginator.value + 2}
+
+
+
+
+
+
+ pagination(0, paginateOperation.NEXT)}
+ href="#"
+ />
+
+
+
);
}
diff --git a/app/app/(dashboard)/qrcodes/page.tsx b/app/app/(dashboard)/qrcodes/page.tsx
index 5e827ca..8937cb6 100644
--- a/app/app/(dashboard)/qrcodes/page.tsx
+++ b/app/app/(dashboard)/qrcodes/page.tsx
@@ -1,28 +1,162 @@
-"use client"
+"use client";
import { QRCodeCardComponent } from "@/components/CardComponents/QRCodeCardComponent";
-import { QRCodeType, linkType } from "@/interfaces/types";
+import { QRCodeType, linkType, paginationType } from "@/interfaces/types";
import { getLinks } from "@/lib/actions/getLinksAction";
import { Label } from "@radix-ui/react-label";
import { useEffect, useState } from "react";
import Loading from "./loading";
-
-export default function QRCodePage(){
-
- const [loading,setLoading] = useState(false);
- const [links,setLinks] = useState([])
-
- useEffect(()=>{
- setLoading(true)
- getLinks().then((res)=>{
- const linkList:linkType[] | undefined = res.links;
- setLinks(linkList)
- setLoading(false)
- })
- },[])
-
- return
-
- {loading?
:
{links?.map((qr)=>)}
}
+import { pageOrder, paginateOperation } from "@/lib/constants";
+import { toast } from "@/components/ui/use-toast";
+import {
+ Pagination,
+ PaginationContent,
+ PaginationEllipsis,
+ PaginationItem,
+ PaginationLink,
+ PaginationNext,
+ PaginationPrevious,
+} from "@/components/ui/pagination";
+
+export default function QRCodePage() {
+ const [loading, setLoading] = useState
(false);
+ const [links, setLinks] = useState([]);
+
+ const [totalPages, setTotalPages] = useState(0);
+
+ const [paginator, setPaginator] = useState({
+ value: 1,
+ pageActive: pageOrder.ONE,
+ });
+
+ const pagination = (page: pageOrder, action: paginateOperation) => {
+ if (
+ (page + paginator.value > totalPages && page + paginator.value != 1) ||
+ (paginator.pageActive + paginator.value + 1 > totalPages &&
+ action == paginateOperation.NEXT)
+ ) {
+ toast({
+ title: "End of the links",
+ description: "That's all we have",
+ });
+ return;
+ }
+
+ if (paginateOperation.NEXT == action) {
+ if (paginator.pageActive == pageOrder.ONE) {
+ setPaginator((c) => {
+ return { ...c, pageActive: pageOrder.TWO };
+ });
+ } else if (paginator.pageActive == pageOrder.TWO) {
+ setPaginator((c) => {
+ return { ...c, pageActive: pageOrder.THREE };
+ });
+ } else {
+ setPaginator((c) => {
+ return { value: c.value + 1, pageActive: pageOrder.THREE };
+ });
+ }
+ } else if (paginateOperation.PREV == action) {
+ if (paginator.pageActive == pageOrder.THREE) {
+ setPaginator((c) => {
+ return { ...c, pageActive: pageOrder.TWO };
+ });
+ } else if (paginator.pageActive == pageOrder.TWO) {
+ setPaginator((c) => {
+ return { ...c, pageActive: pageOrder.ONE };
+ });
+ } else {
+ setPaginator((c) => {
+ return {
+ value: c.value - Number(c.value != 1),
+ pageActive: pageOrder.ONE,
+ };
+ });
+ }
+ } else {
+ setPaginator((c) => {
+ return { ...c, pageActive: page };
+ });
+ }
+ };
+
+ useEffect(() => {
+ setLoading(true);
+ getLinks((paginator.value + paginator.pageActive).toString()).then(
+ (res) => {
+ const linkList: linkType[] | undefined = res.links;
+ setTotalPages(res.total_pages || 0);
+ setLinks(linkList);
+ setLoading(false);
+ }
+ );
+ }, [paginator]);
+
+ return (
+
+
+ {loading ? (
+
+ ) : (
+
+ {links?.map((qr) => (
+
+ ))}
+
+
+
+
+ pagination(0, paginateOperation.PREV)}
+ href="#"
+ />
+
+
+
+ pagination(pageOrder.ONE, paginateOperation.CLICK)
+ }
+ isActive={paginator.pageActive == pageOrder.ONE}
+ href="#"
+ >
+ {paginator.value}
+
+
+
+
+ pagination(pageOrder.TWO, paginateOperation.CLICK)
+ }
+ isActive={paginator.pageActive == pageOrder.TWO}
+ href="#"
+ >
+ {paginator.value + 1}
+
+
+
+
+ pagination(pageOrder.THREE, paginateOperation.CLICK)
+ }
+ isActive={paginator.pageActive == pageOrder.THREE}
+ href="#"
+ >
+ {paginator.value + 2}
+
+
+
+
+
+
+ pagination(0, paginateOperation.NEXT)}
+ href="#"
+ />
+
+
+
+
+ )}
-}
\ No newline at end of file
+ );
+}
diff --git a/components/ui/pagination.tsx b/components/ui/pagination.tsx
new file mode 100644
index 0000000..7715f05
--- /dev/null
+++ b/components/ui/pagination.tsx
@@ -0,0 +1,121 @@
+import * as React from "react"
+import {
+ ChevronLeftIcon,
+ ChevronRightIcon,
+ DotsHorizontalIcon,
+} from "@radix-ui/react-icons"
+
+import { cn } from "@/lib/utils"
+import { ButtonProps, buttonVariants } from "@/components/ui/button"
+
+const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
+
+)
+Pagination.displayName = "Pagination"
+
+const PaginationContent = React.forwardRef<
+ HTMLUListElement,
+ React.ComponentProps<"ul">
+>(({ className, ...props }, ref) => (
+
+))
+PaginationContent.displayName = "PaginationContent"
+
+const PaginationItem = React.forwardRef<
+ HTMLLIElement,
+ React.ComponentProps<"li">
+>(({ className, ...props }, ref) => (
+
+))
+PaginationItem.displayName = "PaginationItem"
+
+type PaginationLinkProps = {
+ isActive?: boolean
+} & Pick &
+ React.ComponentProps<"a">
+
+const PaginationLink = ({
+ className,
+ isActive,
+ size = "icon",
+ ...props
+}: PaginationLinkProps) => (
+
+)
+PaginationLink.displayName = "PaginationLink"
+
+const PaginationPrevious = ({
+ className,
+ ...props
+}: React.ComponentProps) => (
+
+
+ Previous
+
+)
+PaginationPrevious.displayName = "PaginationPrevious"
+
+const PaginationNext = ({
+ className,
+ ...props
+}: React.ComponentProps) => (
+
+ Next
+
+
+)
+PaginationNext.displayName = "PaginationNext"
+
+const PaginationEllipsis = ({
+ className,
+ ...props
+}: React.ComponentProps<"span">) => (
+
+
+ More pages
+
+)
+PaginationEllipsis.displayName = "PaginationEllipsis"
+
+export {
+ Pagination,
+ PaginationContent,
+ PaginationLink,
+ PaginationItem,
+ PaginationPrevious,
+ PaginationNext,
+ PaginationEllipsis,
+}
diff --git a/interfaces/types.ts b/interfaces/types.ts
index 413604f..cea971c 100644
--- a/interfaces/types.ts
+++ b/interfaces/types.ts
@@ -1,3 +1,5 @@
+import { pageOrder } from "@/lib/constants";
+
export interface gettingStartedStatus {
createLink: boolean;
clickLink: boolean;
@@ -70,4 +72,9 @@ export type linkType = {
long_url: string;
created_at: Date;
title: string | null;
+}
+
+export type paginationType = {
+ value: number,
+ pageActive: pageOrder
}
\ No newline at end of file
diff --git a/lib/actions/getLinksAction.ts b/lib/actions/getLinksAction.ts
index 0532406..80ec45f 100644
--- a/lib/actions/getLinksAction.ts
+++ b/lib/actions/getLinksAction.ts
@@ -1,20 +1,19 @@
"use server"
-import { NextRequest } from "next/server";
import { getServerSession } from "next-auth";
import { ISessionType } from "@/interfaces/url";
import authOptions from "@/lib/authOptions";
import PrismaClientManager from "@/lib/services/pgConnect";
-import { HTTP_STATUS, RESPONSE } from "@/lib/constants";
+import { HTTP_STATUS } from "@/lib/constants";
-export async function getLinks() {
+export async function getLinks(pageNumber: string) {
const posgresInstance = PrismaClientManager.getInstance();
const prisma = posgresInstance.getPrismaClient();
const session: ISessionType | null = await getServerSession(authOptions);
// const searchParams = req.nextUrl.searchParams;
- const page_size = "10";
- const page = "1";
+ const page_size = "5";
+ const page = pageNumber;
if (!session?.user) {
return {
@@ -37,6 +36,9 @@ export async function getLinks() {
status:HTTP_STATUS.OK
}
}
+
+ const total_pages = Math.ceil(totalLinks/Number.parseInt(page_size))
+
const links = await prisma.links.findMany({
where: {
user: {
@@ -49,6 +51,7 @@ export async function getLinks() {
return {
links,
totalLinks,
+ total_pages,
status: HTTP_STATUS.CREATED
}
}
diff --git a/lib/constants.ts b/lib/constants.ts
index d19770f..07809ee 100644
--- a/lib/constants.ts
+++ b/lib/constants.ts
@@ -24,3 +24,15 @@ export const RESPONSE = (data: any, status: number) => {
status: status,
});
};
+
+export enum paginateOperation {
+ NEXT,
+ PREV,
+ CLICK
+}
+
+export enum pageOrder {
+ ONE = 0,
+ TWO = 1,
+ THREE = 2
+}
\ No newline at end of file