Populate filter sidebar when clicking a popular request
Two bugs prevented the popular-requests click from filling the filter: 1. OnlineBoardFilter seeded its fields from initial* props via useState(...), which only runs once. When a user clicked a popular request the parent pushed ?departure=SVO&arrival=LED into the URL and re-rendered with new initial* props, but the sidebar fields kept their previous empty values. Add an effect that diffs the initial* props against a ref and pushes the changes into local state, matching Angular's ngOnChanges behaviour. 2. CityAutocomplete's selectedCity only looked the value up in cityByCode. Airport codes like SVO aren't cities, so the header code label stayed blank. Fall back to airportByCode → city_code so the top-right code renders as 'MOW' when the input shows 'Шереметьево'. End-to-end behaviour now matches Angular: clicking 'Маршрут: Шереметьево - Санкт-Петербург' on the start page updates the URL, populates 'Шереметьево' / 'Санкт-Петербург' in the inputs, shows 'MOW' / 'LED' codes in the labels.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
* @module
|
||||
*/
|
||||
|
||||
import { type FC, useState, useCallback, type FormEvent } from "react";
|
||||
import { type FC, useState, useCallback, useEffect, useRef, type FormEvent } from "react";
|
||||
import { useNavigate, useParams } from "@modern-js/runtime/router";
|
||||
import { Calendar } from "primereact/calendar";
|
||||
import { Slider, type SliderChangeEvent } from "primereact/slider";
|
||||
@@ -91,6 +91,46 @@ export const OnlineBoardFilter: FC<OnlineBoardFilterProps> = ({
|
||||
);
|
||||
const [timeRange, setTimeRange] = useState<[number, number]>([0, 1440]);
|
||||
|
||||
// When the parent feeds new initial* props (e.g. a popular-request click
|
||||
// pushes ?departure=SVO&arrival=LED into the URL), keep the fields in
|
||||
// sync. useState only reads initial values once, so without this effect
|
||||
// clicking a popular route left the sidebar untouched.
|
||||
const lastInitialRef = useRef({
|
||||
departure: initialDeparture,
|
||||
arrival: initialArrival,
|
||||
date: initialDate,
|
||||
tab: initialTab,
|
||||
flightNumber: initialFlightNumber,
|
||||
});
|
||||
useEffect(() => {
|
||||
const prev = lastInitialRef.current;
|
||||
if (prev.departure !== initialDeparture) {
|
||||
setRouteDepartureCode(initialDeparture ?? "");
|
||||
}
|
||||
if (prev.arrival !== initialArrival) {
|
||||
setRouteArrivalCode(initialArrival ?? "");
|
||||
}
|
||||
if (prev.date !== initialDate && initialDate) {
|
||||
setRouteDate(yyyymmddToDate(initialDate));
|
||||
if (initialTab === "flight") {
|
||||
setFlightDate(yyyymmddToDate(initialDate));
|
||||
}
|
||||
}
|
||||
if (prev.tab !== initialTab && initialTab) {
|
||||
setActiveTab(initialTab);
|
||||
}
|
||||
if (prev.flightNumber !== initialFlightNumber) {
|
||||
setFlightNumber(initialFlightNumber ?? "");
|
||||
}
|
||||
lastInitialRef.current = {
|
||||
departure: initialDeparture,
|
||||
arrival: initialArrival,
|
||||
date: initialDate,
|
||||
tab: initialTab,
|
||||
flightNumber: initialFlightNumber,
|
||||
};
|
||||
}, [initialDeparture, initialArrival, initialDate, initialTab, initialFlightNumber]);
|
||||
|
||||
const handleTabClick = useCallback((tab: AccordionTab) => {
|
||||
setActiveTab((prev) => (prev === tab ? prev : tab));
|
||||
}, []);
|
||||
|
||||
@@ -107,7 +107,21 @@ export const CityAutocomplete: FC<CityAutocompleteProps> = ({
|
||||
);
|
||||
}, []);
|
||||
|
||||
const selectedCity = dictionaries?.cityByCode.get(value.toUpperCase()) ?? null;
|
||||
// Resolve the code to the owning city. The API (popular-requests,
|
||||
// deep links, etc.) hands us either a city code like "MOW" or an
|
||||
// airport code like "SVO"; in the latter case we look up the airport
|
||||
// and follow its city_code so the label reads "MOW" instead of blank.
|
||||
const selectedCity = (() => {
|
||||
if (!value || !dictionaries) return null;
|
||||
const upper = value.toUpperCase();
|
||||
const direct = dictionaries.cityByCode.get(upper);
|
||||
if (direct) return direct;
|
||||
const airport = dictionaries.airportByCode.get(upper);
|
||||
if (airport) {
|
||||
return dictionaries.cityByCode.get(airport.city_code.toUpperCase()) ?? null;
|
||||
}
|
||||
return null;
|
||||
})();
|
||||
const hasValue = Boolean(selectedCity);
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user