150 lines
9.1 KiB
JavaScript
150 lines
9.1 KiB
JavaScript
'use client';
|
|
import { useState, useEffect } from 'react';
|
|
import { useRouter } from 'next/navigation';
|
|
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";
|
|
|
|
export default function StaffBooking() {
|
|
const { darkMode } = useTheme();
|
|
const router = useRouter();
|
|
const [appointmentDate] = useState(new Date().toISOString().split('T')[0]);
|
|
const [stats, setStats] = useState({
|
|
totalTokens: 0,
|
|
booked: 0,
|
|
done: 0,
|
|
missed: 0
|
|
});
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
useEffect(() => {
|
|
const fetchStats = async () => {
|
|
try {
|
|
const today = new Date().toISOString().split('T')[0];
|
|
const statsResponse = await databases.listDocuments(
|
|
DATABASE_ID,
|
|
COLLECTION_ID,
|
|
[Query.equal('date', today)]
|
|
);
|
|
|
|
const allTokens = statsResponse.documents;
|
|
const bookedTokens = allTokens.filter(t => t.status === 'booked');
|
|
const doneTokens = allTokens.filter(t => t.status === 'done');
|
|
const missedTokens = allTokens.filter(t => t.status === 'missed');
|
|
|
|
setStats({
|
|
totalTokens: allTokens.length,
|
|
booked: bookedTokens.length,
|
|
done: doneTokens.length,
|
|
missed: missedTokens.length
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error("Error fetching statistics:", error);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
fetchStats();
|
|
}, []);
|
|
|
|
if (loading) {
|
|
return <div className="flex items-center justify-center min-h-screen">
|
|
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500"></div>
|
|
</div>;
|
|
}
|
|
|
|
return (
|
|
<div className={`flex flex-col min-h-screen ${darkMode ? 'dark bg-gray-900' : 'bg-white'}`}>
|
|
<div className="flex h-screen overflow-hidden">
|
|
<div className="relative flex flex-col flex-1 overflow-x-hidden overflow-y-auto">
|
|
<div className={`flex ${darkMode ? 'bg-gray-800' : 'bg-white'} shadow-sm sticky top-0 z-50 w-full`}>
|
|
<Header />
|
|
</div>
|
|
|
|
<main className="p-4 mx-auto max-w-[--breakpoint-2xl] md:p-6">
|
|
{/* Statistics Overview */}
|
|
{/* <div className={`mb-8 p-6 rounded-lg ${darkMode ? 'bg-gray-800' : 'bg-gray-50'} border ${darkMode ? 'border-gray-700' : 'border-gray-200'}`}>
|
|
<h3 className={`text-lg font-medium mb-4 ${darkMode ? 'text-white' : 'text-gray-800'}`}>
|
|
Today's Overview
|
|
</h3>
|
|
<div className="grid grid-cols-2 md:grid-cols-3 gap-4">
|
|
<div className={`p-4 rounded-lg text-center ${darkMode ? 'bg-gray-700' : 'bg-white'} border ${darkMode ? 'border-gray-600' : 'border-gray-200'}`}>
|
|
<p className={`text-sm ${darkMode ? 'text-gray-300' : 'text-gray-600'}`}>Total Tokens</p>
|
|
<p className={`text-2xl font-bold ${darkMode ? 'text-white' : 'text-gray-900'}`}>{stats.totalTokens}</p>
|
|
</div>
|
|
<div className={`p-4 rounded-lg text-center ${darkMode ? 'bg-gray-700' : 'bg-white'} border ${darkMode ? 'border-gray-600' : 'border-gray-200'}`}>
|
|
<p className={`text-sm ${darkMode ? 'text-gray-300' : 'text-gray-600'}`}>Pending</p>
|
|
<p className={`text-2xl font-bold ${darkMode ? 'text-white' : 'text-gray-900'}`}>{stats.booked}</p>
|
|
</div>
|
|
<div className={`p-4 rounded-lg text-center ${darkMode ? 'bg-gray-700' : 'bg-white'} border ${darkMode ? 'border-gray-600' : 'border-gray-200'}`}>
|
|
<p className={`text-sm ${darkMode ? 'text-gray-300' : 'text-gray-600'}`}>Completed</p>
|
|
<p className={`text-2xl font-bold ${darkMode ? 'text-white' : 'text-gray-900'}`}>{stats.done}</p>
|
|
</div>
|
|
</div>
|
|
</div> */}
|
|
|
|
{/* Booking Options */}
|
|
<div className="space-y-4">
|
|
<h3 className={`text-lg font-medium ${darkMode ? 'text-white' : 'text-gray-800'}`}>
|
|
New Booking
|
|
</h3>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div
|
|
onClick={() => router.push('/pages/SingleBooking')}
|
|
className={`p-6 cursor-pointer rounded-lg border transition-all hover:shadow-md ${darkMode ?
|
|
'bg-gray-800 border-gray-700 hover:border-blue-600 hover:bg-gray-700' :
|
|
'bg-white border-gray-200 hover:border-blue-500 hover:bg-blue-50'
|
|
}`}
|
|
>
|
|
<div className="flex items-center gap-4">
|
|
<div className={`p-3 rounded-full ${darkMode ? 'bg-blue-900/30 text-blue-400' : 'bg-blue-100 text-blue-600'}`}>
|
|
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<h3 className={`font-medium ${darkMode ? 'text-white' : 'text-gray-800'}`}>Single Booking</h3>
|
|
<p className={`text-sm ${darkMode ? 'text-gray-400' : 'text-gray-600'}`}>
|
|
Book one token for a patient
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
onClick={() => router.push('/pages/MultiBooking')}
|
|
className={`p-6 cursor-pointer rounded-lg border transition-all hover:shadow-md ${darkMode ?
|
|
'bg-gray-800 border-gray-700 hover:border-blue-600 hover:bg-gray-700' :
|
|
'bg-white border-gray-200 hover:border-blue-500 hover:bg-blue-50'
|
|
}`}
|
|
>
|
|
<div className="flex items-center gap-4">
|
|
<div className={`p-3 rounded-full ${darkMode ? 'bg-purple-900/30 text-purple-400' : 'bg-purple-100 text-purple-600'}`}>
|
|
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<h3 className={`font-medium ${darkMode ? 'text-white' : 'text-gray-800'}`}>Multi Booking</h3>
|
|
<p className={`text-sm ${darkMode ? 'text-gray-400' : 'text-gray-600'}`}>
|
|
Book multiple tokens at once
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className={`text-center text-sm mt-8 ${darkMode ? 'text-gray-400' : 'text-gray-600'}`}>
|
|
<p>Staff can book tokens for patients. Choose single booking for individual patients or multi-booking for group entries.</p>
|
|
<p>All tokens will be assigned for {new Date(appointmentDate).toLocaleDateString()}.</p>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
} |