markers, map, button states

This commit is contained in:
2024-04-16 17:57:33 +05:00
parent e0498a7d25
commit 1c906ce371
14 changed files with 290 additions and 22 deletions
+40 -4
View File
@@ -1,12 +1,48 @@
const tabs = ["Masterplan", "Search", "Favorites", "Company"];
import { useState } from "react";
import { Tab } from "../../types/tab";
import NavbarTab from "./NavbarTab";
const tabs: Tab[] = [
{
value: "Masterplan",
id: "1",
count: 0,
},
{
value: "Search",
id: "2",
count: 0,
},
{
value: "Favorites",
id: "3",
count: 3,
},
{
value: "Company",
id: "4",
count: 0,
},
];
const Navbar = () => {
const [selectedTab, setSelectedTab] = useState<Tab | null>(null);
const onTabClick = (tab: Tab) => {
setSelectedTab(tab);
};
return (
<nav className="flex text-[#73787C] self-center col-span-2 justify-center">
{tabs.map((tab) => (
<button key={tab} className="px-4 py-[10px]">
{tab}
</button>
<NavbarTab
key={tab.id}
tab={tab}
isSelected={selectedTab?.id === tab.id}
onClick={onTabClick}
/>
// <button key={tab} className="px-4 py-[10px]">
// {tab}
// </button>
))}
</nav>
);
+33
View File
@@ -0,0 +1,33 @@
import { Tab } from "../../types/tab";
interface NavbarTabProps {
tab: Tab;
isSelected: boolean;
onClick: (tab: Tab) => void;
}
const NavbarTab = ({ tab, onClick, isSelected = false }: NavbarTabProps) => {
return (
<button
className="px-4 text-[#73787C] hover:text-black relative"
onClick={() => onClick(tab)}
>
<div
className={`py-[10px] border-b transition-all duration-300 ${
isSelected
? "border-b-[#00BED7]"
: "border-b-transparent hover:border-b-[#E2E2DC] active:border-b-[#00BED7]"
}`}
>
{tab.value}
</div>
{tab.count !== 0 && (
<div className="absolute top-0 right-0 w-4 h-4 bg-[#00BED7] rounded-full text-white text-[10px] flex items-center justify-center">
{tab.count}
</div>
)}
</button>
);
};
export default NavbarTab;
+43
View File
@@ -0,0 +1,43 @@
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
import ImageMarker from "react-image-marker";
import { MarkerComponentProps } from "react-image-marker";
import Marker from "./Marker";
import { markers } from "../../consts/markers";
const Map = () => {
const imageMarkers: MarkerComponentProps[] = markers.map((marker) => {
return {
top: marker.top,
left: marker.left,
itemNumber: marker.itemNumber,
};
});
return (
<TransformWrapper
alignmentAnimation={{ sizeX: 0, sizeY: 0 }}
wheel={{ step: 1 }}
zoomAnimation={{
disabled: false,
size: 0,
animationType: "easeOutQuart",
animationTime: 2000,
}}
// velocityAnimation={{
// sensitivity: 1000,
// animationTime: 1000,
// animationType: "easeOut",
// }}
>
<TransformComponent wrapperClass="h-[calc(100vh-60px)]">
<ImageMarker
src="images/Map.jpg"
markers={imageMarkers}
markerComponent={Marker}
/>
</TransformComponent>
</TransformWrapper>
);
};
export default Map;
+47
View File
@@ -0,0 +1,47 @@
import { MarkerComponentProps } from "react-image-marker";
import { markers } from "../../consts/markers";
import useMarker from "../../store/useMarker";
const Marker = (props: MarkerComponentProps) => {
const { hoveredMarker, setHoveredMarker } = useMarker();
const currentMarker = markers.find(
(marker) => marker.itemNumber === props.itemNumber
);
const handleOnMouseEnter = () => {
const hoveredMarker = currentMarker ? currentMarker : null;
setHoveredMarker(hoveredMarker);
};
const handleOnMouseLeave = () => {
setHoveredMarker(null);
};
return (
<div className="flex gap-1">
<div
className={`flex items-end transition-opacity duration-300 ${
hoveredMarker?.itemNumber === currentMarker?.itemNumber
? "opacity-100"
: "opacity-0"
}`}
>
<div className="flex items-center py-2">
<div className="bg-white px-2 py-1 rounded-lg">
{currentMarker && (
<img src={currentMarker.popup} alt="1" width={48} height={24} />
)}
</div>
<div className="relative w-[5.5px] h-2">
<div className="w-0 h-0 border-y-4 border-l-8 border-r-0 border-transparent border-l-[#fff] absolute top-0 -left-[2.5px]" />
</div>
</div>
</div>
<div onMouseEnter={handleOnMouseEnter} onMouseLeave={handleOnMouseLeave}>
<img src="/images/markers/1.png" alt="1" width={48} height={65} />
</div>
</div>
);
};
export default Marker;
+48 -4
View File
@@ -1,13 +1,57 @@
import { useOnClickOutside } from "usehooks-ts";
import { useEffect, useRef, useState } from "react";
import SearchPlusIcon from "../icons/SearchIcon";
import OpenFullscreenIcon from "../icons/OpenFullscreenIcon";
import LineIcon from "../icons/LineIcon";
import useModal from "../../store/useModal";
const ZoomHint = () => {
const { setModal } = useModal();
const [isTransparent, setIsTransparent] = useState(false);
const ref = useRef(null);
const handleOnScroll = () => {
setIsTransparent(true);
const timeOut = setTimeout(() => {
setModal(null);
clearTimeout(timeOut);
}, 300);
};
const handleClickOutside = () => {
setIsTransparent(true);
const timeOut = setTimeout(() => {
setModal(null);
clearTimeout(timeOut);
}, 300);
};
useEffect(() => {
const map = document.querySelector(".react-transform-wrapper");
if (!map) return;
map.addEventListener("wheel", handleOnScroll);
return () => {
map.removeEventListener("wheel", handleOnScroll);
};
}, []);
useOnClickOutside(ref, handleClickOutside);
return (
<div className="absolute z-10 m-auto top-1/2 left-1/2 flex bg-[#0D192266] p-4 text-white gap-4 items-center">
<SearchPlusIcon />
<LineIcon />
<OpenFullscreenIcon />
<div
className={`absolute z-10 m-auto top-1/2 left-1/2 flex flex-col items-center bg-[#0D192266] p-4 text-white gap-3 rounded-lg transition-opacity duration-300 ${
isTransparent ? "opacity-0" : "opacity-100"
}`}
ref={ref}
>
<div className="flex gap-4 items-center">
<SearchPlusIcon />
<LineIcon />
<OpenFullscreenIcon />
</div>
<p>Zoom and Move to select a location</p>
</div>
);
};