Skip to content

Commit 9b337dc

Browse files
authored
Merge pull request #49 from rafiattrach/fix/emailjs-contact-form
Replace Formspree with EmailJS for contact form
2 parents aa5655f + 5209359 commit 9b337dc

File tree

3 files changed

+61
-99
lines changed

3 files changed

+61
-99
lines changed

webapp/package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webapp/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"private": true,
55
"homepage": "https://rafiattrach.github.io/m3",
66
"dependencies": {
7+
"@emailjs/browser": "^4.4.1",
78
"@testing-library/dom": "^10.4.0",
89
"@testing-library/jest-dom": "^6.6.3",
910
"@testing-library/react": "^16.3.0",

webapp/src/components/Contact.js

Lines changed: 50 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,21 @@
11
import React, { useState } from 'react';
2+
import emailjs from '@emailjs/browser';
23

34
const Contact = () => {
4-
// Configuration for multiple emails and form IDs
5-
const getContactConfig = () => {
6-
// Parse comma-separated lists from environment variables
7-
const emailList = process.env.REACT_APP_CONTACT_EMAILS
8-
? process.env.REACT_APP_CONTACT_EMAILS.split(',').map(email => email.trim())
9-
: (process.env.REACT_APP_CONTACT_EMAIL ? [process.env.REACT_APP_CONTACT_EMAIL] : ['[email protected]']);
10-
11-
const formIdList = process.env.REACT_APP_FORMSPREE_FORM_IDS
12-
? process.env.REACT_APP_FORMSPREE_FORM_IDS.split(',').map(id => id.trim())
13-
: (process.env.REACT_APP_FORMSPREE_FORM_ID ? [process.env.REACT_APP_FORMSPREE_FORM_ID] : ['YOUR_FORM_ID']);
14-
15-
return {
16-
emails: emailList,
17-
formIds: formIdList
18-
};
5+
// EmailJS configuration with your actual credentials
6+
const EMAILJS_CONFIG = {
7+
serviceId: 'm3_contact_service',
8+
templateId: 'template_sn5rm19',
9+
publicKey: 'aUrTfsE6oJtpIe1ac'
1910
};
2011

21-
// Development warnings for missing configuration
22-
if (process.env.NODE_ENV === 'development') {
23-
const config = getContactConfig();
24-
25-
if (config.formIds.length === 0 || config.formIds.some(id => !id || id === 'YOUR_FORM_ID')) {
26-
console.warn('⚠️ Contact forms not configured: Please set REACT_APP_FORMSPREE_FORM_IDS (comma-separated) in webapp/.env');
27-
}
28-
29-
if (config.emails.length === 0 || config.emails.some(email => !email || email.includes('@example.com'))) {
30-
console.warn('⚠️ Contact emails not configured: Please set REACT_APP_CONTACT_EMAILS (comma-separated) in webapp/.env');
31-
}
32-
33-
console.log(`📧 Configured emails: ${config.emails.join(', ')}`);
34-
console.log(`📝 Configured form IDs: ${config.formIds.join(', ')}`);
35-
}
36-
3712
const [contactForm, setContactForm] = useState({
3813
email: '',
3914
inquiryType: 'hospital',
4015
message: ''
4116
});
4217
const [isSubmitting, setIsSubmitting] = useState(false);
43-
const [submitStatus, setSubmitStatus] = useState('');
18+
const [submitStatus, setSubmitStatus] = useState(null);
4419

4520
const handleInputChange = (e) => {
4621
const { name, value } = e.target;
@@ -53,74 +28,57 @@ const Contact = () => {
5328
const handleSubmit = async (e) => {
5429
e.preventDefault();
5530
setIsSubmitting(true);
56-
setSubmitStatus('');
31+
setSubmitStatus(null);
5732

5833
try {
59-
// Get configuration for multiple emails and form IDs
60-
const config = getContactConfig();
61-
62-
if (config.formIds.length === 0 || config.formIds.some(id => !id || id === 'YOUR_FORM_ID')) {
63-
throw new Error('Form service not configured. Please set REACT_APP_FORMSPREE_FORM_IDS in .env file.');
64-
}
65-
66-
// Submit to all configured form IDs simultaneously
67-
const submissionPromises = config.formIds.map(formId =>
68-
fetch(`https://formspree.io/f/${formId}`, {
69-
method: 'POST',
70-
headers: {
71-
'Content-Type': 'application/json',
72-
},
73-
body: JSON.stringify({
74-
email: contactForm.email,
75-
inquiryType: contactForm.inquiryType,
76-
message: contactForm.message,
77-
destinationEmails: config.emails.join(', '), // Include all destination emails for tracking
78-
subject: `M3 Contact: ${contactForm.inquiryType === 'hospital' ? 'Hospital/EHR MCP Request' :
79-
contactForm.inquiryType === 'suggestions' ? 'Suggestions' : 'General Contact'}`
80-
}),
81-
})
34+
// Prepare template parameters
35+
const templateParams = {
36+
user_email: contactForm.email,
37+
user_name: contactForm.email.split('@')[0], // Extract name from email
38+
inquiry_type: contactForm.inquiryType,
39+
message: contactForm.message || 'No additional message provided',
40+
inquiry_type_label: contactForm.inquiryType === 'hospital' ? 'Hospital/EHR MCP Request' :
41+
contactForm.inquiryType === 'suggestions' ? 'Suggestions & Feedback' : 'General Contact',
42+
timestamp: new Date().toLocaleString()
43+
};
44+
45+
// Send email using EmailJS
46+
const response = await emailjs.send(
47+
EMAILJS_CONFIG.serviceId,
48+
EMAILJS_CONFIG.templateId,
49+
templateParams,
50+
EMAILJS_CONFIG.publicKey
8251
);
8352

84-
// Wait for all submissions to complete
85-
const responses = await Promise.allSettled(submissionPromises);
86-
87-
// Check if at least one submission was successful
88-
const hasSuccessfulSubmission = responses.some(result =>
89-
result.status === 'fulfilled' && result.value.ok
90-
);
53+
console.log('Email sent successfully:', response);
54+
setSubmitStatus({ type: 'success', message: 'Message sent successfully! We\'ll get back to you soon.' });
55+
setContactForm({ email: '', inquiryType: 'hospital', message: '' });
9156

92-
if (hasSuccessfulSubmission) {
93-
setSubmitStatus('success');
94-
setContactForm({ email: '', inquiryType: 'hospital', message: '' });
95-
96-
// Log any failed submissions for debugging
97-
const failedSubmissions = responses.filter(result =>
98-
result.status === 'rejected' || (result.status === 'fulfilled' && !result.value.ok)
99-
);
100-
101-
if (failedSubmissions.length > 0) {
102-
console.warn(`${failedSubmissions.length} of ${config.formIds.length} form submissions failed`);
103-
}
104-
} else {
105-
throw new Error('All form submissions failed');
106-
}
10757
} catch (error) {
108-
console.error('Error submitting form:', error);
58+
console.error('Error sending email:', error);
10959
setSubmitStatus('error');
60+
// Store the specific error message for display
61+
setSubmitStatus({ type: 'error', message: getErrorMessage(error) });
11062
} finally {
11163
setIsSubmitting(false);
11264
}
11365
};
11466

115-
const handleMailtoFallback = () => {
116-
// Use all configured emails
117-
const config = getContactConfig();
118-
const emailList = config.emails.join(',');
119-
120-
const subject = `M3 Contact: ${contactForm.inquiryType === 'hospital' ? 'Hospital/EHR MCP Request' :
121-
contactForm.inquiryType === 'suggestions' ? 'Suggestions' : 'General Contact'}`;
122-
const body = `Email: ${contactForm.email}%0D%0A%0D%0AMessage: ${contactForm.message}`;
123-
window.open(`mailto:${emailList}?subject=${encodeURIComponent(subject)}&body=${body}`);
67+
const getErrorMessage = (error) => {
68+
// Handle different types of errors
69+
if (error.message?.includes('rate limit') || error.status === 429) {
70+
return 'Too many emails sent recently. Please try again in a few minutes.';
71+
}
72+
if (error.message?.includes('invalid email') || error.status === 400) {
73+
return 'Please check your email address and try again.';
74+
}
75+
if (error.message?.includes('network') || !navigator.onLine) {
76+
return 'Network error. Please check your internet connection and try again.';
77+
}
78+
if (error.status === 403) {
79+
return 'Service temporarily unavailable. Please try again later.';
80+
}
81+
return 'Failed to send message. Please try again later.';
12482
};
12583

12684
return (
@@ -355,22 +313,15 @@ const Contact = () => {
355313
</button>
356314
</div>
357315

358-
{submitStatus === 'success' && (
316+
{submitStatus?.type === 'success' && (
359317
<div className="status-message status-success">
360-
Message sent successfully! We'll get back to you soon.
318+
{submitStatus.message}
361319
</div>
362320
)}
363321

364-
{submitStatus === 'error' && (
322+
{submitStatus?.type === 'error' && (
365323
<div className="status-message status-error">
366-
❌ Failed to send message. Please try again or{' '}
367-
<button
368-
type="button"
369-
onClick={handleMailtoFallback}
370-
style={{ background: 'none', border: 'none', color: 'inherit', textDecoration: 'underline', cursor: 'pointer' }}
371-
>
372-
send via email
373-
</button>.
324+
{submitStatus.message}
374325
</div>
375326
)}
376327
</form>

0 commit comments

Comments
 (0)