navbar, desktop, responsive element, fixes
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
import clsx from "clsx";
|
||||
import { Link, useLocation } from "react-router";
|
||||
import YoutubeIcon from "./icons/YoutubeIcon";
|
||||
import InstagramIcon from "./icons/InstagramIcon";
|
||||
import FacebookIcon from "./icons/FacebookIcon";
|
||||
import LinkedInIcon from "./icons/LinkedInIcon";
|
||||
import TwitterIcon from "./icons/TwitterIcon";
|
||||
|
||||
function Footer() {
|
||||
const { pathname } = useLocation();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"lg:px-[2.222vw] lg:pb-[2.222vw] lg:pt-[2.778vw] md:max-lg:p-6 px-4 py-6 flex lg:gap-[1.667vw] gap-6 lg:rounded-[1.667vw] rounded-3xl border border-[#E2E2DC] max-lg:hidden",
|
||||
(pathname === "/" || pathname.startsWith("/complex")) && "hidden"
|
||||
)}
|
||||
>
|
||||
<div className="space-y-14 flex-1">
|
||||
<img src="/images/logo.svg" className="lg:w-[5.972vw]" alt="" />
|
||||
<div className="flex lg:gap-[2.778vw] gap-10">
|
||||
<p className="lg:max-w-[17.083vw] text-s text-[#0D1922]/40">
|
||||
For more information, visit our website:
|
||||
<Link
|
||||
className="text-[#00BED7] underline"
|
||||
to={"https://www.irth.ae"}
|
||||
>
|
||||
www.irth.ae
|
||||
</Link>
|
||||
</p>
|
||||
<div className="lg:space-y-[0.833vw] space-y-3">
|
||||
<p className="text-s text-[#0D1922]/40">Follow us for more:</p>
|
||||
<div className="flex lg:gap-[0.278vw] gap-1">
|
||||
<div className="lg:p-[0.417vw] p-1.5 bg-[#E2E2DC] lg:rounded-[0.278vw] rounded">
|
||||
<div className="lg:w-[1.389vw] lg:h-[1.389vw] w-5 h-5 text-[#0D1922]/70">
|
||||
<YoutubeIcon />
|
||||
</div>
|
||||
</div>
|
||||
<div className="lg:p-[0.417vw] p-1.5 bg-[#E2E2DC] lg:rounded-[0.278vw] rounded">
|
||||
<div className="lg:w-[1.389vw] lg:h-[1.389vw] w-5 h-5 text-[#0D1922]/70">
|
||||
<InstagramIcon />
|
||||
</div>
|
||||
</div>
|
||||
<div className="lg:p-[0.417vw] p-1.5 bg-[#E2E2DC] lg:rounded-[0.278vw] rounded">
|
||||
<div className="lg:w-[1.389vw] lg:h-[1.389vw] w-5 h-5 text-[#0D1922]/70">
|
||||
<FacebookIcon />
|
||||
</div>
|
||||
</div>
|
||||
<div className="lg:p-[0.417vw] p-1.5 bg-[#E2E2DC] lg:rounded-[0.278vw] rounded">
|
||||
<div className="lg:w-[1.389vw] lg:h-[1.389vw] w-5 h-5 text-[#0D1922]/70">
|
||||
<LinkedInIcon />
|
||||
</div>
|
||||
</div>
|
||||
<div className="lg:p-[0.417vw] p-1.5 bg-[#E2E2DC] lg:rounded-[0.278vw] rounded">
|
||||
<div className="lg:w-[1.389vw] lg:h-[1.389vw] w-5 h-5 text-[#0D1922]/70">
|
||||
<TwitterIcon />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 lg:gap-[1.667vw] gap-6 flex-1">
|
||||
<div className="lg:border-l-[0.069vw] border-l border-[#E2E2DC] lg:pl-[1.111vw] pl-4 flex flex-col">
|
||||
<Link to={"/"} className="text-m flex-1 content-center">
|
||||
Map
|
||||
</Link>
|
||||
<Link to={"/unit-types"} className="text-m flex-1 content-center">
|
||||
Unit Types
|
||||
</Link>
|
||||
<Link to={"/about-irth"} className="text-m flex-1 content-center">
|
||||
About IRTH
|
||||
</Link>
|
||||
</div>
|
||||
<div className="lg:border-l-[0.069vw] border-l border-[#E2E2DC] lg:pl-[1.111vw] pl-4 flex flex-col">
|
||||
<Link to={"/favorites"} className="text-m flex-1 content-center">
|
||||
Favorites
|
||||
</Link>
|
||||
<Link to={"/search"} className="text-m flex-1 content-center">
|
||||
Search
|
||||
</Link>
|
||||
<Link to={"/"} className="text-m flex-1 content-center">
|
||||
Brochures
|
||||
</Link>
|
||||
</div>
|
||||
<div className="content-end text-right">
|
||||
<Link to={"/"} className="text-m">
|
||||
Privacy Policy
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Footer;
|
||||
@@ -34,7 +34,7 @@ function FullScreenButton({
|
||||
onlyIcon
|
||||
size="small"
|
||||
variant="secondary"
|
||||
className="absolute lg:top-[1.667vw] lg:right-[1.667vw] top-4 right-4 z-10"
|
||||
className="absolute lg:top-[1.667vw] lg:right-[1.667vw] top-4 right-4"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<span className="lg:w-[1.389vw] lg:h-[1.389vw] w-5 h-5">
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { NavLink } from "react-router";
|
||||
import LocationIcon from "./icons/LocationIcon";
|
||||
import clsx from "clsx";
|
||||
import ArrowDownIcon from "./icons/ArrowDownIcon";
|
||||
import { useState } from "react";
|
||||
|
||||
function Header() {
|
||||
function handleLogoClick() {
|
||||
@@ -6,10 +10,10 @@ function Header() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="sticky top-0 left-0 w-full h-[3.889vw] max-lg:h-14 max-md:h-16 flex items-center justify-between bg-white">
|
||||
<div className="flex lg:gap-[1.111vw] gap-4">
|
||||
<div className="sticky top-0 left-0 w-full h-[3.889vw] max-lg:h-14 max-md:h-16 flex items-center justify-center bg-white">
|
||||
<div className="flex lg:gap-[1.111vw] gap-4 flex-1">
|
||||
<div
|
||||
className="lg:px-[1.667vw] lg:py-[1.111vw] md:max-lg:p-4 max-md:px-4 max-md:py-5 self-stretch lg:border-r-[0.07vw] border-r border-[#E2E2DC] cursor-pointer"
|
||||
className="lg:px-[1.667vw] lg:py-[1.111vw] md:max-lg:p-4 max-md:px-4 max-md:py-5 cursor-pointer"
|
||||
onClick={handleLogoClick}
|
||||
>
|
||||
<img
|
||||
@@ -25,10 +29,66 @@ function Header() {
|
||||
<p className="text-s text-[#0D1922]/40">Dubai</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className=""></div>
|
||||
<div className=""></div>
|
||||
<NavBar />
|
||||
<div className="flex-1"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Header;
|
||||
|
||||
function NavBar() {
|
||||
return (
|
||||
<>
|
||||
<nav className="flex lg:gap-[0.556vw] gap-2 items-center max-lg:hidden">
|
||||
<NavItem href={"/"} title={"Map"} />
|
||||
<NavItem href={"/unit-types"} title={"Unit Types"} />
|
||||
<NavItem href={"/about"} title={"About IRTH"} />
|
||||
<NavItem href={"/favourites"} title={"Favourites"} />
|
||||
<BrochuresDropdown />
|
||||
<NavItem href={"/search"} title={"Search"} />
|
||||
</nav>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function NavItem({ href, title }: { href: string; title: string }) {
|
||||
return (
|
||||
<NavLink
|
||||
to={href}
|
||||
className={({ isActive }) =>
|
||||
clsx(
|
||||
"text-m lg:px-[1.25vw] lg:py-[0.903vw] px-4.5 py-[13px] lg:rounded-[0.833vw] rounded-xl transition-colors duration-300",
|
||||
isActive && "bg-[#00BED7] text-[#FFFFFF]"
|
||||
)
|
||||
}
|
||||
>
|
||||
{title}
|
||||
</NavLink>
|
||||
);
|
||||
}
|
||||
|
||||
function BrochuresDropdown() {
|
||||
const [opened, setOpened] = useState(false);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<button
|
||||
className="lg:px-[0.972vw] lg:py-[0.694vw] px-3.5 py-2.5 flex items-center"
|
||||
onClick={() => setOpened((prev) => !prev)}
|
||||
>
|
||||
<p className="lg:px-[0.278vw] lg:py-[0.208vw] px-1 py-[3px]">
|
||||
<span className="text-m">Brochures</span>
|
||||
</p>
|
||||
<span
|
||||
className={clsx(
|
||||
"text-[#0D1922] lg:w-[1.389vw] lg:h-[1.389vw] w-5 h-5 transition-transform duration-300",
|
||||
opened && "rotate-180"
|
||||
)}
|
||||
>
|
||||
<ArrowDownIcon />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+42
-27
@@ -17,6 +17,7 @@ import { isMobile } from "react-device-detect";
|
||||
import SelectedComplexCard from "./SelectedComplexCard";
|
||||
import FullScreenButton from "./FullScreenButton";
|
||||
import useWindowSize from "../hooks/useWindowSize";
|
||||
import TouchIcon from "./icons/TouchIcon";
|
||||
|
||||
interface Position {
|
||||
x: number;
|
||||
@@ -589,7 +590,6 @@ function Map({ maxZoom = 1 }: MapProps) {
|
||||
onLoad={handleLoad}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={clsx(
|
||||
"pointer-events-none absolute max-w-none transition-opacity duration-300 bg-black",
|
||||
@@ -597,17 +597,16 @@ function Map({ maxZoom = 1 }: MapProps) {
|
||||
)}
|
||||
style={imageStyle}
|
||||
/>
|
||||
|
||||
<div
|
||||
style={cloudStyle}
|
||||
ref={cloudsRef}
|
||||
className={clsx(
|
||||
`absolute w-full h-full pointer-events-none transition-opacity duration-300 will-change-[opacity,scale,translate,transform]`,
|
||||
`absolute w-full h-full pointer-events-none transition-[opacity] duration-300 will-change-[opacity,scale,translate,transform]`,
|
||||
hoveredMarker && "opacity-80"
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="h-full flex"
|
||||
className="h-full flex transition-transformduration-300"
|
||||
style={{
|
||||
rotate: `${90 + windDirection}deg`,
|
||||
transform: `translateX(${Math.round(
|
||||
@@ -628,7 +627,6 @@ function Map({ maxZoom = 1 }: MapProps) {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ref={markersContainerRef} className="absolute" style={imageStyle}>
|
||||
<div className="relative h-full">
|
||||
{markers.map((marker) => (
|
||||
@@ -644,44 +642,61 @@ function Map({ maxZoom = 1 }: MapProps) {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<WeatherWidget temperature={temperature} />
|
||||
|
||||
<AnimatePresence>
|
||||
{isShowInstruction && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className="absolute inset-0 flex items-center justify-center pointer-events-none"
|
||||
>
|
||||
<div className="w-fit bg-[#0D1922]/40 rounded-lg backdrop-blur-sm space-y-3 p-4 text-white">
|
||||
<div className="flex items-center justify-center gap-4">
|
||||
<SearchIcon />
|
||||
<div className="w-px h-4 bg-white"></div>
|
||||
<MoveIcon />
|
||||
{isShowInstruction &&
|
||||
(isMobile ? (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className="absolute inset-0 flex items-center justify-center pointer-events-none"
|
||||
>
|
||||
<div className="w-fit bg-[#0D1922]/40 lg:rounded-[0.556vw] rounded-lg backdrop-blur-sm lg:space-y-[0.833vw] space-y-3 lg:p-[1.111vw] p-4 text-white">
|
||||
<div className="flex items-center justify-center gap-4">
|
||||
<span className="lg:w-[3.333vw] lg:h-[3.333vw] w-12 h-12">
|
||||
<MoveIcon />
|
||||
</span>
|
||||
<div className="w-px lg:h-[1.111vw] h-4 bg-white" />
|
||||
<span className="lg:w-[3.333vw] lg:h-[3.333vw] w-12 h-12">
|
||||
<TouchIcon />
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-sm text-center">Tap to move</p>
|
||||
</div>
|
||||
<div className="">
|
||||
</motion.div>
|
||||
) : (
|
||||
<motion.div
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0 }}
|
||||
className="absolute inset-0 flex items-center justify-center pointer-events-none"
|
||||
>
|
||||
<div className="w-fit bg-[#0D1922]/40 lg:rounded-[0.556vw] rounded-lg backdrop-blur-sm lg:space-y-[0.833vw] space-y-3 lg:p-[1.111vw] p-4 text-white">
|
||||
<div className="flex items-center justify-center gap-4">
|
||||
<span className="lg:w-[3.333vw] lg:h-[3.333vw] w-12 h-12">
|
||||
<SearchIcon />
|
||||
</span>
|
||||
<div className="w-px lg:h-[1.111vw] h-4 bg-white" />
|
||||
<span className="lg:w-[3.333vw] lg:h-[3.333vw] w-12 h-12">
|
||||
<MoveIcon />
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-sm">Zoom and Move to select a location</p>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</motion.div>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
|
||||
<FullScreenButton
|
||||
isFullScreen={isFullScreen}
|
||||
onFullScreenChange={setIsFullScreen}
|
||||
onClick={handleFullScreenClick}
|
||||
/>
|
||||
|
||||
<div className="absolute lg:right-[1.667vw] lg:bottom-[1.667vw] right-4 bottom-4 flex lg:gap-[0.556vw] gap-2">
|
||||
<DisclaimerButton />
|
||||
<PrivacyPolicyButton />
|
||||
</div>
|
||||
|
||||
<Compass />
|
||||
|
||||
<AnimatePresence>
|
||||
{isMobile && hoveredMarker && (
|
||||
<SelectedComplexCard marker={hoveredMarker} />
|
||||
|
||||
@@ -29,13 +29,6 @@ function ModalContainer() {
|
||||
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (!rootRef.current || !modal) return;
|
||||
// if (document.fullscreenElement) {
|
||||
// rootRef.current?.requestFullscreen();
|
||||
// }
|
||||
// }, [modal]);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("resize", handleResize);
|
||||
window.addEventListener("keydown", handleKeydown);
|
||||
@@ -77,7 +70,7 @@ function ModalContainer() {
|
||||
{modal}
|
||||
<Button
|
||||
onlyIcon
|
||||
variant="tertiary"
|
||||
variant="secondary"
|
||||
className="absolute top-[1.111vw] right-[1.111vw]"
|
||||
onClick={() => setModal(null)}
|
||||
>
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
import useModalStore from "../stores/useModalStore";
|
||||
import QuestionIcon from "./icons/QuestionIcon";
|
||||
import PrivacyPolicyModal from "./modals/PrivacyPolicyModal";
|
||||
import Button from "./ui/Button";
|
||||
|
||||
export default function PrivacyPolicyButton() {
|
||||
const { setModal } = useModalStore();
|
||||
|
||||
return (
|
||||
<Button size="small" variant="secondary" onlyIcon>
|
||||
<span className="lg:w-[1.389vw] lg:h-[1.389vw] w-5 h-5">
|
||||
<Button
|
||||
size="small"
|
||||
variant="secondary"
|
||||
onlyIcon
|
||||
onClick={() => setModal(<PrivacyPolicyModal />)}
|
||||
>
|
||||
<span className="lg:w-[1.389vw] lg:h-[1.389vw] w-5 h-5 text-[#0D1922]">
|
||||
<QuestionIcon />
|
||||
</span>
|
||||
</Button>
|
||||
|
||||
@@ -59,7 +59,6 @@ export default function SelectedComplexCard({ marker }: { marker: IMarker }) {
|
||||
variant="tertiary"
|
||||
size="small"
|
||||
className="w-fit"
|
||||
// onClick={() => navigate(`/complex/${marker.name}`)}
|
||||
onTouchStart={() => navigate(`/complex/${marker.name}`)}
|
||||
>
|
||||
Explore
|
||||
|
||||
@@ -12,6 +12,7 @@ import InfoIcon from "./icons/InfoIcon";
|
||||
import FullScreenButton from "./FullScreenButton";
|
||||
import BottomButton from "./DisclaimerButton";
|
||||
import PrivacyPolicyButton from "./PrivacyPolicyButton";
|
||||
import DisclaimerButton from "./DisclaimerButton";
|
||||
|
||||
interface SequenceSliderProps {
|
||||
complexName: string;
|
||||
@@ -198,7 +199,7 @@ function SequenceSlider({ complexName }: SequenceSliderProps) {
|
||||
<Button
|
||||
onlyIcon
|
||||
variant="secondary"
|
||||
className="absolute top-1/2 -translate-y-1/2 z-100 lg:left-[1.111vw] left-4"
|
||||
className="absolute top-1/2 -translate-y-1/2 lg:left-[1.111vw] left-4"
|
||||
roundedFull
|
||||
disabled={isAnimating || !isShowVideo}
|
||||
onClick={() => handleSwipe("prev")}
|
||||
@@ -210,7 +211,7 @@ function SequenceSlider({ complexName }: SequenceSliderProps) {
|
||||
<Button
|
||||
onlyIcon
|
||||
variant="secondary"
|
||||
className="absolute top-1/2 -translate-y-1/2 z-100 lg:right-[1.111vw] right-4"
|
||||
className="absolute top-1/2 -translate-y-1/2 lg:right-[1.111vw] right-4"
|
||||
roundedFull
|
||||
disabled={isAnimating || !isShowVideo}
|
||||
onClick={() => handleSwipe("next")}
|
||||
@@ -219,15 +220,15 @@ function SequenceSlider({ complexName }: SequenceSliderProps) {
|
||||
<ArrowRightIcon />
|
||||
</span>
|
||||
</Button>
|
||||
<div className="max-md:hidden">
|
||||
<Compass imgStyle={{ transform: `rotate(${currentIndex}deg)` }} />
|
||||
<div className="absolute right-[28px] bottom-[32px] flex gap-2">
|
||||
<DisclaimerButton />
|
||||
<PrivacyPolicyButton />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className="max-md:hidden">
|
||||
<Compass imgStyle={{ transform: `rotate(${currentIndex}deg)` }} />
|
||||
<div className="absolute right-[28px] bottom-[32px] flex gap-2">
|
||||
<BottomButton />
|
||||
<PrivacyPolicyButton />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function WeatherWidget({
|
||||
const formattedTime = `${hours}:${minutes}`;
|
||||
|
||||
return (
|
||||
<div className="absolute left-[1.667vw] top-[1.667vw] z-10 rounded-2xl space-y-4 min-w-50 w-[8.333vw] p-4 font-medium text-white bg-black/40 pointer-events-none max-[1440px]:hidden backdrop-blur-2xl">
|
||||
<div className="absolute left-[1.667vw] top-[1.667vw] rounded-2xl space-y-4 min-w-50 w-[8.333vw] p-4 font-medium text-white bg-black/40 pointer-events-none max-[1440px]:hidden backdrop-blur-2xl">
|
||||
<div>
|
||||
<div className="flex justify-between">
|
||||
<p>{day}</p>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
function ArrowDownIcon() {
|
||||
return (
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M11.47 16.53a.75.75 0 0 0 1.06 0l7-7a.75.75 0 1 0-1.06-1.06L12 14.94 5.53 8.47a.75.75 0 0 0-1.06 1.06z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default ArrowDownIcon;
|
||||
@@ -0,0 +1,12 @@
|
||||
function FacebookIcon() {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M11.834 2.396A3.854 3.854 0 0 0 7.979 6.25v2.146H5.917a.19.19 0 0 0-.188.187v2.834c0 .103.084.187.188.187h2.062v5.813c0 .103.084.187.188.187H11a.19.19 0 0 0 .188-.187v-5.813h2.08a.19.19 0 0 0 .182-.142l.709-2.833a.187.187 0 0 0-.182-.233h-2.79V6.25a.646.646 0 0 1 .647-.646H14a.187.187 0 0 0 .188-.187V2.583A.187.187 0 0 0 14 2.396z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default FacebookIcon;
|
||||
@@ -0,0 +1,12 @@
|
||||
function InstagramIcon() {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M13.75 1.875h-7.5A4.38 4.38 0 0 0 1.875 6.25v7.5a4.38 4.38 0 0 0 4.375 4.375h7.5a4.38 4.38 0 0 0 4.375-4.375v-7.5a4.38 4.38 0 0 0-4.375-4.375M10 13.75a3.75 3.75 0 1 1 0-7.5 3.75 3.75 0 0 1 0 7.5m4.688-7.5a.937.937 0 1 1 0-1.874.937.937 0 0 1 0 1.874M12.5 10a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default InstagramIcon;
|
||||
@@ -0,0 +1,12 @@
|
||||
function LinkedInIcon() {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M3.958 1.563a1.77 1.77 0 1 0 0 3.541 1.77 1.77 0 0 0 0-3.541m-1.666 5a.104.104 0 0 0-.104.104V17.5c0 .058.046.104.104.104h3.333a.104.104 0 0 0 .104-.104V6.667a.104.104 0 0 0-.104-.104zm5.416 0a.104.104 0 0 0-.104.104V17.5c0 .058.047.104.104.104h3.334a.104.104 0 0 0 .104-.104v-5.833a1.563 1.563 0 0 1 3.125 0V17.5c0 .058.046.104.104.104h3.333a.104.104 0 0 0 .105-.104v-7.183c0-2.022-1.76-3.604-3.771-3.422a6 6 0 0 0-1.807.457l-1.09.466V6.667a.104.104 0 0 0-.103-.104z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default LinkedInIcon;
|
||||
@@ -0,0 +1,20 @@
|
||||
function TouchIcon() {
|
||||
return (
|
||||
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M19.83 12.87c.77-.757 1.87-1.37 3.157-1.37 1.189 0 2.334.464 3.182 1.298a4.44 4.44 0 0 1 1.33 3.165v5.269a4.56 4.56 0 0 1 4.67 1.049c.297.291.549.62.75.975a4.55 4.55 0 0 1 5.25.802 4.44 4.44 0 0 1 1.331 3.164v5.926c0 1.757-.352 3.496-1.035 5.118a13.3 13.3 0 0 1-2.943 4.332 13.6 13.6 0 0 1-4.395 2.889A13.7 13.7 0 0 1 25.95 46.5c-3.665 0-6.472-1.007-8.982-3.482-2.39-2.358-4.453-5.998-6.89-11.052a4.43 4.43 0 0 1-.423-3.344c.155-.57.422-1.102.784-1.567a4.5 4.5 0 0 1 1.326-1.144 4.55 4.55 0 0 1 3.411-.442 4.5 4.5 0 0 1 2.739 2.071l.002.004.583.983V16.035c0-1.192.482-2.33 1.33-3.165M33.5 27.221v1.08h-3v-2.856c0-.38-.153-.75-.434-1.025a1.54 1.54 0 0 0-1.078-.438c-.41 0-.797.16-1.079.438a1.4 1.4 0 0 0-.409 1.025v1.77h-3V15.963c0-.38-.154-.75-.435-1.026a1.54 1.54 0 0 0-1.078-.437c-.31 0-.692.154-1.053.509a1.44 1.44 0 0 0-.434 1.026V34l-2.79.765-3.382-5.705a1.5 1.5 0 0 0-.385-.432 1.56 1.56 0 0 0-1.697-.109 1.5 1.5 0 0 0-.441.381 1.42 1.42 0 0 0-.107 1.604l.058.11c2.457 5.099 4.334 8.31 6.319 10.268 1.873 1.847 3.886 2.618 6.875 2.618 1.39 0 2.764-.27 4.046-.791a10.6 10.6 0 0 0 3.423-2.25 10.3 10.3 0 0 0 2.281-3.358c.528-1.254.8-2.597.8-3.953v-5.926c0-.38-.153-.75-.434-1.026a1.54 1.54 0 0 0-1.078-.437c-.41 0-.797.16-1.079.438-.258.254-.41.612-.41 1.024"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M26.699 6.173A10.5 10.5 0 0 0 13.907 21.25l-2.598 1.5a13.5 13.5 0 1 1 24.731-3.256l-2.898-.776A10.5 10.5 0 0 0 26.7 6.173"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default TouchIcon;
|
||||
@@ -0,0 +1,16 @@
|
||||
function TwitterIcon() {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="m16.82 16.683-5.498-7.988-.621-.904-3.934-5.714-.326-.473H1.608l1.18 1.713 5.229 7.598.621.903 4.202 6.105.326.473H18zm-3.08.62L9.376 10.96l-.621-.903-5.066-7.36h2.18L9.963 8.65l.621.903 5.335 7.75z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
<path
|
||||
d="m8.754 10.057.622.903-.737.857-5.655 6.579H1.59l6.427-7.481zm8.664-8.453-6.095 7.09-.738.858-.621-.903.737-.858 4.129-4.805 1.193-1.382z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default TwitterIcon;
|
||||
@@ -0,0 +1,14 @@
|
||||
function YoutubeIcon() {
|
||||
return (
|
||||
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M19.814 5.423a2.52 2.52 0 0 1 1.768 1.79C22 8.79 22 12.082 22 12.082s0 3.293-.418 4.871a2.52 2.52 0 0 1-1.768 1.79c-1.56.423-7.814.423-7.814.423s-6.254 0-7.814-.423a2.52 2.52 0 0 1-1.768-1.79C2 15.377 2 12.084 2 12.084s0-3.294.418-4.872a2.52 2.52 0 0 1 1.768-1.79C5.746 5 12 5 12 5s6.254 0 7.814.423m-9.48 3.744V15l5-2.917z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export default YoutubeIcon;
|
||||
@@ -1,15 +1,11 @@
|
||||
function MoveIcon() {
|
||||
return (
|
||||
<svg
|
||||
width={49}
|
||||
height={48}
|
||||
viewBox="0 0 49 48"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<svg viewBox="0 0 49 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="m11.9 29-5.4-5m0 0 5.4-5m-5.4 5h11.7m12.6 0h11.7m0 0-5.4 5m5.4-5-5.4-5m-7.6 17.6-5 5.4m0 0-5-5.4m5 5.4V30.3m0-12.6V6m0 0 5 5.4m-5-5.4-5 5.4"
|
||||
stroke="#fff"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={3}
|
||||
/>
|
||||
</svg>
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
function SearchIcon() {
|
||||
return (
|
||||
<svg
|
||||
width={49}
|
||||
height={48}
|
||||
viewBox="0 0 49 48"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<svg viewBox="0 0 49 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="m41.5 41-7.686-7.686m0 0A15.95 15.95 0 0 0 38.5 22c0-8.837-7.163-16-16-16s-16 7.163-16 16 7.163 16 16 16a15.95 15.95 0 0 0 11.306-4.678zM16.5 22h12m-6-6v12"
|
||||
stroke="currentColor"
|
||||
strokeWidth={3}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={3}
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
function PrivacyPolicyModal() {
|
||||
return (
|
||||
<div className="lg:rounded-[1.111vw] bg-white rounded-2xl lg:p-[2.222vw] lg:w-[38.889vw] p-8">
|
||||
<div className="bg-[#00BED7] lg:h-[0.139vw] h-0.5 lg:w-[8.646vw] lg:rounded-[0.208vw] rounded-[3px]" />
|
||||
<h2 className="text-subheadline-m font-semibold py-6">
|
||||
Privacy Policy for IRTH Group and its companies:
|
||||
</h2>
|
||||
<div className="space-y-4">
|
||||
<p className="text-caption-s">
|
||||
At IRTH Group and its companies, we are committed to protecting the
|
||||
privacy and security of your personal information. This Privacy Policy
|
||||
explains how we collect, use, disclose, and safeguard your information
|
||||
when you visit our website or use our services.
|
||||
</p>
|
||||
|
||||
<div className="space-y-2">
|
||||
<p className="text-caption-m">Information We Collect:</p>
|
||||
<ul className="text-caption-s list-disc ml-5">
|
||||
<li>
|
||||
Personal Information: We may collect personal information such as
|
||||
your name, contact details, and address when you voluntarily
|
||||
provide it to us, such as when you register through a form or
|
||||
request information
|
||||
</li>
|
||||
<li>
|
||||
Usage Information: We automatically collect certain information
|
||||
about your device and usage of our website, such as your IP
|
||||
address, browser type, operating system, pages visited, and time
|
||||
spent on each page. This information helps us analyze trends,
|
||||
administer the website, and improve our services.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<p className="text-caption-m">How We Use Your Information:</p>
|
||||
<ul className="text-caption-s list-disc ml-5">
|
||||
<li>
|
||||
To Provide Services:We use your personal information to deliver
|
||||
the services you request, such as facilitating property
|
||||
transactions, responding to inquiries, and sending you relevant
|
||||
updates and notifications
|
||||
</li>
|
||||
<li>
|
||||
To Improve Our Services: We analyze usage data to understand how
|
||||
our website is accessed and used, identify areas for improvement,
|
||||
and enhance the user experience.
|
||||
</li>
|
||||
<li>
|
||||
To Communicate with You: We may use your contact information to
|
||||
communicate with you about properties, services, promotions, and
|
||||
updates. You can opt out of receiving marketing communications at
|
||||
any time by following the unsubscribe instructions provided in our
|
||||
emails or contacting us directly.
|
||||
</li>
|
||||
<li>
|
||||
To Protect Our Rights: We may use your information to enforce our
|
||||
terms of service, protect our rights, or comply with legal
|
||||
obligations.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<p className="text-caption-m">Information Sharing and Disclosure:</p>
|
||||
<p className="text-caption-s">
|
||||
We may share your personal information with trusted third-party
|
||||
service providers who assist us in operating our website, conducting
|
||||
business, or servicing you, as long as those parties agree to keep
|
||||
this information confidential. We may also disclose your information
|
||||
when required by law, to enforce our site policies, or to protect
|
||||
our or others' rights, property, or safety.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<p className="text-caption-m">Data Security:</p>
|
||||
<p className="text-caption-s">
|
||||
We implement a variety of security measures to safeguard your
|
||||
personal information and protect it from unauthorized access,
|
||||
alteration, disclosure, or destruction. However, no method of
|
||||
transmission over the Internet or electronic storage is 100% secure,
|
||||
so we cannot guarantee absolute security.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<p className="text-caption-m">Your Rights:</p>
|
||||
<p className="text-caption-s">
|
||||
You have the right to access, update, or delete your personal
|
||||
information at any time. You can do this by contacting us directly.
|
||||
We will make reasonable efforts to accommodate your request, subject
|
||||
to any legal or contractual obligations.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<p className="text-caption-m">Contact Us:</p>
|
||||
<p className="text-caption-s">
|
||||
If you have any questions or concerns about this Privacy Policy or
|
||||
our privacy practices, please contact us at info@irth.ae
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<p className="text-caption-m">Effective Date:</p>
|
||||
<p className="text-caption-s">
|
||||
This Privacy Policy is effective as of 07/03/2024 and supersedes any
|
||||
prior versions
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default PrivacyPolicyModal;
|
||||
@@ -1,5 +1,6 @@
|
||||
import Header from "../components/Header";
|
||||
import { Outlet } from "react-router";
|
||||
import Footer from "../components/Footer";
|
||||
|
||||
function DefaultLayout() {
|
||||
return (
|
||||
@@ -8,6 +9,7 @@ function DefaultLayout() {
|
||||
<div className="h-[calc(100dvh-3.889vw)] max-lg:h-[calc(100dvh-56px)] max-md:h-[calc(100dvh-64px)]">
|
||||
<Outlet />
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@ import MainPage from "./pages/MainPage.tsx";
|
||||
import ModalContainer from "./components/ModalContainer.tsx";
|
||||
import ComplexPage from "./pages/ComplexPage.tsx";
|
||||
import FloorsPage from "./pages/FloorsPage.tsx";
|
||||
import UnitTypesPage from "./pages/UnitTypesPages.tsx";
|
||||
import AboutPage from "./pages/AboutPages.tsx";
|
||||
import FavouritesPage from "./pages/FavouritesPage.tsx";
|
||||
import SearchPage from "./pages/SearchPage.tsx";
|
||||
|
||||
const route = createBrowserRouter([
|
||||
{
|
||||
@@ -24,6 +28,22 @@ const route = createBrowserRouter([
|
||||
path: "/complex/:complexName/floors",
|
||||
element: <FloorsPage />,
|
||||
},
|
||||
{
|
||||
path: "/unit-types",
|
||||
element: <UnitTypesPage />,
|
||||
},
|
||||
{
|
||||
path: "/about",
|
||||
element: <AboutPage />,
|
||||
},
|
||||
{
|
||||
path: "/favourites",
|
||||
element: <FavouritesPage />,
|
||||
},
|
||||
{
|
||||
path: "/search",
|
||||
element: <SearchPage />,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
function AboutPage() {
|
||||
return <div>AboutPage</div>;
|
||||
}
|
||||
|
||||
export default AboutPage;
|
||||
@@ -0,0 +1,5 @@
|
||||
function FavouritesPage() {
|
||||
return <div>FavouritesPage</div>;
|
||||
}
|
||||
|
||||
export default FavouritesPage;
|
||||
@@ -0,0 +1,5 @@
|
||||
function SearchPage() {
|
||||
return <div>SearchPage</div>;
|
||||
}
|
||||
|
||||
export default SearchPage;
|
||||
@@ -0,0 +1,5 @@
|
||||
function UnitTypesPage() {
|
||||
return <div>UnitTypesPage</div>;
|
||||
}
|
||||
|
||||
export default UnitTypesPage;
|
||||
Reference in New Issue
Block a user