Skip to content

Commit b0e7d95

Browse files
committed
fix: improve contact form with better UX and direct email support
- Fix fullscreen positioning with proper fixed positioning - Remove subheaders and shorten titles to reduce content length - Create compact horizontal employment status selection UI - Replace vertical radio buttons with inline pill-style buttons - Reduce form height and improve space efficiency - Add EmailJS integration for direct email sending - Include fallback to mailto approach when EmailJS not configured - Fix JSX syntax errors and improve form structure - Optimize form layout for better mobile experience - Add environment variable support for EmailJS configuration
1 parent 738d7cd commit b0e7d95

File tree

1 file changed

+127
-108
lines changed

1 file changed

+127
-108
lines changed

src/components/ui/ContactForm.tsx

Lines changed: 127 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useState } from 'react';
44
import { motion, AnimatePresence } from 'framer-motion';
55
import { X, Send, User, Mail, MessageSquare, Briefcase, Linkedin, Building, Check, AlertCircle } from 'lucide-react';
6+
import emailjs from '@emailjs/browser';
67

78
interface ContactFormProps {
89
isOpen: boolean;
@@ -46,9 +47,44 @@ const ContactForm = ({ isOpen, onClose }: ContactFormProps) => {
4647
setError('');
4748

4849
try {
49-
// For now, we'll use the mailto approach since EmailJS requires setup
50-
// TODO: Set up EmailJS service for direct email sending
51-
const emailBody = `
50+
// Check if EmailJS is configured
51+
const emailjsPublicKey = process.env.NEXT_PUBLIC_EMAILJS_PUBLIC_KEY;
52+
53+
if (emailjsPublicKey && emailjsPublicKey !== 'YOUR_PUBLIC_KEY') {
54+
// Use EmailJS for direct email sending
55+
emailjs.init(emailjsPublicKey);
56+
57+
const templateParams = {
58+
from_name: formData.name,
59+
from_email: formData.email,
60+
occupation: formData.occupation,
61+
linkedin: formData.linkedin || 'Not provided',
62+
employment_status: formData.employmentStatus === 'yes' ? 'Yes, employed' : formData.employmentStatus === 'no' ? 'No, not employed' : 'Student',
63+
workplace: formData.employmentStatus === 'yes' ? formData.workplace : '',
64+
message: formData.discussion,
65+
to_email: 'max@buzzvil.com'
66+
};
67+
68+
const result = await emailjs.send(
69+
process.env.NEXT_PUBLIC_EMAILJS_SERVICE_ID!,
70+
process.env.NEXT_PUBLIC_EMAILJS_TEMPLATE_ID!,
71+
templateParams,
72+
emailjsPublicKey
73+
);
74+
75+
if (result.status === 200) {
76+
setIsSubmitted(true);
77+
setTimeout(() => {
78+
setIsSubmitted(false);
79+
onClose();
80+
resetForm();
81+
}, 2000);
82+
} else {
83+
throw new Error('Email sending failed');
84+
}
85+
} else {
86+
// Fallback to mailto approach
87+
const emailBody = `
5288
New Coffee Chat Request
5389
5490
=== About You ===
@@ -64,20 +100,21 @@ ${formData.employmentStatus === 'yes' ? `Current Workplace: ${formData.workplace
64100
=== Discussion Topic ===
65101
What would you like to discuss:
66102
${formData.discussion}
67-
`.trim();
103+
`.trim();
68104

69-
const mailtoLink = `mailto:max@buzzvil.com?subject=Coffee Chat Request from ${formData.name}&body=${encodeURIComponent(emailBody)}`;
70-
window.open(mailtoLink, '_blank');
71-
72-
setIsSubmitted(true);
73-
setTimeout(() => {
74-
setIsSubmitted(false);
75-
onClose();
76-
resetForm();
77-
}, 2000);
105+
const mailtoLink = `mailto:max@buzzvil.com?subject=Coffee Chat Request from ${formData.name}&body=${encodeURIComponent(emailBody)}`;
106+
window.open(mailtoLink, '_blank');
107+
108+
setIsSubmitted(true);
109+
setTimeout(() => {
110+
setIsSubmitted(false);
111+
onClose();
112+
resetForm();
113+
}, 2000);
114+
}
78115
} catch (error) {
79116
console.error('Error submitting form:', error);
80-
setError('Something went wrong. Please try again.');
117+
setError('Failed to send email. Please try again or contact us directly.');
81118
} finally {
82119
setIsSubmitting(false);
83120
}
@@ -104,37 +141,28 @@ ${formData.discussion}
104141
initial={{ opacity: 0 }}
105142
animate={{ opacity: 1 }}
106143
exit={{ opacity: 0 }}
107-
className="fixed inset-0 z-50 bg-background overflow-y-auto"
144+
className="fixed inset-0 z-50 bg-background"
145+
style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0 }}
108146
>
109147
{/* Header */}
110-
<div className="sticky top-0 z-10 bg-background/95 backdrop-blur-sm border-b border-border">
111-
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
112-
<div className="flex items-center justify-between py-4">
113-
<div>
114-
<h1 className="text-2xl sm:text-3xl font-bold text-foreground">Coffee Chat Request</h1>
115-
<p className="text-muted-foreground mt-1">Let&apos;s discuss design over coffee!</p>
116-
</div>
117-
<button
118-
onClick={onClose}
119-
className="p-2 rounded-lg hover:bg-muted/50 transition-colors"
120-
>
121-
<X className="w-6 h-6 text-muted-foreground" />
122-
</button>
123-
</div>
124-
</div>
148+
<div className="flex items-center justify-between p-4 border-b border-border">
149+
<h1 className="text-xl font-bold text-foreground">Coffee Chat Request</h1>
150+
<button
151+
onClick={onClose}
152+
className="p-2 rounded-lg hover:bg-muted/50 transition-colors"
153+
>
154+
<X className="w-5 h-5 text-muted-foreground" />
155+
</button>
125156
</div>
126157

127158
{/* Form */}
128-
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
129-
<form onSubmit={handleSubmit} className="space-y-12">
159+
<div className="flex-1 overflow-y-auto p-6">
160+
<form onSubmit={handleSubmit} className="space-y-8">
130161
{/* Section 1: About You */}
131-
<div className="space-y-6">
132-
<div className="border-l-4 border-primary pl-4">
133-
<h2 className="text-xl font-semibold text-foreground">Tell us a bit about you!</h2>
134-
<p className="text-muted-foreground mt-1">Help us get to know you better</p>
135-
</div>
162+
<div className="space-y-4">
163+
<h2 className="text-lg font-semibold text-foreground">About You</h2>
136164

137-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
165+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
138166
{/* Name */}
139167
<div>
140168
<label className="block text-sm font-medium text-foreground mb-2">
@@ -205,93 +233,84 @@ ${formData.discussion}
205233
</div>
206234

207235
{/* Section 2: Employment Status */}
208-
<div className="space-y-6">
209-
<div className="border-l-4 border-primary pl-4">
210-
<h2 className="text-xl font-semibold text-foreground">Are you currently employed?</h2>
211-
<p className="text-muted-foreground mt-1">This helps us understand your background</p>
212-
</div>
236+
<div className="space-y-4">
237+
<h2 className="text-lg font-semibold text-foreground">Employment Status</h2>
213238

214-
<div className="space-y-4">
215-
{/* Radio buttons */}
216-
<div className="space-y-3">
217-
<label className="flex items-center space-x-3 cursor-pointer p-3 rounded-lg hover:bg-muted/30 transition-colors">
218-
<input
219-
type="radio"
220-
name="employmentStatus"
221-
value="yes"
222-
checked={formData.employmentStatus === 'yes'}
223-
onChange={handleRadioChange}
224-
className="w-4 h-4 text-primary bg-muted/30 border-border focus:ring-primary"
225-
/>
226-
<span className="text-foreground font-medium">Yes</span>
227-
</label>
228-
229-
<label className="flex items-center space-x-3 cursor-pointer p-3 rounded-lg hover:bg-muted/30 transition-colors">
230-
<input
231-
type="radio"
232-
name="employmentStatus"
233-
value="no"
234-
checked={formData.employmentStatus === 'no'}
235-
onChange={handleRadioChange}
236-
className="w-4 h-4 text-primary bg-muted/30 border-border focus:ring-primary"
237-
/>
238-
<span className="text-foreground font-medium">No</span>
239-
</label>
240-
241-
<label className="flex items-center space-x-3 cursor-pointer p-3 rounded-lg hover:bg-muted/30 transition-colors">
242-
<input
243-
type="radio"
244-
name="employmentStatus"
245-
value="student"
246-
checked={formData.employmentStatus === 'student'}
247-
onChange={handleRadioChange}
248-
className="w-4 h-4 text-primary bg-muted/30 border-border focus:ring-primary"
249-
/>
250-
<span className="text-foreground font-medium">I am a student</span>
239+
<div className="flex flex-wrap gap-3">
240+
<label className="flex items-center space-x-2 cursor-pointer px-4 py-2 rounded-lg border border-border hover:bg-muted/30 transition-colors">
241+
<input
242+
type="radio"
243+
name="employmentStatus"
244+
value="yes"
245+
checked={formData.employmentStatus === 'yes'}
246+
onChange={handleRadioChange}
247+
className="w-4 h-4 text-primary bg-muted/30 border-border focus:ring-primary"
248+
/>
249+
<span className="text-sm font-medium">Yes</span>
250+
</label>
251+
252+
<label className="flex items-center space-x-2 cursor-pointer px-4 py-2 rounded-lg border border-border hover:bg-muted/30 transition-colors">
253+
<input
254+
type="radio"
255+
name="employmentStatus"
256+
value="no"
257+
checked={formData.employmentStatus === 'no'}
258+
onChange={handleRadioChange}
259+
className="w-4 h-4 text-primary bg-muted/30 border-border focus:ring-primary"
260+
/>
261+
<span className="text-sm font-medium">No</span>
262+
</label>
263+
264+
<label className="flex items-center space-x-2 cursor-pointer px-4 py-2 rounded-lg border border-border hover:bg-muted/30 transition-colors">
265+
<input
266+
type="radio"
267+
name="employmentStatus"
268+
value="student"
269+
checked={formData.employmentStatus === 'student'}
270+
onChange={handleRadioChange}
271+
className="w-4 h-4 text-primary bg-muted/30 border-border focus:ring-primary"
272+
/>
273+
<span className="text-sm font-medium">Student</span>
274+
</label>
275+
</div>
276+
277+
{/* Workplace Input - only show if employed */}
278+
{formData.employmentStatus === 'yes' && (
279+
<div>
280+
<label className="block text-sm font-medium text-foreground mb-2">
281+
<Building className="w-4 h-4 inline mr-2" />
282+
What is your current workplace? *
251283
</label>
284+
<input
285+
type="text"
286+
name="workplace"
287+
value={formData.workplace}
288+
onChange={handleInputChange}
289+
required
290+
className="w-full px-4 py-3 bg-muted/30 border border-border rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent transition-all"
291+
placeholder="Your current company or organization"
292+
/>
252293
</div>
253-
254-
{/* Workplace Input - only show if employed */}
255-
{formData.employmentStatus === 'yes' && (
256-
<div>
257-
<label className="block text-sm font-medium text-foreground mb-2">
258-
<Building className="w-4 h-4 inline mr-2" />
259-
What is your current workplace? *
260-
</label>
261-
<input
262-
type="text"
263-
name="workplace"
264-
value={formData.workplace}
265-
onChange={handleInputChange}
266-
required
267-
className="w-full px-4 py-3 bg-muted/30 border border-border rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent transition-all"
268-
placeholder="Your current company or organization"
269-
/>
270-
</div>
271-
)}
272-
</div>
294+
)}
273295
</div>
274296

275297
{/* Section 3: Discussion Topic */}
276-
<div className="space-y-6">
277-
<div className="border-l-4 border-primary pl-4">
278-
<h2 className="text-xl font-semibold text-foreground">What would you like to discuss with us?</h2>
279-
<p className="text-muted-foreground mt-1">Tell us what&apos;s on your mind</p>
280-
</div>
298+
<div className="space-y-4">
299+
<h2 className="text-lg font-semibold text-foreground">Discussion Topic</h2>
281300

282301
<div>
283302
<label className="block text-sm font-medium text-foreground mb-2">
284303
<MessageSquare className="w-4 h-4 inline mr-2" />
285-
Your message *
304+
What would you like to discuss? *
286305
</label>
287306
<textarea
288307
name="discussion"
289308
value={formData.discussion}
290309
onChange={handleInputChange}
291310
required
292-
rows={4}
311+
rows={3}
293312
className="w-full px-4 py-3 bg-muted/30 border border-border rounded-lg focus:ring-2 focus:ring-primary focus:border-transparent transition-all resize-none"
294-
placeholder="What would you like to discuss? Any specific topics, questions, or areas of interest?"
313+
placeholder="Tell us what you'd like to discuss..."
295314
/>
296315
</div>
297316
</div>

0 commit comments

Comments
 (0)