Skip to content

Commit 2512466

Browse files
committed
UI: patient dashboard
1 parent 637592e commit 2512466

5 files changed

Lines changed: 467 additions & 59 deletions

File tree

Lines changed: 318 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,334 @@
11
'use client';
22

3+
import Link from 'next/link';
4+
import { useEffect, useState } from 'react';
5+
36
import MyQueueCard from '@/src/features/appointments/components/MyQueueCard';
7+
import AppointmentCard from '@/src/features/appointments/components/AppointmentCard';
8+
9+
import { getAppointmentHistory } from '@/src/features/appointments/api/getHistory';
10+
import { getPatientDocuments } from '@/src/features/patient/api/getDocument';
11+
import { getProfile } from '@/src/features/patient/api/getProfile';
12+
13+
import { Calendar, FileText, CalendarPlus, Upload, CloudCog } from 'lucide-react';
414

515
export default function DashboardHome() {
16+
17+
const [appointments, setAppointments] = useState<any[]>([]);
18+
const [documents, setDocuments] = useState<any[]>([]);
19+
20+
const [profile, setProfile] = useState<any>(null);
21+
const [patientName, setPatientName] = useState('');
22+
23+
const [totalAppointments, setTotalAppointments] = useState(0);
24+
const [upcomingAppointments, setUpcomingAppointments] = useState(0);
25+
const [totalDocuments, setTotalDocuments] = useState(0);
26+
27+
useEffect(() => {
28+
29+
async function loadData() {
30+
31+
const appts = await getAppointmentHistory();
32+
const docs = await getPatientDocuments();
33+
const profileData = await getProfile();
34+
35+
console.log('profiledata',profileData);
36+
37+
setProfile(profileData);
38+
setPatientName(profileData.name);
39+
40+
const upcoming = appts.filter((a: any) =>
41+
new Date(a.appointment_time) > new Date() &&
42+
a.status === 'SCHEDULED'
43+
);
44+
45+
setAppointments(upcoming.slice(0, 3));
46+
47+
setTotalAppointments(appts.length);
48+
setUpcomingAppointments(upcoming.length);
49+
50+
setDocuments(docs);
51+
setTotalDocuments(docs.length);
52+
}
53+
54+
loadData();
55+
56+
}, []);
57+
658
return (
7-
<div className="space-y-8">
59+
<div className="space-y-10">
60+
61+
{/* Header */}
62+
63+
<div className="flex items-center justify-between">
64+
65+
<div className="flex items-center gap-4">
66+
67+
{/* Profile Image */}
68+
69+
{profile?.profile_image ? (
70+
71+
<img
72+
src={profile.profile_image}
73+
alt="Profile"
74+
className="w-18 h-18 rounded-full object-cover border"
75+
/>
76+
77+
) : (
78+
79+
<div className="w-12 h-12 rounded-full bg-slate-200 flex items-center justify-center text-slate-600 font-semibold">
80+
{patientName?.charAt(0)}
81+
</div>
82+
83+
)}
84+
85+
<div>
86+
87+
<h1 className="text-2xl font-bold">
88+
Welcome back{patientName ? `, ${patientName}` : ''}
89+
</h1>
90+
91+
<p className="text-gray-600">
92+
Track your appointment and queue status in real time.
93+
</p>
94+
95+
</div>
96+
97+
</div>
98+
99+
<Link
100+
href="/dashboard/profile"
101+
className="text-sm text-blue-600 hover:underline"
102+
>
103+
View Profile
104+
</Link>
105+
106+
</div>
107+
108+
{/* Quick Actions */}
8109

9110
<div>
10-
<h1 className="text-2xl font-bold mb-2">
11-
Welcome to your Dashboard
12-
</h1>
13111

14-
<p className="text-gray-600">
15-
Track your appointment and queue status in real time.
16-
</p>
112+
<h2 className="text-lg font-semibold mb-4">
113+
Quick Actions
114+
</h2>
115+
116+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
117+
118+
<Link
119+
href="/dashboard/book"
120+
className="flex items-center gap-4 p-6 bg-white border rounded-2xl shadow-sm hover:shadow-md transition"
121+
>
122+
123+
<div className="p-3 rounded-xl bg-blue-100 text-blue-600">
124+
<CalendarPlus size={22} />
125+
</div>
126+
127+
<div>
128+
<p className="font-semibold">
129+
Book Appointment
130+
</p>
131+
132+
<p className="text-sm text-slate-500">
133+
Schedule a doctor visit
134+
</p>
135+
</div>
136+
137+
</Link>
138+
139+
<Link
140+
href="/dashboard/documents"
141+
className="flex items-center gap-4 p-6 bg-white border rounded-2xl shadow-sm hover:shadow-md transition"
142+
>
143+
144+
<div className="p-3 rounded-xl bg-green-100 text-green-600">
145+
<Upload size={22} />
146+
</div>
147+
148+
<div>
149+
<p className="font-semibold">
150+
Upload Documents
151+
</p>
152+
153+
<p className="text-sm text-slate-500">
154+
Upload medical reports
155+
</p>
156+
</div>
157+
158+
</Link>
159+
160+
</div>
161+
17162
</div>
18163

19-
{/* 🔥 Live Queue Card */}
164+
{/* Stats Cards */}
165+
166+
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
167+
168+
<div className="bg-white border rounded-2xl p-6 shadow-sm flex items-center gap-4">
169+
170+
<div className="p-3 rounded-xl bg-blue-100 text-blue-600">
171+
<Calendar size={22} />
172+
</div>
173+
174+
<div>
175+
176+
<p className="text-sm text-slate-500">
177+
Total Appointments
178+
</p>
179+
180+
<p className="text-2xl font-bold">
181+
{totalAppointments}
182+
</p>
183+
184+
</div>
185+
186+
</div>
187+
188+
<div className="bg-white border rounded-2xl p-6 shadow-sm flex items-center gap-4">
189+
190+
<div className="p-3 rounded-xl bg-green-100 text-green-600">
191+
<Calendar size={22} />
192+
</div>
193+
194+
<div>
195+
196+
<p className="text-sm text-slate-500">
197+
Upcoming Visits
198+
</p>
199+
200+
<p className="text-2xl font-bold">
201+
{upcomingAppointments}
202+
</p>
203+
204+
</div>
205+
206+
</div>
207+
208+
<div className="bg-white border rounded-2xl p-6 shadow-sm flex items-center gap-4">
209+
210+
<div className="p-3 rounded-xl bg-purple-100 text-purple-600">
211+
<FileText size={22} />
212+
</div>
213+
214+
<div>
215+
216+
<p className="text-sm text-slate-500">
217+
Documents Uploaded
218+
</p>
219+
220+
<p className="text-2xl font-bold">
221+
{totalDocuments}
222+
</p>
223+
224+
</div>
225+
226+
</div>
227+
228+
</div>
229+
230+
{/* Queue */}
231+
20232
<MyQueueCard />
21233

234+
{/* Upcoming Appointments */}
235+
236+
<div>
237+
238+
<div className="flex items-center justify-between mb-4">
239+
240+
<h2 className="text-lg font-semibold">
241+
Upcoming Appointments
242+
</h2>
243+
244+
<Link
245+
href="/dashboard/appointments"
246+
className="text-sm text-blue-600 hover:underline"
247+
>
248+
View All
249+
</Link>
250+
251+
</div>
252+
253+
{appointments.length === 0 ? (
254+
255+
<div className="bg-white border rounded-2xl p-6 text-slate-500">
256+
No upcoming appointments
257+
</div>
258+
259+
) : (
260+
261+
<div className="space-y-4">
262+
263+
{appointments.map((appt) => (
264+
265+
<AppointmentCard
266+
key={appt.id}
267+
appointment={appt}
268+
/>
269+
270+
))}
271+
272+
</div>
273+
274+
)}
275+
276+
</div>
277+
278+
{/* Documents */}
279+
280+
<div>
281+
282+
<div className="flex items-center justify-between mb-4">
283+
284+
<h2 className="text-lg font-semibold">
285+
Documents
286+
</h2>
287+
288+
<Link
289+
href="/dashboard/documents"
290+
className="text-sm text-blue-600 hover:underline"
291+
>
292+
View All
293+
</Link>
294+
295+
</div>
296+
297+
{documents.length === 0 ? (
298+
299+
<div className="bg-white border rounded-2xl p-6 text-slate-500">
300+
No documents uploaded yet
301+
</div>
302+
303+
) : (
304+
305+
<div className="bg-white border rounded-2xl divide-y">
306+
307+
{documents.slice(0, 3).map((doc: any) => (
308+
309+
<a
310+
key={doc.file_key}
311+
href={doc.file_url}
312+
target="_blank"
313+
className="flex items-center gap-3 p-4 hover:bg-slate-50 transition"
314+
>
315+
316+
<FileText size={18} className="text-blue-600" />
317+
318+
<span className="text-sm font-medium text-slate-800">
319+
{doc.file_name}
320+
</span>
321+
322+
</a>
323+
324+
))}
325+
326+
</div>
327+
328+
)}
329+
330+
</div>
331+
22332
</div>
23333
);
24334
}

0 commit comments

Comments
 (0)