Skip to content

Commit b8ee696

Browse files
committed
staff service ui
1 parent e005f86 commit b8ee696

18 files changed

Lines changed: 855 additions & 312 deletions

File tree

frontend/src/app/staff/dashboard/layout.tsx

Lines changed: 107 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,24 @@ import { ReactNode, useEffect } from 'react';
44
import Link from 'next/link';
55
import { usePathname, useRouter } from 'next/navigation';
66
import { useStaffAuth } from '../../../staff/auth/staff.auth.provider';
7+
import { motion } from 'framer-motion';
8+
import {
9+
LayoutDashboard,
10+
Calendar,
11+
User,
12+
LogOut,
13+
Activity,
14+
Settings,
15+
Bed,
16+
ClipboardPlus,
17+
FileMinus
18+
} from 'lucide-react';
19+
import {
20+
Tooltip,
21+
TooltipContent,
22+
TooltipProvider,
23+
TooltipTrigger,
24+
} from '@/components/ui/tooltip';
725

826
export default function StaffLayout({
927
children,
@@ -20,90 +38,102 @@ export default function StaffLayout({
2038
}
2139
}, [auth.isRestoring, auth.accessToken, router]);
2240

23-
if (auth.isRestoring) return <div>Loading...</div>;
41+
if (auth.isRestoring) {
42+
return (
43+
<div className="flex items-center justify-center min-h-[60vh]">
44+
<div className="relative">
45+
<div className="h-16 w-16 rounded-full border-4 border-slate-100 border-t-blue-600 animate-spin"></div>
46+
</div>
47+
</div>
48+
);
49+
}
2450
if (!auth.accessToken) return null;
2551

26-
function SidebarLink({
27-
href,
28-
label,
29-
active,
30-
}: {
31-
href: string;
32-
label: string;
33-
active: boolean;
34-
}) {
35-
return (
36-
<Link
37-
href={href}
38-
className={`block px-3 py-2 rounded ${
39-
active
40-
? 'bg-white text-black font-semibold'
41-
: 'hover:bg-blue-700'
42-
}`}
43-
>
44-
{label}
45-
</Link>
46-
);
47-
}
48-
49-
return (
50-
<div className="h-screen flex overflow-hidden">
51-
<aside className="w-64 bg-white text-bl p-6 flex flex-col justify-between shrink-0">
52-
<div>
53-
<h2 className="text-xl font-bold mb-8">Doctor Panel</h2>
52+
const isDoctor = auth.staff?.role === 'DOCTOR';
5453

55-
<nav className="space-y-4">
56-
<SidebarLink
57-
href="/staff/dashboard"
58-
label="Dashboard"
59-
active={pathname === '/staff/dashboard'}
60-
/>
54+
const navItems = isDoctor ? [
55+
{ label: 'Dashboard', icon: LayoutDashboard, path: '/staff/dashboard' },
56+
{ label: "Today's Queue", icon: Activity, path: '/staff/dashboard/queue' },
57+
{ label: 'Manage Availability', icon: Calendar, path: '/staff/dashboard/availability' },
58+
{ label: 'Patients', icon: User, path: '/staff/dashboard/patients' },
59+
] : [
60+
{ label: 'Dashboard', icon: LayoutDashboard, path: '/staff/dashboard' },
61+
{ label: 'Beds', icon: Bed, path: '/staff/dashboard/beds' },
62+
{ label: 'Admissions', icon: ClipboardPlus, path: '/staff/dashboard/admissions' },
63+
{ label: 'Discharge', icon: FileMinus, path: '/staff/dashboard/discharge' },
64+
];
6165

62-
<SidebarLink
63-
href="/staff/dashboard/queue"
64-
label="Today's Queue"
65-
active={pathname === '/staff/dashboard/queue'}
66-
/>
66+
return (
67+
<TooltipProvider>
68+
<div className="flex h-screen overflow-hidden bg-gray-50">
69+
<motion.aside
70+
initial={{ x: -20, opacity: 0 }}
71+
animate={{ x: 0, opacity: 1 }}
72+
transition={{ duration: 0.3 }}
73+
className="sticky top-0 z-20 flex h-screen w-[78px] flex-col items-center py-6 hos-gradient-bg shadow-xl"
74+
style={{ borderRadius: '0 24px 24px 0' }}
75+
>
76+
{/* Logo */}
77+
<div className="mb-8">
78+
<div className="flex h-11 w-11 items-center justify-center rounded-2xl bg-white/20 backdrop-blur-sm">
79+
<Activity size={22} className="text-white" strokeWidth={2.2} />
80+
</div>
81+
</div>
6782

68-
<SidebarLink
69-
href="/staff/dashboard/availability"
70-
label="Manage Availability"
71-
active={pathname === '/staff/dashboard/availability'}
72-
/>
73-
<SidebarLink
74-
href='/staff/dashboard/beds'
75-
label='Beds'
76-
active={pathname === '/staff/dashboard/beds'}
77-
/>
78-
<SidebarLink
79-
href='/staff/dashboard/admissions'
80-
label='Admissions'
81-
active={pathname === '/staff/dashboard/admissions'}
82-
/>
83-
<SidebarLink
84-
href='/staff/dashboard/discharge'
85-
label='Discharge'
86-
active={pathname === '/staff/dashboard/Discharge'}
87-
/>
88-
<SidebarLink
89-
href='/staff/dashboard/patients'
90-
label='Patients'
91-
active={pathname === '/staff/dashboard/patients'}
92-
/>
83+
{/* Navigation */}
84+
<nav className="flex flex-1 flex-col items-center gap-2">
85+
{navItems.map((item) => {
86+
const isActive = pathname === item.path;
87+
return (
88+
<Tooltip key={item.path} delayDuration={0}>
89+
<TooltipTrigger asChild>
90+
<Link
91+
href={item.path}
92+
className={`flex h-11 w-11 items-center justify-center rounded-2xl transition-all duration-200 ${isActive
93+
? 'bg-white text-indigo-600 shadow-lg'
94+
: 'text-white/60 hover:bg-white/10 hover:text-white'
95+
}`}
96+
>
97+
<item.icon size={20} strokeWidth={isActive ? 2 : 1.5} />
98+
</Link>
99+
</TooltipTrigger>
100+
<TooltipContent side="right" className="font-medium">
101+
{item.label}
102+
</TooltipContent>
103+
</Tooltip>
104+
);
105+
})}
93106
</nav>
94-
</div>
95107

96-
<button
97-
onClick={logout}
98-
className="bg-red-500 px-4 py-2 rounded"
99-
>
100-
Logout
101-
</button>
102-
</aside>
108+
{/* Bottom Actions */}
109+
<div className="mt-auto flex flex-col items-center gap-2">
110+
<Tooltip delayDuration={0}>
111+
<TooltipTrigger asChild>
112+
<button className="flex h-11 w-11 items-center justify-center rounded-2xl text-white/60 transition-all hover:bg-white/10 hover:text-white">
113+
<Settings size={20} strokeWidth={1.5} />
114+
</button>
115+
</TooltipTrigger>
116+
<TooltipContent side="right" className="font-medium">Settings</TooltipContent>
117+
</Tooltip>
118+
119+
<Tooltip delayDuration={0}>
120+
<TooltipTrigger asChild>
121+
<button
122+
onClick={() => { logout(); router.push('/staff/login'); }}
123+
className="flex h-11 w-11 items-center justify-center rounded-2xl text-white/60 transition-all hover:bg-white/10 hover:text-white"
124+
>
125+
<LogOut size={20} strokeWidth={1.5} />
126+
</button>
127+
</TooltipTrigger>
128+
<TooltipContent side="right" className="font-medium">Sign out</TooltipContent>
129+
</Tooltip>
130+
</div>
131+
</motion.aside>
103132

104-
<main className="flex-1 bg-gray-100 overflow-y-auto p-8">
105-
{children}
106-
</main>
107-
</div>
133+
<main className="flex-1 overflow-y-auto p-8">
134+
{children}
135+
</main>
136+
</div>
137+
</TooltipProvider>
108138
);
109139
}

frontend/src/app/staff/dashboard/page.tsx

Lines changed: 109 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useStaffAuth } from '../../../staff/auth/staff.auth.provider';
44
import { useRouter } from 'next/navigation';
55
import { useEffect } from 'react';
66
import Link from 'next/link';
7+
import { LayoutDashboard, Calendar, FileText, User, Activity, ClipboardPlus, Bed } from 'lucide-react';
78

