diff --git a/frontend/components/LinesExplorerContentSelectPattern/LinesExplorerContentSelectPattern.js b/frontend/components/LinesExplorerContentSelectPattern/LinesExplorerContentSelectPattern.js index 4739d0a8..80e93547 100644 --- a/frontend/components/LinesExplorerContentSelectPattern/LinesExplorerContentSelectPattern.js +++ b/frontend/components/LinesExplorerContentSelectPattern/LinesExplorerContentSelectPattern.js @@ -2,9 +2,8 @@ /* * */ -import useSWR from 'swr'; import { Combobox, TextInput, useCombobox, ActionIcon, Group } from '@mantine/core'; -import { useEffect, useMemo, useState } from 'react'; +import { useEffect, useState } from 'react'; import { useTranslations } from 'next-intl'; import styles from './LinesExplorerContentSelectPattern.module.css'; import useSearch from '@/hooks/useSearch'; @@ -25,18 +24,63 @@ export default function LinesExplorerContentSelectPattern() { const linesExplorerContext = useLinesExplorerContext(); const comboboxStore = useCombobox(); const [searchQuery, setSearchQuery] = useState(''); - const [debouncedSearchQuery] = useDebouncedValue(searchQuery, 300); + const [debouncedSearchQuery] = useDebouncedValue(searchQuery, 10); + const [allPatternsData, setAllPatternsData] = useState([]); // - // D. Search + // B. Fetch data + + useEffect(() => { + (async function () { + // Exit if no line is selected + if (!linesExplorerContext.entities?.line?.id) return; + // Exit if no date is selected + if (!linesExplorerContext.entities?.date_string) return; + // Initiate a temporaty variable to hold formatted patterns + let formattedPatternOptions = []; + // Loop through each line pattern to retrieve its info + for (const patternId of linesExplorerContext.entities.line.patterns) { + // Fetch pattern info + const patternDataResponse = await fetch(`https://api.carrismetropolitana.pt/patterns/${patternId}`); + const patternData = await patternDataResponse.json(); + // Check if this pattern is valid on the selected date + const isValidOnSelectedDate = patternData.valid_on.includes(linesExplorerContext.entities.date_string); + // Format response + formattedPatternOptions.push({ + id: patternData.id, + line_id: patternData.line_id, + route_id: patternData.route_id, + short_name: patternData.short_name, + direction: patternData.direction, + headsign: patternData.headsign, + color: patternData.color, + text_color: patternData.text_color, + municipalities: patternData.municipalities, + localities: patternData.localities, + label: patternData.headsign || 'no headsign', + disabled: !isValidOnSelectedDate, + }); + } + // Update state with formatted patterns + setAllPatternsData(formattedPatternOptions); + // Pre-select the first pattern if none is selected + if (!linesExplorerContext.entities.pattern) { + linesExplorerContext.selectPattern(formattedPatternOptions[0]); + } + // + })(); + }, [linesExplorerContext]); - const allPatternsDataFilteredBySearchQuery = useSearch(debouncedSearchQuery, linesExplorerContext.entities?.available_patterns, { - keys: ['id', 'headsign'], + // + // C. Search + + const allPatternsDataFilteredBySearchQuery = useSearch(debouncedSearchQuery, allPatternsData, { + keys: ['id', 'headsign', 'municipalities', 'localities'], regexReplace: /[^a-zA-Z0-9\s]/g, }); // - // E. Handle actions + // D. Handle actions const handleClickSearchField = ({ currentTarget }) => { if (currentTarget.select) currentTarget.select(); @@ -61,17 +105,20 @@ export default function LinesExplorerContentSelectPattern() { comboboxStore.openDropdown(); }; - const handleSelectLine = (chosenSelectItemValue) => { - linesExplorerContext.selectPattern(chosenSelectItemValue); - comboboxStore.closeDropdown(); + const handleSelectPattern = (chosenSelectItemValue) => { + const foundPattern = allPatternsData.find((item) => item.id === chosenSelectItemValue); + if (foundPattern) { + linesExplorerContext.selectPattern(foundPattern); + comboboxStore.closeDropdown(); + } }; // - // F. Render components + // E. Render components return (
- + {linesExplorerContext.entities.line?.id && linesExplorerContext.entities.pattern?.id && !comboboxStore.dropdownOpened ? ( @@ -111,7 +158,7 @@ export default function LinesExplorerContentSelectPattern() { {t('no_results')} ) : ( allPatternsDataFilteredBySearchQuery.map((item) => ( - +
{item.headsign}
)) diff --git a/frontend/components/LinesExplorerToolbarSelectDate/LinesExplorerToolbarSelectDate.js b/frontend/components/LinesExplorerToolbarSelectDate/LinesExplorerToolbarSelectDate.js index 5f721910..bfae1e91 100644 --- a/frontend/components/LinesExplorerToolbarSelectDate/LinesExplorerToolbarSelectDate.js +++ b/frontend/components/LinesExplorerToolbarSelectDate/LinesExplorerToolbarSelectDate.js @@ -18,17 +18,14 @@ export default function LinesExplorerToolbarSelectDate() { const t = useTranslations('LinesExplorerToolbarSelectDate'); // - // C. Handle actions + // B. Transform data const todayDate = useMemo(() => { // Get the current date and time const currentDate = new Date(); const currentHour = currentDate.getHours(); - // If the current hour is after midnight and before 4AM, - // set the date to the previous day. - if (currentHour >= 0 && currentHour < 4) { - currentDate.setDate(currentDate.getDate() - 1); - } + // If the current hour is after midnight and before 4AM, set the date to the previous day. + if (currentHour >= 0 && currentHour < 4) currentDate.setDate(currentDate.getDate() - 1); // Return date for today return currentDate; // @@ -39,10 +36,6 @@ export default function LinesExplorerToolbarSelectDate() { return todayDateString === linesExplorerContext.entities.date; }, [linesExplorerContext.entities.date, todayDate]); - // - // - // - const tomorrowDate = useMemo(() => { // Get the current date and time const currentDate = new Date(); @@ -66,19 +59,15 @@ export default function LinesExplorerToolbarSelectDate() { // C. Handle actions const handleSetToday = () => { - // Set the date value for today handleSetDate(todayDate); }; const handleSetTomorrow = () => { - // Set the date value for tomorrow handleSetDate(tomorrowDate); }; const handleSetDate = (value) => { - // Set the date value for tomorrow - // lineForm.setFieldValue('date', value); - // lineForm.setFieldValue('date_string', parseDateToString(value)); + linesExplorerContext.selectDate(value); }; // @@ -87,30 +76,30 @@ export default function LinesExplorerToolbarSelectDate() { return (
- - - +
); - return ( -
-
-
- {t('today')} -
-
- {t('tomorrow')} -
- -
-
- ); + // return ( + //
+ //
+ //
+ // {t('today')} + //
+ //
+ // {t('tomorrow')} + //
+ // + //
+ //
+ // ); // } diff --git a/frontend/contexts/LinesExplorerContext.js b/frontend/contexts/LinesExplorerContext.js index f5b3f510..f30d9812 100644 --- a/frontend/contexts/LinesExplorerContext.js +++ b/frontend/contexts/LinesExplorerContext.js @@ -4,6 +4,7 @@ import useSWR from 'swr'; import { createContext, useCallback, useContext, useMemo, useState } from 'react'; +import parseDateToString from '@/services/parseDateToString'; /* * */ @@ -99,7 +100,7 @@ export function LinesExplorerContextProvider({ children }) { // --------- const selectLine = useCallback( - async (lineId) => { + (lineId) => { const foundLine = allLinesData.find((item) => item.id === lineId); if (foundLine) { setEntitiesState((prev) => ({ ...prev, line: foundLine, pattern: null, shape: null })); @@ -116,7 +117,18 @@ export function LinesExplorerContextProvider({ children }) { // --------- - const selectPattern = useCallback(async (patternData) => { + const selectDate = useCallback((date) => { + if (!date) return; + setEntitiesState((prev) => ({ ...prev, date: date, date_string: parseDateToString(date) })); + }, []); + + const clearSelectedDate = useCallback(() => { + setEntitiesState((prev) => ({ ...prev, date: null, date_string: null })); + }, []); + + // --------- + + const selectPattern = useCallback((patternData) => { setEntitiesState((prev) => ({ ...prev, pattern: patternData })); }, []); @@ -160,11 +172,14 @@ export function LinesExplorerContextProvider({ children }) { selectLine, clearSelectedLine, // + selectDate, + clearSelectedDate, + // selectPattern, clearSelectedPattern, // }), - [mapState, updateMapState, entitiesState, updateEntitiesState, selectMunicipality, clearSelectedMunicipality, selectLine, clearSelectedLine, selectPattern, clearSelectedPattern] + [mapState, updateMapState, entitiesState, updateEntitiesState, selectMunicipality, clearSelectedMunicipality, selectLine, clearSelectedLine, selectDate, clearSelectedDate, selectPattern, clearSelectedPattern] ); //