diff --git a/src/components/dashboard/AdminDashboard.astro b/src/components/dashboard/AdminDashboard.astro index edd5784..853d812 100644 --- a/src/components/dashboard/AdminDashboard.astro +++ b/src/components/dashboard/AdminDashboard.astro @@ -1,2533 +1,3 @@ --- -// Admin Dashboard Component -import { Authentication } from "../../scripts/pocketbase/Authentication"; -import { Get } from "../../scripts/pocketbase/Get"; -import { - Collections, - type User, - type Event, - type Officer, - type Reimbursement, -} from "../../schemas/pocketbase"; -import { Icon } from "astro-icon/components"; -import AdminSystemActivity from "./AdminDashboard/AdminSystemActivity"; - -const auth = Authentication.getInstance(); -const get = Get.getInstance(); - -// Fetch initial data for the dashboard -let users: User[] = []; -let officers: Officer[] = []; -let events: Event[] = []; -let reimbursements: Reimbursement[] = []; -let userCount = 0; -let officerCount = 0; -let eventCount = 0; -let reimbursementCount = 0; -let pendingReimbursements = 0; -let upcomingEvents = 0; - -// Interface for expanded reimbursement data -interface ExpandedReimbursement extends Reimbursement { - expand?: { - submitted_by?: User; - }; -} - -try { - if (auth.isAuthenticated()) { - // Get users with pagination - const userResponse = await get.getList( - Collections.USERS, - 1, - 50, - "", - "-created" - ); - users = userResponse.items; - userCount = userResponse.totalItems; - - // Get officers with user expansion - const officerResponse = await get.getList( - Collections.OFFICERS, - 1, - 50, - "", - "-created", - { expand: "user" } - ); - officers = officerResponse.items; - officerCount = officerResponse.totalItems; - - // Get events - const eventResponse = await get.getList( - Collections.EVENTS, - 1, - 50, - "", - "-start_date" - ); - events = eventResponse.items; - eventCount = eventResponse.totalItems; - - // Get upcoming events - const now = new Date().toISOString(); - const upcomingEventsResponse = await get.getList( - Collections.EVENTS, - 1, - 1, - `start_date > "${now}" && published = true`, - "start_date" - ); - upcomingEvents = upcomingEventsResponse.totalItems; - - // Get reimbursements with user expansion - const reimbursementResponse = await get.getList( - Collections.REIMBURSEMENTS, - 1, - 50, - "", - "-created", - { expand: "submitted_by" } - ); - reimbursements = reimbursementResponse.items; - reimbursementCount = reimbursementResponse.totalItems; - - // Get pending reimbursements - const pendingReimbursementsResponse = await get.getList( - Collections.REIMBURSEMENTS, - 1, - 1, - `status = "submitted" || status = "under_review"`, - "-created" - ); - pendingReimbursements = pendingReimbursementsResponse.totalItems; - } -} catch (error) { - console.error("Error fetching admin dashboard data:", error); -} - -// Format date for display -const formatDate = (dateString: string) => { - const date = new Date(dateString); - return date.toLocaleDateString("en-US", { - year: "numeric", - month: "short", - day: "numeric", - hour: "2-digit", - minute: "2-digit", - }); -}; - -// Get user name from reimbursement -const getUserName = (reimbursement: ExpandedReimbursement) => { - if (reimbursement.expand?.submitted_by?.name) { - return reimbursement.expand.submitted_by.name; - } - - // Try to find user by ID if expansion failed - const user = users.find((u) => u.id === reimbursement.submitted_by); - return user?.name || "Unknown User"; -}; ---- -
-
-

- - Administrator Dashboard -
Real-time
- -

- - -
- -
-
-
-

Users

-
- -
-
-

- {userCount} -

-
-

Total registered

-
Active
-
-
-
- - -
-
-
-

Officers

-
- -
-
-

- {officerCount} -

-
-

Active officers

- -
-
-
- - -
-
-
-

Events

-
- -
-
-

- {eventCount} -

-
-

Total events

- -
-
-
- - -
-
-
-

Upcoming

-
- -
-
-

- {upcomingEvents} -

-
-

Future events

-
Active
-
-
-
- - -
-
-
-

Reimbursements

-
- -
-
-

- {reimbursementCount} -

-
-

Total requests

- -
-
-
- - -
-
-
-

Pending

-
- -
-
-

- {pendingReimbursements} -

-
-

Awaiting review

- { - pendingReimbursements > 0 && ( -
- Action needed -
- ) - } -
-
-
-
- - -
-

- - Administrative Actions -

-
- - - - -
-
- - -
- -
-
-

- - User Management -