89
export default function StaffDashboardPage() {
910
const { auth, logout } = useStaffAuth();
@@ -15,42 +16,124 @@ export default function StaffDashboardPage() {
1516
}
1617
}, [auth.accessToken, auth.isRestoring, router]);
1718

18-
if (auth.isRestoring) {
19-
return (
20-
<div className="min-h-screen flex items-center justify-center">
21-
<div className="h-6 w-6 animate-spin rounded-full border-2 border-gray-300 border-t-blue-600" />
19+
if (auth.isRestoring) return (
20+
<div className="flex items-center justify-center min-h-[60vh]">
21+
<div className="relative">
22+
<div className="h-16 w-16 rounded-full border-4 border-slate-100 border-t-blue-600 animate-spin"></div>
2223
</div>
23-
);
24-
}
24+
</div>
25+
);
2526

2627
if (!auth.accessToken) return null;
2728

29+
const staff = auth.staff;
30+
const isDoctor = staff?.role === 'DOCTOR';
31+
2832
return (
29-
<div className="min-h-screen p-8 bg-gray-50">
30-
31-
{/* 🔥 LOGOUT BUTTON */}
32-
<div className="flex justify-end mb-6">
33-
<button
34-
onClick={logout}
35-
className="bg-red-600 text-white px-4 py-2 rounded-md hover:bg-red-700 transition"
36-
>
37-
Logout
38-
</button>
33+
<div className="space-y-10">
34+
35+
{/* Header */}
36+
<div className="flex items-center justify-between">
37+
<div className="flex items-center gap-4">
38+
<div className="w-16 h-16 rounded-full bg-slate-200 flex items-center justify-center text-slate-600 font-semibold text-2xl border">
39+
{staff?.name?.charAt(0) || 'S'}
40+
</div>
41+
42+
<div>
43+
<h1 className="text-2xl font-bold">
44+
Welcome back{staff?.name ? `, ${staff?.name}` : ''}
45+
</h1>
46+
<p className="text-gray-600">
47+
{isDoctor ? "Manage your patients and queue for the day." : "Oversee hospital operations and admission requests."}
48+
</p>
49+
</div>
50+
</div>
51+
</div>
52+
53+
{/* Stats Cards */}
54+
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
55+
56+
<div className="bg-white border rounded-2xl p-6 shadow-sm flex items-center gap-4">
57+
<div className="p-3 rounded-xl bg-blue-100 text-blue-600">
58+
<User size={22} />
59+
</div>
60+
<div>
61+
<p className="text-sm text-slate-500">Role</p>
62+
<p className="text-lg font-bold">{staff?.role}</p>
63+
</div>
64+
</div>
65+
66+
<div className="bg-white border rounded-2xl p-6 shadow-sm flex items-center gap-4">
67+
<div className="p-3 rounded-xl bg-green-100 text-green-600">
68+
<LayoutDashboard size={22} />
69+
</div>
70+
<div>
71+
<p className="text-sm text-slate-500">Department</p>
72+
<p className="text-lg font-bold truncate max-w-[150px]">{staff?.department}</p>
73+
</div>
74+
</div>
75+
76+
<div className="bg-white border rounded-2xl p-6 shadow-sm flex items-center gap-4">
77+
<div className="p-3 rounded-xl bg-purple-100 text-purple-600">
78+
<FileText size={22} />
79+
</div>
80+
<div>
81+
<p className="text-sm text-slate-500">Job Title</p>
82+
<p className="text-lg font-bold truncate max-w-[150px]">{staff?.job_title}</p>
83+
</div>
84+
</div>
85+
3986
</div>
4087

41-
<h1 className="text-2xl font-semibold mb-6">
42-
Staff Dashboard
43-
</h1>
88+
{/* Quick Actions */}
89+
<div>
90+
<h2 className="text-lg font-semibold mb-4">Quick Actions</h2>
4491

45-
<div className="bg-white shadow rounded p-6 space-y-2">
46-
<p><strong>Name:</strong> {auth.staff?.name}</p>
47-
<p><strong>Email:</strong> {auth.staff?.email}</p>
48-
<p><strong>Department:</strong> {auth.staff?.department}</p>
49-
<p><strong>Role:</strong> {auth.staff?.role}</p>
50-
<p><strong>Job Title:</strong> {auth.staff?.job_title}</p>
92+
{isDoctor ? (
93+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
94+
<Link href="/staff/dashboard/queue" className="flex items-center gap-4 p-6 bg-white border rounded-2xl shadow-sm hover:shadow-md transition">
95+
<div className="p-3 rounded-xl bg-blue-100 text-blue-600">
96+
<Activity size={22} />
97+
</div>
98+
<div>
99+
<p className="font-semibold">Today's Queue</p>
100+
<p className="text-sm text-slate-500">View your queued patients</p>
101+
</div>
102+
</Link>
103+
<Link href="/staff/dashboard/patients" className="flex items-center gap-4 p-6 bg-white border rounded-2xl shadow-sm hover:shadow-md transition">
104+
<div className="p-3 rounded-xl bg-green-100 text-green-600">
105+
<User size={22} />
106+
</div>
107+
<div>
108+
<p className="font-semibold">My Patients</p>
109+
<p className="text-sm text-slate-500">View admitted patients</p>
110+
</div>
111+
</Link>
112+
</div>
113+
) : (
114+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
115+
<Link href="/staff/dashboard/admissions" className="flex items-center gap-4 p-6 bg-white border rounded-2xl shadow-sm hover:shadow-md transition">
116+
<div className="p-3 rounded-xl bg-purple-100 text-purple-600">
117+
<ClipboardPlus size={22} />
118+
</div>
119+
<div>
120+
<p className="font-semibold">Admission Requests</p>
121+
<p className="text-sm text-slate-500">Acknowledge pending requests</p>
122+
</div>
123+
</Link>
124+
<Link href="/staff/dashboard/beds" className="flex items-center gap-4 p-6 bg-white border rounded-2xl shadow-sm hover:shadow-md transition">
125+
<div className="p-3 rounded-xl bg-blue-100 text-blue-600">
126+
<Bed size={22} />
127+
</div>
128+
<div>
129+
<p className="font-semibold">Bed Management</p>
130+
<p className="text-sm text-slate-500">Manage ward allocations</p>
131+
</div>
132+
</Link>
133+
</div>
134+
)}
51135
</div>
52136

53-
54137
</div>
55138
);
56139
}

0 commit comments

Comments
 (0)