467 lines
21 KiB
TypeScript
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's Build Something Great</h2>
|
|
<p className="desc">Partner with Canada'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;
|