Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
247 changes: 224 additions & 23 deletions client/src/pages/SurgeryPage.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// src/pages/SurgeryPage.jsx
import React, { useState } from 'react';
import axios from 'axios';
import { FaSpinner, FaCheckCircle, FaExclamationCircle, FaUpload } from 'react-icons/fa';
import styles from './SurgeryPage.module.css';

function SurgeryPage() {
Expand All @@ -13,28 +13,114 @@ function SurgeryPage() {
surgeryType: '',
prescription: null,
});

const [errors, setErrors] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitStatus, setSubmitStatus] = useState({ success: false, message: '' });
const [selectedFile, setSelectedFile] = useState(null);

const validateForm = () => {
const newErrors = {};

if (!formData.name.trim()) newErrors.name = 'Name is required';

if (!formData.email) {
newErrors.email = 'Email is required';
} else if (!/\S+@\S+\.\S+/.test(formData.email)) {
newErrors.email = 'Email is invalid';
}

if (!formData.phone) {
newErrors.phone = 'Phone number is required';
} else if (!/^\d{10}$/.test(formData.phone)) {
newErrors.phone = 'Phone number must be 10 digits';
}

if (!formData.doctor.trim()) newErrors.doctor = 'Doctor\'s name is required';
if (!formData.date) newErrors.date = 'Please select a date';
if (!selectedFile) newErrors.prescription = 'Please upload a prescription';

setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};

const handleFileChange = (e) => {
const file = e.target.files[0];
if (file) {
const validTypes = ['application/pdf', 'image/jpeg', 'image/png'];
const maxSize = 5 * 1024 * 1024; // 5MB

if (!validTypes.includes(file.type)) {
setErrors({
...errors,
prescription: 'Please upload a valid file type (PDF, JPG, or PNG)'
});
return;
}

if (file.size > maxSize) {
setErrors({
...errors,
prescription: 'File size should be less than 5MB'
});
return;
}

setSelectedFile(file);
setFormData({ ...formData, prescription: file });
setErrors({ ...errors, prescription: null });
}
};

