corrections updated
@ -20,7 +20,7 @@ export default function RootLayout({ children }) {
|
||||
<html lang="en" className={`${poppins.variable}`}>
|
||||
<body>
|
||||
{children}
|
||||
<AutoPopup/>
|
||||
{/* <AutoPopup/> */}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
@ -24,13 +24,13 @@ export default function Home() {
|
||||
return (
|
||||
<>
|
||||
<Layout headerStyle={2} footerStyle={2}>
|
||||
{/* <div className="d-none d-md-block"> */}
|
||||
<div className="d-none d-md-block">
|
||||
<Banner />
|
||||
{/* </div> */}
|
||||
{/*
|
||||
</div>
|
||||
|
||||
<div className="d-block d-md-none">
|
||||
<MobileBanner />
|
||||
</div> */}
|
||||
</div>
|
||||
{/* <Features /> */}
|
||||
<AboutSection />
|
||||
{/* <ProcessSection /> */}
|
||||
|
||||
@ -1,63 +1,327 @@
|
||||
"use client";
|
||||
import React, { useState } from "react";
|
||||
import ReCAPTCHA from "react-google-recaptcha";
|
||||
import axios from "axios";
|
||||
|
||||
export default function ContactFloat() {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [showChat, setShowChat] = useState(false);
|
||||
|
||||
/** 3 extra contact icons */
|
||||
/** Contact actions */
|
||||
const extraIcons = [
|
||||
{
|
||||
href: "mailto:info@example.com",
|
||||
href: "mailto:bloor@rapharehab.ca",
|
||||
src: "/assets/images/icons/mail.png",
|
||||
label: "Mail",
|
||||
offset: 30, // main button bottom(60) + 20 = 80
|
||||
},
|
||||
{
|
||||
href: "https://wa.me/1234567890",
|
||||
src: "/assets/images/icons/whatsapp.png",
|
||||
label: "WhatsApp",
|
||||
offset: 90, // 60 + 90
|
||||
href: "tel:647-722-3434",
|
||||
src: "/assets/images/icons/call.png",
|
||||
label: "Call",
|
||||
},
|
||||
{
|
||||
href: "sms:1234567890",
|
||||
src: "/assets/images/icons/sms.png",
|
||||
label: "SMS",
|
||||
offset: 150, // 60 + 160
|
||||
action: () => setShowChat(true),
|
||||
src: "/assets/images/icons/chat.png",
|
||||
label: "Chat",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Floating Contact Buttons */}
|
||||
<div className="contact-icon-container">
|
||||
{/* Extra icons */}
|
||||
{extraIcons.map((icon, i) => (
|
||||
{open && (
|
||||
<div
|
||||
className="extra-icons-wrapper"
|
||||
style={{
|
||||
position: "absolute",
|
||||
bottom: "10px",
|
||||
right: "-80",
|
||||
background: "#fff",
|
||||
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}
|
||||
className={`contact-icon-outer extra-icon ${open ? "show" : ""}`}
|
||||
style={{ bottom: `${icon.offset}px` }}
|
||||
style={{
|
||||
background: "#102548",
|
||||
borderRadius: "50%",
|
||||
padding: "8px",
|
||||
width: "45px",
|
||||
height: "45px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<img src={icon.src} alt={icon.label} className="contact-icon" />
|
||||
<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
|
||||
type="button"
|
||||
aria-label={open ? "Close" : "Call Us"}
|
||||
aria-label={open ? "Close" : "Contact Us"}
|
||||
className="contact-icon-outer toggle-btn"
|
||||
onClick={() => setOpen((prev) => !prev)}
|
||||
style={{
|
||||
position: "fixed",
|
||||
bottom: "5px",
|
||||
right: "20px",
|
||||
left: "20px",
|
||||
background: "#102548",
|
||||
borderRadius: "50%",
|
||||
padding: "15px",
|
||||
// boxShadow: "0 4px 12px #102548",
|
||||
border: "none",
|
||||
zIndex: 9999,
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={
|
||||
open
|
||||
? "/assets/images/icons/close.png" // show close icon when menu is open
|
||||
: "/assets/images/icons/call.png" // default call icon
|
||||
? "/assets/images/icons/cross-out.png"
|
||||
: "/assets/images/icons/call.png"
|
||||
}
|
||||
alt="Contact"
|
||||
className="contact-icon"
|
||||
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>
|
||||
);
|
||||
}
|
||||
|
||||
99
components/SocialFloat.js
Normal 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>
|
||||
);
|
||||
}
|
||||
@ -18,6 +18,7 @@ import Header2 from './header/Header2';
|
||||
import Header3 from "./header/Header3";
|
||||
import Header4 from "./header/Header4";
|
||||
import ContactFloat from "../ContactFloat";
|
||||
import SocialFloat from "../SocialFloat";
|
||||
|
||||
export default function Layout({ headerStyle, footerStyle, headTitle, breadcrumbTitle, bannerImage, children, wrapperCls }) {
|
||||
const [scroll, setScroll] = useState(0);
|
||||
@ -68,6 +69,7 @@ export default function Layout({ headerStyle, footerStyle, headTitle, breadcrumb
|
||||
{footerStyle === 2 && <Footer2 />}
|
||||
</div>
|
||||
<ContactFloat />
|
||||
<SocialFloat/>
|
||||
<BackToTop scroll={scroll} />
|
||||
</>
|
||||
);
|
||||
|
||||
@ -53,7 +53,15 @@ export default function MobileBanner() {
|
||||
id: 0,
|
||||
variant: 'topToBottom',
|
||||
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,
|
||||
@ -137,7 +145,7 @@ export default function MobileBanner() {
|
||||
<div
|
||||
className="auto-container"
|
||||
style={{
|
||||
minHeight: '400px', // force same height for first slide
|
||||
minHeight: '400px',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center'
|
||||
@ -146,16 +154,14 @@ export default function MobileBanner() {
|
||||
{!slide.hideContent && (
|
||||
<div
|
||||
className={`content-box custom-content-box ${slide.contentStyle || ''}`}
|
||||
style={slide.contentStyle === 'with-background' ? {
|
||||
backgroundColor: '#fff',
|
||||
opacity: 0.8,
|
||||
borderRadius: '20px',
|
||||
padding: '30px'
|
||||
} : {}}
|
||||
|
||||
style={{
|
||||
transform: "translateY(200px)",
|
||||
}}
|
||||
>
|
||||
<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.description}</p>
|
||||
<div className="btn-box mt-3">
|
||||
@ -164,6 +170,7 @@ export default function MobileBanner() {
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -691,7 +691,7 @@
|
||||
.scroll-to-top {
|
||||
position: fixed;
|
||||
right: 20px;
|
||||
bottom: 60px;
|
||||
bottom: 4px;
|
||||
transform: rotate(0deg);
|
||||
z-index: 99;
|
||||
width: 50px;
|
||||
|
||||
BIN
public/assets/images/banner-2.jpeg
Normal file
|
After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 11 KiB |
BIN
public/assets/images/icon.png
Normal file
|
After Width: | Height: | Size: 12 KiB |