website open after 10 sec open popup for contact form submition
This commit is contained in:
parent
9c6b7b2de1
commit
e0fc5034ad
233
components/AutoPopup.js
Normal file
233
components/AutoPopup.js
Normal file
@ -0,0 +1,233 @@
|
||||
"use client";
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import SimpleReactValidator from "simple-react-validator";
|
||||
import ReCAPTCHA from "react-google-recaptcha";
|
||||
import axios from "axios";
|
||||
import { useTranslation } from "next-i18next";
|
||||
|
||||
export default function AutoPopup() {
|
||||
const [show, setShow] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setShow(true), 10000); // Show after 10s
|
||||
return () => clearTimeout(timer);
|
||||
}, []);
|
||||
|
||||
const { t } = useTranslation("contact");
|
||||
const subjectOptions = t("form.subjectOptions", { returnObjects: true });
|
||||
|
||||
const [forms, setForms] = useState({
|
||||
name: "",
|
||||
email: "",
|
||||
subject: "",
|
||||
phone: "",
|
||||
message: "",
|
||||
});
|
||||
|
||||
const [validator] = useState(
|
||||
new SimpleReactValidator({
|
||||
className: "errorMessage",
|
||||
})
|
||||
);
|
||||
|
||||
const recaptchaRef = useRef(null);
|
||||
const [recaptchaToken, setRecaptchaToken] = useState(null);
|
||||
|
||||
const RECAPTCHA_SITEKEY = "6Lc5wKUrAAAAAKqIviSUY2PsqLQ8Bq8CJJaHFA_f";
|
||||
|
||||
const changeHandler = (e) => {
|
||||
const { name, value } = e.target;
|
||||
setForms({ ...forms, [name]: value });
|
||||
|
||||
if (validator.allValid() && recaptchaToken) {
|
||||
validator.hideMessages();
|
||||
} else {
|
||||
validator.showMessages();
|
||||
}
|
||||
};
|
||||
|
||||
const handleRecaptcha = (token) => {
|
||||
setRecaptchaToken(token);
|
||||
if (validator.allValid() && token) {
|
||||
validator.hideMessages();
|
||||
}
|
||||
};
|
||||
|
||||
const submitHandler = async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (validator.allValid() && recaptchaToken) {
|
||||
validator.hideMessages();
|
||||
|
||||
const emailPayload = {
|
||||
name: forms.name,
|
||||
email: forms.email,
|
||||
phone: forms.phone,
|
||||
subject: forms.subject,
|
||||
message: `Subject: ${forms.subject}\n\nMessage:\n${forms.message}`,
|
||||
to: "info@janahanlaw.com",
|
||||
senderName: "Janahan Law",
|
||||
recaptchaToken: recaptchaToken,
|
||||
};
|
||||
|
||||
try {
|
||||
await axios.post("https://mailserver.metatronnest.com/send", emailPayload, {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
|
||||
alert(t("form.successMessage"));
|
||||
|
||||
setForms({
|
||||
name: "",
|
||||
email: "",
|
||||
subject: "",
|
||||
phone: "",
|
||||
message: "",
|
||||
});
|
||||
|
||||
validator.hideMessages();
|
||||
|
||||
if (recaptchaRef.current) {
|
||||
try {
|
||||
recaptchaRef.current.reset();
|
||||
} catch (err) { }
|
||||
}
|
||||
setRecaptchaToken(null);
|
||||
} catch (err) {
|
||||
alert(t("form.failedMessage"));
|
||||
}
|
||||
} else {
|
||||
validator.showMessages();
|
||||
setForms((prev) => ({ ...prev }));
|
||||
}
|
||||
};
|
||||
|
||||
if (!show) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
{/* Backdrop */}
|
||||
<div
|
||||
className="position-fixed top-0 start-0 w-100 h-100"
|
||||
style={{
|
||||
backgroundColor: "rgba(0,0,0,0.5)", // gray transparent background
|
||||
zIndex: 99, // below popup but above page
|
||||
}}
|
||||
onClick={() => setShow(false)} // click on backdrop closes modal
|
||||
></div>
|
||||
|
||||
{/* Popup */}
|
||||
<div
|
||||
className="position-fixed top-50 start-50 translate-middle w-100 px-3"
|
||||
style={{
|
||||
maxWidth: "600px", // limit on desktop
|
||||
zIndex: 10000,
|
||||
}}
|
||||
>
|
||||
<div className="card shadow-lg">
|
||||
<div className="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 className="mb-0">{t('contactInfo.pageTitle')}</h5>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-close"
|
||||
onClick={() => setShow(false)}
|
||||
></button>
|
||||
</div>
|
||||
<div className="card-body p-0">
|
||||
<div style={{ padding: "15px 10px 15px 20px" }}>
|
||||
<form onSubmit={submitHandler} className="contact-validation-active">
|
||||
<div className="row w-100">
|
||||
<div className="col-6">
|
||||
<input
|
||||
value={forms.name}
|
||||
type="text"
|
||||
name="name"
|
||||
onBlur={changeHandler}
|
||||
onChange={changeHandler}
|
||||
placeholder={t("form.namePlaceholder")}
|
||||
className="form-control mb-2"
|
||||
/>
|
||||
{validator.message("name", forms.name, "required|alpha_space")}
|
||||
</div>
|
||||
|
||||
<div className="col-6">
|
||||
<input
|
||||
value={forms.email}
|
||||
type="email"
|
||||
name="email"
|
||||
onBlur={changeHandler}
|
||||
onChange={changeHandler}
|
||||
placeholder={t("form.emailPlaceholder")}
|
||||
className="form-control mb-2"
|
||||
/>
|
||||
{validator.message("email", forms.email, "required|email")}
|
||||
</div>
|
||||
|
||||
<div className="col-6">
|
||||
<input
|
||||
value={forms.phone}
|
||||
type="phone"
|
||||
name="phone"
|
||||
onBlur={changeHandler}
|
||||
onChange={changeHandler}
|
||||
placeholder={t("form.phonePlaceholder")}
|
||||
className="form-control mb-2"
|
||||
/>
|
||||
{validator.message("phone", forms.phone, "required|phone")}
|
||||
</div>
|
||||
|
||||
<div className="col-6">
|
||||
<select
|
||||
onBlur={changeHandler}
|
||||
onChange={changeHandler}
|
||||
value={forms.subject}
|
||||
name="subject"
|
||||
className="form-select mb-2"
|
||||
>
|
||||
<option value="">{t("form.subjectPlaceholder")}</option>
|
||||
{Array.isArray(subjectOptions) &&
|
||||
subjectOptions.map((opt, idx) => (
|
||||
<option key={idx}>{opt}</option>
|
||||
))}
|
||||
</select>
|
||||
{validator.message("subject", forms.subject, "required")}
|
||||
</div>
|
||||
|
||||
<div className="col-12">
|
||||
<textarea
|
||||
onBlur={changeHandler}
|
||||
onChange={changeHandler}
|
||||
value={forms.message}
|
||||
name="message"
|
||||
placeholder={t("form.messagePlaceholder")}
|
||||
className="form-control mb-2"
|
||||
></textarea>
|
||||
{validator.message("message", forms.message, "required")}
|
||||
</div>
|
||||
|
||||
<div className="col-12 mb-2">
|
||||
<ReCAPTCHA
|
||||
ref={recaptchaRef}
|
||||
sitekey={RECAPTCHA_SITEKEY}
|
||||
onChange={handleRecaptcha}
|
||||
/>
|
||||
{!recaptchaToken && (
|
||||
<div className="errorMessage">
|
||||
{t("form.requiredMessages.recaptcha")}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" className="theme-btn w-100" >
|
||||
{t("form.submitButton")}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -57,8 +57,8 @@ const ContactForm = () => {
|
||||
phone: forms.phone,
|
||||
subject: forms.subject,
|
||||
message: `Subject: ${forms.subject}\n\nMessage:\n${forms.message}`,
|
||||
to: "your-receiving-email@example.com",
|
||||
senderName: "Website Contact Form",
|
||||
to: "info@janahanlaw.com",
|
||||
senderName: "Janahan Law",
|
||||
recaptchaToken: recaptchaToken,
|
||||
};
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ const HeaderTopbar = () => {
|
||||
{/* 🔹 Show only Spanish switch if current lang is English */}
|
||||
{i18n.language === 'en' && (
|
||||
<div>
|
||||
<div className="d-flex justify-content-center align-items-center gap-5 flex-wrap">
|
||||
<div className="d-flex justify-content-center align-items-center gap-1 gap-md-5 flex-wrap">
|
||||
<div className="text-center text-white">
|
||||
Haz clic en el botón para cambiar el idioma a <b>Español</b>.
|
||||
</div>
|
||||
@ -59,7 +59,7 @@ const HeaderTopbar = () => {
|
||||
{
|
||||
i18n.language === 'es' && (
|
||||
<div>
|
||||
<div className="d-flex justify-content-center align-items-center gap-5 flex-wrap">
|
||||
<div className="d-flex justify-content-center align-items-center gap-1 gap-md-5 flex-wrap">
|
||||
<div className="text-center text-white">
|
||||
Haz clic en el botón para cambiar el idioma a <b>Inglés</b>.
|
||||
</div>
|
||||
@ -77,7 +77,7 @@ const HeaderTopbar = () => {
|
||||
{/* 🔹 Show only English switch if current lang is Spanish */}
|
||||
{i18n.language === 'en' && (
|
||||
<div>
|
||||
<div className="d-flex justify-content-center align-items-center gap-5 flex-wrap">
|
||||
<div className="d-flex justify-content-center align-items-center gap-1 gap-md-5 flex-wrap">
|
||||
<div className="text-center text-white">
|
||||
Click the button to switch the language to <b>Spanish</b>.
|
||||
</div>
|
||||
@ -92,7 +92,7 @@ const HeaderTopbar = () => {
|
||||
)}
|
||||
{i18n.language === 'es' && (
|
||||
<div>
|
||||
<div className="d-flex justify-content-center align-items-center gap-5 flex-wrap">
|
||||
<div className="d-flex justify-content-center align-items-center gap-1 gap-md-5 flex-wrap">
|
||||
<div className="text-center text-white">
|
||||
Click the button to switch the language to <b>English</b>.
|
||||
</div>
|
||||
|
||||
@ -16,15 +16,17 @@ import Head from "next/head";
|
||||
|
||||
// Import appWithTranslation from next-i18next
|
||||
import { appWithTranslation } from 'next-i18next';
|
||||
import AutoPopup from "../components/AutoPopup";
|
||||
|
||||
function MyApp({ Component, pageProps }) {
|
||||
return (
|
||||
<div>
|
||||
<div className="position-relative">
|
||||
<Head>
|
||||
<title>Janahan Law - US Immigration Law</title>
|
||||
</Head>
|
||||
<Provider store={store}>
|
||||
<PersistGate loading={null} persistor={persistor}>
|
||||
<AutoPopup />
|
||||
<Component {...pageProps} />
|
||||
<ToastContainer />
|
||||
</PersistGate>
|
||||
|
||||
@ -50,7 +50,7 @@ export default AboutPage;
|
||||
export async function getStaticProps({ locale }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale, ['common', 'menu', 'ourStory', 'aboutService', 'aboutMission', 'aboutRacial', 'aboutDonor', 'footer', 'innerBanner'])), // Add 'home', 'footer', etc. if needed
|
||||
...(await serverSideTranslations(locale, ['common', 'menu', 'ourStory', 'aboutService', 'aboutMission', 'aboutRacial', 'aboutDonor', 'footer', 'innerBanner', 'contact'])), // Add 'home', 'footer', etc. if needed
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ export default AboutPage;
|
||||
export async function getStaticProps({ locale }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale, ['common', 'menu', 'innerBanner', 'ourMission', 'footer'])), // Add 'home', 'footer', etc. if needed
|
||||
...(await serverSideTranslations(locale, ['common', 'menu', 'innerBanner', 'ourMission', 'footer', 'contact'])), // Add 'home', 'footer', etc. if needed
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ export default AboutPage;
|
||||
export async function getStaticProps({ locale }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale, ['common', 'menu', 'innerBanner', 'racialJustice', 'footer'])), // Add 'home', 'footer', etc. if needed
|
||||
...(await serverSideTranslations(locale, ['common', 'menu', 'innerBanner', 'racialJustice', 'footer', 'contact'])), // Add 'home', 'footer', etc. if needed
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -96,7 +96,7 @@ export async function getStaticPaths() {
|
||||
export async function getStaticProps({ locale }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale, ['common', 'menu', 'blog', 'footer', 'innerBanner'])),
|
||||
...(await serverSideTranslations(locale, ['common', 'menu', 'blog', 'footer', 'innerBanner', 'contact'])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ export default BlogPage;
|
||||
export async function getStaticProps({ locale }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale, ['common', 'menu', 'innerBanner', 'blog', 'footer'])), // Add 'home', 'footer', etc. if needed
|
||||
...(await serverSideTranslations(locale, ['common', 'menu', 'innerBanner', 'blog', 'footer', 'contact'])), // Add 'home', 'footer', etc. if needed
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ export default HomePage;
|
||||
export async function getStaticProps({ locale }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale, ['common', 'menu', 'homeHero', 'home4Card', '(home)/homeAbout', '(home)/homeFeature', '(home)/testimonial', '(home)/homeCalltoAction', 'blog', 'footer', 'services'])), // Add 'home', 'footer', etc. if needed
|
||||
...(await serverSideTranslations(locale, ['common', 'menu', 'homeHero', 'home4Card', '(home)/homeAbout', '(home)/homeFeature', '(home)/testimonial', '(home)/homeCalltoAction', 'blog', 'footer', 'services', 'contact', 'innerBanner'])), // Add 'home', 'footer', etc. if needed
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@ export default OurApproach;
|
||||
export async function getStaticProps({ locale }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale, ['menu',"common","ourApproach","footer", 'innerBanner'])),
|
||||
...(await serverSideTranslations(locale, ['menu',"common","ourApproach","footer", 'innerBanner', 'contact'])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -117,7 +117,7 @@ export async function getStaticProps({ params, locale }) {
|
||||
return {
|
||||
props: {
|
||||
service,
|
||||
...(await serverSideTranslations(locale, ["common", "menu", "services", , 'footer'])),
|
||||
...(await serverSideTranslations(locale, ["common", "menu", "services", , 'footer', 'contact'])),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ export default Services;
|
||||
export async function getStaticProps({ locale }) {
|
||||
return {
|
||||
props: {
|
||||
...(await serverSideTranslations(locale, ['common', 'menu', 'services', 'footer'])), // Add 'home', 'footer', etc.
|
||||
...(await serverSideTranslations(locale, ['common', 'menu', 'services', 'footer', 'contact'])), // Add 'home', 'footer', etc.
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -5,7 +5,8 @@
|
||||
"callTitle": "Call Now",
|
||||
"phone": "+1 (305) 330-7413",
|
||||
"questionTitle": "Have Any Question?",
|
||||
"questionDesc": "We’re here to help with all your U.S. immigration and legal needs — contact Janahan Law for trusted guidance today."
|
||||
"questionDesc": "We’re here to help with all your U.S. immigration and legal needs — contact Janahan Law for trusted guidance today.",
|
||||
"pageTitle": "Contact Us"
|
||||
},
|
||||
"form": {
|
||||
"namePlaceholder": "Your Name",
|
||||
|
||||
@ -5,7 +5,8 @@
|
||||
"callTitle": "Llama ahora",
|
||||
"phone": "+1 (305) 330-7413",
|
||||
"questionTitle": "¿Tienes alguna pregunta?",
|
||||
"questionDesc": "Estamos aquí para ayudarte con todas tus necesidades legales y de inmigración en EE. UU. — contacta a Janahan Law para obtener orientación confiable hoy."
|
||||
"questionDesc": "Estamos aquí para ayudarte con todas tus necesidades legales y de inmigración en EE. UU. — contacta a Janahan Law para obtener orientación confiable hoy.",
|
||||
"pageTitle": "Contáctenos"
|
||||
},
|
||||
"form": {
|
||||
"namePlaceholder": "Tu Nombre",
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
.topbar {
|
||||
padding: 20px 0;
|
||||
border-bottom: 1px solid #D9D9D9;
|
||||
background-color: white;
|
||||
|
||||
.contact-info-wrap {
|
||||
display: flex;
|
||||
@ -961,6 +962,8 @@
|
||||
|
||||
|
||||
.wpo-site-header {
|
||||
background-color: white;
|
||||
|
||||
.navigation {
|
||||
background-color: transparent;
|
||||
margin-bottom: 0;
|
||||
|
||||
@ -228,3 +228,117 @@
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.form-field {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.errorMessage {
|
||||
color: red;
|
||||
font-size: 14px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
form input,
|
||||
form select,
|
||||
form textarea {
|
||||
background: transparent;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 0px;
|
||||
box-shadow: none !important;
|
||||
padding-left: 25px;
|
||||
border: 1px solid #ebebeb;
|
||||
color: #a9a9a9;
|
||||
|
||||
@include media-query(991px) {
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border-color: $theme-primary-color;
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
form textarea {
|
||||
height: 180px;
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
form {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
|
||||
@include placeholder-style(#9d9c9c, 15px, normal);
|
||||
|
||||
select {
|
||||
display: inline-block;
|
||||
color: #a9a9a9;
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
padding: 6px 25px;
|
||||
font-size: 15px;
|
||||
font-size: calc-rem-value(15);
|
||||
-webkit-appearance: none;
|
||||
-ms-appearance: none;
|
||||
-o-appearance: none;
|
||||
appearance: none;
|
||||
-moz-appearance: none;
|
||||
background: transparent url(/images/select-icon2.png) no-repeat calc(100% - 15px) center;
|
||||
position: relative;
|
||||
|
||||
&:focus {
|
||||
background: transparent url(/images/select-icon2.png) no-repeat calc(100% - 15px) center;
|
||||
}
|
||||
}
|
||||
|
||||
.submit-area {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 0;
|
||||
|
||||
@include media-query(767px) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.theme-btn {
|
||||
border-radius: 0px;
|
||||
font-family: $base-font;
|
||||
font-size: 16px;
|
||||
|
||||
&:after {
|
||||
border-radius: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
form>div {
|
||||
margin: 0 15px 25px;
|
||||
|
||||
@include media-query(600px) {
|
||||
width: calc(100% - 25px);
|
||||
}
|
||||
}
|
||||
|
||||
form .fullwidth {
|
||||
width: calc(100% - 25px);
|
||||
float: none;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
form>div>div {
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
||||
.popup-form {
|
||||
position: absolute;
|
||||
top: "20% !important;";
|
||||
right: "35% !important;";
|
||||
z-index: 10000 !important;
|
||||
width: "600px !important;";
|
||||
max-width: "100% !important;";
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user