source: frontend/src/pages/referrals/ReferralList.js@ d30d820

Last change on this file since d30d820 was d30d820, checked in by MBK <marija.karapandzova@…>, 4 months ago

Add pages and routing for medical recors, medical reports and referrals with api services

  • Property mode set to 100644
File size: 14.0 KB
Line 
1import React, { useState, useEffect } from 'react';
2import { referralService } from '../../services/referralService';
3import { patientService } from '../../services/patientService';
4import { doctorService } from '../../services/doctorService';
5import { medicalRecordService } from '../../services/medicalRecordService';
6import ErrorAlert from '../../components/ErrorAlert';
7import SuccessAlert from '../../components/SuccessAlert';
8
9function ReferralList() {
10 const user = JSON.parse(localStorage.getItem('user') || '{}');
11 const isDoctor = user.role === 'DOCTOR';
12
13 const [referrals, setReferrals] = useState([]);
14 const [doctors, setDoctors] = useState([]);
15 const [patients, setPatients] = useState([]);
16 const [error, setError] = useState(null);
17 const [success, setSuccess] = useState(null);
18 const [searchType, setSearchType] = useState('patient'); // 'patient', 'fromDoctor', 'toDoctor'
19 const [searchValue, setSearchValue] = useState('');
20 const [searched, setSearched] = useState(false);
21 const [loading, setLoading] = useState(false);
22
23 // For creating referral
24 const [showCreateForm, setShowCreateForm] = useState(false);
25 const getDefaultAppointmentDate = () => {
26 const tomorrow = new Date();
27 tomorrow.setDate(tomorrow.getDate() + 1);
28 return tomorrow.toISOString().split('T')[0];
29 };
30 const [formData, setFormData] = useState({
31 fromDoctorId: isDoctor ? (user.doctorId || '') : '',
32 toDoctorId: '',
33 patientId: '',
34 recordId: '',
35 reason: '',
36 referralDate: new Date().toISOString().split('T')[0],
37 appointmentDate: getDefaultAppointmentDate(),
38 appointmentTime: '14:00',
39 });
40
41 useEffect(() => {
42 loadDoctorsAndPatients();
43 }, []);
44
45 const loadDoctorsAndPatients = async () => {
46 try {
47 const [doctorsRes, patientsRes] = await Promise.all([
48 doctorService.getAllDoctors(),
49 patientService.getAllPatients(),
50 ]);
51 setDoctors(doctorsRes.data);
52 setPatients(patientsRes.data);
53 } catch (err) {
54 console.error('Error loading data:', err);
55 }
56 };
57
58 const handleSearch = async (e) => {
59 e.preventDefault();
60 setError(null);
61 setLoading(true);
62
63 try {
64 if (!searchValue.trim()) {
65 setError('Please enter a search value');
66 setLoading(false);
67 return;
68 }
69
70 let response;
71 if (searchType === 'patient') {
72 response = await referralService.getReferralsByPatient(searchValue);
73 } else if (searchType === 'fromDoctor') {
74 response = await referralService.getReferralsByFromDoctor(searchValue);
75 } else {
76 response = await referralService.getReferralsByToDoctor(searchValue);
77 }
78
79 setReferrals(Array.isArray(response.data) ? response.data : [response.data]);
80 setSearched(true);
81 } catch (err) {
82 setError('No referrals found');
83 setReferrals([]);
84 setSearched(true);
85 } finally {
86 setLoading(false);
87 }
88 };
89
90 const handleCreateReferral = async (e) => {
91 e.preventDefault();
92 setError(null);
93
94 try {
95 if (!formData.fromDoctorId || !formData.toDoctorId || !formData.patientId || !formData.reason || !formData.appointmentDate || !formData.appointmentTime) {
96 setError('Please fill in all required fields');
97 return;
98 }
99
100 // Get patient's medical record ID
101 const patientId = parseInt(formData.patientId);
102 const medicalRecordRes = await medicalRecordService.getMedicalRecordByPatientId(patientId);
103 const recordId = medicalRecordRes.data.recordId;
104
105 const referralData = {
106 medicalRecordId: recordId,
107 fromDoctorId: parseInt(formData.fromDoctorId),
108 toDoctorId: parseInt(formData.toDoctorId),
109 reason: formData.reason,
110 referralDate: formData.referralDate,
111 appointmentDate: formData.appointmentDate,
112 appointmentTime: formData.appointmentTime + ':00',
113 };
114
115 await referralService.createReferral(referralData);
116 setSuccess('Referral created successfully!');
117 setFormData({
118 fromDoctorId: '',
119 toDoctorId: '',
120 patientId: '',
121 recordId: '',
122 reason: '',
123 referralDate: new Date().toISOString().split('T')[0],
124 appointmentDate: getDefaultAppointmentDate(),
125 appointmentTime: '14:00',
126 });
127 setShowCreateForm(false);
128
129 // Refresh referrals list
130 setTimeout(() => {
131 setSearched(false);
132 setSearchValue('');
133 }, 1500);
134 } catch (err) {
135 setError(err.response?.data?.error || 'Failed to create referral');
136 }
137 };
138
139 const handleFormChange = (e) => {
140 const { name, value } = e.target;
141 setFormData(prev => ({
142 ...prev,
143 [name]: value
144 }));
145 };
146
147 return (
148 <div>
149 <h1 className="text-3xl font-bold mb-6" style={{ color: '#7c3aed' }}>Doctor Referrals</h1>
150
151 {error && <ErrorAlert message={error} onClose={() => setError(null)} />}
152 {success && <SuccessAlert message={success} onClose={() => setSuccess(null)} />}
153
154 {/* Create Referral Button */}
155 <div className="mb-6">
156 <button
157 onClick={() => setShowCreateForm(!showCreateForm)}
158 style={{
159 background: '#bfdbfe',
160 color: '#1e1035',
161 padding: '8px 24px',
162 borderRadius: '6px',
163 border: 'none',
164 cursor: 'pointer',
165 fontSize: '14px',
166 fontWeight: '400'
167 }}
168 onMouseEnter={(e) => e.currentTarget.style.background = '#93c5fd'}
169 onMouseLeave={(e) => e.currentTarget.style.background = '#bfdbfe'}
170 >
171 {showCreateForm ? 'Cancel' : 'Create New Referral'}
172 </button>
173 </div>
174
175 {/* Create Referral Form */}
176 {showCreateForm && (
177 <div className="bg-white rounded-lg shadow p-6 mb-6">
178 <h2 className="text-xl font-bold mb-4">Create New Referral</h2>
179 <form onSubmit={handleCreateReferral} className="space-y-4">
180 <div className="grid grid-cols-2 gap-4">
181 <div>
182 <label className="block text-sm font-semibold mb-2">From Doctor *</label>
183 {isDoctor ? (
184 <p className="px-4 py-2 bg-gray-100 rounded-lg text-gray-700">
185 Dr. {user.firstName} {user.lastName}
186 </p>
187 ) : (
188 <select
189 name="fromDoctorId"
190 value={formData.fromDoctorId}
191 onChange={handleFormChange}
192 className="w-full px-4 py-2 border rounded-lg"
193 required
194 >
195 <option value="">Select referring doctor</option>
196 {doctors.map(doctor => (
197 <option key={doctor.doctorId} value={doctor.doctorId}>
198 Dr. {doctor.firstName} {doctor.lastName} ({doctor.specialization.specializationName})
199 </option>
200 ))}
201 </select>
202 )}
203 </div>
204
205 <div>
206 <label className="block text-sm font-semibold mb-2">To Doctor *</label>
207 <select
208 name="toDoctorId"
209 value={formData.toDoctorId}
210 onChange={handleFormChange}
211 className="w-full px-4 py-2 border rounded-lg"
212 required
213 >
214 <option value="">Select receiving doctor</option>
215 {doctors.map(doctor => (
216 <option key={doctor.doctorId} value={doctor.doctorId}>
217 Dr. {doctor.firstName} {doctor.lastName} ({doctor.specialization.specializationName})
218 </option>
219 ))}
220 </select>
221 </div>
222
223 <div>
224 <label className="block text-sm font-semibold mb-2">Patient *</label>
225 <select
226 name="patientId"
227 value={formData.patientId}
228 onChange={handleFormChange}
229 className="w-full px-4 py-2 border rounded-lg"
230 required
231 >
232 <option value="">Select patient</option>
233 {patients.map(patient => (
234 <option key={patient.patientId} value={patient.patientId}>
235 {patient.firstName} {patient.lastName} ({patient.embg})
236 </option>
237 ))}
238 </select>
239 </div>
240
241 <div>
242 <label className="block text-sm font-semibold mb-2">Referral Date *</label>
243 <input
244 type="date"
245 name="referralDate"
246 value={formData.referralDate}
247 onChange={handleFormChange}
248 className="w-full px-4 py-2 border rounded-lg"
249 required
250 />
251 </div>
252
253 <div>
254 <label className="block text-sm font-semibold mb-2">Appointment Date *</label>
255 <input
256 type="date"
257 name="appointmentDate"
258 value={formData.appointmentDate}
259 onChange={handleFormChange}
260 className="w-full px-4 py-2 border rounded-lg"
261 required
262 />
263 </div>
264
265 <div>
266 <label className="block text-sm font-semibold mb-2">Appointment Time *</label>
267 <input
268 type="time"
269 name="appointmentTime"
270 value={formData.appointmentTime}
271 onChange={handleFormChange}
272 className="w-full px-4 py-2 border rounded-lg"
273 required
274 />
275 </div>
276 </div>
277
278 <div>
279 <label className="block text-sm font-semibold mb-2">Reason for Referral *</label>
280 <textarea
281 name="reason"
282 value={formData.reason}
283 onChange={handleFormChange}
284 placeholder="e.g., Requires specialist evaluation for suspected cardiac condition"
285 className="w-full px-4 py-2 border rounded-lg"
286 rows="3"
287 required
288 />
289 </div>
290
291 <button
292 type="submit"
293 className="bg-purple-600 text-white px-6 py-2 rounded hover:bg-purple-700"
294 >
295 Create Referral
296 </button>
297 </form>
298 </div>
299 )}
300
301 {/* Search Form */}
302 <div className="bg-white rounded-lg shadow p-6 mb-6">
303 <h2 className="text-xl font-bold mb-4">Search Referrals</h2>
304 <form onSubmit={handleSearch} className="space-y-4">
305 <div className="flex gap-4">
306 <div className="flex-1">
307 <label className="block text-sm font-semibold mb-2">Search By</label>
308 <select
309 value={searchType}
310 onChange={(e) => {
311 setSearchType(e.target.value);
312 setSearchValue('');
313 setSearched(false);
314 }}
315 className="w-full px-4 py-2 border rounded-lg"
316 >
317 <option value="patient">Patient ID</option>
318 <option value="fromDoctor">Referring Doctor ID</option>
319 <option value="toDoctor">Receiving Doctor ID</option>
320 </select>
321 </div>
322
323 <div className="flex-1">
324 <label className="block text-sm font-semibold mb-2">Enter ID</label>
325 <input
326 type="number"
327 value={searchValue}
328 onChange={(e) => setSearchValue(e.target.value)}
329 placeholder="Enter ID"
330 className="w-full px-4 py-2 border rounded-lg"
331 />
332 </div>
333
334 <div className="flex items-end">
335 <button
336 type="submit"
337 disabled={loading}
338 className="bg-purple-600 text-white px-8 py-2 rounded-full hover:bg-purple-700 disabled:bg-gray-400"
339 >
340 {loading ? 'Searching...' : 'Search'}
341 </button>
342 </div>
343 </div>
344 </form>
345 </div>
346
347 {/* Referrals List */}
348 {searched && referrals.length > 0 && (
349 <div className="bg-white rounded-lg shadow overflow-hidden">
350 <table className="w-full">
351 <thead className="bg-gray-100">
352 <tr>
353 <th className="px-6 py-3 text-left text-sm font-semibold">From Doctor</th>
354 <th className="px-6 py-3 text-left text-sm font-semibold">To Doctor</th>
355 <th className="px-6 py-3 text-left text-sm font-semibold">Patient</th>
356 <th className="px-6 py-3 text-left text-sm font-semibold">Reason</th>
357 <th className="px-6 py-3 text-left text-sm font-semibold">Referral Date</th>
358 <th className="px-6 py-3 text-left text-sm font-semibold">Appointment Date</th>
359 <th className="px-6 py-3 text-left text-sm font-semibold">Appointment Time</th>
360 </tr>
361 </thead>
362 <tbody>
363 {referrals.map(referral => (
364 <tr key={referral.referralId} className="border-t hover:bg-gray-50">
365 <td className="px-6 py-3">{referral.fromDoctorName}</td>
366 <td className="px-6 py-3">{referral.toDoctorName}</td>
367 <td className="px-6 py-3">{referral.patientName}</td>
368 <td className="px-6 py-3">{referral.reason}</td>
369 <td className="px-6 py-3">{referral.referralDate}</td>
370 <td className="px-6 py-3">{referral.appointmentDate}</td>
371 <td className="px-6 py-3">{referral.appointmentTime}</td>
372 </tr>
373 ))}
374 </tbody>
375 </table>
376 </div>
377 )}
378
379 {/* No results message */}
380 {searched && referrals.length === 0 && (
381 <div className="bg-blue-50 rounded-lg p-6 text-center">
382 <p className="text-gray-600">No referrals found</p>
383 </div>
384 )}
385 </div>
386 );
387}
388
389export default ReferralList;
Note: See TracBrowser for help on using the repository browser.