1
- import { PureComponent , useEffect , useState } from 'react' ;
2
- import { DivIcon , DragEndEventHandlerFn , LatLngBoundsExpression } from 'leaflet' ;
3
- import { Marker , Popup , SVGOverlay , useMapEvents } from 'react-leaflet' ;
1
+ import { useEffect , useMemo , useState } from 'react' ;
2
+ import { DivIcon , LatLngBoundsExpression } from 'leaflet' ;
3
+ import { Marker , SVGOverlay , useMapEvents } from 'react-leaflet' ;
4
4
import classnames from 'classnames' ;
5
- import produce from 'immer' ;
6
5
7
- // import type { BusStop, BusTiming } from 'types/venues';
8
- import type { EmptyProps } from 'types/utils' ;
9
-
10
- import busStopJSON from 'data/bus-stops.json' ;
11
6
import isbStopJson from 'data/isb-stops.json' ;
12
- import { allowBusStopEditing } from 'utils/debug' ;
13
- import { nextBus } from 'apis/nextbus' ;
14
7
import isbServicesJSON from 'data/isb-services.json' ;
15
8
import { getRouteSegments , segmentsToClasses } from 'utils/mobility' ;
16
9
import styles from './ISBServices.scss' ;
17
- import { ArrivalTimes } from './ArrivalTimes' ;
10
+
11
+ // these eslint warnings are disabled because we're doing some convoluted svg importing as react components :,)
12
+ // SHOULD be changed into using polyline instead, as that's the correct way to do it
13
+ // but i am but a stupid graphic designer who knows how to use illustrator and not how to use GIS software
14
+
18
15
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
19
16
// @ts -ignore
20
17
import KRC from './routes/KRC.svg?svgr' ;
21
18
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
22
19
// @ts -ignore
23
20
import BTC from './routes/BTC.svg?svgr' ;
24
21
22
+ const BTCStops = [ 'CG' , 'OTH' , 'BG-MRT' ] ;
23
+
25
24
type Props =
26
- | { mapMode : 'all' ; onStopClicked : ( stop : string | null ) => void ; focusStop : string | null }
25
+ | {
26
+ mapMode : 'all' ;
27
+ onStopClicked : ( stop : string | null ) => void ;
28
+ focusStop : string | null ;
29
+ campus : 'KRC' | 'BTC' ;
30
+ }
27
31
| {
28
32
mapMode : 'selected' ;
29
33
selectedSegments : {
@@ -37,6 +41,7 @@ type Props =
37
41
} [ ] ;
38
42
onStopClicked : ( stop : string | null ) => void ;
39
43
focusStop : string | null ;
44
+ campus : 'KRC' | 'BTC' ;
40
45
} ;
41
46
42
47
const KRCBounds : LatLngBoundsExpression = [
@@ -48,7 +53,6 @@ const BTCBounds: LatLngBoundsExpression = [
48
53
[ 1.3289028289795464 , 103.83893751900072 ] ,
49
54
] ;
50
55
51
- const btcStops = [ 'CG' , 'OTH' , 'BG-MRT' ] ;
52
56
const isbServices = isbServicesJSON ;
53
57
54
58
export default function ISBStops ( props : Props ) {
@@ -66,34 +70,33 @@ export default function ISBStops(props: Props) {
66
70
} ,
67
71
} ) ;
68
72
69
- let selectedSegments : { classes : string [ ] ; color : string } [ ] = [ ] ;
70
- let selectedStops : { name : string ; color : string ; subtext ?: string } [ ] = [ ] ;
71
- if ( props . mapMode === 'selected' ) {
72
- selectedSegments = segmentsToClasses ( props . selectedSegments ) ;
73
- selectedStops = props . selectedStops ;
74
- } else if ( props . mapMode === 'all' && currentFocusStop ) {
75
- const currentFocusStopDetails = isbStopJson . find ( ( stop ) => stop . name === currentFocusStop ) ;
76
- if ( currentFocusStopDetails ) {
77
- // get all services passing by this stop
78
- const passingServices = currentFocusStopDetails . shuttles
79
- . map ( ( service ) => {
80
- const serviceDetails = isbServices . find ( ( s ) => s . name === service . name ) ;
81
- if ( ! serviceDetails ) return null ;
82
- return serviceDetails ;
83
- } )
84
- . filter ( Boolean ) as ( typeof isbServices ) [ number ] [ ] ;
85
-
86
- // for each service, get the route segments, and merge it into selectedSegments
87
- // selectedSegments returns an array of segments, so do not use map
88
- passingServices . forEach ( ( service ) => {
89
- selectedSegments = selectedSegments . concat (
90
- segmentsToClasses ( getRouteSegments ( service . stops , '#3087d8' ) ) ,
91
- ) ;
92
- } ) ;
93
-
94
- // console.log('selectedSegments', selectedSegments);
73
+ const selection = useMemo ( ( ) => {
74
+ let selectedSegments : { classes : string [ ] ; color : string } [ ] = [ ] ;
75
+ let selectedStops : { name : string ; color : string ; subtext ?: string } [ ] = [ ] ;
76
+ if ( props . mapMode === 'selected' ) {
77
+ selectedSegments = segmentsToClasses ( props . selectedSegments ) ;
78
+ selectedStops = props . selectedStops ;
79
+ } else if ( props . mapMode === 'all' && currentFocusStop ) {
80
+ const currentFocusStopDetails = isbStopJson . find ( ( stop ) => stop . name === currentFocusStop ) ;
81
+ if ( currentFocusStopDetails ) {
82
+ const passingServices = currentFocusStopDetails . shuttles
83
+ . map ( ( service ) => {
84
+ const serviceDetails = isbServices . find ( ( s ) => s . name === service . name ) ;
85
+ if ( ! serviceDetails ) return null ;
86
+ return serviceDetails ;
87
+ } )
88
+ . filter ( Boolean ) as ( typeof isbServices ) [ number ] [ ] ;
89
+ passingServices . forEach ( ( service ) => {
90
+ selectedSegments = selectedSegments . concat (
91
+ segmentsToClasses ( getRouteSegments ( service . stops , '#3087d8' ) ) ,
92
+ ) ;
93
+ } ) ;
94
+ }
95
95
}
96
- }
96
+ return { selectedSegments, selectedStops } ;
97
+ } , [ props , currentFocusStop ] ) ;
98
+
99
+ const { selectedSegments, selectedStops } = selection ;
97
100
98
101
return (
99
102
< >
@@ -103,6 +106,13 @@ export default function ISBStops(props: Props) {
103
106
return null ;
104
107
}
105
108
109
+ if (
110
+ ( props . campus === 'KRC' && BTCStops . includes ( stop . name ) ) ||
111
+ ( props . campus === 'BTC' && ! BTCStops . includes ( stop . name ) )
112
+ ) {
113
+ return null ;
114
+ }
115
+
106
116
let hasPairAndIsTheOpposite = false ;
107
117
let displayType : 'normal' | 'interchange' | 'no-label' | 'hidden' = 'normal' ;
108
118
let subtext = '' ;
@@ -138,7 +148,6 @@ export default function ISBStops(props: Props) {
138
148
hasPairAndIsTheOpposite = true ;
139
149
}
140
150
}
141
-
142
151
break ;
143
152
default :
144
153
break ;
@@ -167,7 +176,6 @@ export default function ISBStops(props: Props) {
167
176
isLeft && styles . left ,
168
177
isFocused && styles . focused ,
169
178
) ;
170
- // [styles.left]: stop.displayRoutesLeft,
171
179
172
180
const routeNameClass = classnames ( styles . stopName ) ;
173
181
@@ -195,6 +203,7 @@ export default function ISBStops(props: Props) {
195
203
. join ( '' ) } </div>`
196
204
: '' ;
197
205
206
+ // for the love of god if anyone knows a better way that defining RAW HTML
198
207
const icon = new DivIcon ( {
199
208
// language=HTML
200
209
html : `
@@ -218,8 +227,6 @@ export default function ISBStops(props: Props) {
218
227
} `,
219
228
className : styles . iconWrapper ,
220
229
iconSize : [ 30 , 30 ] ,
221
- // Move the popup a bit higher so it won't cover the bus stop icon
222
- popupAnchor : [ 0 , - 5 ] ,
223
230
} ) ;
224
231
225
232
return (
@@ -230,14 +237,11 @@ export default function ISBStops(props: Props) {
230
237
eventHandlers = { {
231
238
click : ( ) => {
232
239
if ( props . onStopClicked ) {
233
- // setCurrentFocusStop(stop.name);
234
240
props . onStopClicked ( stop . name ) ;
235
- map . flyTo ( [ stop . latitude , stop . longitude ] , 17 ) ;
241
+ map . flyTo ( [ stop . latitude , stop . longitude ] , 16 ) ;
236
242
}
237
243
} ,
238
244
} }
239
- // draggable={allowEditing}
240
- // autoPan={allowEditing}
241
245
/>
242
246
) ;
243
247
} ) }
@@ -281,7 +285,7 @@ export default function ISBStops(props: Props) {
281
285
. join ( ' ' ) }
282
286
</ style >
283
287
284
- { /* background */ }
288
+ { /* background (lines' stroke) */ }
285
289
< SVGOverlay bounds = { KRCBounds } className = "overlay_bg" >
286
290
< KRC className = { mapMode === 'all' && ! currentFocusStop ? 'allRoutes' : '' } />
287
291
</ SVGOverlay >
@@ -290,7 +294,7 @@ export default function ISBStops(props: Props) {
290
294
< BTC className = { mapMode === 'all' && ! currentFocusStop ? 'allRoutes' : '' } />
291
295
</ SVGOverlay >
292
296
293
- { /* foreground */ }
297
+ { /* foreground (lines fill) */ }
294
298
< SVGOverlay bounds = { KRCBounds } className = "overlay_fg" >
295
299
< KRC className = { mapMode === 'all' && ! currentFocusStop ? 'allRoutes' : '' } />
296
300
</ SVGOverlay >
0 commit comments