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 */}
-
-
- {/* Box 3 - Recent Activity */}
-
-
- Recent Activity
-
-
-
-
-
-
Logged in
-
2 minutes ago
-
-
-
-
-
-
Project created
-
15 minutes ago
-
-
-
-
-
- {/* Box 4 - Quick Actions */}
-
-
- Quick Actions
-
-
-
- New Project
-
-
- Add Task
-
-
-
-
-
- {/* 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 ;
+
+ 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.
+ ) : (
+ <>
+
+
+
+ Token
+ Name
+ Booked By
+ Status
+ {/* Wait Time */}
+ Actions
+
+
+
+ {currentEntries.map((entry) => (
+
+ {entry.tokenNumber}
+ {entry.patientName}
+
+
+ {entry.bookedBy}
+
+
+
+
+ {entry.status === "booked" ? "In-Queue" : entry.status}
+
+
+ {/*
+ {entry.status === "booked" ?
+ `~${calculateWaitTime(entry.tokenNumber)} mins` :
+ '-'}
+ */}
+
+ {entry.status === "booked" && (
+ <>
+ updateStatus(entry.$id, "done")}
+ className="border border-green-600 text-green-600 rounded-full px-2 py-1 text-xs hover:bg-green-50"
+ >
+ Done
+
+ updateStatus(entry.$id, "missed")}
+ className="border border-red-600 text-red-600 rounded-full px-2 py-1 text-xs hover:bg-red-50"
+ >
+ Missed
+
+ >
+ )}
+
+
+ ))}
+
+
+
+ {/* Pagination */}
+
+ setCurrentPage((prev) => prev - 1)}
+ className="px-3 py-1 border rounded disabled:opacity-50"
+ >
+ Previous
+
+
+ Page {currentPage} of {totalPages}
+
+ setCurrentPage((prev) => prev + 1)}
+ className="px-3 py-1 border rounded disabled:opacity-50"
+ >
+ Next
+
+
+ >
+ )}
+
+ );
+}
\ No newline at end of file