source: frontend/src/pages/appointments/AppointmentForm.js@ 20468d3

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

Add pages and routing for patients, doctors, departments and appointments with api services

  • Property mode set to 100644
File size: 6.1 KB
Line 
1import React, { useState, useEffect } from 'react';
2import { useNavigate } from 'react-router-dom';
3import { appointmentService } from '../../services/appointmentService';
4import { patientService } from '../../services/patientService';
5import { doctorService } from '../../services/doctorService';
6import ErrorAlert from '../../components/ErrorAlert';
7import SuccessAlert from '../../components/SuccessAlert';
8
9function AppointmentForm() {
10 const navigate = useNavigate();
11 const user = JSON.parse(localStorage.getItem('user') || '{}');
12 const isPatient = user.role === 'PATIENT';
13 const isDoctor = user.role === 'DOCTOR';
14
15 const [formData, setFormData] = useState({
16 patientId: isPatient ? (user.patientId || '') : '',
17 doctorId: isDoctor ? (user.doctorId || '') : '',
18 appointmentDate: '',
19 appointmentTime: '',
20 });
21 const [patients, setPatients] = useState([]);
22 const [doctors, setDoctors] = useState([]);
23 const [error, setError] = useState(null);
24 const [success, setSuccess] = useState(null);
25 const [loading, setLoading] = useState(false);
26
27 useEffect(() => {
28 fetchData();
29 }, []);
30
31 const fetchData = async () => {
32 try {
33 // For patients, we don't need to fetch all patients
34 if (!isPatient) {
35 const patientsRes = await patientService.getAllPatients();
36 setPatients(patientsRes.data);
37 }
38
39 const doctorsRes = await doctorService.getAllDoctors();
40 setDoctors(doctorsRes.data);
41 } catch (err) {
42 setError('Failed to fetch doctors');
43 }
44 };
45
46 const handleChange = (e) => {
47 const { name, value } = e.target;
48 setFormData(prev => ({
49 ...prev,
50 [name]: value
51 }));
52 };
53
54 const handleSubmit = async (e) => {
55 e.preventDefault();
56
57 if (!formData.patientId || !formData.doctorId || !formData.appointmentDate || !formData.appointmentTime) {
58 setError('Please fill in all required fields');
59 return;
60 }
61
62 try {
63 setLoading(true);
64 await appointmentService.createAppointment({
65 patientId: parseInt(formData.patientId),
66 doctorId: parseInt(formData.doctorId),
67 appointmentDate: formData.appointmentDate,
68 appointmentTime: formData.appointmentTime,
69 });
70 setSuccess('Appointment created successfully!');
71 setTimeout(() => navigate('/appointments'), 1500);
72 } catch (err) {
73 setError(err.response?.data?.error || 'Failed to create appointment');
74 } finally {
75 setLoading(false);
76 }
77 };
78
79 return (
80 <div className="max-w-2xl mx-auto">
81 <h1 className="text-3xl font-bold mb-6">Create Appointment</h1>
82
83 {error && <ErrorAlert message={error} onClose={() => setError(null)} />}
84 {success && <SuccessAlert message={success} onClose={() => setSuccess(null)} />}
85
86 <form onSubmit={handleSubmit} className="bg-white rounded-lg shadow p-6 space-y-4">
87 {isPatient ? (
88 <div className="bg-blue-50 rounded-lg p-4 mb-4">
89 <p className="text-sm text-gray-700">
90 <strong>Patient:</strong> {user.firstName} {user.lastName} ({user.username})
91 </p>
92 </div>
93 ) : (
94 <div>
95 <label className="block text-sm font-semibold mb-2">Patient *</label>
96 <select
97 name="patientId"
98 value={formData.patientId}
99 onChange={handleChange}
100 className="w-full px-4 py-2 border rounded-lg"
101 required
102 >
103 <option value="">Select Patient</option>
104 {patients.map(patient => (
105 <option key={patient.patientId} value={patient.patientId}>
106 {patient.firstName} {patient.lastName} ({patient.embg})
107 </option>
108 ))}
109 </select>
110 </div>
111 )}
112
113 {isDoctor ? (
114 <div>
115 <label className="block text-sm font-semibold mb-2">Doctor</label>
116 <p className="px-4 py-2 bg-gray-100 rounded-lg text-gray-700">
117 Dr. {user.firstName} {user.lastName}
118 </p>
119 </div>
120 ) : (
121 <div>
122 <label className="block text-sm font-semibold mb-2">Doctor *</label>
123 <select
124 name="doctorId"
125 value={formData.doctorId}
126 onChange={handleChange}
127 className="w-full px-4 py-2 border rounded-lg"
128 required
129 >
130 <option value="">Select Doctor</option>
131 {doctors.map(doctor => (
132 <option key={doctor.doctorId} value={doctor.doctorId}>
133 Dr. {doctor.firstName} {doctor.lastName}
134 </option>
135 ))}
136 </select>
137 </div>
138 )}
139
140 <div className="grid grid-cols-2 gap-4">
141 <div>
142 <label className="block text-sm font-semibold mb-2">Appointment Date *</label>
143 <input
144 type="date"
145 name="appointmentDate"
146 value={formData.appointmentDate}
147 onChange={handleChange}
148 className="w-full px-4 py-2 border rounded-lg"
149 required
150 />
151 </div>
152 <div>
153 <label className="block text-sm font-semibold mb-2">Appointment Time *</label>
154 <input
155 type="time"
156 name="appointmentTime"
157 value={formData.appointmentTime}
158 onChange={handleChange}
159 className="w-full px-4 py-2 border rounded-lg"
160 required
161 />
162 </div>
163 </div>
164
165 <div className="flex gap-4 pt-4">
166 <button
167 type="submit"
168 disabled={loading}
169 className="bg-purple-600 text-white px-6 py-2 rounded hover:bg-purple-700 disabled:opacity-50"
170 >
171 {loading ? 'Creating...' : 'Create Appointment'}
172 </button>
173 <button
174 type="button"
175 onClick={() => navigate('/appointments')}
176 className="bg-gray-300 text-gray-700 px-6 py-2 rounded hover:bg-gray-400"
177 >
178 Cancel
179 </button>
180 </div>
181 </form>
182 </div>
183 );
184}
185
186export default AppointmentForm;
Note: See TracBrowser for help on using the repository browser.