2026-03-03 21:33:01 +05:30

467 lines
21 KiB
TypeScript

"use client";
import React, { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
import ReCAPTCHA from "react-google-recaptcha";
import axios from "axios";
interface ContactPopupProps {
isOpen: boolean;
onClose: () => void;
}
import ContactStatus from '../../contact/ContactStatus';
interface ContactPopupProps {
isOpen: boolean;
onClose: () => void;
}
const ContactPopup: React.FC<ContactPopupProps> = ({ isOpen, onClose }) => {
const [status, setStatus] = useState<'idle' | 'submitting' | 'success' | 'error'>('idle');
const [formData, setFormData] = useState({
name: "",
phone: "",
email: "",
businessName: "",
projectRequirement: "",
budgetRange: "",
});
const [formErrors, setFormErrors] = useState<any>({});
const [captchaToken, setCaptchaToken] = useState<string | null>(null);
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
// Close on ESC key
useEffect(() => {
const handleEsc = (e: KeyboardEvent) => {
if (e.key === 'Escape') onClose();
};
window.addEventListener('keydown', handleEsc);
return () => window.removeEventListener('keydown', handleEsc);
}, [onClose]);
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
const { name, value } = e.target;
setFormData((prev) => ({ ...prev, [name]: value }));
};
const handleCaptchaChange = (token: string | null) => {
setCaptchaToken(token);
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
const errors: any = {};
if (!formData.name.trim()) errors.name = "Name is required.";
if (!formData.phone.trim()) errors.phone = "Phone is required.";
if (!formData.email.trim()) errors.email = "Email is required.";
if (!formData.businessName.trim()) errors.businessName = "Business name requested.";
if (!formData.projectRequirement.trim()) errors.projectRequirement = "Requirement details needed.";
if (!formData.budgetRange) errors.budgetRange = "Please select a budget range.";
// if (!captchaToken) errors.captcha = "Please verify the CAPTCHA.";
setFormErrors(errors);
if (Object.keys(errors).length > 0) return;
setStatus('submitting');
const emailData = {
...formData,
message: `Business: ${formData.businessName}<br />Budget: ${formData.budgetRange}<br /><br />Requirement: ${formData.projectRequirement}`,
to: "akashlucaas@gmail.com",
senderName: "Metatroncube Contact Popup",
recaptchaToken: captchaToken,
};
try {
await axios.post("https://mailserver.metatronnest.com/send", emailData, {
headers: { "Content-Type": "application/json" },
});
setStatus('success');
setFormData({
name: "",
phone: "",
email: "",
businessName: "",
projectRequirement: "",
budgetRange: "",
});
setCaptchaToken(null);
setFormErrors({});
} catch (error) {
console.error("❌ Error sending email:", error);
setStatus('error');
}
};
const handleCloseStatus = () => {
if (status === 'success') {
onClose();
setStatus('idle');
} else {
setStatus('idle');
}
};
if (!mounted || !isOpen) return null;
const modalContent = (
<div className={`contact-popup-overlay ${isOpen ? 'active' : ''}`} onClick={onClose}>
<div className="contact-popup-content" onClick={(e) => e.stopPropagation()}>
<div className="row g-0 h-100">
{/* Left Side: Info */}
<div className="col-lg-5 info-panel" style={{ color: '#fff', position: 'relative' }}>
<div style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', background: 'linear-gradient(135deg, #1a1f2b 0%, #3779b9 100%)', zIndex: 0 }}></div>
<div className="info-inner" style={{ position: 'relative', zIndex: 1 }}>
<h2 className="title">Let&apos;s Build Something Great</h2>
<p className="desc">Partner with Canada&apos;s leading web development agency to scale your business.</p>
<div className="contact-details">
<div className="detail-item">
<div className="icon"><i className="fa-solid fa-envelope"></i></div>
<div className="text">
<p>Email Us</p>
<h5>info@metatroncubesolutions.com</h5>
</div>
</div>
<div className="detail-item">
<div className="icon"><i className="fa-solid fa-phone"></i></div>
<div className="text">
<p>Call Us Free</p>
<h5><a href="tel:+16476797651" style={{ color: 'inherit', textDecoration: 'none' }}>+1-647-679-7651</a></h5>
</div>
</div>
</div>
<div className="social-links">
<a href="https://www.facebook.com/metatroncubecanada" target="_blank" rel="noopener noreferrer" className="social-icon"><i className="fa-brands fa-facebook-f"></i></a>
<a href="https://x.com/MetatroncubeDA" target="_blank" rel="noopener noreferrer" className="social-icon"><i className="fa-brands fa-twitter"></i></a>
<a href="https://www.linkedin.com/company/metatroncube-software-solutions/posts/?feedView=all" target="_blank" rel="noopener noreferrer" className="social-icon"><i className="fa-brands fa-linkedin-in"></i></a>
<a href="https://www.instagram.com/metatron_digitalagency" target="_blank" rel="noopener noreferrer" className="social-icon"><i className="fa-brands fa-instagram"></i></a>
<a href="https://www.youtube.com/@metatron_digitalagency" target="_blank" rel="noopener noreferrer" className="social-icon"><i className="fa-brands fa-youtube"></i></a>
</div>
</div>
</div>
{/* Right Side: Form */}
<div className="col-lg-7 form-panel">
<button onClick={onClose} className="close-btn">
<i className="fa-solid fa-xmark"></i>
</button>
{status === 'idle' || status === 'submitting' ? (
<>
<h3 className="form-title">Start Your Project</h3>
<form className="contact-form" onSubmit={handleSubmit}>
<div className="row g-3">
<div className="col-md-6">
<input type="text" name="name" placeholder="Full Name" value={formData.name} onChange={handleChange} className="form-input" disabled={status === 'submitting'} />
{formErrors.name && <small className="text-danger">{formErrors.name}</small>}
</div>
<div className="col-md-6">
<input type="email" name="email" placeholder="Email Address" value={formData.email} onChange={handleChange} className="form-input" disabled={status === 'submitting'} />
{formErrors.email && <small className="text-danger">{formErrors.email}</small>}
</div>
<div className="col-md-6">
<input type="text" name="phone" placeholder="Phone Number" value={formData.phone} onChange={handleChange} className="form-input" disabled={status === 'submitting'} />
{formErrors.phone && <small className="text-danger">{formErrors.phone}</small>}
</div>
<div className="col-md-6">
<input type="text" name="businessName" placeholder="Business Name" value={formData.businessName} onChange={handleChange} className="form-input" disabled={status === 'submitting'} />
{formErrors.businessName && <small className="text-danger">{formErrors.businessName}</small>}
</div>
<div className="col-12">
<select name="budgetRange" value={formData.budgetRange} onChange={handleChange} className="form-input form-select" disabled={status === 'submitting'}>
<option value="">Select Budget Range</option>
<option value="$1,000 - $5,000">$1,000 - $5,000</option>
<option value="$5,000 - $10,000">$5,000 - $10,000</option>
<option value="$10,000 - $25,000">$10,000 - $25,000</option>
<option value="$25,000+">$25,000+</option>
</select>
{formErrors.budgetRange && <small className="text-danger">{formErrors.budgetRange}</small>}
</div>
</div>
<textarea
name="projectRequirement"
placeholder="Your Project Requirements"
rows={3}
value={formData.projectRequirement}
onChange={handleChange}
className="form-textarea mt-3"
disabled={status === 'submitting'}
></textarea>
{formErrors.projectRequirement && <small className="text-danger">{formErrors.projectRequirement}</small>}
<div className="mt-3 g-recaptcha-container">
<div className="g-recaptcha">
<ReCAPTCHA
sitekey="6LekfpwrAAAAAOTwuP1d2gg-Fv9UEsAjE2gjOQJl"
onChange={handleCaptchaChange}
/>
</div>
{formErrors.captcha && <small className="text-danger d-block mt-1">{formErrors.captcha}</small>}
</div>
<button type="submit" className="vl-btn1 submit-btn" disabled={status === 'submitting'}>
{status === 'submitting' ? 'Sending...' : 'Submit & Get Free Proposal'} <i className="fa-solid fa-arrow-right"></i>
</button>
</form>
</>
) : (
<div className="status-wrapper">
<ContactStatus type={status as 'success' | 'error'} onClose={handleCloseStatus} />
</div>
)}
</div>
</div>
</div>
<style jsx>{`
.status-wrapper {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.contact-popup-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(2, 6, 11, 0.85);
backdrop-filter: blur(8px);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
padding: 15px;
opacity: 0;
visibility: hidden;
transition: all 0.4s cubic-bezier(0.165, 0.84, 0.44, 1);
}
.contact-popup-overlay.active {
opacity: 1;
visibility: visible;
}
.contact-popup-content {
background: #fff;
width: 100%;
max-width: 1000px;
max-height: 95vh;
border-radius: 20px;
overflow: hidden;
box-shadow: 0 40px 100px rgba(0,0,0,0.4);
position: relative;
display: flex;
flex-direction: column;
}
.info-panel {
padding: 50px;
display: flex;
flex-direction: column;
justify-content: center;
}
.info-inner {
position: relative;
z-index: 1;
}
.title {
font-size: 28px;
font-weight: 800;
margin-bottom: 15px;
line-height: 1.2;
color: #ffffff !important;
}
.desc {
font-size: 15px;
color: #ffffff !important;
line-height: 1.5;
}
.contact-details {
margin-top: 30px;
margin-bottom: 25px;
}
.detail-item {
display: flex;
align-items: center;
margin-bottom: 15px;
gap: 12px;
}
.icon {
width: 40px;
height: 40px;
border-radius: 50%;
background: rgba(255,255,255,0.1);
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
}
.text p {
margin: 0;
color: #ffffff !important;
font-size: 12px;
}
.text h5 {
margin: 0;
font-size: 15px;
color: #ffffff !important;
}
.social-links {
display: flex;
gap: 10px;
}
.social-icon {
width: 32px;
height: 32px;
border-radius: 50%;
background: rgba(255,255,255,0.1);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
transition: 0.3s;
font-size: 13px;
}
.social-icon:hover {
background: #fff;
color: #3779b9;
}
.form-panel {
padding: 40px 50px;
position: relative;
background: #fff;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: #3779b9 #f1f1f1;
}
.form-panel::-webkit-scrollbar { width: 6px; }
.form-panel::-webkit-scrollbar-track { background: #f1f1f1; }
.form-panel::-webkit-scrollbar-thumb { background: #3779b9; border-radius: 10px; }
.close-btn {
position: absolute;
top: 20px;
right: 20px;
background: #f3f4f6;
border: none;
width: 35px;
height: 35px;
border-radius: 50%;
font-size: 18px;
cursor: pointer;
color: #1a1f2b;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s;
z-index: 100;
}
.close-btn:hover {
background: #3779b9;
color: #fff;
transform: rotate(90deg);
}
.form-title {
font-size: 24px;
font-weight: 700;
margin-bottom: 20px;
color: #1a1f2b;
}
.form-input, .form-textarea, .form-select {
width: 100%;
padding: 10px 15px;
border-radius: 8px;
border: 1px solid #e2e8f0;
outline: none;
background: #f8fafc;
transition: 0.2s;
font-size: 13.5px;
}
.form-input:focus, .form-textarea:focus, .form-select:focus {
border-color: #3779b9;
background: #fff;
box-shadow: 0 0 0 3px rgba(55,121,185,0.1);
}
.form-textarea { resize: none; }
.submit-btn {
width: 100%;
border: none;
padding: 14px;
border-radius: 8px;
margin-top: 15px;
background: #3779b9;
color: #fff;
font-weight: 700;
font-size: 14px;
cursor: pointer;
transition: all 0.3s;
}
.submit-btn:hover:not(:disabled) {
background: #1a1f2b;
transform: translateY(-1px);
}
/* Mobile Optimizations */
@media (max-width: 991px) {
.info-panel { display: none; }
.form-panel { padding: 40px 30px; }
.contact-popup-content { max-width: 550px; }
}
@media (max-width: 575px) {
.contact-popup-overlay { padding: 10px; }
.contact-popup-content { border-radius: 15px; }
.form-panel { padding: 30px 20px; }
.form-title { font-size: 20px; margin-bottom: 15px; }
.form-input, .form-textarea, .form-select { font-size: 13px; padding: 8px 12px; }
/* Scale ReCAPTCHA for small screens */
.g-recaptcha {
transform: scale(0.85);
-webkit-transform: scale(0.85);
transform-origin: 0 0;
-webkit-transform-origin: 0 0;
}
}
@media (max-width: 375px) {
.form-panel { padding: 25px 15px; }
.g-recaptcha {
transform: scale(0.77);
-webkit-transform: scale(0.77);
}
}
@media (max-width: 320px) {
.form-panel { padding: 15px 10px; }
.form-title { font-size: 16px; margin-bottom: 8px; }
.form-input, .form-textarea, .form-select { font-size: 12px; padding: 6px 10px; }
.submit-btn { padding: 10px; font-size: 12px; margin-top: 10px; }
.row.g-3 { --bs-gutter-y: 0.5rem; --bs-gutter-x: 0.5rem; }
.mt-3 { margin-top: 0.5rem !important; }
.g-recaptcha {
transform: scale(0.68);
-webkit-transform: scale(0.68);
}
}
`}</style>
</div>
);
return typeof document !== 'undefined'
? createPortal(modalContent, document.body)
: null;
};
export default ContactPopup;