diff --git a/src/app/dashboard/page.js b/src/app/dashboard/page.js index aad7cec..248ce64 100644 --- a/src/app/dashboard/page.js +++ b/src/app/dashboard/page.js @@ -4,6 +4,7 @@ import { useRouter } from "next/navigation"; import { useAuth } from "../context/AuthContext"; import { useEffect } from "react"; import { useTheme } from "../context/ThemeContext"; +import EntriesTable from "../pages/entries/EntriesTable"; export default function DashboardPage() { @@ -37,105 +38,7 @@ export default function DashboardPage() { return (
-

- Dashboard -

- {/* -------------user role-------------- */} -

- User Profile -

-
-
-
-

John Doe

-

john@example.com

-

Role: {userRole}

{/* 👈 Added */} -
-
-{/* */} - - {/* 2x2 Grid Layout */} -
- {/* Box 1 - User Profile */} -
-

- User Profile -

-
-
-
-

John Doe

-

john@example.com

-
-
-
- - {/* Box 2 - Statistics */} -
-

- Statistics -

-
-
-

Projects

-

12

-
-
-

Tasks

-

24

-
-
-
- - {/* Box 3 - Recent Activity */} -
-

- Recent Activity -

-
-
-
-
-

Logged in

-

2 minutes ago

-
-
-
-
-
-

Project created

-

15 minutes ago

-
-
-
-
- - {/* Box 4 - Quick Actions */} -
-

- Quick Actions -

-
- - -
-
-
- - {/* Additional content can go here */} -
-

- Welcome to Your Dashboard -

-

- This is a simple dashboard layout with four main components arranged in a 2x2 grid. - You can easily add more components or modify these boxes as needed. -

-
+
); } \ No newline at end of file diff --git a/src/app/pages/entries/EntriesTable.js b/src/app/pages/entries/EntriesTable.js new file mode 100644 index 0000000..4cbdba0 --- /dev/null +++ b/src/app/pages/entries/EntriesTable.js @@ -0,0 +1,270 @@ +"use client"; +import { useEffect, useState } from "react"; +import { databases, Query } from "../../lib/appwrite"; +import { DATABASE_ID, COLLECTION_ID } from "../../lib/api"; +import Header from "../../components/partials/header"; +import { useTheme } from "../../context/ThemeContext"; +import { useAuth } from "../../context/AuthContext"; + +export default function EntriesTable() { + const { userRole } = useAuth(); + const { darkMode } = useTheme(); + const [entries, setEntries] = useState([]); + const [filteredEntries, setFilteredEntries] = useState([]); + const [searchQuery, setSearchQuery] = useState(""); + const [currentPage, setCurrentPage] = useState(1); + const [avgConsultTime, setAvgConsultTime] = useState(15); // Default 15 mins + const entriesPerPage = 20; + + const [currentToken, setCurrentToken] = useState(null); + const [previousToken, setPreviousToken] = useState(null); + const [nextToken, setNextToken] = useState(null); + const [missedTokens, setMissedTokens] = useState(""); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + // Calculate waiting time based on position in queue + const calculateWaitTime = (tokenNumber) => { + const bookedEntries = entries.filter(e => e.status === "booked"); + const position = bookedEntries.findIndex(e => e.tokenNumber === tokenNumber); + return position >= 0 ? (position * avgConsultTime) : 0; + }; + + const getEntries = async () => { + try { + const today = new Date().toISOString().split('T')[0]; + const response = await databases.listDocuments( + DATABASE_ID, + COLLECTION_ID, + [ + Query.equal('date', today), + Query.orderAsc('tokenNumber') + ], + 100 + ); + return response.documents; + } catch (error) { + console.error("Fetch error:", error); + throw error; + } + }; + + const updateTokenInfo = (entries) => { + if (entries.length === 0) { + setCurrentToken(null); + setPreviousToken(null); + setNextToken(null); + setMissedTokens(""); + return; + } + + const currentIndex = entries.findIndex((entry) => entry.status === "booked"); + const current = currentIndex >= 0 ? entries[currentIndex] : null; + + setCurrentToken(current?.tokenNumber || null); + setPreviousToken(currentIndex > 0 ? entries[currentIndex - 1]?.tokenNumber : null); + setNextToken(currentIndex < entries.length - 1 ? entries[currentIndex + 1]?.tokenNumber : null); + + const missed = entries + .filter((entry) => entry.status === "missed") + .map((entry) => entry.tokenNumber) + .join(", "); + setMissedTokens(missed || "None"); + }; + + const updateStatus = async (entryId, newStatus) => { + try { + setLoading(true); + await databases.updateDocument( + DATABASE_ID, + COLLECTION_ID, + entryId, + { status: newStatus } + ); + const data = await getEntries(); + setEntries(data); + setFilteredEntries(data); + updateTokenInfo(data); + } catch (error) { + console.error("Update error:", error); + setError(error.message); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + if (userRole === "patient") return; // Don't load data if patient + + const loadData = async () => { + try { + const data = await getEntries(); + setEntries(data); + setFilteredEntries(data); + updateTokenInfo(data); + + // Load settings (avg consultation time) + // const settings = await getSettings(); + // setAvgConsultTime(settings?.avgConsultationTime || 15); + } catch (err) { + setError(err.message); + } finally { + setLoading(false); + } + }; + loadData(); + }, [userRole]); + + useEffect(() => { + const filtered = entries.filter((entry) => { + return ( + entry.patientName.toLowerCase().includes(searchQuery.toLowerCase()) || + entry.tokenNumber.toString().includes(searchQuery) + ); + }); + setFilteredEntries(filtered); + setCurrentPage(1); + }, [searchQuery, entries]); + + const indexOfLastEntry = currentPage * entriesPerPage; + const indexOfFirstEntry = indexOfLastEntry - entriesPerPage; + const currentEntries = filteredEntries.slice(indexOfFirstEntry, indexOfLastEntry); + const totalPages = Math.ceil(filteredEntries.length / entriesPerPage); + + if (loading) return
+
+

Loading...

+
; + + if (error) return
Error: {error}
; + + // Check user role and show permission message if patient + if (userRole === "patient") { + return ( +
+
+
+

Access Denied

+

You don't have permission to view this page.

+
+
+
+ ); + } + + return ( +
+
+
+
+

Today's Entries

+ setSearchQuery(e.target.value)} + /> + + {filteredEntries.length === 0 ? ( +
No entries found for today.
+ ) : ( + <> + + + + + + + + {/* */} + + + + + {currentEntries.map((entry) => ( + + + + + + {/* */} + + + ))} + +
TokenNameBooked ByStatusWait TimeActions
{entry.tokenNumber}{entry.patientName} + + {entry.bookedBy} + + + + {entry.status === "booked" ? "In-Queue" : entry.status} + + + {entry.status === "booked" ? + `~${calculateWaitTime(entry.tokenNumber)} mins` : + '-'} + + {entry.status === "booked" && ( + <> + + + + )} +
+ + {/* Pagination */} +
+ + + Page {currentPage} of {totalPages} + + +
+ + )} +
+ ); +} \ No newline at end of file