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

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

Fix frontend appearance

  • Property mode set to 100644
File size: 6.5 KB
Line 
1import React, { useState, useEffect } from 'react';
2import { useNavigate, useParams } from 'react-router-dom';
3import { patientService } from '../../services/patientService';
4import ErrorAlert from '../../components/ErrorAlert';
5import SuccessAlert from '../../components/SuccessAlert';
6
7function PatientForm() {
8 const { id } = useParams();
9 const navigate = useNavigate();
10 const [formData, setFormData] = useState({
11 firstName: '',
12 lastName: '',
13 emailAddress: '',
14 embg: '',
15 phoneNumber: '',
16 dateOfBirth: '',
17 gender: '',
18 bloodType: '',
19 });
20 const [error, setError] = useState(null);
21 const [success, setSuccess] = useState(null);
22 const [loading, setLoading] = useState(false);
23
24 useEffect(() => {
25 if (id) {
26 const fetchPatient = async () => {
27 try {
28 setLoading(true);
29 const response = await patientService.getPatientById(id);
30 setFormData(response.data);
31 } catch (err) {
32 setError('Failed to fetch patient');
33 } finally {
34 setLoading(false);
35 }
36 };
37
38 fetchPatient();
39 }
40 }, [id]);
41
42 const handleChange = (e) => {
43 const { name, value } = e.target;
44 setFormData(prev => ({
45 ...prev,
46 [name]: value
47 }));
48 };
49
50 const handleSubmit = async (e) => {
51 e.preventDefault();
52
53 if (!formData.firstName || !formData.lastName || !formData.embg) {
54 setError('Please fill in all required fields');
55 return;
56 }
57
58 try {
59 setLoading(true);
60 if (id) {
61 await patientService.updatePatient(id, formData);
62 setSuccess('Patient updated successfully!');
63 } else {
64 await patientService.createPatient(formData);
65 setSuccess('Patient created successfully!');
66 }
67 setTimeout(() => navigate('/patients'), 1500);
68 } catch (err) {
69 setError(err.response?.data?.error || 'Failed to save patient');
70 } finally {
71 setLoading(false);
72 }
73 };
74
75 return (
76 <div className="max-w-2xl mx-auto">
77 <h1 className="text-3xl font-bold mb-6">
78 {id ? 'Edit Patient' : 'Add New Patient'}
79 </h1>
80
81 {error && <ErrorAlert message={error} onClose={() => setError(null)} />}
82 {success && <SuccessAlert message={success} onClose={() => setSuccess(null)} />}
83
84 <form onSubmit={handleSubmit} className="bg-white rounded-lg shadow p-6 space-y-4">
85 <div className="grid grid-cols-2 gap-4">
86 <div>
87 <label className="block text-sm font-semibold mb-2">First Name *</label>
88 <input
89 type="text"
90 name="firstName"
91 value={formData.firstName}
92 onChange={handleChange}
93 className="w-full px-4 py-2 border rounded-lg"
94 required
95 />
96 </div>
97 <div>
98 <label className="block text-sm font-semibold mb-2">Last Name *</label>
99 <input
100 type="text"
101 name="lastName"
102 value={formData.lastName}
103 onChange={handleChange}
104 className="w-full px-4 py-2 border rounded-lg"
105 required
106 />
107 </div>
108 </div>
109
110 <div>
111 <label className="block text-sm font-semibold mb-2">EMBG *</label>
112 <input
113 type="text"
114 name="embg"
115 value={formData.embg}
116 onChange={handleChange}
117 className="w-full px-4 py-2 border rounded-lg"
118 required
119 disabled={!!id}
120 />
121 </div>
122
123 <div>
124 <label className="block text-sm font-semibold mb-2">Email</label>
125 <input
126 type="email"
127 name="emailAddress"
128 value={formData.emailAddress}
129 onChange={handleChange}
130 className="w-full px-4 py-2 border rounded-lg"
131 />
132 </div>
133
134 <div className="grid grid-cols-2 gap-4">
135 <div>
136 <label className="block text-sm font-semibold mb-2">Phone</label>
137 <input
138 type="tel"
139 name="phoneNumber"
140 value={formData.phoneNumber}
141 onChange={handleChange}
142 className="w-full px-4 py-2 border rounded-lg"
143 />
144 </div>
145 <div>
146 <label className="block text-sm font-semibold mb-2">Date of Birth</label>
147 <input
148 type="date"
149 name="dateOfBirth"
150 value={formData.dateOfBirth}
151 onChange={handleChange}
152 className="w-full px-4 py-2 border rounded-lg"
153 />
154 </div>
155 </div>
156
157 <div className="grid grid-cols-2 gap-4">
158 <div>
159 <label className="block text-sm font-semibold mb-2">Gender</label>
160 <select
161 name="gender"
162 value={formData.gender}
163 onChange={handleChange}
164 className="w-full px-4 py-2 border rounded-lg"
165 >
166 <option value="">Select Gender</option>
167 <option value="MALE">Male</option>
168 <option value="FEMALE">Female</option>
169 <option value="OTHER">Other</option>
170 </select>
171 </div>
172 <div>
173 <label className="block text-sm font-semibold mb-2">Blood Type</label>
174 <select
175 name="bloodType"
176 value={formData.bloodType}
177 onChange={handleChange}
178 className="w-full px-4 py-2 border rounded-lg"
179 >
180 <option value="">Select Blood Type</option>
181 <option value="O_POSITIVE">O+</option>
182 <option value="O_NEGATIVE">O-</option>
183 <option value="A_POSITIVE">A+</option>
184 <option value="A_NEGATIVE">A-</option>
185 <option value="B_POSITIVE">B+</option>
186 <option value="B_NEGATIVE">B-</option>
187 <option value="AB_POSITIVE">AB+</option>
188 <option value="AB_NEGATIVE">AB-</option>
189 </select>
190 </div>
191 </div>
192
193 <div className="flex gap-4 pt-4">
194 <button
195 type="submit"
196 disabled={loading}
197 className="bg-purple-600 text-white px-6 py-2 rounded hover:bg-purple-700 disabled:opacity-50"
198 >
199 {loading ? 'Saving...' : 'Save Patient'}
200 </button>
201 <button
202 type="button"
203 onClick={() => navigate('/patients')}
204 className="bg-gray-300 text-gray-700 px-6 py-2 rounded hover:bg-gray-400"
205 >
206 Cancel
207 </button>
208 </div>
209 </form>
210 </div>
211 );
212}
213
214export default PatientForm;
Note: See TracBrowser for help on using the repository browser.