Skip to content

Commit

Permalink
feat: planned route map (#434)
Browse files Browse the repository at this point in the history
Co-authored-by: Noam Gaash <noam.gaash@applitools.com>
  • Loading branch information
itai-rozen and NoamGaash committed Mar 2, 2024
1 parent c8c0fc5 commit b6994a6
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 104 deletions.
Binary file added public/marker-bus-stop.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/marker-dot.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion src/locale/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -144,5 +144,7 @@
"error": "An error occurred while sending the report. Please try again later.",
"success": "The report was sent successfully. Thank you for your help!",
"viewIssue": "View issue"
}
},
"plannedRoute": "Planned Route",
"actualRoute": "Actual Route"
}
4 changes: 3 additions & 1 deletion src/locale/he.json
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,7 @@
"error": "אירעה שגיאה בעת שליחת הדיווח. אנא נסה שוב מאוחר יותר.",
"success": "תודה על הדיווח!",
"viewIssue": "לצפייה בדיווח"
}
},
"plannedRoute": "מסלול מתוכנן",
"actualRoute": "מסלול בפועל"
}
49 changes: 48 additions & 1 deletion src/pages/Map.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,59 @@ main,
main > div,
.map-container,
.leaflet-container,
.map-info {
.map-info,
.map-index-item-config {
display: flex;
flex-direction: column;
flex: 1 1 auto;
}

.map-info {
position: relative;

.map-index {
position: absolute;
top: 1em;
right: 1em;
z-index: 1000;
border: 2px solid black;
background-color: rgba($color: #fff, $alpha: 50%);
padding: 1em;

&-item {
display: flex;
justify-content: space-between;
align-items: center;

&-config {
align-items: center;
margin-left: 1em;
}

&-line {
width: 25px;
height: 4px;
}

&-icon {
width: 20px;
height: 20px;
margin: 0 auto;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}

&-title {
width: 100px;
text-align: left;
}
}
}
}



pre {
direction: ltr;
height: 200px;
Expand Down
105 changes: 89 additions & 16 deletions src/pages/components/map-related/MapWithLocationsAndPath.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import { MapContainer, Marker, Polyline, Popup, TileLayer } from 'react-leaflet'
import { Icon, IconOptions } from 'leaflet'
import { useAgencyList } from 'src/api/agencyList'
import { Point } from 'src/pages/realtimeMap'
import { busIcon, busIconPath } from '../utils/BusIcon'
import { BusToolTip } from './MapLayers/BusToolTip'
import { VehicleLocation } from 'src/model/vehicleLocation'
import { getColorByHashString } from 'src/pages/dashboard/AllLineschart/OperatorHbarChart/utils'
import { useCallback, useState } from 'react'
import { Button } from 'antd'
import { ExpandAltOutlined } from '@ant-design/icons'
import { BusStop } from 'src/model/busStop'
import { t } from 'i18next'
import '../../Map.scss'

const position: Point = {
loc: [32.3057988, 34.85478613], // arbitrary default value... Netanya - best city to live & die in
color: 0,
}

export interface Path {
locations: VehicleLocation[]
lineRef: number
Expand All @@ -23,15 +26,30 @@ export interface Path {

export function MapWithLocationsAndPath({
positions,
paths,
plannedRouteStops,
}: {
positions: Point[]
paths: Path[]
plannedRouteStops: BusStop[]
}) {
const agencyList = useAgencyList()
const [isExpanded, setIsExpanded] = useState<boolean>(false)
const toggleExpanded = useCallback(() => setIsExpanded((expanded) => !expanded), [])
console.log('MapWithLocationsAndPath', `${isExpanded ? 'expanded' : 'collapsed'}`)

const getIcon = (path: string, width: number = 10, height: number = 10): Icon<IconOptions> => {
return new Icon<IconOptions>({
iconUrl: path,
iconSize: [width, height],
})
}
// configs for planned & actual routes - line color & marker icon
const actualRouteStopMarkerPath = '/marker-dot.png'
const plannedRouteStopMarkerPath = '/marker-bus-stop.png'
const actualRouteLineColor = 'orange'
const plannedRouteLineColor = 'black'
const actualRouteStopMarker = getIcon(actualRouteStopMarkerPath, 20, 20)
const plannedRouteStopMarker = getIcon(plannedRouteStopMarkerPath, 20, 25)

return (
<div className={`map-info ${isExpanded ? 'expanded' : 'collapsed'}`}>
<Button
Expand All @@ -41,17 +59,32 @@ export function MapWithLocationsAndPath({
onClick={toggleExpanded}
icon={<ExpandAltOutlined />}
/>
<MapContainer center={position.loc} zoom={8} scrollWheelZoom={true}>
<MapContainer center={position.loc} zoom={13} scrollWheelZoom={true}>
<TileLayer
attribution='&copy <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://tile-a.openstreetmap.fr/hot/{z}/{x}/{y}.png"
/>

<div className="map-index">
<MapIndex
lineColor={actualRouteLineColor}
imgSrc={actualRouteStopMarkerPath}
title={t('actualRoute')}
/>
<MapIndex
lineColor={plannedRouteLineColor}
imgSrc={plannedRouteStopMarkerPath}
title={t('plannedRoute')}
/>
</div>
{positions.map((pos, i) => {
const icon = busIcon({
operator_id: pos.operator?.toString() || 'default',
name: agencyList.find((agency) => agency.operator_ref === pos.operator)?.agency_name,
})
const icon =
i === 0
? busIcon({
operator_id: pos.operator?.toString() || 'default',
name: agencyList.find((agency) => agency.operator_ref === pos.operator)
?.agency_name,
})
: actualRouteStopMarker
return (
<Marker position={pos.loc} icon={icon} key={i}>
<Popup minWidth={300} maxWidth={700}>
Expand All @@ -61,16 +94,56 @@ export function MapWithLocationsAndPath({
)
})}

{paths.map((path) => (
{plannedRouteStops?.length && (
<Polyline
pathOptions={{ color: plannedRouteLineColor }}
positions={plannedRouteStops.map((stop) => [
stop.location.latitude,
stop.location.longitude,
])}
/>
)}
{plannedRouteStops?.length &&
plannedRouteStops.map((stop) => {
const { latitude, longitude } = stop.location
return (
<Marker
key={'' + latitude + longitude}
position={[latitude, longitude]}
icon={plannedRouteStopMarker}></Marker>
)
})}
{positions.length && (
<Polyline
key={path.vehicleRef}
pathOptions={{
color: getColorByHashString(path.vehicleRef.toString()),
}}
positions={path.locations.map(({ lat, lon }) => [lat, lon])}
pathOptions={{ color: actualRouteLineColor }}
positions={positions.map((position) => position.loc)}
/>
))}
)}
</MapContainer>
</div>
)
}

export function MapIndex({
lineColor,
imgSrc,
title,
}: {
lineColor: string
imgSrc: string
title: string
}) {
return (
<div className="map-index-item">
<div className="map-index-item-config">
<p className="map-index-item-line" style={{ backgroundColor: lineColor }}></p>
<p className="map-index-item-icon" style={{ backgroundImage: `url(${imgSrc})` }}>
{/* <img src={imgSrc} alt="planned route stop icon" /> */}
</p>
</div>
<div className="map-index-item-title">
<h3>{title}</h3>
</div>
</div>
)
}

0 comments on commit b6994a6

Please sign in to comment.