source: frontend/src/pages/patients/PatientList.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 3.6 KB
Line 
1import React, { useState, useEffect } from 'react';
2import { Link } from 'react-router-dom';
3import { patientService } from '../../services/patientService';
4import Loading from '../../components/Loading';
5import ErrorAlert from '../../components/ErrorAlert';
6
7function PatientList() {
8 const user = JSON.parse(localStorage.getItem('user') || '{}');
9 const isAdmin = user.role === 'ADMIN';
10 const [patients, setPatients] = useState([]);
11 const [loading, setLoading] = useState(true);
12 const [error, setError] = useState(null);
13 const [searchTerm, setSearchTerm] = useState('');
14
15 useEffect(() => {
16 fetchPatients();
17 }, []);
18
19 const fetchPatients = async () => {
20 try {
21 setLoading(true);
22 const response = await patientService.getAllPatients();
23 setPatients(response.data);
24 } catch (err) {
25 setError('Failed to fetch patients');
26 console.error(err);
27 } finally {
28 setLoading(false);
29 }
30 };
31
32 const filteredPatients = patients.filter(patient =>
33 patient.firstName.toLowerCase().includes(searchTerm.toLowerCase()) ||
34 patient.lastName.toLowerCase().includes(searchTerm.toLowerCase()) ||
35 patient.embg.includes(searchTerm)
36 );
37
38 if (loading) return <Loading />;
39
40 return (
41 <div>
42 <div className="flex justify-between items-center mb-6">
43 <h1 className="text-3xl font-bold" style={{ color: '#7c3aed' }}>Patients</h1>
44 {isAdmin && (
45 <Link to="/patients/new" style={{
46 display: 'inline-block',
47 background: '#bfdbfe',
48 color: '#1e1035',
49 padding: '8px 16px',
50 borderRadius: '6px',
51 textDecoration: 'none',
52 fontSize: '14px',
53 fontWeight: '400'
54 }} onMouseEnter={(e) => e.currentTarget.style.background = '#93c5fd'} onMouseLeave={(e) => e.currentTarget.style.background = '#bfdbfe'}>
55 Add Patient
56 </Link>
57 )}
58 </div>
59
60 {error && <ErrorAlert message={error} onClose={() => setError(null)} />}
61
62 <div className="mb-6">
63 <input
64 type="text"
65 placeholder="Search by name or EMBG..."
66 className="w-full px-4 py-2 border rounded-lg"
67 value={searchTerm}
68 onChange={(e) => setSearchTerm(e.target.value)}
69 />
70 </div>
71
72 <div className="bg-white rounded-lg shadow overflow-hidden">
73 <table className="w-full">
74 <thead className="bg-gray-100">
75 <tr>
76 <th className="px-6 py-3 text-left text-sm font-semibold">Name</th>
77 <th className="px-6 py-3 text-left text-sm font-semibold">EMBG</th>
78 <th className="px-6 py-3 text-left text-sm font-semibold">Email</th>
79 <th className="px-6 py-3 text-left text-sm font-semibold">Phone</th>
80 <th className="px-6 py-3 text-left text-sm font-semibold">Actions</th>
81 </tr>
82 </thead>
83 <tbody>
84 {filteredPatients.map(patient => (
85 <tr key={patient.patientId} className="border-t hover:bg-gray-50">
86 <td className="px-6 py-3">{patient.firstName} {patient.lastName}</td>
87 <td className="px-6 py-3">{patient.embg}</td>
88 <td className="px-6 py-3">{patient.emailAddress}</td>
89 <td className="px-6 py-3">{patient.phoneNumber}</td>
90 <td className="px-6 py-3">
91 <Link to={`/patients/${patient.patientId}`} className="text-purple-600 hover:underline">
92 View
93 </Link>
94 </td>
95 </tr>
96 ))}
97 </tbody>
98 </table>
99 </div>
100 </div>
101 );
102}
103
104export default PatientList;
Note: See TracBrowser for help on using the repository browser.