This commit is contained in:
2024-07-26 12:59:11 +05:00
commit b3e6ff5e9c
856 changed files with 30776 additions and 0 deletions
@@ -0,0 +1,23 @@
import { isMobile } from "react-device-detect";
import AuthDesktop from "./AuthDesktop";
import AuthMobile from "./AuthMobile";
interface AuthProps {
isAuth?: boolean;
}
const Auth = ({ isAuth = false }: AuthProps) => {
const userName = "Full Name";
return (
<>
{isMobile ? (
<AuthMobile isAuth={isAuth} userName={userName} />
) : (
<AuthDesktop isAuth={isAuth} userName={userName} />
)}
</>
);
};
export default Auth;
@@ -0,0 +1,45 @@
import useModal from "../../../store/useModal";
import Button from "../../Button";
import AuthIcon from "../../icons/AuthIcon";
import LoginModal from "../../modals/auth/LoginModal";
interface AuthProps {
isAuth: boolean;
userName: string;
}
const AuthDesktop = ({ isAuth, userName }: AuthProps) => {
const { setModal } = useModal();
const handleOnLoginBtnClick = () => {
setModal(<LoginModal />);
};
return (
<div className="flex gap-4 py-2 pr-6 text-black col-span-2 justify-end text-s">
{isAuth ? (
<>
<div>
<p className="">{userName}</p>
<p className="text-[#0D192266] text-caption-m font-semibold">
Company
</p>
</div>
<div className="rounded-full w-10 h-10 bg-[#E2E2DC] overflow-clip flex items-center justify-center font-semibold">
{/* <img src="" alt="avatar" className="bg-[#E2E2DC]" /> */}
FN
</div>
</>
) : (
<Button
buttonType="cta"
text="Login"
onClick={handleOnLoginBtnClick}
icon={<AuthIcon />}
/>
)}
</div>
);
};
export default AuthDesktop;
@@ -0,0 +1,33 @@
import Button from "../../Button";
import AuthIcon from "../../icons/AuthIcon";
interface AuthProps {
isAuth: boolean;
userName: string;
}
const AuthMobile = ({ isAuth, userName }: AuthProps) => {
return (
<>
{isAuth ? (
<div className="flex gap-4 text-black justify-start w-full items-center px-4 py-2 bg-white rounded-lg">
<p>{userName}</p>
<div className="rounded-full w-10 h-10 bg-[#E2E2DC] overflow-clip">
{/* <img src="" alt="avatar" className="bg-[#E2E2DC]" /> */}
</div>
</div>
) : (
<div className="flex gap-4 text-black justify-center w-full items-center">
<Button
buttonType="cta"
text="Login"
icon={<AuthIcon />}
className="w-full justify-center"
/>
</div>
)}
</>
);
};
export default AuthMobile;
@@ -0,0 +1,19 @@
import Auth from "../Auth/Auth";
import Logo from "../../Logo";
import Navbar from "../Navbar/Navbar";
import Location from "../Location";
const DesktopHeader = () => (
<header className="bg-white fixed left-0 top-0 w-full z-[99999999] font-usual text-m select-none flex justify-between">
<div className="flex gap-4 col-span-2">
<Logo />
<Location />
</div>
<Navbar />
<div className="flex gap-5">
<Auth isAuth={false} />
</div>
</header>
);
export default DesktopHeader;
@@ -0,0 +1,49 @@
import { useState } from "react";
import LogoIcon from "../../icons/LogoIcon";
import Auth from "../Auth/Auth";
import Navbar from "../Navbar/Navbar";
import Location from "../Location";
import BurgerMenuIcon from "../../icons/BurgerMenuIcon";
const MobileHeader = () => {
const [isToggled, setIsToggled] = useState(false);
const isAuth = false;
const handleOnToggleClick = () => {
setIsToggled((prev) => !prev);
};
return (
<header
className={`bg-white w-full ${
isToggled
? "rounded-ee-lg rounded-es-lg shadow-[#00000026] shadow-md"
: ""
} text-white flex flex-col text-sm items-center transition-all duration-500 ease-in-out absolute top-0 left-0 z-[99999900] overflow-hidden font-usual ${
isToggled ? "max-h-[472px]" : "max-h-14"
}`}
>
<div className="flex justify-between w-full p-4">
<div className={`text-[#0D1922] transition-opacity duration-500`}>
<LogoIcon />
</div>
<div className="w-6 h-6 text-[#0D1922]" onClick={handleOnToggleClick}>
<BurgerMenuIcon isToggled={isToggled} />
</div>
</div>
<div className="flex flex-col justify-between h-full items-end w-full p-4 bg-[#F3F3F2]">
{isAuth && (
<div className="pb-2 w-full">
<Auth isAuth={isAuth} />
</div>
)}
<Navbar />
<div className="py-3">
<Location />
</div>
{!isAuth && <Auth isAuth={isAuth} />}
</div>
</header>
);
};
export default MobileHeader;
+12
View File
@@ -0,0 +1,12 @@
import LocationIcon from "../icons/LocationIcon";
const Location = () => {
return (
<div className="text-[#73787C] flex gap-1 items-center justify-center">
<LocationIcon />
<p className="">Dubai</p>
</div>
);
};
export default Location;
@@ -0,0 +1,67 @@
/* eslint-disable react-hooks/exhaustive-deps */
import { useEffect, useState } from "react";
import { isMobile } from "react-device-detect";
import { useNavigate, useLocation } from "react-router-dom";
import { Tab } from "../../../types/tab";
import NavbarDesktop from "./NavbarDesktop";
import NavbarMobile from "./NavbarMobile";
import { tabs as _tabs } from "../../../consts/tabs";
import useFavorites from "../../../store/useFavorites";
const Navbar = () => {
const [selectedTab, setSelectedTab] = useState<Tab | null>(null);
const [tabs, setTabs] = useState(_tabs);
const location = useLocation();
const navigate = useNavigate();
const { favorites, setFavorites } = useFavorites();
const onTabClick = (tab: Tab) => {
setSelectedTab(tab);
navigate(tab.path);
};
useEffect(() => {
const pathname = location.pathname;
const tab = tabs.find((tab) => tab.path === pathname);
const defaultTab = tabs[0];
if (tab) {
setSelectedTab(tab);
} else {
setSelectedTab(defaultTab);
}
}, [location.pathname]);
useEffect(() => {
const _favorites = localStorage.getItem("Favorites");
if (!_favorites) return;
const convertedFavorute = JSON.parse(_favorites);
setFavorites(convertedFavorute);
}, [setFavorites]);
useEffect(() => {
const updatedTabs = _tabs.map((tab) => {
if (tab.value === "Favorites") {
return { ...tab, count: favorites.length };
}
return tab;
});
setTabs(updatedTabs);
}, [favorites]);
return (
<>
{isMobile ? (
<NavbarMobile onTabClick={onTabClick} tabs={tabs} />
) : (
<NavbarDesktop
selectedTab={selectedTab}
onTabClick={onTabClick}
tabs={tabs}
/>
)}
</>
);
};
export default Navbar;
@@ -0,0 +1,34 @@
import { Tab } from "../../../types/tab";
import NavbarTabDesktop from "./NavbarTabDesktop";
import NavbarTabDesktopBrochure from "./NavbarTabDesktopBrochure";
interface NavbarProps {
selectedTab: Tab | null;
onTabClick: (tab: Tab) => void;
tabs: Tab[];
}
function NavbarDesktop({ selectedTab, onTabClick, tabs }: NavbarProps) {
return (
<nav
className={`text-[#091118] self-center col-span-2 justify-center flex h-full`}
>
{tabs.map((tab) => {
if (tab.value === "Brochures") {
return <NavbarTabDesktopBrochure key={tab.id} tab={tab} />;
} else {
return (
<NavbarTabDesktop
key={tab.id}
tab={tab}
isSelected={selectedTab?.id === tab.id}
onClick={onTabClick}
/>
);
}
})}
</nav>
);
}
export default NavbarDesktop;
@@ -0,0 +1,19 @@
import { Tab } from "../../../types/tab";
import NavbarTabMobile from "./NavbarTabMobile";
interface NavbarProps {
onTabClick: (tab: Tab) => void;
tabs: Tab[];
}
const NavbarMobile = ({ onTabClick, tabs }: NavbarProps) => (
<nav
className={`text-[#73787C] flex w-full flex-col bg-white rounded-lg px-4`}
>
{tabs.map((tab) => (
<NavbarTabMobile key={tab.id} tab={tab} onClick={onTabClick} />
))}
</nav>
);
export default NavbarMobile;
@@ -0,0 +1,40 @@
import useFavoritesStore from "../../../store/useFavoritesStore";
import { Tab } from "../../../types/tab";
interface NavbarTabProps {
tab: Tab;
isSelected: boolean;
onClick: (tab: Tab) => void;
}
const NavbarTabDesktop = ({
tab,
onClick,
isSelected = false,
}: NavbarTabProps) => {
const { favoriteUnits } = useFavoritesStore();
return (
<button
className="px-4 text-[#73787C] hover:text-black relative w-fit h-full"
onClick={() => onClick(tab)}
>
<div
className={`py-4 border-b-2 h-full flex items-center transition-all duration-300 ${
isSelected
? "border-b-[#00BED7]"
: "border-b-transparent hover:border-b-[#E2E2DC] active:border-b-[#00BED7]"
}`}
>
{tab.value}
</div>
{tab.value === "Favorites" && favoriteUnits.length > 0 && (
<div className="absolute top-2 right-0 w-4 h-4 bg-[#00BED7] rounded-full text-white text-[10px] font-mono flex items-center justify-center">
<span className="leading-none">{favoriteUnits.length}</span>
</div>
)}
</button>
);
};
export default NavbarTabDesktop;
@@ -0,0 +1,111 @@
import { useState } from "react";
import { Tab } from "../../../types/tab";
import ChevronDownIcon from "../../icons/ChevronDownIcon";
import DownloadIcon from "../../icons/DownloadIcon";
import { useClickAway } from "@uidotdev/usehooks";
interface Props {
tab: Tab;
}
function NavbarTabDesktopBrochure({ tab }: Props) {
const [isShowMenu, setIsShowMenu] = useState<boolean>(false);
const ref = useClickAway<HTMLDivElement>(() => {
setIsShowMenu(false);
});
return (
<div ref={ref} className="relative px-4 w-fit h-full text-[#73787C]">
<button
onClick={() => setIsShowMenu((prev) => !prev)}
className={`py-4 border-b-2 h-full transition-all duration-300 border-b-transparent hover:text-[#0D1922] hover:border-b-[#E2E2DC] flex items-center gap-2`}
>
{tab.value} <ChevronDownIcon className="w-5 h-5" />
</button>
{isShowMenu && (
<div className="absolute top-[calc(100%+16px)] left-0 bg-[#F3F3F2] rounded-2xl p-4 flex flex-col gap-3 shadow-lg">
<div className="space-y-2">
<div className="border-b pb-2">
<p className="text-sm text-[#0D1922] text-left">
Rove Home Marasi Drive
</p>
</div>
<div className="space-y-2">
<a
href="/files/marasi-drive/ROVE_MAIN_BROCHURE.pdf"
className="px-3 py-2 bg-white rounded-lg flex items-center justify-between bg-[#FFFFFFCC] w-72 hover:text-[#0D1922] transition-colors"
download
>
<span className="text-xs font-semibold">
Rove Main Brochure
</span>
<DownloadIcon className="min-w-5 min-h-5" />
</a>
<a
href="/files/marasi-drive/ROVE_AMENITIES_BROCHURE.pdf"
className="px-3 py-2 bg-white rounded-lg flex items-center justify-between bg-[#FFFFFFCC] w-72 hover:text-[#0D1922] transition-colors"
download
>
<span className="text-xs font-semibold text-nowrap">
Rove Amenties Brochure
</span>
<DownloadIcon className="min-w-5 min-h-5" />
</a>
<a
href="/files/marasi-drive/ROVE_TECHNICAL_BROCHURE.pdf"
className="px-3 py-2 bg-white rounded-lg flex items-center justify-between bg-[#FFFFFFCC] w-72 hover:text-[#0D1922] transition-colors"
download
>
<span className="text-xs font-semibold">
Rove Technical Brochure
</span>
<DownloadIcon className="min-w-5 min-h-5" />
</a>
</div>
</div>
<div className="space-y-2">
<div className="border-b pb-2">
<p className="text-sm text-[#0D1922] text-left">
Rove Home Downtown
</p>
</div>
<div className="space-y-2">
<a
href="/files/downtown/ROVE_MAIN_BROCHURE.pdf"
className="px-3 py-2 bg-white rounded-lg flex items-center justify-between bg-[#FFFFFFCC] w-72 hover:text-[#0D1922] transition-colors"
download
>
<span className="text-xs font-semibold">
Rove Main Brochure
</span>
<DownloadIcon className="min-w-5 min-h-5" />
</a>
<a
href="/files/downtown/ROVE_AMENITIES_BROCHURE.pdf"
className="px-3 py-2 bg-white rounded-lg flex items-center justify-between bg-[#FFFFFFCC] w-72 hover:text-[#0D1922] transition-colors"
download
>
<span className="text-xs font-semibold text-nowrap">
Rove Amenties Brochure
</span>
<DownloadIcon className="min-w-5 min-h-5" />
</a>
<a
href="/files/downtown/ROVE_PLANS_BROCHURE.pdf"
className="px-3 py-2 bg-white rounded-lg flex items-center justify-between bg-[#FFFFFFCC] w-72 hover:text-[#0D1922] transition-colors"
download
>
<span className="text-xs font-semibold">
Rove Plans & Mood Board Brochure
</span>
<DownloadIcon className="min-w-5 min-h-5" />
</a>
</div>
</div>
</div>
)}
</div>
);
}
export default NavbarTabDesktopBrochure;
@@ -0,0 +1,30 @@
import { Tab } from "../../../types/tab";
import RightArrowIcon from "../../icons/RightArrowIcon";
interface NavbarTabProps {
tab: Tab;
onClick: (tab: Tab) => void;
}
const NavbarTabMobile = ({ tab, onClick }: NavbarTabProps) => {
return (
<button className="w-full border-b last:border-b-0 flex justify-between py-4 ">
<div
className=" text-[#0D1922] relative w-fit"
onClick={() => onClick(tab)}
>
<div className={` transition-all duration-300`}>{tab.value}</div>
{tab.count !== 0 && (
<div className="absolute top-0 -right-4 w-4 h-4 bg-[#00BED7] rounded-full text-white text-[10px] flex items-center justify-center">
{tab.count}
</div>
)}
</div>
<div className="text-[#73787C]">
<RightArrowIcon />
</div>
</button>
);
};
export default NavbarTabMobile;