Skip to content

Commit

Permalink
feat(component): update map settings display
Browse files Browse the repository at this point in the history
Pin is now like the Map page and, when clicked, displays the popup

fix ONEARMY#3856
  • Loading branch information
Lahuen Garcia committed Sep 25, 2024
1 parent ab5f426 commit c558381
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 97 deletions.
10 changes: 1 addition & 9 deletions packages/components/src/MapWithPin/MapPin.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,5 @@ export default {

export const Default: StoryFn<typeof MapPin> = () => {
const position = { lat: 0, lng: 0 }
return (
<MapPin
position={position}
draggable={true}
ondragend={(lng: number) => {
position.lng = lng
}}
/>
)
return <MapPin position={position} />
}
23 changes: 7 additions & 16 deletions packages/components/src/MapWithPin/MapPin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import L from 'leaflet'

import customMarkerIcon from '../../assets/icons/map-marker.png'

import type { DivIcon } from 'leaflet'

const customMarker = L.icon({
iconUrl: customMarkerIcon,
iconSize: [20, 28],
Expand All @@ -15,31 +17,20 @@ export interface IProps {
lat: number
lng: number
}
draggable: boolean
ondragend(lng: number): void
markerIcon?: DivIcon
onClick?: () => void
}

export const MapPin = (props: IProps) => {
const markerRef = React.useRef(null)

return (
<Marker
draggable={props.draggable}
ondragend={() => {
const marker: any = markerRef.current

if (!marker) {
return null
}

const markerLatLng = marker.leafletElement.getLatLng()
if (props.ondragend) {
props.ondragend(markerLatLng)
}
}}
draggable
position={[props.position.lat, props.position.lng]}
ref={markerRef}
icon={customMarker}
icon={props.markerIcon || customMarker}
onclick={props.onClick}
/>
)
}
7 changes: 6 additions & 1 deletion packages/components/src/MapWithPin/MapWithPin.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import React from 'react'

import { MapWithPin } from './MapWithPin'

import type { Meta, StoryFn } from '@storybook/react'
import type { Map } from 'react-leaflet'

export default {
title: 'Map/MapWithPin',
Expand All @@ -9,10 +12,12 @@ export default {

export const Default: StoryFn<typeof MapWithPin> = () => {
const position = { lat: 0, lng: 0 }
const newMapRef = React.useRef<Map>(null)

return (
<MapWithPin
mapRef={newMapRef}
position={position}
draggable={true}
updatePosition={(_position: { lat: number; lng: number }) => {
position.lat = _position.lat
position.lng = _position.lng
Expand Down
104 changes: 51 additions & 53 deletions packages/components/src/MapWithPin/MapWithPin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,37 @@ import { Map } from '../Map/Map'
import { OsmGeocoding } from '../OsmGeocoding/OsmGeocoding'
import { MapPin } from './MapPin'

import type { LeafletMouseEvent } from 'leaflet'
import type { DivIcon, LeafletMouseEvent } from 'leaflet'
import type { Map as MapType } from 'react-leaflet'
import type { Result } from '../OsmGeocoding/types'

import 'leaflet/dist/leaflet.css'

const useUserLocation = 'Use my current location'
const mapInstructions =
"You can click on the map, or drag the marker to adjust it's position."
"You can double click on the map to adjust it's position. Click on your pin to see the preview of your card."

export interface Props {
mapRef: React.RefObject<MapType>
position: {
lat: number
lng: number
}
draggable: boolean
markerIcon?: DivIcon
updatePosition?: any
center?: any
zoom?: number
hasUserLocation?: boolean
onClickMapPin?: () => void
popup?: React.ReactNode
}

export const MapWithPin = (props: Props) => {
const [zoom, setZoom] = React.useState(props.zoom || 1)
const [center, setCenter] = React.useState(
props.center || [props.position.lat, props.position.lng],
)
const { draggable, position } = props
const { mapRef, position, markerIcon, onClickMapPin, popup } = props

const hasUserLocation = props.hasUserLocation || false
const onPositionChanged =
Expand All @@ -58,22 +62,20 @@ export const MapWithPin = (props: Props) => {
)
}

const onClick = (evt: LeafletMouseEvent) => {
const onDblClick = (evt: LeafletMouseEvent) => {
onPositionChanged({ ...evt.latlng })
}

return (
<Flex sx={{ flexDirection: 'column', gap: 2 }}>
{draggable && (
<Alert
variant="info"
sx={{
marginTop: 2,
}}
>
<Text sx={{ fontSize: 1 }}>{mapInstructions}</Text>
</Alert>
)}
<Alert
variant="info"
sx={{
marginTop: 2,
}}
>
<Text sx={{ fontSize: 1 }}>{mapInstructions}</Text>
</Alert>
<div
style={{
position: 'relative',
Expand All @@ -90,59 +92,55 @@ export const MapWithPin = (props: Props) => {
zIndex: 2,
}}
>
{draggable && (
<Flex style={{ width: '280px' }}>
<OsmGeocoding
callback={(data: Result) => {
if (data.lat && data.lon) {
onPositionChanged({
lat: data.lat,
lng: data.lon,
})
setCenter([data.lat, data.lon])
setZoom(15)
}
<Flex style={{ width: '280px' }}>
<OsmGeocoding
callback={(data: Result) => {
if (data.lat && data.lon) {
onPositionChanged({
lat: data.lat,
lng: data.lon,
})
setCenter([data.lat, data.lon])
setZoom(15)
}
}}
countrycodes=""
acceptLanguage="en"
/>
{hasUserLocation && (
<Button
type="button"
mx={2}
onClick={(evt) => {
evt.preventDefault()
setLocationToNavigatorLocation()
}}
countrycodes=""
acceptLanguage="en"
/>
{hasUserLocation && (
<Button
type="button"
mx={2}
onClick={(evt) => {
evt.preventDefault()
setLocationToNavigatorLocation()
}}
>
{useUserLocation}
</Button>
)}
</Flex>
)}
>
{useUserLocation}
</Button>
)}
</Flex>
</Box>
<Map
ref={mapRef}
className="markercluster-map"
center={center}
zoom={zoom}
zoomControl={false}
setZoom={setZoom}
onclick={onClick}
ondblclick={onDblClick}
doubleClickZoom={false}
style={{
height: '300px',
zIndex: 1,
}}
>
{popup}
<ZoomControl position="topright" />
<MapPin
position={position}
draggable={draggable}
ondragend={(evt: any) => {
if (evt.lat && evt.lng)
onPositionChanged({
lat: evt.lat,
lng: evt.lng,
})
}}
markerIcon={markerIcon}
onClick={onClickMapPin}
/>
</Map>
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/models/common.models.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export interface ILocation {
postcode: string
value: string
}
interface ILatLng {

export interface ILatLng {
lat: number
lng: number
}
Expand Down
6 changes: 0 additions & 6 deletions src/models/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import type { IComment } from './discussion.models'

export * from './common.models'
export * from './discussion.models'
export * from './howto.models'
Expand All @@ -14,7 +12,3 @@ export * from './tags.model'
export * from './user.models'
export * from './moderation.model'
export * from './userPreciousPlastic.models'

export interface UserComment extends IComment {
isEditable: boolean
}
55 changes: 45 additions & 10 deletions src/pages/UserSettings/SettingsPageMapPin.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react'
import React, { useEffect, useState } from 'react'
import { Field, Form } from 'react-final-form'
import { toJS } from 'mobx'
import {
Expand All @@ -22,14 +22,23 @@ import { randomIntFromInterval } from 'src/utils/helpers'
import { required } from 'src/utils/validators'
import { Alert, Box, Flex, Heading, Text } from 'theme-ui'

import { Popup } from '../Maps/Content/MapView/Popup'
import { createMarkerIcon } from '../Maps/Content/MapView/Sprites'
import { SettingsFormNotifications } from './content/SettingsFormNotifications'
import { MAX_PIN_LENGTH } from './constants'

import type { ILocation, IMapPin, IUserPPDB } from 'src/models'
import type { DivIcon } from 'leaflet'
import type { Map } from 'react-leaflet'
import type {
ILatLng,
ILocation,
IMapPinWithDetail,
IUserPPDB,
} from 'src/models'
import type { IFormNotification } from './content/SettingsFormNotifications'

interface IPinProps {
mapPin: IMapPin | undefined
mapPin: IMapPinWithDetail | undefined
}

interface ILocationProps {
Expand Down Expand Up @@ -145,25 +154,38 @@ const DeleteMapPin = (props: IPropsDeletePin) => {
}

export const SettingsPageMapPin = () => {
const [mapPin, setMapPin] = useState<IMapPin>()
const [mapPin, setMapPin] = useState<IMapPinWithDetail>()
const [markerIcon, setMarkerIcon] = useState<DivIcon>()
const [showPopup, setShowPopup] = useState<boolean>(false)
const [isLoading, setIsLoading] = useState<boolean>(true)
const [notification, setNotification] = useState<
IFormNotification | undefined
>(undefined)

const { mapsStore, themeStore, userStore } = useCommonStores().stores
const user = userStore.activeUser
const isMember = user?.profileType === ProfileTypeList.MEMBER

const { addPinTitle, yourPinTitle } = headings.map

const formId = 'MapSection'
const isMember = user?.profileType === ProfileTypeList.MEMBER

const currentTheme = themeStore.currentTheme

const newMapRef = React.useRef<Map>(null)

useEffect(() => {
const init = async () => {
if (!user) return

const pin = (await mapsStore.getPin(user.userName)) || null
setMapPin(pin)
const pin = await mapsStore.getPin(user.userName)
if (!pin) return

const pinDetail = await mapsStore.getPinDetail(pin)
if (!pinDetail) return

setMapPin(pinDetail)
setMarkerIcon(createMarkerIcon(pin, currentTheme))
setIsLoading(false)
}

Expand Down Expand Up @@ -223,7 +245,7 @@ export const SettingsPageMapPin = () => {
>
<Flex sx={{ flexDirection: 'column', gap: 1 }}>
<Heading as="h2" id="your-map-pin">
{mapPin ? addPinTitle : yourPinTitle}
{mapPin ? yourPinTitle : addPinTitle}
</Heading>
{isMember && (
<Text
Expand Down Expand Up @@ -286,11 +308,24 @@ export const SettingsPageMapPin = () => {

return (
<MapWithPin
mapRef={newMapRef}
position={location.latlng}
draggable={true}
updatePosition={(newPosition) => {
updatePosition={(newPosition: ILatLng) => {
onChange({ latlng: newPosition })
}}
markerIcon={markerIcon}
zoom={mapPin ? 15 : 1}
onClickMapPin={() => setShowPopup(!showPopup)}
popup={
mapPin && showPopup ? (
<Popup
activePin={mapPin}
mapRef={newMapRef}
newMap
onClose={() => setShowPopup(!showPopup)}
/>
) : undefined
}
/>
)
}}
Expand Down
2 changes: 1 addition & 1 deletion src/stores/Maps/maps.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ export class MapsStore extends ModuleStore {
}
}
// call additional action when pin detail received to inform mobx correctly of update
private async getPinDetail(pin: IMapPin) {
public async getPinDetail(pin: IMapPin) {
const detail: IMapPinDetail = await this.getUserProfilePin(pin._id)
const pinWithDetail: IMapPinWithDetail = { ...pin, detail }
return pinWithDetail
Expand Down

0 comments on commit c558381

Please sign in to comment.