corrections updated

This commit is contained in:
Selvi 2025-09-16 17:09:09 +05:30
commit 0441510e46
14 changed files with 451 additions and 57 deletions

View File

@ -20,7 +20,7 @@ export default function RootLayout({ children }) {
<html lang="en" className={`${poppins.variable}`}> <html lang="en" className={`${poppins.variable}`}>
<body> <body>
{children} {children}
<AutoPopup/> {/* <AutoPopup/> */}
</body> </body>
</html> </html>
); );

View File

@ -24,13 +24,13 @@ export default function Home() {
return ( return (
<> <>
<Layout headerStyle={2} footerStyle={2}> <Layout headerStyle={2} footerStyle={2}>
{/* <div className="d-none d-md-block"> */} <div className="d-none d-md-block">
<Banner /> <Banner />
{/* </div> */} </div>
{/*
<div className="d-block d-md-none"> <div className="d-block d-md-none">
<MobileBanner /> <MobileBanner />
</div> */} </div>
{/* <Features /> */} {/* <Features /> */}
<AboutSection /> <AboutSection />
{/* <ProcessSection /> */} {/* <ProcessSection /> */}

View File

@ -1,63 +1,327 @@
"use client"; "use client";
import React, { useState } from "react"; import React, { useState } from "react";
import ReCAPTCHA from "react-google-recaptcha";
import axios from "axios";
export default function ContactFloat() { export default function ContactFloat() {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [showChat, setShowChat] = useState(false);
/** 3 extra contact icons */ /** Contact actions */
const extraIcons = [ const extraIcons = [
{ {
href: "mailto:info@example.com", href: "mailto:bloor@rapharehab.ca",
src: "/assets/images/icons/mail.png", src: "/assets/images/icons/mail.png",
label: "Mail", label: "Mail",
offset: 30, // main button bottom(60) + 20 = 80
}, },
{ {
href: "https://wa.me/1234567890", href: "tel:647-722-3434",
src: "/assets/images/icons/whatsapp.png", src: "/assets/images/icons/call.png",
label: "WhatsApp", label: "Call",
offset: 90, // 60 + 90
}, },
{ {
href: "sms:1234567890", action: () => setShowChat(true),
src: "/assets/images/icons/sms.png", src: "/assets/images/icons/chat.png",
label: "SMS", label: "Chat",
offset: 150, // 60 + 160
}, },
]; ];
return ( return (
<div className="contact-icon-container"> <>
{/* Extra icons */} {/* Floating Contact Buttons */}
{extraIcons.map((icon, i) => ( <div className="contact-icon-container">
<a {open && (
key={i} <div
href={icon.href} className="extra-icons-wrapper"
aria-label={icon.label} style={{
className={`contact-icon-outer extra-icon ${open ? "show" : ""}`} position: "absolute",
style={{ bottom: `${icon.offset}px` }} bottom: "10px",
> right: "-80",
<img src={icon.src} alt={icon.label} className="contact-icon" /> background: "#fff",
</a> borderRadius: "30px 30px 0 0",
))} boxShadow: "0 4px 12px rgba(0,0,0,0.2)",
padding: "10px",
display: "flex",
flexDirection: "column",
gap: "15px",
alignItems: "center",
}}
>
{extraIcons.map((icon, i) =>
icon.href ? (
<a
key={i}
href={icon.href}
aria-label={icon.label}
style={{
background: "#102548",
borderRadius: "50%",
padding: "8px",
width: "45px",
height: "45px",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
<img
src={icon.src}
alt={icon.label}
style={{ width: "22px", height: "22px" }}
/>
</a>
) : (
<button
key={i}
onClick={icon.action}
aria-label={icon.label}
style={{
background: "#102548",
borderRadius: "50%",
padding: "8px",
width: "45px",
height: "45px",
display: "flex",
alignItems: "center",
justifyContent: "center",
border: "none",
}}
>
<img
src={icon.src}
alt={icon.label}
style={{ width: "22px", height: "22px" }}
/>
</button>
)
)}
</div>
)}
{/* Main floating button */} <button
<button type="button"
type="button" aria-label={open ? "Close" : "Contact Us"}
aria-label={open ? "Close" : "Call Us"} className="contact-icon-outer toggle-btn"
className="contact-icon-outer toggle-btn" onClick={() => setOpen((prev) => !prev)}
onClick={() => setOpen((prev) => !prev)} style={{
> position: "fixed",
<img bottom: "5px",
src={ right: "20px",
open left: "20px",
? "/assets/images/icons/close.png" // show close icon when menu is open background: "#102548",
: "/assets/images/icons/call.png" // default call icon borderRadius: "50%",
} padding: "15px",
alt="Contact" // boxShadow: "0 4px 12px #102548",
className="contact-icon" border: "none",
/> zIndex: 9999,
</button> }}
>
<img
src={
open
? "/assets/images/icons/cross-out.png"
: "/assets/images/icons/call.png"
}
alt="Contact"
style={{ width: "28px", height: "28px" }}
/>
</button>
</div>
{/* Chat Form Sidebar */}
{showChat && (
<ChatForm onClose={() => setShowChat(false)} />
)}
</>
);
}
/** Contact Form Sidebar */
function ChatForm({ onClose }) {
const [formData, setFormData] = useState({
username: "",
lname: "",
email: "",
phone: "",
subject: "",
message: "",
});
const [formErrors, setFormErrors] = useState({});
const [captchaToken, setCaptchaToken] = useState(null);
const [alert, setAlert] = useState({ show: false, type: "", message: "" });
const handleChange = (e) => {
const { name, value } = e.target;
setFormData((prev) => ({ ...prev, [name]: value }));
};
const handleCaptchaChange = (token) => {
setCaptchaToken(token);
};
const handleSubmit = async (e) => {
e.preventDefault();
const errors = {};
if (!formData.username.trim()) errors.username = "First Name is required.";
if (!formData.lname.trim()) errors.lname = "Last Name is required.";
if (!formData.email.trim()) errors.email = "Email is required.";
if (!formData.phone.trim()) errors.phone = "Phone is required.";
if (!formData.subject.trim()) errors.subject = "Subject is required.";
if (!formData.message.trim()) errors.message = "Message is required.";
if (!captchaToken) errors.captcha = "Please verify the CAPTCHA.";
setFormErrors(errors);
if (Object.keys(errors).length > 0) return;
const emailData = {
...formData,
message: `Subject: ${formData.subject}<br /><br />Message: ${formData.message}`,
to: "bloor@rapharehab.ca",
senderName: "Rapha Rehab Chat Form",
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({
username: "",
lname: "",
email: "",
phone: "",
subject: "",
message: "",
});
setCaptchaToken(null);
setFormErrors({});
} catch (error) {
setAlert({
show: true,
type: "danger",
message: "Failed to send message. Please try again later.",
});
}
};
return (
<div
className="chat-form-wrapper"
style={{
position: "fixed",
right: "10px",
bottom: "90px",
width: "350px",
background: "#fff",
borderRadius: "10px",
boxShadow: "0 4px 12px rgba(0,0,0,0.3)",
zIndex: 2000,
maxHeight: "80vh",
overflowY: "auto",
}}
>
<div className="p-3 border-bottom d-flex justify-content-between align-items-center">
<h5 style={{ margin: 0, color: "#bc0000" }}>Chat with Us</h5>
<button onClick={onClose} className="btn-close"></button>
</div>
<div className="p-3">
{alert.show && (
<div className={`alert alert-${alert.type}`}>{alert.message}</div>
)}
<form onSubmit={handleSubmit} className="default-form">
<input
type="text"
name="username"
placeholder="First Name"
value={formData.username}
onChange={handleChange}
className="form-control mb-2"
/>
{formErrors.username && <small className="text-danger">{formErrors.username}</small>}
<input
type="text"
name="lname"
placeholder="Last Name"
value={formData.lname}
onChange={handleChange}
className="form-control mb-2"
/>
{formErrors.lname && <small className="text-danger">{formErrors.lname}</small>}
<input
type="email"
name="email"
placeholder="Your Email"
value={formData.email}
onChange={handleChange}
className="form-control mb-2"
/>
{formErrors.email && <small className="text-danger">{formErrors.email}</small>}
<input
type="text"
name="phone"
placeholder="Phone"
value={formData.phone}
onChange={handleChange}
className="form-control mb-2"
/>
{formErrors.phone && <small className="text-danger">{formErrors.phone}</small>}
<input
type="text"
name="subject"
placeholder="Subject"
value={formData.subject}
onChange={handleChange}
className="form-control mb-2"
/>
{formErrors.subject && <small className="text-danger">{formErrors.subject}</small>}
<textarea
name="message"
placeholder="Message"
value={formData.message}
onChange={handleChange}
className="form-control mb-2"
></textarea>
{formErrors.message && <small className="text-danger">{formErrors.message}</small>}
<div className="mb-2">
<ReCAPTCHA
sitekey="6LekfpwrAAAAAOTwuP1d2gg-Fv9UEsAjE2gjOQJl"
onChange={handleCaptchaChange}
/>
{formErrors.captcha && <small className="text-danger">{formErrors.captcha}</small>}
</div>
<button
className="btn w-100"
type="submit"
style={{
background: "#bc0000",
color: "#fff",
padding: "10px",
fontSize: "16px",
fontWeight: "bold",
border: "none",
}}
>
SUBMIT NOW
</button>
</form>
</div>
</div> </div>
); );
} }

99
components/SocialFloat.js Normal file
View File

@ -0,0 +1,99 @@
"use client";
import React, { useState } from "react";
export default function SocialFloat() {
const [open, setOpen] = useState(false);
/** Social icons */
const socialIcons = [
{
href: "https://www.facebook.com/ELRaphaRehabCenter/",
iconClass: "icon-4", // Facebook
label: "Facebook",
offset: -40,
},
{
href: "https://www.instagram.com/elrapharehab/",
iconClass: "icon-7", // Instagram
label: "Instagram",
offset: 40,
},
];
return (
<div>
{/* Extra social icons */}
{open && (
<div
style={{
position: "fixed",
top: "50%",
right: "70px",
transform: "translateY(-50%)",
display: "flex",
flexDirection: "column",
gap: "15px",
zIndex: 9999,
}}
>
{socialIcons.map((icon, i) => (
<a
key={i}
href={icon.href}
target="_blank"
rel="noopener noreferrer"
aria-label={icon.label}
style={{
background: "#102548",
borderRadius: "50%",
width: "45px",
height: "45px",
display: "flex",
alignItems: "center",
justifyContent: "center",
color: "#fff", // White icon color
fontSize: "22px",
textDecoration: "none",
}}
>
<i className={icon.iconClass}></i>
</a>
))}
</div>
)}
{/* Main floating button */}
<button
type="button"
aria-label={open ? "Close Socials" : "Open Socials"}
onClick={() => setOpen((prev) => !prev)}
style={{
position: "fixed",
top: "50%",
right: "20px",
transform: "translateY(-50%)",
background: "#102548",
borderRadius: "50%",
padding: "15px",
border: "none",
zIndex: 9999,
display: "flex",
alignItems: "center",
justifyContent: "center",
cursor: "pointer",
color: "#fff", // Main button icon color white
}}
>
<img
src={
open
? "/assets/images/logo-2.png"
: "/assets/images/logo-2.png"
}
alt="Social"
style={{ width: "28px", height: "28px" }}
/>
</button>
</div>
);
}

View File

@ -18,6 +18,7 @@ import Header2 from './header/Header2';
import Header3 from "./header/Header3"; import Header3 from "./header/Header3";
import Header4 from "./header/Header4"; import Header4 from "./header/Header4";
import ContactFloat from "../ContactFloat"; import ContactFloat from "../ContactFloat";
import SocialFloat from "../SocialFloat";
export default function Layout({ headerStyle, footerStyle, headTitle, breadcrumbTitle, bannerImage, children, wrapperCls }) { export default function Layout({ headerStyle, footerStyle, headTitle, breadcrumbTitle, bannerImage, children, wrapperCls }) {
const [scroll, setScroll] = useState(0); const [scroll, setScroll] = useState(0);
@ -68,6 +69,7 @@ export default function Layout({ headerStyle, footerStyle, headTitle, breadcrumb
{footerStyle === 2 && <Footer2 />} {footerStyle === 2 && <Footer2 />}
</div> </div>
<ContactFloat /> <ContactFloat />
<SocialFloat/>
<BackToTop scroll={scroll} /> <BackToTop scroll={scroll} />
</> </>
); );

View File

@ -53,7 +53,15 @@ export default function MobileBanner() {
id: 0, id: 0,
variant: 'topToBottom', variant: 'topToBottom',
bgImage: '/assets/images/banner/mobile-banner/banner-1.webp', bgImage: '/assets/images/banner/mobile-banner/banner-1.webp',
hideContent: true upperText: 'The Journey to Better Health Begins here',
title: 'Your Path to',
titleSpan: 'Recovery',
titleEnd: 'Starts Today',
subtitle: 'Expert Physiotherapy in Mississauga for You.',
description: 'Our skilled team provides physiotherapy in Mississauga to help you regain mobility and live pain-free. Compassionate care designed around your needs.',
buttonText: 'Book Your Appointment',
buttonLink: 'tel:+647-722-3434',
contentStyle: 'mobile-style'
}, },
{ {
id: 1, id: 1,
@ -137,7 +145,7 @@ export default function MobileBanner() {
<div <div
className="auto-container" className="auto-container"
style={{ style={{
minHeight: '400px', // force same height for first slide minHeight: '400px',
display: 'flex', display: 'flex',
justifyContent: 'center', justifyContent: 'center',
alignItems: 'center' alignItems: 'center'
@ -146,16 +154,14 @@ export default function MobileBanner() {
{!slide.hideContent && ( {!slide.hideContent && (
<div <div
className={`content-box custom-content-box ${slide.contentStyle || ''}`} className={`content-box custom-content-box ${slide.contentStyle || ''}`}
style={slide.contentStyle === 'with-background' ? { style={{
backgroundColor: '#fff', transform: "translateY(200px)",
opacity: 0.8, }}
borderRadius: '20px',
padding: '30px'
} : {}}
> >
<span className="upper-text">{slide.upperText}</span> <span className="upper-text">{slide.upperText}</span>
<h2>{slide.title} <span>{slide.titleSpan}</span> {slide.titleEnd}</h2> <h2>
{slide.title} <span>{slide.titleSpan}</span> {slide.titleEnd}
</h2>
<p>{slide.subtitle}</p> <p>{slide.subtitle}</p>
<p>{slide.description}</p> <p>{slide.description}</p>
<div className="btn-box mt-3"> <div className="btn-box mt-3">
@ -164,6 +170,7 @@ export default function MobileBanner() {
</Link> </Link>
</div> </div>
</div> </div>
)} )}
</div> </div>

View File

@ -680,6 +680,28 @@
} }
@media only screen and (max-width:426px){
.banner-carousel .content-box h2 span{
position: relative;
display: inline-block;
font-weight: 400;
color: #fff;
}
.banner-carousel .content-box h2 span:before{
position: absolute;
content: '';
background: #bc0000;
width: 100%;
height: 4px;
left: 0px;
bottom: 0px;
border-radius: 5px;
}
}

View File

@ -691,7 +691,7 @@
.scroll-to-top { .scroll-to-top {
position: fixed; position: fixed;
right: 20px; right: 20px;
bottom: 60px; bottom: 4px;
transform: rotate(0deg); transform: rotate(0deg);
z-index: 99; z-index: 99;
width: 50px; width: 50px;

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB