/** * Converts a number value to a string for input fields. * Returns empty string for undefined or NaN values. */ export const numberValue = (value?: number): string => value === undefined || isNaN(value) ? '' : String(value); /** * Extracts the appropriate value from an input event based on input type. */ export const extractEventValue = ( event: React.ChangeEvent ): string | number | boolean => { const { type, valueAsNumber, checked, value } = event.target; if (type === 'number') return valueAsNumber; if (type === 'checkbox') return checked; return value; }; type UpdateEntity = (state: (prevState: Readonly) => S) => void; /** * Creates an event handler that updates an entity's state based on input changes. */ export const updateValue = >(updateEntity: UpdateEntity) => (event: React.ChangeEvent): void => { const { name } = event.target; const value = extractEventValue(event); updateEntity((prevState) => ({ ...prevState, [name]: value })); }; /** * Creates an event handler that tracks dirty flags for modified fields. * Optimized to minimize state updates and unnecessary array operations. */ export const updateValueDirty = >( origData: T, dirtyFlags: string[], setDirtyFlags: React.Dispatch>, updateDataValue: (updater: (prevState: T) => T) => void ) => (event: React.ChangeEvent): void => { const { name } = event.target; const updatedValue = extractEventValue(event); updateDataValue((prevState) => ({ ...prevState, [name]: updatedValue })); const isDirty = origData[name] !== updatedValue; const wasDirty = dirtyFlags.includes(name); // Only update dirty flags if the state changed if (isDirty !== wasDirty) { setDirtyFlags( isDirty ? [...dirtyFlags, name] : dirtyFlags.filter((f) => f !== name) ); } };