From 1c906ce3716691b0bfd4e5317b0b6fb5f0735286 Mon Sep 17 00:00:00 2001 From: zojgame Date: Tue, 16 Apr 2024 17:57:33 +0500 Subject: [PATCH] markers, map, button states --- package.json | 2 ++ public/images/markers/1.png | Bin 0 -> 17397 bytes public/images/markers/popups/1.svg | 9 +++++ src/components/header/Navbar.tsx | 44 ++++++++++++++++++++--- src/components/header/NavbarTab.tsx | 33 ++++++++++++++++++ src/components/map/Map.tsx | 43 +++++++++++++++++++++++ src/components/map/Marker.tsx | 47 +++++++++++++++++++++++++ src/components/modals/ZoomHint.tsx | 52 +++++++++++++++++++++++++--- src/consts/markers.ts | 18 ++++++++++ src/pages/Main.tsx | 18 +++------- src/store/useMarker.tsx | 14 ++++++++ src/types/marker.ts | 7 ++++ src/types/tab.ts | 7 ++++ yarn.lock | 18 ++++++++++ 14 files changed, 290 insertions(+), 22 deletions(-) create mode 100644 public/images/markers/1.png create mode 100644 public/images/markers/popups/1.svg create mode 100644 src/components/header/NavbarTab.tsx create mode 100644 src/components/map/Map.tsx create mode 100644 src/components/map/Marker.tsx create mode 100644 src/consts/markers.ts create mode 100644 src/store/useMarker.tsx create mode 100644 src/types/marker.ts create mode 100644 src/types/tab.ts diff --git a/package.json b/package.json index 8e18b2e..5d0f40c 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,10 @@ "dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0", + "react-image-marker": "^1.2.0", "react-router-dom": "^6.22.3", "react-zoom-pan-pinch": "^3.4.4", + "usehooks-ts": "^3.1.0", "zustand": "^4.5.2" }, "devDependencies": { diff --git a/public/images/markers/1.png b/public/images/markers/1.png new file mode 100644 index 0000000000000000000000000000000000000000..a3ed737322052870b4e15a1e9b6000a773222578 GIT binary patch literal 17397 zcmdRUW0NjC6Xw{qZQHhO+qOMtY}|u0wr!oUZQHhI_Ida7{(()UuMVoaQmIa=yOSs- z1xa`q92g)VAb4phF_r&#;(s&@1^OSxZpO^~$Dp00v|WLKh`Ihpz~br5MnFKIKuU6I z;=jMYn-|Xq*DoulPqRmldsok6yZ7@akCXfN!`pXfw=ZjF&nGv}{yu)whYxC+#=F}) zGh-tz&R$Adw&LP4lFBw3I#xnr%2ae*IJiXeY8Hxm-iLep2BvNs%M0Sdf^2-s;URwn zg`}7`W!BfWq9Y<59bCCZb)*!H-Q4}f_V4Mo|qUJRg~0p3>||5f+vOsj0}vD6H`b?$zx&?=O@P%l=Z}=RAr^* zmS$%}W%PD8mOZ>e{DWdt4E;3?-KFKVxcQ_U12Sn@#PkfT96e*LEp6C^wEQCS^flF$ zWu+LHcx-GOEu12`xP@98n{{*yWhF%aX626j>(Ms#lU8>$(bYUXJk(H>o19wkad+$Q z?zHz#Ra4XDFF6*JbrWxEm>Jutf{I&L&N%;Th_mI6Q0rL z>lf}7oKaI&77|xv=9!tF1&E5vv@kU*tL~^ME;4jZO^u5>zj|hB+^XzWkS zs?oI!Jv%whsT)bpYZxA#;gK-v8Jx8gI+zlY{`5=#gF6F)!P z_zyq7zW>9D!mR%g5(;j1^H@=p*DJBfBguB!hHJb0K30^%eTdvb^li!2NCP>I#VF*tvL8=7??YIO) zW6q{R*c3^5C`+{fL{uC!T8A7?d7);0IJ|lMWrWRP;i)jQy2^jjgU5H3|4Pq}<8wvY zD${T;K1PwC*D&|-Fa}ZZmM_r#iP-t!XONQD@T*#pQsD;)k>DPDaI_C@?sdtFkKl<> za-l8|I-k<<@KHOF-#sx`;RyffYB?|Je#Wbt)&3P9EZgt|JC&>7LNqo79J36D<2p%P z)73yYD#hExvfDKvceiR|+uaTVvuJVD8?47G#$R2iJB6=EC-H7dK6|_*^~ZfjNYTK! zKMEAc+s(dzYA|#GA%fq|u#Mmp)-9;SQh*_`2Ajt#{Fw|aX=lT&QRQIO8w@yP0`dtVAOxkcbczSG)S?y=(1R|2rRLCG}(6`I`yMrJu2*=^|eTsk@TH;ZDv6s~<+QNlnu zJ{v^jP!*!4JzB@$!9&NyBN&eAwkq4wstc4`oeGny;yiKhQpj6RgVkulJMcT4k@#oE z@VwxSwJvzqakTX&cF{25%$(sVq}$m*#GBBDV~PBII~QKTTyP#vgY(hMuScU1d_-Kf`$^qxYmjpUgB${ykeVtMH&hMqJ~m(aUf{#7|aPDDObm zgkV0J-mwfdO01G(D&~{EaIGJ9^xf)@?Jwp6Lb=+Ybz-zAwxc<~2V>R7n4Jp)G!~Ix z40(?cVgy3_>IU|aeaCZ*pQNZ=Diy`vbzqrv^B*}4PLB!iV~ORLEZTc77q)-YiE=kb z)5~v3$LgSo%T^zuvwo5DQ&pwG(+8ehzzr~6Dzq1L%NyoKy2In`y+0EK1;@;yB_fwv zC&iyO(0h#>T)TvUD~^@A@EYO7hXbcU&xF=F)EQ3a#Se^upoRwcjYx;AmYCfXJkd%i z1$eEj4}!rAr4|+^@mzr#d_2(Uf#cAwnutDO__x1}teeo0pX`MiCL9@Z(XGEvUdO3xvpt*jg@ zHz8z{TJ&lT*E4ExO+EU4`q%{TzpE~&(Jdzgn}-1$?k=wSd4@S2JBumbNQF zrJwai|4c4EM^-AD7?3mwhk-4Gt*Je6O6&=Bkjp`=^aZ>UB<+R^7XAXE#+_4$T_ zAy)tUX8h&n`lqhbMD8A$^WArha};P*iZr5!Lu}6q6syOHg;!$Pkj_jw+p5?oe#30| zi#Yo0Gwttt-`Ri6%Vyq~Kb&>dC*!E#0y%+pSFJg&TYo2_#oa^%ke#qckL*k}{o)^A zS-n+Yu;-X2;Qu{sN#<*kc(jmr0)co+tG-9y!NWc12N~yo!e9t#wN;(GF=yZ^`WN@=w9pg4o>|^<51-n5peJE`{x-s4dLrcM*<&G zk7PsU`Ew~w7wb(%R(Mj7z8F*?GFqt@^?v7sI z5x0H1gI&Td?ftEe#<0k)KpHciFCTqZ zbC%9bTGzR3z3uhN^Y-^;gPpj!XI~d5H*+IRmdl-|z-RMk&GlmBtb&@4t6bqX=h@{~ znsyfC%`U~hbeg5G+oCp{SE(MVS^u6PI3^lK1+8QcC_0*?K;U1@0Y=h?kVY(@UjawF z)e_7Khk(qmG|zG?&zk*}>0&0EEpN*D_{O#wYv8cKmV-sp`e^fU7~$=!ui)R?)4z{B zUc#pd(iM$m;>+(HA#yY-@ rB*&=(Qy&d<}PVqtFbcn5U`^ly*)iiC3831(0`_z z6~tUu`{uDXx&vCXbk6%h^&~j8l9EoCIf7?9kS?#%g*4)J_N%hrtaSbQa$(78KAC8^i2%&hp zPbEv^8x))Ji@p!PvE&3pr>Hv>sO(rGv3BI?n?@1Kul+F={b7l$$jHphzQs0ylF!d1 zL}NJv2QW;((yD?s97*x3wkIEU;3ggyk(!nFBj2ND@|2~~DFK_5ZS|7^cPEWMJ+b;l z=0P~6FX_&=DBYUd5K=jt&lmqC7X+0(*FhZdiVG<@lKQ@`-xNihp1e_5Jqc0I=O`E5 z03TNH=Y&)u`9K3oy!)Wsq$n{rA8yb(J#l$1=ZE4Ll*_d-o5aNTPr{ zsoaAJiS6&_D^P|KL6Wu*j<~WYFT+g3Aw^SRc)GdG5iRNc{xri|Uu-Jk0L~psQdaLm zi{30V$_D45jx!B6rX;#mpk$Wjbf_=Z_K5%mHAlCMao1&iw5}v6J&*6BnVRfqP9evX?M?L zI68E^KB&ua(zv%~OlqUBFeqJkOqlX{O5Q>F5DqFYB^d+!twT(H&R!v~y9Ns3#kv ziXA&Ak#J*OTaQ{zef!rMGh%=KiS zUp40HN?PYxFxiWWIQs1$q_9UBI?biPs;!tT`;N331t(cF--QaQd9x{Z(*D&gQ+9)w zt*g5uXge#_!xV%XTJOuj%gU|J(Y9A$sB<-83x&%*BDJ;>ve@vMNE2B!04f6#PyX?2 zO--Oj9FUTbvJlaoaGpBS{p|FgJEj#k z;2)4qjLLDMyzjz$V{WRh?tmU->y$@?96}FgN99vL!{BP&U3eQoHOR)PV4^y#&j+&sO@FHLs--UaOc4e54|X>dz=TZFic z4N3TDv-d_9^Fae0WHSDi-L2nU5Lu^fTa#w%ZXkl!_M5f|*U|2yLZQST9=x)Xp>; zD-);St5Q&4%@?+VGJosMsun**vtf!GrO=bOn4+!8MjZY`f1`c=MOycIwr0@HKga19 zf2n-%D#@8yUCo^MS)Yke#bYuRHx#!56hBvx$`nPnF>Jd!p(C6E0eWwaq{h=#{9+GR z7p{TJxSOy$0L7nLfbM`D&@c36f3WNSbQBo%v>RkV9)H=s`Z)`C@6`_q=4`U~#K2Bv z&1`dk6N5kue1w7m%=w<^^fN_iWr}8w&Wqk_xw$!c=y?r~Mep+sWm2BIbfIRbD_^XhE2~6&#kbBoFjg&>4^ZYE#IU6p|TdsD=OP5toQ3$66r1wY%5Em;6aQfUB z)&8;Q*Rrzrb`F|1x~!#fm%hAIuBZ^N0Cx{n9-^m4Ebz_Yaz1#&jEaB45c2Gm#Qd80 zRP}4yHSoUOYnchJ=|07SxChRru4d)|#o&fQEw*5`^k@ydIG*&AFtBg&r)(50PC^## z5>HCp5D=zruVx2FQSlU1xXX8j^Y4H44B(hEoF7f_{zV_#M(gnOiflHbMZD2|_X{Vw zVv+#UK(A%j4LIQ}jJ9K5%*U$h!6~y@SJHqOP%ZakHMO;kiQxua8Yv`T25W7Xy;$A3 z`wBf=*F;n-!F(kWOvVq#gP;<+HdFp68>0^bFGFEFjF{e`=FIN zw>KS}kDHm+e^Tf{wMK%8q2h0>hWQeKrg@I~m3-Smpf_4D%w{L^0uEX{s5A|j9A_}Q;F@AkMtLtLNS&ra<$ z85*oYtq?GzuD)~}M9^q$O73Q`yq)XCv$liI zP%s*$vbn&rsK31*5&cjktBbm@$^3Mm_Fr@h^iFbig$UhBa3gv>7V#yp$j8s3fWF+( z&|jmgQ>jM9#MTg2t2)1+vZO}Wx#Iu2J$>rgslyoZ+BnPwQ8P~d`nLiy8Ac}NhE9g3 z4!)4OnmrE!fp0b7GccdisPB!S1s08el)r}0UswFXV$xDymZ4coK8#F-pFg4J*H~jE z6OW<<#h+bT1fi@FydsBGgB@55C}eqaA5I1SVomibls_GvQS33kN7oMr`s znvmJtnul<5slDo34-fF+EU{!-Pe9ad5D(u1V_DQ1Kmck`yNOe%jnoqVKp#>r$yF zjIIu0+(zLAYM`OdkLBgkz|uhRkr%3crBq*U|Dp6B_&Pr{G8DhWu~`rM=1n2TJ@AcJ zO5NNOd8NFopB|q(-FN*JmRdgbI<%;_K*9vdWl`*DC(K`1RaK3u z7U3%S+J$C(nylY;UE0asW_U18BooVC?_D^d;twAc{{!G4Z7n=(?0q-d z_j5CvrmWf&sk7nHs%eK;eTUEBGe<}6veLiO8n!B4Uh7GVb}7lSn@$+hb#<5T)t|dW z->K6RQFv& z@^BE7MrO&-Mk9A*cnqm!Miat>_h;;U#AOjhIbd0T?iv-+7RUga!gf;ZyQG|J@l%MH z&rr4+6mnE%i9!5FqnyIReFLmJxb3HY-o7^qDF2Y4uq^CqqU|Xw(fz2IpgWj1Q1zmv z#E4DilAgrxR%TP8Y44GIMacn^fgNDfn=7XU0;ImCQ!9MInhH*y!6g4E(W)f^5g|UN zS&h1yRPtBN%cAPB^qu?P&vw>J2L|*&i0+d+_VKvGNeZEy+_l)(bjM-f3RDnUYGBvx zUiwz6(ki|A?MJl0oz16T)1X+lam*dZc|Kg<@vr6^JMoi3)X=zvI00*0QZguI-bOsalJYtkmu;#W~wIx03-wiHdL zc#wK4#ooAyK0yGZi9sMeS3(fz@`kgF_^1Z-*|=m$cA`C$=phq&%ycT5mCRMi{U zmO_Q(;BcfBEpDvhon%q)3NJ^+SK z*`I*b6^V$M-46Hp3qI=u2E`%|FCd6sk^SMbb%Z&?Z~UI3YosxDTxy%FReIvcms2$3k@S3mwxXQ*Ivs6>)&g{Y@R17XOZgo<7tS!O4; zs$t6hLJlzhV0f$_VIr!_^6l*Oc{z7!~d2Z`P86O-sz*s?qxvL^dLfm|=5f zO>;iKj3oKg_?kB&;Eeiu)6qQ!7_ffuhXPWMXr=hc`H~y}4)5qql2j3@znFzWCl88z z0Tj$T5xb0s1qTD{ly8XEL{XC#I@9n$Tt_tTVjEBMMtX8`V;{mNUJE!3EG*djDhVT0 zcZ7dmPdah{wu?#qlhEz;ND68rRdRJt3v`cK%%n_BITsxfDqkU+gv7~VY(#A510;@D z7~Ox7yM5NRZzBz9QtZ5B*AJ7WP~fqPtpun$A(64}q8tF{MmyE=9j zxVC5KZG&fs^OU!H9UiCqMy@x1&?G+0)FHvJx28i#J!V3-KGsXm1|0OWOhhYHGDWjv z`-ZZ3;j76>86zUXI3`swKLpAt^)KB;MeC^|Uw%zz&>NTU>&?2IE!Goix9!`3cNmc3 zsEjQ+Xdny4gA`X!Rde}j{AdL@`rEg4dukoksOllO8cnbeQr<+2X+u~H3ISK96qyRM zq1?1O8paQR(KS$pwda7Vx@22h1pVpwMMMm_L#n;UC5j>h3mXl%rWs7G+s?)Tq%n3p zf4iK0N3AsIV?cM z{QNpOW&TUP2s>DPHB2uu2JJ{TPNP0I9e^HUjuCcoa0^oh@HEt1RHMnl0jgL|bz#R$ zf?g!>K&ia{*nv3p=bvV1%m|Ier)DuszX`fu-H#a3xdp4R@rQ<64aNr6RAWqnLOXod z>tfKfDEqk^#F8)3s89>H(IJkLz@^o!Dv#pmE~u#yd_#bahk#CiIlAil?-eXF_LwRG zfatDGP;^9`r^@cO=&+Qg@8;G5XacjLNo6croN^Q6=LaE0!O2e|QV1W<LcmB7aoRvRJOJ0>QQpP zk6WQnDJT6oysVc$Cr5YdcYV#VVqUF+Lg(gdD%JGP|-_{U1{rJbE&(8&9Og@vwHVe`2;7YZ@Kk?EBo!>tX!k>uX@j zYw};*sApi&HStSOP1wPA^!q{^=4a*1y!z^Lb2%jJ-(2n0Bb$t2|0iSy*e6n;56*TN z{2>O^$-kkGN&?3y?E}3#Cv6_Bd~a7z9Wikn%yQyjY?Vd`7m2RxdOlWUM=z8p(4|A2 zTuseS^`{W0Ea%N0NCiq}RUI3wLn{oG%9Ykc;Orl>fIK;G{m{_(9fO|9eJ6OE@Q)~- z{0h#zd|mbv%O}VLIgA9&ne6TjT6%tUJd|++3{9x^DF!!Pa}aLWB%FoeJ?uEY4# zCdgCZam=1}SAK0c(mHm)G1F`d>^S2Njwi>f9yIq`YM}zx9>VXmOpTu*z=5k(6`NWNIFD=L)O@r>&G%57vgU1^l7MN(p z!owoUdSM?8+1u>7apOZNt`v8CtSf2bvFUit)A9maf#(_0cp& zJmT+-2smj7QC~knzLsSMO8q8^VS|?ydpb|cI;Sr}lR3D5Kf&sQcEvj+Og_o=N@oZS9`r<+G!Qu=m_ke&1L;v>|;EYJ_EaLP{ z%hG;)3eB(ywzj^Gs~`51{(rJKM16Go!#zwv2^m+h;rSm#F1o2P}rli48N`Bag3%Tj3d9Kjd zg4^MHX5?_VKpHnkr>CkOw`f zqAk+!Fk^D!C%9cnl6Lar#=oZ%R7ancF5IUPllhYHVBVaTA%ba}@L^R#bG{ghpr@(+ zE$9=Ya8gHQ;3MY_i$)vPvm3i7lfM+6)bkZ3ZQ#b~e1L?q!%4!f8P+|F(^rjjj^6+v=(`<~*OLvw3of zwc9qZ@2I%<i;~R%HT<;Z=?2FX8k3HbS?6E^(l9? zNFn8HZ5FKptGu1vr`PDStbNrs;UbD8Jajq8oSDhj7tIg_`O=LN1AOnwBW(;TYK)kg z{JQRxc{Mil>~(Qf50KDt+}&OA7ngPtpHMDUB{*z(j&AMbj*M+k5gwe39}V*{q#( zRQWk_q$%Vn!LI@5NYbtADKOE>@aJSS5diB zc#z=wiKp=wYgz+$sBdP_nU3+Nq=a>qbd6}RJ~oReTaf|a^9T6Nw_u2|ip4TAwuJ)} zeUh6nU5Q3K6j~jQ_nZuaTxt(j6cI7F*IXaJElHB@t-)1dNNxNkm#Bmtyw(+pWM%&m zED2GqtuZ0=*#Aeyr?f_0z34*KB^rvVr_Mw+VCNnkHkP)-s1PRy^~{Uzo#AO$7hii{ z7k-ys0AaCs;qS!9S?)ggCw3-=JGX?p)ZzFFYpB4!c*ZL~32eMn_RdT*twv(t+*x!P zF;_yUo54W(Q#wbrn?7J_{P3zHS=k^9 zYUlOkX-4d1u_iCboq8eDy)_|72Cd0d465iuULqp?3 zOM~Zb_Uh#Fb{&Nt>0@!SzPVV2M`WXz5}xg&;W^)u0xqJVS~b?+uk)uJ*RY3gcZ2T@ z%xg}U`r>lAxd5%#^xY`QZls8UDD- z*Bt#F%o@JZdnph@aiuGf&wbwo|z2c-hh^yOvArNQE|5^Iz*p0ySx;eL6uS56kcsS zX5j|ANxNPUH88>a%&;7AeBdIqoNL(EXw7p8vg6~i67I21**s}d-hpDv`*k7kDgkU) z7{Wd_0-?2Jf9O&ctH59UN^7(hL^P((v`CNO{^{S3NlJPEoj3Yef5#A>i9o4Y8yu-{ z!sQw$3>xm99km=9I(2`6&cKPeJ>`(k3EzI{72isL0C*HQb!B4nd)ObOxJNnHke5hL zPhU!Ok+DtAJZhuO7ORVuXw1T2F|W6hjWr` zE``@_g_(~vmuEop&!zaS`y6#(Hf1L1juVVH z05>Gjr>_8U7ks9L)H2Cbm2gWsxTxk4uMlff^7-6My*7Sh#jL5_(rA#k~ZRmAda z)Cvma>O<>tZ!pj#P~}<-9IC&^v`P*PFW!HEJIq+LQ%K3OF|`ZOF`QFCtrHdLl4URH zi&KLbY|HD{*UXRETW9P)TyRyH=WO<)>FkafBGY2l$CY{(0nR+%xnr>EqbUY5jzswJ zwLnC61TILGRYW50F>PaWdhBzMr5#wH5g^}(BZy~$*h;BejKRF0V=fm1o0}pyXvyJ< z42R@{(nzBBp zV87G6yN;UcwM>ubyF|Chzj`tlR`DM}C6 z1FI02S7Q}4=i)iH2EkG3!GhK`TMEnU+Zi4Qspvl=UZDavG3jw+Yz@bA%-vUlF37&z z4P3UsLK;gHLxCEnh=Y;IiJF7$rc036i?O&_24bY8?1}?N0r%CVS@-fZq@nGzj3{A; zu?`1~#iz6#R$snev>jh2r40uaqkl;}gCAgK#ZRRR1HLEnYk;T=OYUs`M=T}bY0^(J z;`(F=zIHvDunXcZA$xL#-MRpJ5HRZ$DpvqqKx+3KIhrXz0w>dvleW-}!=Y|w*K7}1 zyLqy{gpxl@XQ63KHRA+9;4V#idi_(|>ge!FB0&h;$9#@V+$|2n{&#;GghF052<1tOYznHg%v&#=Y5 zV`0j7CVwSYqv?RG*8aB04zs3R1(FXn-C#X{;qmWZO`<%AG%Se@;-+EZz<9n))h06d zclitpc1^7B>1M+ij%Rm`k@OR30Jr-#i&(z<%jba1tQ=ZWIE37YT`pmjtackhL=LtU zK*scYS{6Mb!a&%BU@VX=+w#wQiH~D*fL!Ye$xMo3dAVr$I(4^YtC!#4eXpW1^k^bw zrzEE}(@#9hZhV1{-BG&cB;1`i&R`JQGJf@UvbE*4xS?!60GNekOVZdpai8a(usxVD z4+5refeKfbk{RT-#JO5?3vm1vb5e3Xd|8=apD@2iwm<5ZD#7llw`1Sy^W3n_$3@(InWmu*;bp;i7oz5~^w-aMe?Kpu1E_tM z-p+xGDtg_v2}d+O6p)z`G=!(9snweCOE_;~y3zQl-`3MGp=9oD9e3#Pr}X-me?Do2P9v%#R2&G8N3xW@y|`~& z#!=L{>|JZx54`O6U)C}*M^Ph0J`z`&tFj(GktZ-Y;1M7oAoq{5udh8b$hFFcNW!(W zAqRRhN9_?HLBx7i2G`GkSJ>^+WMb0j)Khw1M4pQ>L;Jqp@@7}->V?GGenv(40m>G0 zolWY?$_p{ZOn7wv@E~A>7K&oIt~e{b4-ZwhA0w4p`l=@A!2Lu7moFhRJ9{4w1%LGp zj4Fs4&I=ehetm!kqmsZhRSUY!i#Lk&F15Y4m({0$g^}$W**-ops0dCCZ}49HFRn1w z0DeS;v#0+I+ylBh(VmYkwrG-vZubpx3AM+Ji6*d;1s=N1A^uQ+fl{=Ykrbm4TL2?H ze^c|%a<$gA;D8-X?eEL%zgj96LS+^@8#BIzrFWLOONBl3+5K)n1~PA zcN)XGUTWN)`^l#%jzcK;KAXcIXSGs7K?V`JB?_22aD!kCAiCId;>)Xz@o#I>OuB%g z@bCR{@NSku5(}}S1xV_vH);)UUZ*K?ZW5(8XuD)}+>x-GkITR;+se{?#7ggXsM{oPt=&^-<6L4WZ`s!7KFg3z+Q_K67kVup3*kcI) zw1o6EQ=zBUllO;J=m83+E@Y)-(ji1?c*Kb3tryQmM;Qx>_pys1_cacrvuphH^)}$S z_=&h#({B>Xts1eT_Cy0tH<9)%ZJKrHQ47=&)h&4fe&^u$!szLecgl$_Q9XfP0EdRz zH$#UK!CSQ$_N*J=fD5s8>U_CK@{1Hnkv=K?cxJ2!!}`i^(Y`)cNjfZ+XF*h2G#FMS z_p=7+>PQf1X{_<4j8ch2cGx`Qx37GJXE9*{6Ux=mV;5dj`F-K`?cU#S)pEH3nRvXE zNhmHTNa$)G|9AJxkM74smYm7svxAv+ZAsB5hX|G=iJDTWt&wxFOnAU0OMW|y&?wb8 zeE5g9@@@3+J{1i_P*}1h@NE*g=td56{zW9}vKV_l;ehM$T}U&-1!cNPR!K(;d=O_0icXBEgj#6)IHe_Iff8Cxf2ja0k$w9Wm)Rv_?C+zW?Kr@DW5yk2s^It z>mOa`%~5eXFORrMd!{uXCYB#hxi@77v7mBrnkEYDNN90B@j7=Ck}ADTt9=)eaC^2t zxR@2wYQ-uC2lqgS<$y`ws@MSA3qT6$&X-=Y!n~P%bE@hI)WhRy8)0>f3>h`$d2*Fw z$D%6kl!cIX-^orF303Wbwp=Y;@BvQHD(!%SwRR_yCEg`LHbfx=$Z183PMS=)3iy~t zRi@4)XS7!|M2>c@Zq0^-goKqN_bP>p;&wM;Uu=#Yx0pZx5k!FsCU61Ta<86afV-fZ zLKDqI3&8$2xkV_o0$JG%r67i@9<29Ii9IPTZEe!R#di&LMXu!v4qU)vzDNO%4TK zXoeRXp?{ZVe@`K54hv0T!G=N1Bt^x+_JJp=hw0Rfi|p_}-y+Z=S(auJXoTn&Lo%21 zH}cjXJCQrL6EjzBTWNes#x?kYCmFNWPQXw7KTKHB!CWl_5V*w%rUzm+0YM5NB2|ip zRHEGL)NnZg@3$gty?pGy(x5to@;wtESx;7MXpxP7C?}198UEu8=8&;_ZxxpF&V`c z7Z(vZ3E!GrYvUhlVon{mp1`g@0>Z?wK4&G!7bl;$-sYGDpTnywWGrCXtJQ#m$~yt% z^I(}V=a{gRa`JK{%ajk?IVf&6^_!ejMQbS2cD~dx%Ft4A)R5q4?M0PsvD#^Z3eb{x zKE!{IXCR({8N}bs_78ub@_B>y#F|o;FN!Z(&7dG-G(Bu~{jPEIvWx2WN~$lD>JGM^ z74yE#dB_t75H)Oml8;i$z>8 z`kRwSk7fH^0ueYg!IA5|##qKN%P99M~ zeTAWbaJ0wS0Gm!`o=T)&Yr*;|v2t5BKtxvP7YTicldl#BWyPCS7KN6Lw z^ycKiDCh{H&53XN+*x09c;A^)yoS795Oo`2&khpfs3IqP?bsnz#DHv# zLD%H^9v<^T1!ZOd$;%AkZiC9eRvc@`I>~eZeMSqs^t5^-%40Pxkd+CT6muF1y+esd zpTDf}?WB9q%NrT2?8^Ssm6y}9*-MauXNTW3#*V$ZUM-1A9V@|KJ}zae{WG9z=P3D9 zY%T>A3c9JqX|M8t3T>>ld*MIM-r_NUjg<*`$KjCr_{d5rt9I}sX|E6njXTX-3aVQQ zL!vmpyD*JhLguYl0_&QQOSaD}{Xd)by}qv}H-X=u^uWCRtg&!eAUJFmS=_^VQYDM3 z=gn5m^EZV69rO)(NsjJ{W;OeRf2A@b(g}hJn>hjgBCKNV(-n0=grBEnW}ycC$`Fr_t=~qkevRn-|u62U`_=T;=CydLd^EwNt}rLI>G5 zbk^a0_nqWHVY3s*me0ZCbZDG2@VfN`Zkd3E@L2K^kgHCt*z!n+BwP_n)@j$Hw{iZ> zZ8Zv^8sGuL7;O#h`#$QK-p=k$1Aj6TG9L1C;z0e=P6uu@gru=WzBHGsBxYePmvAl2 zIA)}$?&i^-Lixu`P{KZKq?Tz?eHz*7$t^-A*EvOBF)e{FKW-wTV#@}b<&*}hce#x< z0|})659lsM*);YE%>%5%!NT6DT_?irLq0fmSi~CN^764lRayz2Q*$9(sy&pTA`BHK zs=eB!&-0~u69A8;uY;THQ?jT%*$^U0rkuyJ1(Jo*|M-4>ut*YIZ<>IAdvyhQS1s7( zp(MLu*9gb3sb8?k)9juu$-t+rl;NNbfpL*Z&7tdDE5I+lboJiDzvrbpEz{;1ir@%Q zV%)VYU72j3d|Wn;PzDbIMTH;a_2YA2Q7{f56^oU^u4^}!99C$0DXED72;dUFR>;(h z_Q^ss=K`-G3fbiH_~R_vcv}ec-HUegC)6=G*1guT`1>|=rGwGldNrIs04v55aL<2G zB=$&vdQ3P9U}X|~I@x_9Rm#nY@bT38QtFIAf_-?^Nz~cmVl6J6MTbW2k5r zN$>a;pIEH|aFvH%%TXw}^0v+oq= zo#FCd#(_V)n4*=RAOV*tniN_NL1%m6?tGctxkWx}_}fF2d?j-K=dHXpSCApex2}(GI9ezwmb5Io^OavsV zzfxvFzp}K3^;-bNMCgm>)vq38~LHfV^Efbwx(g4RVgDNY~ zY}&gE1)L}=5capx$JgJ(7%(NfIveTE+j%a1^)n1wH{GOmx|<*3;p6@Uc$o1H3V5mQ zy+=0$dclMY9OMBz3{>3rtx8f!s$n|E@tuZsJBH;XNO>|0!M<0+hhM_LrhRg50j!97-1p_duh;T{ub1xexIu%)TD)bdS$lL5mlF0S+QMafR)h;TQHxqt zT=o@E~zlBykFOjUnJaK!e7+hP(yUTsB#pzD=n%oeN(BQ-%DNr~EE~fP zuiJNddwRTJOZxilGvZyhoo2vS_>ktH|NrlS1BtBx3q$RIIu1g*Go)D z0J`U@gyhvn&!0aBI_c5g=X23wb)S?tpdd-aB_L zyE72)91<=vf;#E+ix%1NaA4cR&EIH+mxi&kGT1?;SKIcMU*Bu87v!MB2lgc`=3QU9 z{?nbQx-Up_4ry0CJ%ubcO0KQc0_UcjwOfo;&+4 z3qo8&f^$f`4C}&8NH8&MwXqA_sBhZVCSh+O0(6kFY1^YLaE$G}emyHCcFE#?IajD_ z&RrtulylOq3;X~7$<1@nby-_e<7_RBCGEA_^79o;?Sa9ww>*Du)}zID`nSt%g(^CC z^CF2Bkm?|?o1ozYE)C>TqpN4MPWW^=e#Z9gt#Wg>BIM59zexI-^<+2*R1REuisUG4 z;M~nC_sBAuJO_aj)RRk3AD+YFl!rI3Jh?!&vE(}l+Sa{y@!6G2moDAB2_&vOdvcG` aiv<9Lk*l+;RPc5H0000 + + + + + + + + diff --git a/src/components/header/Navbar.tsx b/src/components/header/Navbar.tsx index 5dd2b73..d86ea48 100644 --- a/src/components/header/Navbar.tsx +++ b/src/components/header/Navbar.tsx @@ -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(null); + const onTabClick = (tab: Tab) => { + setSelectedTab(tab); + }; + return ( ); diff --git a/src/components/header/NavbarTab.tsx b/src/components/header/NavbarTab.tsx new file mode 100644 index 0000000..c03c769 --- /dev/null +++ b/src/components/header/NavbarTab.tsx @@ -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 ( + + ); +}; + +export default NavbarTab; diff --git a/src/components/map/Map.tsx b/src/components/map/Map.tsx new file mode 100644 index 0000000..825cf17 --- /dev/null +++ b/src/components/map/Map.tsx @@ -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 ( + + + + + + ); +}; + +export default Map; diff --git a/src/components/map/Marker.tsx b/src/components/map/Marker.tsx new file mode 100644 index 0000000..ce4ce6a --- /dev/null +++ b/src/components/map/Marker.tsx @@ -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 ( +
+
+
+
+ {currentMarker && ( + 1 + )} +
+
+
+
+
+
+
+ 1 +
+
+ ); +}; + +export default Marker; diff --git a/src/components/modals/ZoomHint.tsx b/src/components/modals/ZoomHint.tsx index 3281399..0ce7661 100644 --- a/src/components/modals/ZoomHint.tsx +++ b/src/components/modals/ZoomHint.tsx @@ -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 ( -
- - - +
+
+ + + +
+

Zoom and Move to select a location

); }; diff --git a/src/consts/markers.ts b/src/consts/markers.ts new file mode 100644 index 0000000..16399ae --- /dev/null +++ b/src/consts/markers.ts @@ -0,0 +1,18 @@ +import { Marker } from "../types/marker"; + +const markers: Marker[] = [ + { + top: 38.5, + left: 51, + itemNumber: 0, + popup: "/images/markers/popups/1.svg", + }, + { + top: 40.5, + left: 52, + itemNumber: 1, + popup: "/images/markers/popups/1.svg", + }, +]; + +export { markers }; diff --git a/src/pages/Main.tsx b/src/pages/Main.tsx index 6d7551f..43e43c1 100644 --- a/src/pages/Main.tsx +++ b/src/pages/Main.tsx @@ -1,27 +1,17 @@ -import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch"; -import useModal from "../store/useModal"; import { useEffect } from "react"; +import useModal from "../store/useModal"; import ZoomHint from "../components/modals/ZoomHint"; +import Map from "../components/map/Map"; const Main = () => { const { setModal } = useModal(); useEffect(() => { setModal(); - - return () => {}; }, []); + return (
- - -
- Map -
-
-
+
); }; diff --git a/src/store/useMarker.tsx b/src/store/useMarker.tsx new file mode 100644 index 0000000..5bff8c8 --- /dev/null +++ b/src/store/useMarker.tsx @@ -0,0 +1,14 @@ +import { create } from "zustand"; +import { Marker } from "../types/marker"; + +interface ModalStore { + hoveredMarker: Marker | null; + setHoveredMarker: (marker: Marker | null) => void; +} + +const useMarker = create((set) => ({ + hoveredMarker: null, + setHoveredMarker: (marker) => set(() => ({ hoveredMarker: marker })), +})); + +export default useMarker; diff --git a/src/types/marker.ts b/src/types/marker.ts new file mode 100644 index 0000000..13598c2 --- /dev/null +++ b/src/types/marker.ts @@ -0,0 +1,7 @@ +import { MarkerComponentProps } from "react-image-marker"; + +type Marker = MarkerComponentProps & { + popup: string; +}; + +export type { Marker }; diff --git a/src/types/tab.ts b/src/types/tab.ts new file mode 100644 index 0000000..a98e2c8 --- /dev/null +++ b/src/types/tab.ts @@ -0,0 +1,7 @@ +interface Tab { + value: string; + id: string; + count: number; +} + +export type { Tab }; diff --git a/yarn.lock b/yarn.lock index 7bdf33b..35d42d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1496,6 +1496,11 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" @@ -1777,6 +1782,11 @@ react-dom@^18.2.0: loose-envify "^1.1.0" scheduler "^0.23.0" +react-image-marker@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/react-image-marker/-/react-image-marker-1.2.0.tgz#2f964a826aaa8c6b18c4ce7cedb0284f8eab8b6c" + integrity sha512-HFrzKVnX/hgZqHlxwV7XQNiyMRowD1IAnbsf4dZCEuSzGlGHxAv+sCv/AU1VHHVxFxoHubNL/xYNpGQfgtX67A== + react-refresh@^0.14.0: version "0.14.0" resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz" @@ -1928,6 +1938,7 @@ source-map-js@^1.2.0: integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== "string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0: + name string-width-cjs version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -2102,6 +2113,13 @@ use-sync-external-store@1.2.0: resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== +usehooks-ts@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/usehooks-ts/-/usehooks-ts-3.1.0.tgz#156119f36efc85f1b1952616c02580f140950eca" + integrity sha512-bBIa7yUyPhE1BCc0GmR96VU/15l/9gP1Ch5mYdLcFBaFGQsdmXkvjV0TtOqW1yUd6VjIwDunm+flSciCQXujiw== + dependencies: + lodash.debounce "^4.0.8" + util-deprecate@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz"