473 lines
21 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"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;
}
const ContactPopup: React.FC<ContactPopupProps> = ({ isOpen, onClose }) => {
const [formData, setFormData] = useState({
name: "",
phone: "",
email: "",
businessName: "",
projectRequirement: "",
budgetRange: "",
});
const [formErrors, setFormErrors] = useState<any>({});
const [captchaToken, setCaptchaToken] = useState<string | null>(null);
const [alert, setAlert] = useState({ show: false, type: "", message: "" });
const [isSubmitting, setIsSubmitting] = useState(false);
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;
setIsSubmitting(true);
const emailData = {
...formData,
message: `Business: ${formData.businessName}<br />Budget: ${formData.budgetRange}<br /><br />Requirement: ${formData.projectRequirement}`,
to: "selvipalanikumarn@gmail.com",
senderName: "Metatroncube Contact Popup",
recaptchaToken: captchaToken,
};
try {
const res = await axios.post("https://mailserver.metatronnest.com/send", emailData, {
headers: { "Content-Type": "application/json" },
});
setAlert({
show: true,
type: "success",
message: res?.data?.message || "Message sent successfully!",
});
setFormData({
name: "",
phone: "",
email: "",
businessName: "",
projectRequirement: "",
budgetRange: "",
});
setCaptchaToken(null);
setFormErrors({});
// Close after delay
setTimeout(onClose, 2000);
} catch (error) {
console.error("❌ Error sending email:", error);
setAlert({
show: true,
type: "danger",
message: "Failed to send message. Please try again later.",
});
} finally {
setIsSubmitting(false);
}
};
useEffect(() => {
if (alert.show) {
const timer = setTimeout(() => {
setAlert((prev) => ({ ...prev, show: false }));
}, 5000);
return () => clearTimeout(timer);
}
}, [alert.show]);
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">Lets Discuss Your App Idea</h2>
<p className="desc">Fill out the form and our team will contact you within 24 hours.</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-x-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>
<h3 className="form-title">Start Your Project</h3>
{alert.show && (
<div className={`alert alert-${alert.type === 'danger' ? 'danger' : 'success'} mb-4`}>
{alert.message}
</div>
)}
<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" />
{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" />
{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" />
{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" />
{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">
<option value="">App Type</option>
<option value="Android">Android</option>
<option value=" iOS"> iOS</option>
<option value="Both">Both</option>
</select>
{formErrors.budgetRange && <small className="text-danger">{formErrors.budgetRange}</small>}
</div>
<div className="col-12">
<select name="budgetRange" value={formData.budgetRange} onChange={handleChange} className="form-input form-select">
<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"
></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={isSubmitting}>
{isSubmitting ? 'Sending...' : 'Submit & Get Free Proposal'} <i className="fa-solid fa-angle-right"></i>
</button>
</form>
</div>
</div>
</div>
<style jsx>{`
.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;
}
.desc {
font-size: 15px;
opacity: 0.9;
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;
opacity: 0.7;
font-size: 12px;
}
.text h5 {
margin: 0;
font-size: 15px;
}
.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;