From 2328bdc71641bce3450bc8e631da387b74c595c2 Mon Sep 17 00:00:00 2001 From: lavanyagarg112 Date: Thu, 10 Jul 2025 13:23:38 +0800 Subject: [PATCH 1/6] add frontend interface for history --- app/history/page.tsx | 16 ++++--- components/history/HistoryComponent.tsx | 60 +++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 6 deletions(-) create mode 100644 components/history/HistoryComponent.tsx diff --git a/app/history/page.tsx b/app/history/page.tsx index 093fd4e..420c6e5 100644 --- a/app/history/page.tsx +++ b/app/history/page.tsx @@ -1,8 +1,12 @@ +"use client"; + +import { useAuth } from "@/context/AuthContext"; +import HistoryComponent from "@/components/history/HistoryComponent"; export default function HistoryPage() { - return ( -
-

History

-

History page content goes here.

-
- ); + const { user } = useAuth(); + + if (!user || !user.hasCompletedOnboarding) { + return null; + } + return ; } diff --git a/components/history/HistoryComponent.tsx b/components/history/HistoryComponent.tsx new file mode 100644 index 0000000..52e84b4 --- /dev/null +++ b/components/history/HistoryComponent.tsx @@ -0,0 +1,60 @@ +"use client"; + +import { useEffect, useState } from "react"; + +interface ActivityLog { + id: number; + action: string; + metadata: Record; + created_at: string; +} + +export default function HistoryComponent() { + const [logs, setLogs] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + fetch("/api/activity", { credentials: "include" }) + .then((res) => { + if (!res.ok) throw new Error(`Status ${res.status}`); + return res.json(); + }) + .then((json: { logs: ActivityLog[] }) => { + setLogs(json.logs); + }) + .catch((err) => { + console.error(err); + setError("Failed to load history."); + }) + .finally(() => setLoading(false)); + }, []); + + if (loading) return

Loading history…

; + if (error) return

{error}

; + if (!logs.length) return

No history available yet.

