Skip to content

Conversation

@Pivouane
Copy link
Contributor

@Pivouane Pivouane commented Jan 21, 2026

Context

The previous TimeCell implementation relied on a input mask and tweaks with a microTask queue.
This was not a good solution for multiple reasons, including complexity.

What changed

The TimeCell now works with a section-based approach:

  • time is represented as three sections (hours, minutes, seconds)
  • all keyboard interactions are handled by a reducer

How should this work

This refactor also focuses on behaviors implied by the UX/UI requirements, to ensure that this sketch is respected here's a few test cases for those who needs to review the component.

  • Typing 0145 while focused on minutes and pressing enter should display 01:45:00
  • Backspace should lead to an intuitive clear of the input
  • Arrow keys shoudl correctly switch between sections
  • Clicking sections should correctly handle the focus

Rewriting the integration of the timeCell also accomodates the work of linking the table with the backend process.

related to https://github.com/osrd-project/osrd-confidential/issues/1281

This closes #14277 and closes #14275

because it will most likely be handled by the backend manipulations.

@Pivouane Pivouane requested a review from a team as a code owner January 21, 2026 09:34
@github-actions github-actions bot added the area:front Work on Standard OSRD Interface modules label Jan 21, 2026
@Pivouane Pivouane changed the title Connceting user props with implemented timecell value-handling behaviors Connecting user props with implemented timecell value-handling behaviors Jan 21, 2026
@Pivouane Pivouane moved this to In Progress in Board PI 18 Jan 22, 2026
@Pivouane Pivouane self-assigned this Jan 22, 2026
@Pivouane Pivouane changed the title Connecting user props with implemented timecell value-handling behaviors Replace masked TimeCell input with section-based state machine Jan 22, 2026
Signed-off-by: Pivouane (Pierre Santamaria) <pierrenumber1@outlook.com>
@Pivouane Pivouane force-pushed the psa/fix-time-stops-table-timecell branch from 8cc6c80 to f3fa397 Compare January 22, 2026 15:51
Signed-off-by: Pivouane (Pierre Santamaria) <pierrenumber1@outlook.com>
Signed-off-by: Pivouane (Pierre Santamaria) <pierrenumber1@outlook.com>
Copy link
Contributor

@kmer2016 kmer2016 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well done ! Just some nit comment.

Integration changes will likely be needed when connecting to backend via PR #14853.

Comment on lines 39 to 45
const toSectionState = (str: string, section: Section): SectionState => {
const digits = str.replace(/\D/g, '').slice(-2);
if (digits.length === 2) return digits;
const sectionPlaceholder = SECTION_PLACEHOLDERS[section];
if (digits.length === 1) return sectionPlaceholder + digits;
return sectionPlaceholder + sectionPlaceholder;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can moving the placeholder variable to the top for clearer separation between setup and conditions:

Suggested change
const toSectionState = (str: string, section: Section): SectionState => {
const digits = str.replace(/\D/g, '').slice(-2);
if (digits.length === 2) return digits;
const sectionPlaceholder = SECTION_PLACEHOLDERS[section];
if (digits.length === 1) return sectionPlaceholder + digits;
return sectionPlaceholder + sectionPlaceholder;
};
const formatSectionDigits = (str: string, section: Section): SectionState => {
const digits = str.replace(/\D/g, '').slice(-2);
const sectionPlaceholder = SECTION_PLACEHOLDERS[section];
if (digits.length === 2) return digits;
if (digits.length === 1) return sectionPlaceholder + digits;
return sectionPlaceholder + sectionPlaceholder;
};

Comment on lines 68 to 71
const getSectionStateDigitCount = (sectionState: SectionState): number => {
const digitCount = sectionState.replace(/\D/g, '').length;
return digitCount;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
const getSectionStateDigitCount = (sectionState: SectionState): number => {
const digitCount = sectionState.replace(/\D/g, '').length;
return digitCount;
};
const countDigits = (sectionState: SectionState): number => sectionState.replace(/\D/g, '').length;

return digitCount;
};

const isFull = (pair: SectionState): boolean => getSectionStateDigitCount(pair) === 2;
Copy link
Contributor

@kmer2016 kmer2016 Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit

Suggested change
const isFull = (pair: SectionState): boolean => getSectionStateDigitCount(pair) === 2;
const hasAllDigits = (pair: SectionState): boolean => getSectionStateDigitCount(pair) === 2;


const isFull = (pair: SectionState): boolean => getSectionStateDigitCount(pair) === 2;

const isEmpty = (pair: SectionState): boolean => getSectionStateDigitCount(pair) === 0;
Copy link
Contributor

@kmer2016 kmer2016 Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
const isEmpty = (pair: SectionState): boolean => getSectionStateDigitCount(pair) === 0;
const hasNoDigits = (pair: SectionState): boolean => getSectionStateDigitCount(pair) === 0;

Signed-off-by: Pivouane (Pierre Santamaria) <pierrenumber1@outlook.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:front Work on Standard OSRD Interface modules

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

Schedule Table, Columns using TimeCell Schedule Table, Time and Date processing in TimeCell

3 participants