diff --git a/src/app/api/sessions/active/route.ts b/src/app/api/sessions/active/route.ts
index 49ec8713..50ec1ad4 100644
--- a/src/app/api/sessions/active/route.ts
+++ b/src/app/api/sessions/active/route.ts
@@ -1,6 +1,6 @@
import { NextResponse } from "next/server"
import { requireAuthApi } from "@/components/auth/require-auth"
-import { IJsonApiResponse, parseJsonApiQuery } from "@/lib/json-api"
+import { getJsonApiSkip, getJsonApiSort, getJsonApiTake, IJsonApiResponse, parseJsonApiQuery } from "@/lib/json-api"
import { prisma } from "@/lib/prisma"
export async function GET(request: Request) {
@@ -9,25 +9,31 @@ export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
const query = parseJsonApiQuery(searchParams)
- console.log(query)
const activeSessions = await prisma.session.findMany({
where: {
userId: session.user.id,
},
+ skip: getJsonApiSkip(query),
+ take: getJsonApiTake(query),
+ orderBy: getJsonApiSort(query),
+ })
+
+ const total = await prisma.session.count({
+ where: {
+ userId: session.user.id,
+ },
})
const response: IJsonApiResponse<(typeof activeSessions)[number]> = {
data: activeSessions,
meta: {
total: activeSessions.length,
- page: 1,
- perPage: 10,
- totalPages: 1,
+ page: query.page,
+ perPage: query.perPage,
+ totalPages: Math.ceil(total / query.perPage),
},
}
- NextResponse.next
-
return NextResponse.json(response)
}
diff --git a/src/components/profile/sessions/sessions-table.tsx b/src/components/profile/sessions/sessions-table.tsx
index 17afc71b..915ce317 100644
--- a/src/components/profile/sessions/sessions-table.tsx
+++ b/src/components/profile/sessions/sessions-table.tsx
@@ -40,6 +40,7 @@ export default function SessionsTable() {
`/api/sessions/active?${jsonApiQuery({
page: currentPage,
perPage: itemsPerPage,
+ sort: ["-lastUsedAt"],
})}`
),
() => {
@@ -91,15 +92,15 @@ export default function SessionsTable() {
{sessions ? rows : skelRows}
- {sessions && (sessions.meta.totalPages > 1 || itemsPerPageInitial !== itemsPerPage) && (
-
- )}
+ 1 || itemsPerPageInitial !== itemsPerPage)}
+ currentNumberOfItems={sessions?.data?.length ?? 0}
+ currentPage={sessions?.meta.page}
+ totalPages={sessions?.meta.totalPages}
+ setCurrentPage={setCurrentPage}
+ itemsPerPage={sessions?.meta.perPage}
+ setItemsPerPage={setItemsPerPage}
+ />
Are you absolutely sure?
diff --git a/src/components/ui/pagination.tsx b/src/components/ui/pagination.tsx
index 89e25294..579780c3 100644
--- a/src/components/ui/pagination.tsx
+++ b/src/components/ui/pagination.tsx
@@ -1,89 +1,105 @@
+"use client"
+
import { Dispatch, SetStateAction } from "react"
+import { logger } from "@/lib/logger"
+import { cn } from "@/lib/utils"
import { Button } from "./button"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select"
import { Icons } from "../icons"
interface PaginationProps {
- currentPage: number
- setCurrentPage: Dispatch>
- totalPages: number
+ currentNumberOfItems?: number
+ currentPage?: number
+ setCurrentPage?: Dispatch>
+ totalPages?: number
itemsPerPage?: number
setItemsPerPage?: Dispatch>
+ show?: boolean
}
export default function Pagination({
+ currentNumberOfItems,
currentPage,
setCurrentPage,
totalPages,
itemsPerPage,
setItemsPerPage,
+ show = true,
}: PaginationProps) {
+ //? If there are no items, and we're not on the first page, go to the first page
+ if (currentNumberOfItems === 0 && (currentPage ?? 1) > 1) {
+ logger.debug("Pagination: No items, going to first page")
+ setCurrentPage?.(1)
+ }
+
return (
-
-
- {itemsPerPage && setItemsPerPage && (
+
+
+
+ {itemsPerPage && setItemsPerPage && (
+
+
Rows per page
+
+
+ )}
+
+ Page {currentPage} of {totalPages}
+
-
Rows per page
-
+
Go to previous page
+
+
+
+
- )}
-
- Page {currentPage} of {totalPages}
-
-
-
-
-
-
diff --git a/src/lib/json-api.ts b/src/lib/json-api.ts
index 06b29349..ba18025a 100644
--- a/src/lib/json-api.ts
+++ b/src/lib/json-api.ts
@@ -76,7 +76,17 @@ export const jsonApiQuery = (query: IJsonApiQuery) => {
return searchParams
}
-export const parseJsonApiQuery = (query: URLSearchParams | string): IJsonApiQuery => {
+export const jsonApiDefaults = {
+ page: 1,
+ perPage: 10,
+}
+
+export type IJsonApiQueryWithDefaults = IJsonApiQuery & typeof jsonApiDefaults
+
+export const parseJsonApiQuery = (
+ query: URLSearchParams | string,
+ defaults = jsonApiDefaults
+): IJsonApiQueryWithDefaults => {
const searchParams = new URLSearchParams(query)
const page = searchParams.get("page")
@@ -87,8 +97,8 @@ export const parseJsonApiQuery = (query: URLSearchParams | string): IJsonApiQuer
const fields = searchParams.get("fields")
return {
- page: page ? parseInt(page) : undefined,
- perPage: perPage ? parseInt(perPage) : undefined,
+ page: page ? parseInt(page) : defaults.page,
+ perPage: perPage ? parseInt(perPage) : defaults.perPage,
sort: sort ? sort.split(",") : undefined,
filter: filter
? filter.split(",").map((filter) => {
@@ -100,3 +110,21 @@ export const parseJsonApiQuery = (query: URLSearchParams | string): IJsonApiQuer
fields: fields ? fields.split(",") : undefined,
}
}
+
+export const getJsonApiSkip = ({ page, perPage }: { page: number; perPage: number }) => {
+ return perPage * (page - 1)
+}
+
+export const getJsonApiTake = ({ perPage }: { perPage: number }) => {
+ return perPage
+}
+
+export const getJsonApiSort = ({ sort }: { sort?: string[] }) => {
+ if (!sort) return undefined
+
+ return sort.map((sort) => {
+ const direction = sort[0] === "-" ? "desc" : "asc"
+ const field = sort.replace(/^-/, "")
+ return { [field]: direction }
+ })
+}