; + + return ( +
+ {logs.map((log) => ( +
+
+
+

+ {log.action.replace(/_/g, " ")} +

+ {Object.keys(log.metadata).length > 0 && ( +
+                  {JSON.stringify(log.metadata, null, 2)}
+                
+ )} +
+ + {new Date(log.created_at).toLocaleString()} + +
+
+ ))} +
+ ); +} From 4500eb8b4d0954462b5919ff017b97b5673c6aa6 Mon Sep 17 00:00:00 2001 From: lavanyagarg112 Date: Thu, 10 Jul 2025 13:25:12 +0800 Subject: [PATCH 2/6] Add history for admins as well --- components/SideNav.tsx | 1 - components/organisation/OrgNav.tsx | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/components/SideNav.tsx b/components/SideNav.tsx index 5aeb36c..9ede2c1 100644 --- a/components/SideNav.tsx +++ b/components/SideNav.tsx @@ -8,7 +8,6 @@ import { HomeIcon, BookOpenIcon, ChartBarIcon, - UsersIcon, MapIcon, ClockIcon, CogIcon, diff --git a/components/organisation/OrgNav.tsx b/components/organisation/OrgNav.tsx index bc14a2a..7ae3ae6 100644 --- a/components/organisation/OrgNav.tsx +++ b/components/organisation/OrgNav.tsx @@ -8,6 +8,7 @@ import { HomeIcon, BookOpenIcon, ChartBarIcon, + ClockIcon, UsersIcon, CogIcon, } from "@heroicons/react/24/outline"; @@ -28,6 +29,7 @@ const menuSections = [ items: [ { label: "My Organisation", href: "/organisation", icon: UsersIcon }, { label: "Users", href: "/users", icon: UsersIcon }, + { label: "History", href: "/history", icon: ClockIcon }, { label: "Settings", href: "/settings", icon: CogIcon }, ], }, From f463343760504d39254bbdfce191ceba88f849ce Mon Sep 17 00:00:00 2001 From: lavanyagarg112 Date: Thu, 10 Jul 2025 13:38:58 +0800 Subject: [PATCH 3/6] Update history timeline ui --- components/history/HistoryComponent.tsx | 63 +++++++++++++++---------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/components/history/HistoryComponent.tsx b/components/history/HistoryComponent.tsx index 52e84b4..0f7846c 100644 --- a/components/history/HistoryComponent.tsx +++ b/components/history/HistoryComponent.tsx @@ -15,14 +15,12 @@ export default function HistoryComponent() { const [error, setError] = useState(null); useEffect(() => { - fetch("/api/activity", { credentials: "include" }) + fetch("/api/history", { credentials: "include" }) .then((res) => { if (!res.ok) throw new Error(`Status ${res.status}`); return res.json(); }) - .then((json: { logs: ActivityLog[] }) => { - setLogs(json.logs); - }) + .then(({ logs }: { logs: ActivityLog[] }) => setLogs(logs)) .catch((err) => { console.error(err); setError("Failed to load history."); @@ -30,31 +28,46 @@ export default function HistoryComponent() { .finally(() => setLoading(false)); }, []); - if (loading) return

Loading history…

; - if (error) return

{error}

; - if (!logs.length) return

No history available yet.

; + if (loading) return

Loading history…

; + if (error) return

{error}

; + if (!logs.length) return

No history yet.

; + + // sort newest first + const sorted = [...logs].sort( + (a, b) => + new Date(b.created_at).getTime() - new Date(a.created_at).getTime() + ); return ( -
- {logs.map((log) => ( -
-
-
-

- {log.action.replace(/_/g, " ")} +
    + {sorted.map((log) => { + const title = log.action.replace(/_/g, " "); + const time = new Date(log.created_at).toLocaleString(); + + return ( +
  • + + +
    +

    + {title}

    - {Object.keys(log.metadata).length > 0 && ( -
    +              
    +            
    + + {Object.keys(log.metadata).length > 0 && ( +
    + + View details + +
                       {JSON.stringify(log.metadata, null, 2)}
                     
    - )} -

- - {new Date(log.created_at).toLocaleString()} - -
-
- ))} -
+ + )} + + ); + })} + ); } From bc113e4de87c80c50d7f10f9cf08e6454520ba99 Mon Sep 17 00:00:00 2001 From: lavanyagarg112 Date: Thu, 10 Jul 2025 13:50:32 +0800 Subject: [PATCH 4/6] Fix endpoint --- components/history/HistoryComponent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/history/HistoryComponent.tsx b/components/history/HistoryComponent.tsx index 0f7846c..72b399f 100644 --- a/components/history/HistoryComponent.tsx +++ b/components/history/HistoryComponent.tsx @@ -15,7 +15,7 @@ export default function HistoryComponent() { const [error, setError] = useState(null); useEffect(() => { - fetch("/api/history", { credentials: "include" }) + fetch("/api/activity", { credentials: "include" }) .then((res) => { if (!res.ok) throw new Error(`Status ${res.status}`); return res.json(); From acd41d25f25fe67e655131d842b584eb3b56db2a Mon Sep 17 00:00:00 2001 From: lavanyagarg112 Date: Thu, 10 Jul 2025 13:52:18 +0800 Subject: [PATCH 5/6] Update history timeline ui --- components/history/HistoryComponent.tsx | 33 ++++++++++++++++--------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/components/history/HistoryComponent.tsx b/components/history/HistoryComponent.tsx index 72b399f..fae2ccd 100644 --- a/components/history/HistoryComponent.tsx +++ b/components/history/HistoryComponent.tsx @@ -38,20 +38,24 @@ export default function HistoryComponent() { new Date(b.created_at).getTime() - new Date(a.created_at).getTime() ); + const formatKey = (key: string) => + key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase()); + return ( -
    - {sorted.map((log) => { - const title = log.action.replace(/_/g, " "); +
      + {sorted.map((log, idx) => { + const title = log.action + .replace(/_/g, " ") + .replace(/\b\w/g, (c) => c.toUpperCase()); const time = new Date(log.created_at).toLocaleString(); return (
    1. - + -
      -

      - {title} -

      +
      + {idx + 1}. +

      {title}

      @@ -60,14 +64,19 @@ export default function HistoryComponent() { View details -
      -                  {JSON.stringify(log.metadata, null, 2)}
      -                
      +
        + {Object.entries(log.metadata).map(([key, val]) => ( +
      • + {formatKey(key)}:{" "} + {String(val)} +
      • + ))} +
      )}
    2. ); })} -
+ ); } From 7b73fe9a31dd4cddc7cb5533397636f15c68562f Mon Sep 17 00:00:00 2001 From: lavanyagarg112 Date: Thu, 10 Jul 2025 14:12:28 +0800 Subject: [PATCH 6/6] Add title and description for history page --- app/history/page.tsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/app/history/page.tsx b/app/history/page.tsx index 420c6e5..b9e7649 100644 --- a/app/history/page.tsx +++ b/app/history/page.tsx @@ -8,5 +8,15 @@ export default function HistoryPage() { if (!user || !user.hasCompletedOnboarding) { return null; } - return ; + return ( +
+

+ Activity History +

+

+ View your recent activity and changes made in the system. +

+ +
+ ); }