diff --git a/app/admin/logs/page.js b/app/admin/logs/page.js index 5ad7020..a60edcd 100644 --- a/app/admin/logs/page.js +++ b/app/admin/logs/page.js @@ -1,38 +1,51 @@ 'use client' import { useRouter } from 'next/navigation' -import { useEffect, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import styles from './style.module.css' import { getSession, removeSession } from '@/utils/session-storage' export default function page() { const [logs, setLogs] = useState([]) + const [isLoading, setIsLoading] = useState(true) + const [isDone, setIsDone] = useState(false) + const skip = useRef(0) + const user = useRef(getSession({ key: "current-user", defaultValue: null })) const router = useRouter() useEffect(() => { - getLogs() - }, []) + const controller = new AbortController() + if (!user.current) { + return router.push("/admin") + } - const getLogs = async () => { - const user = getSession({ key: "current-user", defaultValue: null }) + getLogs({ signal: controller.signal }) - if (!user) { - return router.push("/admin") + return () => { + controller.abort({ message: "Component Unmounted!" }) } + }, []) - const username = user.username - const password = user.password + const getLogs = async ({ signal }) => { + setIsLoading(true) try { - const res = await fetch("/api/admin/logs", { + const res = await fetch(`/api/admin/logs?skip=${skip.current}`, { + signal, headers: { - "Authorization": `Basic ${username}:${password}` + "Authorization": `Basic ${user.current.username}:${user.current.password}` } }) if (res.ok) { const data = await res.json() - setLogs(data) + if (data.logs.length === 0) { + setIsDone(true) + return + } + + setLogs(prev => [...prev, ...data.logs]) + skip.current = data.skip } else { if (res.status === 401) { console.error("Authorization failed: Invalid username or password") @@ -44,6 +57,8 @@ export default function page() { } } catch (error) { console.error("Fetch error:", error.message) + } finally { + setIsLoading(false) } } @@ -76,6 +91,14 @@ export default function page() { ))} + {isLoading | logs.length === 0 | isDone ? null : ( + + )} ) diff --git a/app/admin/logs/style.module.css b/app/admin/logs/style.module.css index de775fd..dc5ce18 100644 --- a/app/admin/logs/style.module.css +++ b/app/admin/logs/style.module.css @@ -1,7 +1,7 @@ .logsContainer { margin-top: 12px; display: flex; - flex-direction: column-reverse; + flex-direction: column; gap: 12px; } diff --git a/app/api/admin/logs/route.js b/app/api/admin/logs/route.js index 79e577b..254a594 100644 --- a/app/api/admin/logs/route.js +++ b/app/api/admin/logs/route.js @@ -2,11 +2,12 @@ import { getLogs } from "../../utils/database/logs" export const dynamic = 'force-dynamic' -export async function GET() { - const logs = await getLogs() +export async function GET(req) { + const skip = parseInt(req.nextUrl.searchParams.get("skip")) + const logs = await getLogs({ skip }) return new Response( - JSON.stringify(logs), + JSON.stringify({ logs, skip: skip + 3 }), { status: 200, headers: { "Content-Type": "application/json" } } ) } diff --git a/app/api/utils/database/logs.js b/app/api/utils/database/logs.js index d1a18fb..890269b 100644 --- a/app/api/utils/database/logs.js +++ b/app/api/utils/database/logs.js @@ -6,10 +6,11 @@ const addLog = async (log) => { .insertOne(log) } -const getLogs = async () => { +const getLogs = async ({ skip } = { skip: 0 }) => { const recorded_logs = await databaseConnection .collection(process.env.LOGGING_MODEL) - .find({}, { projection: { _id: 0 } }) + .find({}, { projection: { _id: 0 }, limit: 3, skip }) + .sort({ _id: -1 }) .toArray() return recorded_logs diff --git a/utils/session-storage.js b/utils/session-storage.js index ce20aed..1d9b998 100644 --- a/utils/session-storage.js +++ b/utils/session-storage.js @@ -1,4 +1,8 @@ const getSession = ({ key, defaultValue } = {}) => { + if (typeof window === "undefined") { + return null + } + const storedSession = sessionStorage.getItem(key) if (storedSession) { return JSON.parse(storedSession)