refactor: allow submitting same value

This commit is contained in:
Carlos Valente
2024-12-21 12:39:46 +01:00
committed by Carlos Valente
parent b173b5a8e8
commit b38a7e5c92
4 changed files with 52 additions and 27 deletions
@@ -16,6 +16,7 @@ export default function useReactiveTextInput(
submitOnEnter?: boolean;
submitOnCtrlEnter?: boolean;
onCancelUpdate?: () => void;
allowSubmitSameValue?: boolean;
},
): UseReactiveTextInputReturn {
const [text, setText] = useState<string>(initialText);
@@ -48,7 +49,7 @@ export default function useReactiveTextInput(
const handleSubmit = useCallback(
(valueToSubmit: string) => {
// No need to update if it hasn't changed
if (valueToSubmit === initialText) {
if (valueToSubmit === initialText && !options?.allowSubmitSameValue) {
options?.onCancelUpdate?.();
} else {
const cleanVal = valueToSubmit.trim();
+41 -22
View File
@@ -225,38 +225,32 @@ export const useEventAction = () => {
*/
const updateTimer = useCallback(
async (eventId: string, field: TimeField, value: string, lockOnUpdate?: boolean) => {
let newValMillis = 0;
// check for previous keyword
if (value === 'p' || value === 'prev' || value === 'previous') {
newValMillis = getPreviousEnd();
// check for adding time keyword
} else if (value.startsWith('+') || value.startsWith('p+') || value.startsWith('p +')) {
// TODO: is this logic solid?
const remainingString = value.substring(1);
newValMillis = getPreviousEnd() + parseUserTime(remainingString);
} else {
newValMillis = parseUserTime(value);
// an empty value with no lock has no domain validity
if (!lockOnUpdate && value === '') {
return;
}
// dont allow timer values over 23:59:59
const cappedMillis = Math.min(newValMillis, dayInMs - MILLIS_PER_SECOND);
const newEvent = {
const newEvent: Partial<OntimeEvent> = {
id: eventId,
[field]: cappedMillis,
};
// check if we should lock the field
if (lockOnUpdate) {
if (field === 'timeEnd') {
newEvent.timeStrategy = TimeStrategy.LockEnd;
// an empty value indicates that we should unlock the field
newEvent.timeStrategy = value === '' ? TimeStrategy.LockDuration : TimeStrategy.LockEnd;
newEvent.timeEnd = value === '' ? undefined : calculateNewValue();
} else if (field === 'duration') {
newEvent.timeStrategy = TimeStrategy.LockDuration;
} else if (field === 'timeStart' && value === '') {
// if user removes the time start, we should link to the previous
newEvent.linkStart = 'true';
// an empty value indicates that we should unlock the field
newEvent.timeStrategy = value === '' ? TimeStrategy.LockEnd : TimeStrategy.LockDuration;
newEvent.duration = value === '' ? undefined : calculateNewValue();
} else if (field === 'timeStart') {
// an empty values means we should link to the previous
newEvent.linkStart = value === '' ? 'true' : null;
newEvent.timeStart = value === '' ? undefined : calculateNewValue();
}
} else {
newEvent[field] = calculateNewValue();
}
try {
@@ -265,6 +259,31 @@ export const useEventAction = () => {
logAxiosError('Error updating event', error);
}
/**
* Utility function to calculate the new time value
*/
function calculateNewValue(): number {
let newValMillis = 0;
// check for previous keyword
if (value === 'p' || value === 'prev' || value === 'previous') {
newValMillis = getPreviousEnd();
// check for adding time keyword
} else if (value.startsWith('+') || value.startsWith('p+') || value.startsWith('p +')) {
// TODO: is this logic solid?
const remainingString = value.substring(1);
newValMillis = getPreviousEnd() + parseUserTime(remainingString);
} else {
newValMillis = parseUserTime(value);
}
// dont allow timer values over 23:59:59
return Math.min(newValMillis, dayInMs - MILLIS_PER_SECOND);
}
/**
* Utility function to get the previous event end time
*/
function getPreviousEnd(): number {
const cachedRundown = queryClient.getQueryData<RundownCached>(RUNDOWN);
@@ -5,16 +5,18 @@ import useReactiveTextInput from '../../../../common/components/input/text-input
interface SingleLineCellProps {
initialValue: string;
allowSubmitSameValue?: boolean;
handleUpdate: (newValue: string) => void;
handleCancelUpdate?: () => void;
}
const SingleLineCell = forwardRef((props: SingleLineCellProps, inputRef) => {
const { initialValue, handleUpdate, handleCancelUpdate } = props;
const { initialValue, allowSubmitSameValue, handleUpdate, handleCancelUpdate } = props;
const ref = useRef<HTMLInputElement | null>(null);
const submitCallback = useCallback((newValue: string) => handleUpdate(newValue), [handleUpdate]);
const { value, onChange, onBlur, onKeyDown } = useReactiveTextInput(initialValue, submitCallback, ref, {
allowSubmitSameValue,
submitOnEnter: true, // single line should submit on enter
submitOnCtrlEnter: true,
onCancelUpdate: handleCancelUpdate,
@@ -41,8 +41,9 @@ export default function TimeInputDuration(props: TimeInputDurationProps) {
(newValue: string) => {
setIsEditing(false);
// Check if there is anything there
// if the user sends an empty string, we want to clear the value
if (newValue === '') {
onSubmit(newValue);
return;
}
@@ -59,14 +60,15 @@ export default function TimeInputDuration(props: TimeInputDurationProps) {
return;
}
if (valueInMillis === initialValue) {
// if the value is the same, we may still want to push the lock change
if (valueInMillis === initialValue && lockedValue) {
return;
}
onSubmit(newValue);
setValue(Number(newValue));
},
[initialValue, onSubmit],
[initialValue, lockedValue, onSubmit],
);
// duration times have a special format
@@ -77,6 +79,7 @@ export default function TimeInputDuration(props: TimeInputDurationProps) {
<SingleLineCell
ref={inputRef}
initialValue={timeString}
allowSubmitSameValue={!lockedValue} // if the value is not locked, submitting will lock the value
handleUpdate={handleUpdate}
handleCancelUpdate={handleFakeBlur}
/>