-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Map feature #40
base: develop
Are you sure you want to change the base?
Map feature #40
Changes from 9 commits
3361121
8af78a7
e707a99
1271e5c
99db406
d3e9eff
4007297
bf68e1c
5e014f3
cbcd413
01afa2b
b059023
2255434
0b86a90
93cfa6c
8558a35
6470d61
42d0677
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { ReactElement } from 'react'; | ||
import { Marker } from 'react-map-gl'; | ||
import LocationVector from 'app/modules/__modules__/_vectors/LocationVector'; | ||
|
||
interface IMarkerProps { | ||
latitude: number; | ||
longitude: number; | ||
showPopUp: () => void; | ||
} | ||
|
||
const MapBoxMarker = ({ | ||
latitude, | ||
longitude, | ||
showPopUp, | ||
}: IMarkerProps): ReactElement => { | ||
return ( | ||
<Marker | ||
latitude={latitude} | ||
longitude={longitude} | ||
onClick={showPopUp} | ||
> | ||
<LocationVector className="text-red-600 h-10 w-10 animate-bounce cursor-pointer" /> | ||
</Marker> | ||
); | ||
}; | ||
|
||
export default MapBoxMarker; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { ReactElement } from 'react'; | ||
import { Popup } from 'react-map-gl'; | ||
import { IProperty } from 'app/modules/@Types'; | ||
|
||
interface IPopUpProps { | ||
property: IProperty | null; | ||
latitude: number; | ||
longitude: number; | ||
closePopUp: () => void; | ||
} | ||
|
||
const MapBoxPopUp = ({ | ||
property, | ||
latitude, | ||
longitude, | ||
closePopUp, | ||
}: IPopUpProps): ReactElement => { | ||
return ( | ||
<Popup | ||
key={property?.propertyId} | ||
latitude={latitude} | ||
longitude={longitude} | ||
onClose={closePopUp} | ||
> | ||
<div> | ||
<p className="w-40 font-extrabold">{property?.title}</p> | ||
<p className="overflow-hidden break-words w-40 text-xs"> | ||
{property?.description} | ||
</p> | ||
</div> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't need to wrap the children inside the div as you have a parent component You can remove that div or just make use of React Fragment. |
||
</Popup> | ||
); | ||
}; | ||
|
||
export default MapBoxPopUp; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import ReactMapGL, { NavigationControl } from 'react-map-gl'; | ||
import { ReactElement, SetStateAction, useState } from 'react'; | ||
import keys from 'app/modules/utils/configs/keys'; | ||
import ShowWidget from 'app/modules/__modules__/ShowWidget'; | ||
import { IProperty } from 'app/modules/@Types'; | ||
import MapBoxMarker from './MapBoxMarker/index'; | ||
import MapBoxPopUp from './MapBoxPopUp/index'; | ||
import CloseVector from '../_vectors/closeVector'; | ||
|
||
interface ICoordinates { | ||
longitude: number; | ||
latitude: number; | ||
zoom: number; | ||
} | ||
|
||
interface Props { | ||
property: IProperty | null; | ||
isLoading: boolean; | ||
closeMap: () => void; | ||
} | ||
|
||
const MapBox = ({ | ||
property, | ||
isLoading, | ||
closeMap, | ||
}: Props): ReactElement => { | ||
const [lng] = useState(32.58252); | ||
const [lat] = useState(0.347596); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's better to merge the two in one state. |
||
const [displayPupUp, setDisplayPopUp] = useState(true); | ||
|
||
const [viewport, setViewport] = useState<ICoordinates>({ | ||
longitude: lng, | ||
latitude: lat, | ||
zoom: 12, | ||
}); | ||
|
||
const showPopUp = () => { | ||
setDisplayPopUp(true); | ||
}; | ||
const closePopUp = () => { | ||
setDisplayPopUp(false); | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you only create one function that toggles the popup? |
||
|
||
return ( | ||
<div className="mt-4 mx-auto"> | ||
<ShowWidget | ||
condition={!isLoading} | ||
fallback={ | ||
<div className="w-full h-full mt-3 sm:mt-0 bg-gray-200 animate-pulse" /> | ||
} | ||
> | ||
<ReactMapGL | ||
{...viewport} | ||
mapStyle={keys.MAPBOX_CUSTOM_STYLE_URL} | ||
mapboxApiAccessToken={keys.MAPBOX_ACCESS_TOKEN} | ||
width="100%" | ||
height="50vh" | ||
onViewportChange={( | ||
viewport: SetStateAction<ICoordinates>, | ||
): void => { | ||
setViewport(viewport); | ||
}} | ||
> | ||
<NavigationControl className="right-4 top-4" /> | ||
<div onClick={closeMap} aria-hidden> | ||
<CloseVector className="text-black bg-white shadow-xl rounded-lg mt-4 ml-4 cursor-pointer" /> | ||
</div> | ||
<MapBoxMarker | ||
latitude={lat} | ||
longitude={lng} | ||
showPopUp={showPopUp} | ||
/> | ||
{displayPupUp && ( | ||
<MapBoxPopUp | ||
property={property} | ||
latitude={lat} | ||
longitude={lng} | ||
closePopUp={closePopUp} | ||
/> | ||
)} | ||
</ReactMapGL> | ||
</ShowWidget> | ||
</div> | ||
); | ||
}; | ||
|
||
export default MapBox; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import React, { ReactElement } from 'react'; | ||
import useResponsive from 'app/modules/Hooks/useResponsive'; | ||
|
||
interface IProps { | ||
onClick?: (event?: React.MouseEvent<HTMLButtonElement>) => void; | ||
} | ||
|
||
const defaultProps: IProps = { | ||
onClick: () => null, | ||
}; | ||
|
||
const MapButton = ({ onClick }: IProps): ReactElement => { | ||
const [isMobile] = useResponsive(); | ||
if (!isMobile) { | ||
return ( | ||
<> | ||
<button | ||
type="button" | ||
className="w-[80%] p-1 bg-brand-bold text-sm text-white rounded-lg px-3 py-2 mt-3 " | ||
onClick={onClick} | ||
> | ||
Voir sur map | ||
</button> | ||
</> | ||
); | ||
} | ||
return ( | ||
<> | ||
<button | ||
type="button" | ||
className="w-full p-3 bg-brand-bold text-white rounded-lg md:mx-auto md:px-16 mt-4 " | ||
onClick={onClick} | ||
> | ||
Voir sur map | ||
</button> | ||
</> | ||
); | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is nice but you don't need to create a component for this button as there are no extra kinds of stuff that you are handling. There is also no need of making use of You can handle responsiveness with just tailwind. |
||
|
||
MapButton.defaultProps = defaultProps; | ||
|
||
export default MapButton; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import React from 'react'; | ||
import { | ||
defaultVectorProps, | ||
classNameInterface, | ||
} from 'app/modules/@Types'; | ||
|
||
const CloseVector = ({ className }: classNameInterface) => { | ||
return ( | ||
<svg | ||
xmlns="http://www.w3.org/2000/svg" | ||
className={className} | ||
width="53.7" | ||
height="53.7" | ||
viewBox="0 0 53.7 53.7" | ||
> | ||
<path | ||
opacity="1" | ||
fill="%23666E6E" | ||
d="M35.6 34.4L28 26.8l7.6-7.6c.2-.2.2-.5 0-.7l-.5-.5c-.2-.2-.5-.2-.7 0l-7.6 7.6-7.5-7.6c-.2-.2-.5-.2-.7 0l-.6.6c-.2.2-.2.5 0 .7l7.6 7.6-7.6 7.5c-.2.2-.2.5 0 .7l.5.5c.2.2.5.2.7 0l7.6-7.6 7.6 7.6c.2.2.5.2.7 0l.5-.5c.2-.2.2-.5 0-.7z" | ||
/> | ||
</svg> | ||
); | ||
}; | ||
|
||
CloseVector.defaultVectorProps = defaultVectorProps; | ||
|
||
export default CloseVector; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,18 +23,22 @@ import useResponsive from 'app/modules/Hooks/useResponsive'; | |
import SearchContainer from 'app/modules/__modules__/SearchContainer'; | ||
import Header from 'app/modules/__modules__/Header'; | ||
import { useSearch } from 'app/modules/Contexts/SearchContext'; | ||
import MapBox from 'app/modules/__modules__/MapBox'; | ||
import RelatedProperties from './RelatedProperties'; | ||
import PropertyCarousel from './PropertyCarousel'; | ||
import PropertyDetails from './PropertyDetails'; | ||
import PropertyAgent from './PropertyAgent'; | ||
import PropertyImages from './PropertyImages'; | ||
import PropertyDetailsDesktop from './PropertyDetailsDesktop'; | ||
import MapButton from '../../__modules__/MapButton/index'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can ignore |
||
|
||
const PropertyContainer = () => { | ||
const [property, setProperty] = useState<IProperty | null>(null); | ||
const [isLoading, setIsLoading] = useState<boolean>(true); | ||
const [agent, setAgent] = useState<IAgent | null>(null); | ||
const [readMore, setReadMore] = useState(false); | ||
const [openMap, setOpenMap] = useState(false); | ||
const [showMapButton, setShowMapButtom] = useState(true); | ||
|
||
const [isMobile] = useResponsive(); | ||
|
||
|
@@ -113,6 +117,16 @@ const PropertyContainer = () => { | |
setReadMore(!readMore); | ||
}; | ||
|
||
const openMapBox = () => { | ||
setOpenMap(true); | ||
setShowMapButtom(false); | ||
}; | ||
|
||
const closeMapBox = () => { | ||
setOpenMap(false); | ||
setShowMapButtom(true); | ||
}; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make use of one toggle function here too. |
||
return ( | ||
<div className="container mx-auto px-0 md:px-8 no-scrollbars"> | ||
{isMobile ? ( | ||
|
@@ -133,6 +147,15 @@ const PropertyContainer = () => { | |
/> | ||
</> | ||
)} | ||
{openMap && ( | ||
<> | ||
<MapBox | ||
property={property} | ||
isLoading={isLoading} | ||
closeMap={closeMapBox} | ||
/> | ||
</> | ||
)} | ||
|
||
{isMobile ? ( | ||
<> | ||
|
@@ -158,6 +181,8 @@ const PropertyContainer = () => { | |
isLoading={isLoading} | ||
property={property} | ||
agent={agent} | ||
openMap={openMapBox} | ||
showMapButton={showMapButton} | ||
/> | ||
)} | ||
|
||
|
@@ -196,7 +221,7 @@ const PropertyContainer = () => { | |
</ShowWidget> | ||
</div> | ||
{isMobile && ( | ||
<div className="mx-4 my-5 md:container md:mx-auto md:px-56 flex justify-center items-center"> | ||
<div className="mx-4 my-5 md:container md:mx-auto md:px-56 flex flex-col justify-center items-center"> | ||
<ShowWidget | ||
condition={!isLoading} | ||
fallback={ | ||
|
@@ -209,6 +234,7 @@ const PropertyContainer = () => { | |
> | ||
Contacter l'agent | ||
</button> | ||
{showMapButton && <MapButton onClick={openMapBox} />} | ||
</ShowWidget> | ||
</div> | ||
)} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,8 @@ type kType = { | |
ALGOLIA_API_KEY: valueType; | ||
ALGOLIA_APP_ID: valueType; | ||
JWT_SECRET_KEY: valueType; | ||
MAPBOX_ACCESS_TOKEN: string; | ||
MAPBOX_CUSTOM_STYLE_URL: valueType | string; | ||
USER_ROLE_KEY: string; | ||
AGENT_ROLE_KEY: string; | ||
GUEST_ROLE_KEY: string; | ||
|
@@ -22,6 +24,11 @@ const keys: kType = { | |
ALGOLIA_INDEX_NAME: process.env.ALGOLIA_INDEX_NAME, | ||
JWT_SECRET_KEY: process.env.JWT_SECRET_KEY, | ||
USER_ROLE_KEY: process.env.USER_ROLE_KEY || 'KF094msdkdE8RL', | ||
MAPBOX_ACCESS_TOKEN: | ||
'pk.eyJ1Ijoiam9uYXRoemloaW5kdWxhIiwiYSI6ImNreW4wZXBwbTNsd2EydW4wamJ1aTdidHgifQ.zVkgrvMk02fZiJFaV_jkDQ', | ||
MAPBOX_CUSTOM_STYLE_URL: | ||
process.env.MAPBOX_CUSTOM_STYLE_URL || | ||
'mapbox://styles/jonathzihindula/ckynaitbt8tyh14qpylblnbwp', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Read these keys from .env file. |
||
AGENT_ROLE_KEY: 'oPer849zcvDJS', | ||
GUEST_ROLE_KEY: 'EGsdg4ma48LT', | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you change this prop name to
onClick
as it reflects that action that has to be performed?