-
- - - - - - - - - - - - - - - - - - - { - users.map((user) => ( - - - - - - - - )) - } - -
NameEmailRoleLast LoginActions
{user.name}{user.email} - {user.member_id || "Member"} - - {user.last_login - ? formatDate( - user.last_login - ) - : "Never"} - -
- - -
-
-
-
-
- - - - - - - - - -
-
-
- - - - +--- diff --git a/src/components/dashboard/AdminDashboard/AdminSystemActivity.tsx b/src/components/dashboard/AdminDashboard/AdminSystemActivity.tsx deleted file mode 100644 index 4892f77..0000000 --- a/src/components/dashboard/AdminDashboard/AdminSystemActivity.tsx +++ /dev/null @@ -1,254 +0,0 @@ -import { useEffect, useState } from "react"; -import { Authentication } from "../../../scripts/pocketbase/Authentication"; -import { Get } from "../../../scripts/pocketbase/Get"; -import { Collections } from "../../../schemas/pocketbase"; -import type { Log, User } from "../../../schemas/pocketbase"; -import { Icon } from "@iconify/react"; - -// Extend the Log type to include expand property -interface ExtendedLog extends Log { - expand?: { - user?: User; - }; -} - -interface AdminSystemActivityProps { - limit?: number; - autoRefresh?: boolean; - refreshInterval?: number; -} - -export default function AdminSystemActivity({ - limit = 10, - autoRefresh = true, - refreshInterval = 30000, // 30 seconds -}: AdminSystemActivityProps) { - const [logs, setLogs] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - - const fetchLogs = async () => { - try { - setLoading(true); - const auth = Authentication.getInstance(); - const get = Get.getInstance(); - - if (!auth.isAuthenticated()) { - setError("Not authenticated"); - setLoading(false); - return; - } - - console.log(`Fetching logs from collection: ${Collections.LOGS} with limit: ${limit}`); - - // Fetch logs with user expansion - const logsResponse = await get.getList( - Collections.LOGS, - 1, - limit, - "", - "-created", - { expand: "user" } - ); - - console.log(`Logs fetched: ${logsResponse.items.length} of ${logsResponse.totalItems} total`); - - if (logsResponse.items.length === 0) { - console.log("No logs found in the response"); - } else { - console.log("First log:", JSON.stringify(logsResponse.items[0], null, 2)); - } - - setLogs(logsResponse.items); - setError(null); - } catch (err) { - console.error("Error fetching logs:", err); - setError(`Failed to load system logs: ${err instanceof Error ? err.message : String(err)}`); - } finally { - setLoading(false); - } - }; - - // Expose the refresh function to the window object - useEffect(() => { - if (typeof window !== 'undefined') { - (window as any).refreshAdminSystemActivity = fetchLogs; - } - - return () => { - if (typeof window !== 'undefined') { - delete (window as any).refreshAdminSystemActivity; - } - }; - }, []); - - useEffect(() => { - // Initial fetch - console.log("AdminSystemActivity mounted, fetching logs..."); - fetchLogs(); - - // Set up auto-refresh if enabled - let intervalId: number | undefined; - if (autoRefresh && typeof window !== 'undefined') { - intervalId = window.setInterval(fetchLogs, refreshInterval); - } - - // Cleanup interval on unmount - return () => { - if (intervalId !== undefined && typeof window !== 'undefined') { - window.clearInterval(intervalId); - } - }; - }, [limit, autoRefresh, refreshInterval]); - - // Format date to a readable format - const formatDate = (dateString: string) => { - const date = new Date(dateString); - - // Check if the date is today - const today = new Date(); - const isToday = date.toDateString() === today.toDateString(); - - if (isToday) { - // If today, show time only - return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); - } else { - // Otherwise show date and time - return date.toLocaleString([], { - month: 'short', - day: 'numeric', - hour: '2-digit', - minute: '2-digit' - }); - } - }; - - // Get appropriate icon for log type - const getLogTypeIcon = (type: string) => { - switch (type.toLowerCase()) { - case "login": - return "heroicons:login"; - case "logout": - return "heroicons:logout"; - case "create": - return "heroicons:plus-circle"; - case "update": - return "heroicons:pencil"; - case "delete": - return "heroicons:trash"; - case "error": - return "heroicons:exclamation-circle"; - default: - return "heroicons:information-circle"; - } - }; - - // Get appropriate color for log type - const getLogTypeColor = (type: string) => { - switch (type.toLowerCase()) { - case "login": - return "text-success"; - case "logout": - return "text-info"; - case "create": - return "text-primary"; - case "update": - return "text-secondary"; - case "delete": - return "text-error"; - case "error": - return "text-error"; - default: - return "text-base-content"; - } - }; - - if (loading && logs.length === 0) { - return ( -
-
- Loading system logs... -
- ); - } - - if (error) { - return ( -
- - {error} -
- ); - } - - if (logs.length === 0) { - return ( -
- - No system logs found. This could be because no logs have been created yet or because you don't have permission to view logs. - -
- ); - } - - return ( -
- - - - - - - - - - - {logs.map((log) => ( - - - - - - - ))} - -
TimeUserActionDetails
- {formatDate(log.created)} - - {log.expand?.user?.name || "System"} - -
- - {log.type} -
-
{log.message}
- - {loading && logs.length > 0 && ( -
-
- Refreshing... -
- )} - -
- -
-
- ); -} \ No newline at end of file