• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hasadna / open-bus-map-search / 14269590516

04 Apr 2025 04:12PM UTC coverage: 81.115% (-0.2%) from 81.34%
14269590516

push

github

web-flow
feat: see planned rout even when no actual ride was executed (#1070)

353 of 498 branches covered (70.88%)

Branch coverage included in aggregate %.

77 of 84 new or added lines in 6 files covered. (91.67%)

11 existing lines in 3 files now uncovered.

1000 of 1170 relevant lines covered (85.47%)

87327.11 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.72
/src/pages/singleLineMap/index.tsx
1
import moment from 'moment'
2
import { useContext, useEffect, useMemo } from 'react'
3
import { useTranslation } from 'react-i18next'
4
import Grid from '@mui/material/Unstable_Grid2'
5
import { CircularProgress, Tooltip } from '@mui/material'
6
import Typography from '@mui/material/Typography'
7
import { SearchContext } from '../../model/pageState'
8
import { NotFound } from '../components/NotFound'
9
import '../Map.scss'
10
import { DateSelector } from '../components/DateSelector'
11
import { FilterPositionsByStartTimeSelector } from '../components/FilterPositionsByStartTimeSelector'
12
import { PageContainer } from '../components/PageContainer'
13
import { MapWithLocationsAndPath } from '../components/map-related/MapWithLocationsAndPath'
14
import InfoYoutubeModal from '../components/YoutubeModal'
15
import { INPUT_SIZE } from 'src/resources/sizes'
16
import RouteSelector from 'src/pages/components/RouteSelector'
17
import OperatorSelector from 'src/pages/components/OperatorSelector'
18
import LineNumberSelector from 'src/pages/components/LineSelector'
19
import { getRoutesAsync } from 'src/api/gtfsService'
20
import { useSingleLineData } from 'src/hooks/useSingleLineData'
21

22
const SingleLineMapPage = () => {
20✔
23
  const { search, setSearch } = useContext(SearchContext)
482✔
24
  const { operatorId, lineNumber, timestamp, routes, routeKey } = search
482✔
25
  const { t } = useTranslation()
482✔
26

27
  useEffect(() => {
482✔
28
    if (!operatorId || operatorId === '0' || !lineNumber) {
72✔
29
      setSearch((current) => ({ ...current, routes: undefined, routeKey: undefined }))
58✔
30
      setStartTime(undefined)
58✔
31
      return
58✔
32
    }
33

34
    const controller = new AbortController()
14✔
35
    const time = moment(timestamp)
14✔
36

37
    getRoutesAsync(time, time, operatorId, lineNumber, controller.signal)
14✔
38
      .then((routes) => {
39
        setSearch((current) => ({
14✔
40
          ...current,
41
          routes,
42
          routeKey:
43
            // if is same line it keep route key
44
            current.lineNumber === lineNumber && current.operatorId === operatorId
42!
45
              ? current.routeKey
46
              : undefined,
47
        }))
48
      })
49
      .catch((err) => {
50
        console.error(err)
×
51
        setSearch((current) => ({ ...current, routes: undefined, routeKey: undefined }))
×
52
      })
53

54
    return () => controller.abort()
14✔
55
  }, [operatorId, lineNumber, timestamp])
56

57
  const selectedRoute = useMemo(
482✔
58
    () => routes?.find((route) => route.key === routeKey),
356✔
59
    [routes, routeKey],
60
  )
61

62
  const {
63
    positions,
64
    filteredPositions,
65
    locationsAreLoading,
66
    options,
67
    plannedRouteStops,
68
    startTime,
69
    setStartTime,
70
  } = useSingleLineData(selectedRoute?.lineRef, selectedRoute?.routeIds)
482✔
71

72
  const handleTimestampChange = (time: moment.Moment | null) => {
482✔
NEW
73
    setSearch((current) => ({ ...current, timestamp: time?.valueOf() ?? Date.now() }))
×
74
  }
75

76
  const handleOperatorChange = (operatorId: string) => {
482✔
77
    setSearch((current) => ({ ...current, operatorId }))
14✔
78
  }
79

80
  const handleLineNumberChange = (lineNumber: string) => {
482✔
81
    setSearch((current) => ({ ...current, lineNumber }))
18✔
82
  }
83

84
  const handleRouteKeyChange = (routeKey?: string) => {
482✔
85
    setSearch((current) => ({ ...current, routeKey }))
12✔
86
  }
87

88
  return (
89
    <PageContainer className="map-container">
90
      <Typography className="page-title" variant="h4">
91
        {t('singleline_map_page_title')}
92
        <InfoYoutubeModal
93
          label={t('open_video_about_this_page')}
94
          title={t('time_based_map_page_description')}
95
          videoUrl="https://www.youtube-nocookie.com/embed/bXg50_j_hTA?si=inyvqDylStvgNRA6&amp;start=93"
96
        />
97
      </Typography>
98
      <Grid container spacing={2} sx={{ maxWidth: INPUT_SIZE }}>
99
        <Grid container spacing={2} xs={12}>
100
          {/* choose date*/}
101
          <Grid sm={4} xs={12}>
102
            <DateSelector time={moment(timestamp)} onChange={handleTimestampChange} />
103
          </Grid>
104
          {/* choose operator */}
105
          <Grid sm={4} xs={12}>
106
            <OperatorSelector operatorId={operatorId} setOperatorId={handleOperatorChange} />
107
          </Grid>
108
          {/* choose line number */}
109
          <Grid sm={4} xs={12}>
110
            <LineNumberSelector lineNumber={lineNumber} setLineNumber={handleLineNumberChange} />
111
          </Grid>
112
        </Grid>
113
        <Grid container spacing={2} xs={12} alignContent={'center'}>
114
          <Grid sm={6} xs={12}>
115
            {/* choose route */}
116
            {routes &&
656✔
117
              (routes.length === 0 ? (
174!
118
                <NotFound>{t('line_not_found')}</NotFound>
119
              ) : (
120
                <RouteSelector
121
                  routes={routes}
122
                  routeKey={routeKey}
123
                  setRouteKey={handleRouteKeyChange}
124
                />
125
              ))}
126
          </Grid>
127
          {positions && (
482✔
128
            <>
129
              <Grid sm={2} xs={12}>
130
                {locationsAreLoading && (
482✔
131
                  <Tooltip title={t('loading_times_tooltip_content')}>
132
                    <CircularProgress />
133
                  </Tooltip>
134
                )}
135
              </Grid>
136
              {/* choose start time */}
137
              <Grid sm={4} xs={12}>
138
                <FilterPositionsByStartTimeSelector
139
                  options={options}
140
                  startTime={startTime}
141
                  setStartTime={setStartTime}
142
                />
143
              </Grid>
144
            </>
145
          )}
146
        </Grid>
147
      </Grid>
148
      <MapWithLocationsAndPath
149
        positions={filteredPositions}
150
        plannedRouteStops={plannedRouteStops}
151
        showNavigationButtons
152
      />
153
    </PageContainer>
154
  )
155
}
156

157
export default SingleLineMapPage
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc