Skip to content

Commit

Permalink
- move useFilterTrainSchedules in Timetable component
Browse files Browse the repository at this point in the history
- remove useEffects in the custom hook in favor of useMemos
- remove displayedTimetableItems state and reuse the filtered array from the custom hook
- group the filters to a single object to facilitate the props drilling
  • Loading branch information
SharglutDev committed Feb 25, 2025
1 parent 8592dc8 commit 2234f05
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,30 @@ import { X } from '@osrd-project/ui-icons';
import cx from 'classnames';
import { useTranslation } from 'react-i18next';

import type { ValidityFilter, ScheduledPointsHonoredFilter } from './types';
import type { ValidityFilter, ScheduledPointsHonoredFilter, TimetableFilters } from './types';

type FilterPanelProps = {
toggleFilterPanel: () => void;
nameLabelFilter: string;
setNameLabelFilter: (filter: string) => void;
rollingStockFilter: string;
setRollingStockFilter: (rollingStockFilter: string) => void;
validityFilter: ValidityFilter;
setValidityFilter: (validityFilter: ValidityFilter) => void;
scheduledPointsHonoredFilter: ScheduledPointsHonoredFilter;
setScheduledPointsHonoredFilter: (
scheduledPointsHonoredFilter: ScheduledPointsHonoredFilter
) => void;
uniqueTags: string[];
selectedTags: Set<string | null>;
setSelectedTags: React.Dispatch<React.SetStateAction<Set<string | null>>>;
timetableFilters: TimetableFilters;
};

const FilterPanel = ({
toggleFilterPanel,
nameLabelFilter,
setNameLabelFilter,
rollingStockFilter,
setRollingStockFilter,
validityFilter,
setValidityFilter,
scheduledPointsHonoredFilter,
setScheduledPointsHonoredFilter,
uniqueTags,
selectedTags,
setSelectedTags,
}: FilterPanelProps) => {
const FilterPanel = ({ toggleFilterPanel, timetableFilters }: FilterPanelProps) => {
const { t } = useTranslation('operationalStudies/scenario');

const {
nameLabelFilter,
setNameLabelFilter,
rollingStockFilter,
setRollingStockFilter,
validityFilter,
setValidityFilter,
scheduledPointsHonoredFilter,
setScheduledPointsHonoredFilter,
uniqueTags,
selectedTags,
setSelectedTags,
} = timetableFilters;

const validityOptions: { value: ValidityFilter; label: string }[] = [
{ value: 'both', label: t('timetable.showAllTrains') },
{ value: 'valid', label: t('timetable.showValidTrains') },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import PacedTrainItem from './PacedTrain/PacedTrainItem';
import TimetableToolbar from './TimetableToolbar';
import TrainScheduleItem from './TrainScheduleItem';
import type { PacedTrainWithResult, TimetableItemResult, TrainScheduleWithDetails } from './types';
import useFilterTrainSchedules from './useFilterTrainSchedules';

type TimetableProps = {
setDisplayTrainScheduleManagement: (mode: string) => void;
Expand Down Expand Up @@ -61,7 +62,6 @@ const Timetable = ({
const { t } = useTranslation(['operationalStudies/scenario', 'common/itemTypes']);
const showPacedTrains = useSelector(getShowPacedTrains);

const [displayedTimetableItems, setDisplayedTimetableItems] = useState<TimetableItemResult[]>([]);
const [conflictsListExpanded, setConflictsListExpanded] = useState(false);
const [selectedTimetableItemIds, setSelectedTimetableItemIds] = useState<TimetableItemId[]>([]);
const [showTrainDetails, setShowTrainDetails] = useState(false);
Expand All @@ -80,6 +80,8 @@ const Timetable = ({
dtoImport();
}, []);

const { filteredTrainSchedules, ...timetableFilters } = useFilterTrainSchedules(timetableItems);

const toggleConflictsListExpanded = () => {
setConflictsListExpanded(!conflictsListExpanded);
};
Expand Down Expand Up @@ -111,8 +113,8 @@ const Timetable = ({
};

const currentDepartureDates = useMemo(
() => displayedTimetableItems.map((train) => formatDepartureDate(train.startTime)),
[displayedTimetableItems]
() => filteredTrainSchedules.map((train) => formatDepartureDate(train.startTime)),
[filteredTrainSchedules]
);

const showDepartureDates = useMemo(() => {
Expand Down Expand Up @@ -180,16 +182,16 @@ const Timetable = ({
showTrainDetails={showTrainDetails}
toggleShowTrainDetails={toggleShowTrainDetails}
timetableItems={timetableItems}
displayedTimetableItems={displayedTimetableItems}
setDisplayedTimetableItems={setDisplayedTimetableItems}
filteredTimetableItems={filteredTrainSchedules}
timetableFilters={timetableFilters}
selectedTimetableItemIds={selectedTimetableItemIds}
setSelectedTimetableItemIds={setSelectedTimetableItemIds}
removeTrains={removeAndUnselectTrains}
trainSchedules={trainSchedules}
isInSelection={selectedTimetableItemIds.length > 0}
/>
<Virtualizer overscan={15}>
{displayedTimetableItems.map((timetableItem, index) => (
{filteredTrainSchedules.map((timetableItem, index) => (
<div key={`timetable-train-card-${timetableItem.id}`}>
{showDepartureDates[index] && (
<div className="scenario-timetable-departure-date">
Expand Down Expand Up @@ -239,7 +241,7 @@ const Timetable = ({
toggleConflictsList={toggleConflictsListExpanded}
// TODO PACED TRAIN : Adapt this props to handle paced trains in issue
trainSchedulesDetails={
displayedTimetableItems.filter((train) =>
filteredTrainSchedules.filter((train) =>
isTrainSchedule(train.id)
) as TrainScheduleWithDetails[]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,15 @@ import { castErrorToFailure } from 'utils/error';
import { formatTrainScheduleIdToEditoastTrainId, isTrainSchedule } from 'utils/trainId';

import FilterPanel from './FilterPanel';
import type { TimetableItemResult } from './types';
import useFilterTrainSchedules from './useFilterTrainSchedules';
import type { TimetableFilters, TimetableItemResult } from './types';
import { timetableHasInvalidTrain } from './utils';

type TimetableToolbarProps = {
showTrainDetails: boolean;
toggleShowTrainDetails: () => void;
timetableItems: TimetableItemResult[];
displayedTimetableItems: TimetableItemResult[];
setDisplayedTimetableItems: (trainSchedulesDetails: TimetableItemResult[]) => void;
filteredTimetableItems: TimetableItemResult[];
timetableFilters: TimetableFilters;
selectedTimetableItemIds: TimetableItemId[];
setSelectedTimetableItemIds: (selectedTimetableIds: TimetableItemId[]) => void;
removeTrains: (trainIds: TimetableItemId[]) => void;
Expand All @@ -44,8 +43,8 @@ const TimetableToolbar = ({
showTrainDetails,
toggleShowTrainDetails,
timetableItems,
displayedTimetableItems,
setDisplayedTimetableItems,
filteredTimetableItems,
timetableFilters,
selectedTimetableItemIds,
setSelectedTimetableItemIds,
removeTrains,
Expand Down Expand Up @@ -97,30 +96,15 @@ const TimetableToolbar = ({

const [deleteTrainSchedules] = osrdEditoastApi.endpoints.deleteTrainSchedule.useMutation();

// TODO: move this hook in Timetable
const {
uniqueTags,
nameLabelFilter,
setNameLabelFilter,
rollingStockFilter,
setRollingStockFilter,
validityFilter,
setValidityFilter,
scheduledPointsHonoredFilter,
setScheduledPointsHonoredFilter,
selectedTags,
setSelectedTags,
} = useFilterTrainSchedules(timetableItems, setDisplayedTimetableItems);

const toggleFilterPanel = () => {
setIsFilterPanelOpen(!isFilterPanelOpen);
};

const toggleAllTrainsSelecton = () => {
if (displayedTimetableItems.length === selectedTimetableItemIds.length) {
if (filteredTimetableItems.length === selectedTimetableItemIds.length) {
setSelectedTimetableItemIds([]);
} else {
const timetableItemsDisplayed = displayedTimetableItems.map(({ id }) => id);
const timetableItemsDisplayed = filteredTimetableItems.map(({ id }) => id);
setSelectedTimetableItemIds(timetableItemsDisplayed);
}
};
Expand Down Expand Up @@ -295,7 +279,7 @@ const TimetableToolbar = ({
</div>
)}
</div>
{timetableHasInvalidTrain(displayedTimetableItems) && (
{timetableHasInvalidTrain(filteredTimetableItems) && (
<div className="invalid-trains">
<Alert size="sm" variant="fill" />
<span data-testid="invalid-trains-message" className="invalid-trains-message">
Expand Down Expand Up @@ -324,17 +308,7 @@ const TimetableToolbar = ({
) : (
<FilterPanel
toggleFilterPanel={toggleFilterPanel}
nameLabelFilter={nameLabelFilter}
setNameLabelFilter={setNameLabelFilter}
rollingStockFilter={rollingStockFilter}
setRollingStockFilter={setRollingStockFilter}
validityFilter={validityFilter}
setValidityFilter={setValidityFilter}
scheduledPointsHonoredFilter={scheduledPointsHonoredFilter}
setScheduledPointsHonoredFilter={setScheduledPointsHonoredFilter}
uniqueTags={uniqueTags}
selectedTags={selectedTags}
setSelectedTags={setSelectedTags}
timetableFilters={timetableFilters}
/>
)}
</div>
Expand Down
16 changes: 16 additions & 0 deletions front/src/modules/trainschedule/components/Timetable/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,19 @@ export type PacedTrainWithResult = TimetableItemWithDetails & {
};

export type TimetableItemResult = TrainScheduleWithDetails | PacedTrainWithResult;

export type TimetableFilters = {
uniqueTags: string[];
nameLabelFilter: string;
setNameLabelFilter: (nameLabelFilter: string) => void;
rollingStockFilter: string;
setRollingStockFilter: (rollingStockFilter: string) => void;
validityFilter: ValidityFilter;
setValidityFilter: (validityFilter: ValidityFilter) => void;
scheduledPointsHonoredFilter: ScheduledPointsHonoredFilter;
setScheduledPointsHonoredFilter: (
scheduledPointsHonoredFilter: ScheduledPointsHonoredFilter
) => void;
selectedTags: Set<string | null>;
setSelectedTags: React.Dispatch<React.SetStateAction<Set<string | null>>>;
};
Loading

0 comments on commit 2234f05

Please sign in to comment.