mobile header
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
"react-device-detect": "^2.2.3",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-image-marker": "^1.2.0",
|
"react-image-marker": "^1.2.0",
|
||||||
"react-router-dom": "^6.22.3",
|
"react-router-dom": "^6.22.3",
|
||||||
|
|||||||
@@ -1,25 +1,59 @@
|
|||||||
|
import { isMobile } from "react-device-detect";
|
||||||
|
|
||||||
import Button from "../Button";
|
import Button from "../Button";
|
||||||
|
|
||||||
|
interface AuthProps {
|
||||||
|
isAuth: boolean;
|
||||||
|
userName: string;
|
||||||
|
}
|
||||||
|
|
||||||
const Auth = () => {
|
const Auth = () => {
|
||||||
const isAuth = false;
|
const isAuth = false;
|
||||||
const username = "Name";
|
const userName = "Name";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex gap-4 py-2 pr-6 text-black col-span-2 justify-end">
|
{isMobile ? (
|
||||||
{isAuth ? (
|
<AuthMobile isAuth={isAuth} userName={userName} />
|
||||||
<>
|
) : (
|
||||||
<p>{username}</p>
|
<AuthDesktop isAuth={isAuth} userName={userName} />
|
||||||
<div className="rounded-full w-10 h-10 bg-[#E2E2DC] overflow-clip">
|
)}
|
||||||
{/* <img src="" alt="avatar" className="bg-[#E2E2DC]" /> */}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Button buttonType="cta" text="Login" />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const AuthMobile = ({ isAuth, userName }: AuthProps) => {
|
||||||
|
return (
|
||||||
|
<div className="flex gap-4 p-4 text-black justify-center w-full items-center">
|
||||||
|
{isAuth ? (
|
||||||
|
<>
|
||||||
|
<p>{userName}</p>
|
||||||
|
<div className="rounded-full w-10 h-10 bg-[#E2E2DC] overflow-clip">
|
||||||
|
{/* <img src="" alt="avatar" className="bg-[#E2E2DC]" /> */}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Button buttonType="cta" text="Login" className="w-full" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const AuthDesktop = ({ isAuth, userName }: AuthProps) => {
|
||||||
|
return (
|
||||||
|
<div className="flex gap-4 py-2 pr-6 text-black col-span-2 justify-end">
|
||||||
|
{isAuth ? (
|
||||||
|
<>
|
||||||
|
<p>{userName}</p>
|
||||||
|
<div className="rounded-full w-10 h-10 bg-[#E2E2DC] overflow-clip">
|
||||||
|
{/* <img src="" alt="avatar" className="bg-[#E2E2DC]" /> */}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Button buttonType="cta" text="Login" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default Auth;
|
export default Auth;
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
import { Outlet } from "react-router-dom";
|
|
||||||
import Logo from "./Logo";
|
|
||||||
import Location from "./Location";
|
|
||||||
import Auth from "./Auth";
|
|
||||||
import Navbar from "./Navbar";
|
|
||||||
import useModal from "../../store/useModal";
|
|
||||||
|
|
||||||
const Header = () => {
|
|
||||||
const { modal } = useModal();
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{modal}
|
|
||||||
<header className="bg-white w-full text-white grid grid-cols-6 text-sm">
|
|
||||||
<div className="flex gap-4 col-span-2">
|
|
||||||
<Logo />
|
|
||||||
<Location />
|
|
||||||
</div>
|
|
||||||
<Navbar />
|
|
||||||
<Auth />
|
|
||||||
</header>
|
|
||||||
<Outlet />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Header;
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import Auth from "../Auth";
|
||||||
|
import Logo from "../Logo";
|
||||||
|
import Navbar from "../Navbar";
|
||||||
|
import Location from "../Location";
|
||||||
|
|
||||||
|
const DesktopHeader = () => (
|
||||||
|
<header className="bg-white w-full text-white sm:grid grid-cols-6 text-sm">
|
||||||
|
<div className="flex gap-4 col-span-2">
|
||||||
|
<Logo />
|
||||||
|
<Location />
|
||||||
|
</div>
|
||||||
|
<Navbar />
|
||||||
|
<Auth />
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default DesktopHeader;
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { Outlet } from "react-router-dom";
|
||||||
|
import { isMobile } from "react-device-detect";
|
||||||
|
import useModal from "../../../store/useModal";
|
||||||
|
import DesktopHeader from "./DesktopHeader";
|
||||||
|
import MobileHeader from "./MobileHeader";
|
||||||
|
|
||||||
|
const Header = () => {
|
||||||
|
const { modal } = useModal();
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{modal}
|
||||||
|
{isMobile ? <MobileHeader /> : <DesktopHeader />}
|
||||||
|
<Outlet />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Header;
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import LogoIcon from "../../icons/LogoIcon";
|
||||||
|
import Auth from "../Auth";
|
||||||
|
import Navbar from "../Navbar";
|
||||||
|
import Location from "../Location";
|
||||||
|
|
||||||
|
const MobileHeader = () => {
|
||||||
|
const [isToggled, setIsToggled] = useState(false);
|
||||||
|
|
||||||
|
const handleOnToggleClick = () => {
|
||||||
|
setIsToggled((prev) => !prev);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<header
|
||||||
|
className={`bg-white w-full text-white flex flex-col text-sm items-center transition-[height] duration-500 ease-in-out absolute top-0 left-0 z-30 overflow-hidden ${
|
||||||
|
isToggled ? "h-[472px]" : "h-14"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="flex justify-between w-full p-4">
|
||||||
|
<div
|
||||||
|
className={`text-[#0D1922] transition-opacity duration-500 ${
|
||||||
|
isToggled ? "opacity-0" : "opacity-100"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<LogoIcon />
|
||||||
|
</div>
|
||||||
|
<div className="bg-black w-6 h-6" onClick={handleOnToggleClick}></div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col justify-between h-full items-center w-full ">
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<div className="text-[#0D1922] items-center">
|
||||||
|
<LogoIcon />
|
||||||
|
</div>
|
||||||
|
<Location />
|
||||||
|
</div>
|
||||||
|
<Navbar />
|
||||||
|
<Auth />
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MobileHeader;
|
||||||
@@ -2,7 +2,7 @@ import LocationIcon from "../icons/LocationIcon";
|
|||||||
|
|
||||||
const Location = () => {
|
const Location = () => {
|
||||||
return (
|
return (
|
||||||
<div className="text-[#73787C] flex gap-1 items-center">
|
<div className="text-[#73787C] flex gap-1 items-center justify-center">
|
||||||
<LocationIcon />
|
<LocationIcon />
|
||||||
<p className="">Dubai</p>
|
<p className="">Dubai</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
import { isMobile } from "react-device-detect";
|
||||||
import { Tab } from "../../types/tab";
|
import { Tab } from "../../types/tab";
|
||||||
import NavbarTab from "./NavbarTab";
|
import NavbarTab from "./NavbarTab";
|
||||||
|
|
||||||
@@ -32,20 +33,47 @@ const Navbar = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<nav className="flex text-[#73787C] self-center col-span-2 justify-center">
|
<>
|
||||||
{tabs.map((tab) => (
|
{isMobile ? (
|
||||||
<NavbarTab
|
<NavbarMobile selectedTab={selectedTab} onTabClick={onTabClick} />
|
||||||
key={tab.id}
|
) : (
|
||||||
tab={tab}
|
<NavbarDesktop selectedTab={selectedTab} onTabClick={onTabClick} />
|
||||||
isSelected={selectedTab?.id === tab.id}
|
)}
|
||||||
onClick={onTabClick}
|
</>
|
||||||
/>
|
|
||||||
// <button key={tab} className="px-4 py-[10px]">
|
|
||||||
// {tab}
|
|
||||||
// </button>
|
|
||||||
))}
|
|
||||||
</nav>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface NavbarProps {
|
||||||
|
selectedTab: Tab | null;
|
||||||
|
onTabClick: (tab: Tab) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NavbarDesktop = ({ selectedTab, onTabClick }: NavbarProps) => (
|
||||||
|
<nav className={`text-[#73787C] self-center col-span-2 justify-center flex`}>
|
||||||
|
{tabs.map((tab) => (
|
||||||
|
<NavbarTab
|
||||||
|
key={tab.id}
|
||||||
|
tab={tab}
|
||||||
|
isSelected={selectedTab?.id === tab.id}
|
||||||
|
onClick={onTabClick}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
|
||||||
|
const NavbarMobile = ({ selectedTab, onTabClick }: NavbarProps) => (
|
||||||
|
<nav
|
||||||
|
className={`text-[#73787C] self-center justify-center flex w-full flex-col items-center`}
|
||||||
|
>
|
||||||
|
{tabs.map((tab) => (
|
||||||
|
<NavbarTab
|
||||||
|
key={tab.id}
|
||||||
|
tab={tab}
|
||||||
|
isSelected={selectedTab?.id === tab.id}
|
||||||
|
onClick={onTabClick}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
|
||||||
export default Navbar;
|
export default Navbar;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ interface NavbarTabProps {
|
|||||||
const NavbarTab = ({ tab, onClick, isSelected = false }: NavbarTabProps) => {
|
const NavbarTab = ({ tab, onClick, isSelected = false }: NavbarTabProps) => {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className="px-4 text-[#73787C] hover:text-black relative"
|
className="px-4 text-[#73787C] hover:text-black relative w-fit"
|
||||||
onClick={() => onClick(tab)}
|
onClick={() => onClick(tab)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
|
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
|
||||||
import ImageMarker from "react-image-marker";
|
import ImageMarker from "react-image-marker";
|
||||||
import { MarkerComponentProps } from "react-image-marker";
|
import { MarkerComponentProps } from "react-image-marker";
|
||||||
|
import { isMobile } from "react-device-detect";
|
||||||
import Marker from "./Marker";
|
import Marker from "./Marker";
|
||||||
import { markers } from "../../consts/markers";
|
import { markers } from "../../consts/markers";
|
||||||
import useMarker from "../../store/useMarker";
|
import useMarker from "../../store/useMarker";
|
||||||
@@ -31,7 +32,9 @@ const Map = () => {
|
|||||||
// animationType: "easeOut",
|
// animationType: "easeOut",
|
||||||
// }}
|
// }}
|
||||||
>
|
>
|
||||||
<TransformComponent wrapperClass="h-[calc(100vh-60px)]">
|
<TransformComponent
|
||||||
|
wrapperClass={`${isMobile ? "h-screen" : "h-[calc(100vh-60px)]"}`}
|
||||||
|
>
|
||||||
<ImageMarker
|
<ImageMarker
|
||||||
src="images/Map.jpg"
|
src="images/Map.jpg"
|
||||||
markers={imageMarkers}
|
markers={imageMarkers}
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
import ReactDOM from "react-dom/client";
|
import ReactDOM from "react-dom/client";
|
||||||
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
||||||
import Header from "./components/header/Header";
|
import Header from "./components/header/Header/Header";
|
||||||
import Main from "./pages/Main";
|
import Main from "./pages/Main";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
|
|
||||||
|
|||||||
@@ -1774,6 +1774,13 @@ queue-microtask@^1.2.2:
|
|||||||
resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
|
resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
|
||||||
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
|
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
|
||||||
|
|
||||||
|
react-device-detect@^2.2.3:
|
||||||
|
version "2.2.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-device-detect/-/react-device-detect-2.2.3.tgz#97a7ae767cdd004e7c3578260f48cf70c036e7ca"
|
||||||
|
integrity sha512-buYY3qrCnQVlIFHrC5UcUoAj7iANs/+srdkwsnNjI7anr3Tt7UY6MqNxtMLlr0tMBied0O49UZVK8XKs3ZIiPw==
|
||||||
|
dependencies:
|
||||||
|
ua-parser-js "^1.0.33"
|
||||||
|
|
||||||
react-dom@^18.2.0:
|
react-dom@^18.2.0:
|
||||||
version "18.2.0"
|
version "18.2.0"
|
||||||
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz"
|
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz"
|
||||||
@@ -2093,6 +2100,11 @@ typescript@^5.2.2:
|
|||||||
resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz"
|
resolved "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz"
|
||||||
integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==
|
integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==
|
||||||
|
|
||||||
|
ua-parser-js@^1.0.33:
|
||||||
|
version "1.0.37"
|
||||||
|
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.37.tgz#b5dc7b163a5c1f0c510b08446aed4da92c46373f"
|
||||||
|
integrity sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==
|
||||||
|
|
||||||
update-browserslist-db@^1.0.13:
|
update-browserslist-db@^1.0.13:
|
||||||
version "1.0.13"
|
version "1.0.13"
|
||||||
resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz"
|
resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz"
|
||||||
|
|||||||
Reference in New Issue
Block a user