diff --git a/src/api/agencyList.ts b/src/api/agencyList.ts index 72e46bd3..625ba628 100644 --- a/src/api/agencyList.ts +++ b/src/api/agencyList.ts @@ -6,15 +6,19 @@ export interface Agency { agency_name: string // example - "אלקטרה אפיקים" } -let json: Agency[] +let agencyList: Agency[] +/** + * Fetch agency data from MOT api + * @returns Agency data array, might contain DUPLICATE agencies with different `date` values + */ export default async function getAgencyList(): Promise { - if (!json) { + if (!agencyList) { const response = await fetch(`${BASE_PATH}/gtfs_agencies/list`) - json = await response.json() + const data = (await response.json()) as Awaited + agencyList = data.filter(Boolean) // filter empty entries } - - return json + return agencyList } export function useAgencyList() { diff --git a/src/model/operator.ts b/src/model/operator.ts index cbb448ed..4c5da887 100644 --- a/src/model/operator.ts +++ b/src/model/operator.ts @@ -1,41 +1,24 @@ -import getAgencyList, { Agency } from 'src/api/agencyList' +import getAgencyList from 'src/api/agencyList' export type Operator = { name: string id: string } -export const getRelevantOperators = async (onlyRelevantOperators: boolean) => { +export const MAJOR_OPERATORS = ['3', '5', '15', '18', '25', '34'] // ['אלקטרה אפיקים', 'דן', 'מטרופולין', 'קווים', 'אגד', 'תנופה'] + +/** + * Get operators list, based on agencies fetched from MOT api + * @param filter Operator ID list + * @returns List of operators + */ +export async function getOperators(filter?: string[]): Promise { const agencyList = await getAgencyList() - if (!onlyRelevantOperators) { - const allOperators = agencyList.map((agency) => ({ - name: agency.agency_name, - id: agency.operator_ref.toString(), - })) - return allOperators - } - const relevant = [ - 'אגד', - 'אגד תעבורה', - 'אלקטרה אפיקים', - 'דן', - 'מטרופולין', - 'נתיב אקספרס', - 'סופרבוס', - 'קווים', - 'תנופה', - ] - const agencyMap: Map = new Map() - agencyList.forEach((obj) => { - if (obj) { - agencyMap.set(obj.agency_name, obj) - } - }) + const allOperators: Operator[] = agencyList.map((agency) => ({ + name: agency.agency_name, + id: agency.operator_ref.toString(), + })) + const res = allOperators.filter((op, i, a) => a.findIndex((op2) => op2.id === op.id) === i) // Filter duplicates - const res = relevant.reduce((acc: Operator[], name: string): Operator[] => { - return agencyMap.has(name) - ? [...acc, { name, id: (agencyMap.get(name) as Agency).operator_ref.toString() }] - : acc - }, []) - return res + return !filter ? res : res.filter((operator) => filter.includes(operator.id)) } diff --git a/src/pages/DataResearch/DataResearch.tsx b/src/pages/DataResearch/DataResearch.tsx index 6ee095f9..285d783b 100644 --- a/src/pages/DataResearch/DataResearch.tsx +++ b/src/pages/DataResearch/DataResearch.tsx @@ -19,7 +19,7 @@ import { import { PageContainer } from '../components/PageContainer' import { getColorName } from '../dashboard/AllLineschart/OperatorHbarChart/OperatorHbarChart' import './DataResearch.scss' -import OperatorSelector, { FilterOperatorOptions } from '../components/OperatorSelector' +import OperatorSelector from '../components/OperatorSelector' const now = moment() const unique: (value: string, index: number, self: string[]) => boolean = (value, index, self) => @@ -126,11 +126,7 @@ function StackedResearchInputs({ customLabel={t('end')} /> - +

בחירת כל המפעילים

- -

בחירת המפעילים הרלוונטיים

- ''} - filter={FilterOperatorOptions.RELEVANT}> + ) } diff --git a/src/pages/components/OperatorSelector.tsx b/src/pages/components/OperatorSelector.tsx index 84f106d6..faa31a71 100644 --- a/src/pages/components/OperatorSelector.tsx +++ b/src/pages/components/OperatorSelector.tsx @@ -1,43 +1,25 @@ import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' -import { Operator, getRelevantOperators } from 'src/model/operator' +import { Operator, getOperators } from 'src/model/operator' import { Autocomplete, TextField } from '@mui/material' -export enum FilterOperatorOptions { - ALL, - RELEVANT, - MAJOR, -} - type OperatorSelectorProps = { operatorId?: string setOperatorId: (operatorId: string) => void - filter?: FilterOperatorOptions + filter?: string[] } -const OperatorSelector = ({ +export default function OperatorSelector({ operatorId, setOperatorId, - filter = FilterOperatorOptions.RELEVANT, -}: OperatorSelectorProps) => { + filter, +}: OperatorSelectorProps) { const { t } = useTranslation() const [operators, setOperators] = useState([]) + useEffect(() => { - const majorOperatorsIds = ['3', '5', '15', '18', '25', '34'] - getRelevantOperators(filter != FilterOperatorOptions.ALL) - .then((list) => - filter === FilterOperatorOptions.ALL - ? [...list, { id: '', name: t('operatorSelectorOptions.all') }] - : list, - ) - .then((resultObj) => - setOperators( - filter == FilterOperatorOptions.MAJOR && resultObj - ? resultObj.filter((item) => majorOperatorsIds.includes(item.id)) - : resultObj, - ), - ) - }, [filter == FilterOperatorOptions.MAJOR]) + getOperators(filter).then((o) => setOperators(o)) + }, [filter]) const valueFinned = operators.find((operator) => operator.id === operatorId) const value = valueFinned ? valueFinned : null @@ -47,7 +29,7 @@ const OperatorSelector = ({ disablePortal style={{ width: '100%' }} value={value} - onChange={(e, value) => setOperatorId(value ? value.id : '')} + onChange={(_, value) => setOperatorId(value ? value.id : '')} id="operator-select" options={operators} renderInput={(params) => } @@ -55,5 +37,3 @@ const OperatorSelector = ({ /> ) } - -export default OperatorSelector diff --git a/src/pages/dashboard/DashboardPage.tsx b/src/pages/dashboard/DashboardPage.tsx index 5bcf1b8c..361ff962 100644 --- a/src/pages/dashboard/DashboardPage.tsx +++ b/src/pages/dashboard/DashboardPage.tsx @@ -14,7 +14,7 @@ import { Alert, Typography } from 'antd' import Grid from '@mui/material/Unstable_Grid2' // Grid version 2 // Components -import OperatorSelector, { FilterOperatorOptions } from 'src/pages/components/OperatorSelector' +import OperatorSelector from 'src/pages/components/OperatorSelector' import DayTimeChart from './ArrivalByTimeChart/DayTimeChart' import AllLinesChart from './AllLineschart/AllLinesChart' import WorstLinesChart from './WorstLinesChart/WorstLinesChart' @@ -63,11 +63,7 @@ const DashboardPage = () => { - + diff --git a/src/pages/dashboard/WorstLinesChart/LineHbarChart/LinesHbarChart.tsx b/src/pages/dashboard/WorstLinesChart/LineHbarChart/LinesHbarChart.tsx index ede480a0..af8d363d 100644 --- a/src/pages/dashboard/WorstLinesChart/LineHbarChart/LinesHbarChart.tsx +++ b/src/pages/dashboard/WorstLinesChart/LineHbarChart/LinesHbarChart.tsx @@ -4,7 +4,6 @@ import { getColorName } from '../../AllLineschart/OperatorHbarChart/OperatorHbar function LinesHbarChart({ lines, complement = false, // complement the chart (100% - actual) instead of actual - operators_whitelist = [], }: { lines: { id: string @@ -15,7 +14,8 @@ function LinesHbarChart({ actual: number }[] complement?: boolean - operators_whitelist?: Array + operators_whitelist?: string[] + defaultOperators?: string[] }) { const percents = lines .map((o) => (o.actual / o.total) * 100) @@ -35,9 +35,6 @@ function LinesHbarChart({ entries={rows .sort((a, b) => a.actual / a.total - b.actual / b.total) .filter((line) => line.total > 10) - .filter( - (line) => !operators_whitelist.length || operators_whitelist.includes(line.operator_name), - ) .filter((line) => line.actual / line.total > 0.4) .slice(0, 200)} complement={complement} diff --git a/src/pages/dashboard/WorstLinesChart/WorstLinesChart.tsx b/src/pages/dashboard/WorstLinesChart/WorstLinesChart.tsx index 429a62aa..853b5894 100644 --- a/src/pages/dashboard/WorstLinesChart/WorstLinesChart.tsx +++ b/src/pages/dashboard/WorstLinesChart/WorstLinesChart.tsx @@ -2,9 +2,9 @@ import { Skeleton } from 'antd' import { GroupByRes, useGroupBy } from 'src/api/groupByService' import LinesHbarChart from './LineHbarChart/LinesHbarChart' import { useTranslation } from 'react-i18next' -import { FC } from 'react' import { Moment } from 'moment/moment' import Widget from 'src/shared/Widget' +import { MAJOR_OPERATORS } from 'src/model/operator' interface WorstLinesChartProps { startDate: Moment @@ -12,7 +12,7 @@ interface WorstLinesChartProps { operatorId: string } -export const WorstLinesChart: FC = ({ startDate, endDate, operatorId }) => { +export const WorstLinesChart = ({ startDate, endDate, operatorId }: WorstLinesChartProps) => { const [groupByLineData, lineDataLoading] = useGroupBy({ dateTo: endDate, dateFrom: startDate, @@ -20,14 +20,15 @@ export const WorstLinesChart: FC = ({ startDate, endDate, }) const { t } = useTranslation() - const convertToWorstLineChartCompatibleStruct = (arr: GroupByRes[], operatorId: string) => { if (!arr || !arr.length) return [] return arr .filter( - (row: GroupByRes) => row.operator_ref?.agency_id === operatorId || !Number(operatorId), + (row) => + operatorId || (row.operator_ref && MAJOR_OPERATORS.includes(row.operator_ref.agency_id)), ) - .map((item: GroupByRes) => ({ + .filter((row) => row.operator_ref?.agency_id === operatorId || !Number(operatorId)) + .map((item) => ({ id: `${item.line_ref}|${item.operator_ref?.agency_id}` || 'Unknown', operator_name: item.operator_ref?.agency_name || 'Unknown', short_name: JSON.parse(item.route_short_name)[0], @@ -45,7 +46,6 @@ export const WorstLinesChart: FC = ({ startDate, endDate, ) : ( )}