const handleChange = (e) => {
if (e.target.name === 'prescription') {
setFormData({ ...formData, prescription: e.target.files[0] });
} else {
setFormData({ ...formData, [e.target.name]: e.target.value });
const { name, value } = e.target;
setFormData({
...formData,
[name]: value
});

// Clear error when user types
if (errors[name]) {
setErrors({
...errors,
[name]: null
});
}
};

const handleSubmit = async (e) => {
e.preventDefault();


if (!validateForm()) return;

setIsSubmitting(true);
setSubmitStatus({ success: false, message: '' });

const submissionData = new FormData();
for (let key in formData) {
submissionData.append(key, formData[key]);
}
Object.keys(formData).forEach(key => {
if (formData[key] !== null) {
submissionData.append(key, formData[key]);
}
});

try {
await axios.post(`${process.env.REACT_APP_API_URL}/api/surgery/book`, submissionData, {
headers: { 'Content-Type': 'multipart/form-data' },
const response = await axios.post(
`${process.env.REACT_APP_API_URL || 'http://localhost:5000'}/api/surgery/book`,
submissionData,
{
headers: {
'Content-Type': 'multipart/form-data',
'Authorization': `Bearer ${localStorage.getItem('token')}`
},
}
);

setSubmitStatus({
success: true,
message: 'Surgery appointment booked successfully! We will contact you soon.'
});
alert('Surgery appointment booked!');

// Reset form
setFormData({
name: '',
email: '',
Expand All @@ -44,24 +130,139 @@ function SurgeryPage() {
surgeryType: '',
prescription: null,
});
setSelectedFile(null);
document.getElementById('prescription-upload').value = '';

} catch (error) {
alert('Booking failed.');
console.error(error);
console.error('Booking failed:', error);
const errorMessage = error.response?.data?.error || 'Failed to book appointment. Please try again.';
setSubmitStatus({
success: false,
message: errorMessage
});
} finally {
setIsSubmitting(false);
}
};

return (
<div className={styles.surgeryContainer}>
<h1>Book a Surgery</h1>
<form className={styles.surgeryForm} onSubmit={handleSubmit}>
<input type="text" name="name" placeholder="Patient Name" value={formData.name} onChange={handleChange} required />
<input type="email" name="email" placeholder="Email" value={formData.email} onChange={handleChange} required />
<input type="tel" name="phone" placeholder="Phone Number" value={formData.phone} onChange={handleChange} required />
<input type="text" name="doctor" placeholder="Doctor's Name" value={formData.doctor} onChange={handleChange} required />
<input type="text" name="surgeryType" placeholder="Surgery Type (if known)" value={formData.surgeryType} onChange={handleChange} />
<input type="date" name="date" value={formData.date} onChange={handleChange} required />
<input type="file" name="prescription" onChange={handleChange} accept=".pdf,.jpg,.png" required />
<button type="submit">Book Surgery</button>

{submitStatus.message && (
<div className={`${styles.alert} ${submitStatus.success ? styles.success : styles.error}`}>
{submitStatus.success ? (
<FaCheckCircle className={styles.icon} />
) : (
<FaExclamationCircle className={styles.icon} />
)}
<span>{submitStatus.message}</span>
</div>
)}

<form className={styles.surgeryForm} onSubmit={handleSubmit} noValidate>
<div className={styles.formGroup}>
<input
type="text"
name="name"
placeholder="Patient Name"
value={formData.name}
onChange={handleChange}
className={errors.name ? styles.errorInput : ''}
/>
{errors.name && <span className={styles.errorText}>{errors.name}</span>}
</div>

<div className={styles.formGroup}>
<input
type="email"
name="email"
placeholder="Email Address"
value={formData.email}
onChange={handleChange}
className={errors.email ? styles.errorInput : ''}
/>
{errors.email && <span className={styles.errorText}>{errors.email}</span>}
</div>

<div className={styles.formGroup}>
<input
type="tel"
name="phone"
placeholder="Phone Number (10 digits)"
value={formData.phone}
onChange={handleChange}
className={errors.phone ? styles.errorInput : ''}
/>
{errors.phone && <span className={styles.errorText}>{errors.phone}</span>}
</div>

<div className={styles.formGroup}>
<input
type="text"
name="doctor"
placeholder="Doctor's Name"
value={formData.doctor}
onChange={handleChange}
className={errors.doctor ? styles.errorInput : ''}
/>
{errors.doctor && <span className={styles.errorText}>{errors.doctor}</span>}
</div>

<div className={styles.formGroup}>
<input
type="text"
name="surgeryType"
placeholder="Surgery Type (e.g., Appendectomy, Knee Replacement)"
value={formData.surgeryType}
onChange={handleChange}
/>
</div>

<div className={styles.formGroup}>
<input
type="date"
name="date"
value={formData.date}
onChange={handleChange}
min={new Date().toISOString().split('T')[0]}
className={errors.date ? styles.errorInput : ''}
/>
{errors.date && <span className={styles.errorText}>{errors.date}</span>}
</div>

<div className={`${styles.fileUpload} ${errors.prescription ? styles.errorUpload : ''}`}>
<label htmlFor="prescription-upload" className={styles.uploadLabel}>
<FaUpload className={styles.uploadIcon} />
{selectedFile ? selectedFile.name : 'Upload Prescription (PDF, JPG, PNG, max 5MB)'}
</label>
<input
id="prescription-upload"
type="file"
name="prescription"
onChange={handleFileChange}
accept=".pdf,.jpg,.jpeg,.png"
className={styles.fileInput}
/>
{errors.prescription && (
<span className={styles.errorText}>{errors.prescription}</span>
)}
</div>

<button
type="submit"
className={styles.submitButton}
disabled={isSubmitting}
>
{isSubmitting ? (
<>
<FaSpinner className={styles.spinner} />
Processing...
</>
) : (
'Book Surgery'
)}
</button>
</form>
</div>
);
Expand Down
Loading