All files / src/components/RelativeRangeDatePicker/hooks useRelativeRangeDatePickerState.ts

100% Statements 11/11
66.66% Branches 6/9
100% Functions 3/3
100% Lines 11/11

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 843x                                                                             25x   25x           25x 25x   12x                                       25x       3x 3x 3x 3x            
import React from 'react';
 
import type {DateTime} from '@gravity-ui/date-utils';
import {useControlledState} from '@gravity-ui/uikit';
 
import type {Value} from '../../RelativeDatePicker';
import type {RangeValue} from '../../types';
import {i18n} from '../../utils/validation/i18n';
import {getRangeValidationResult} from '../../utils/validation/relativeRangeDatePicker';
 
export type RelativeRangeDatePickerValue = RangeValue<Value | null>;
 
export interface RelativeRangeDatePickerState {
    value: RelativeRangeDatePickerValue | null;
    timeZone: string;
    setValue: (value: RelativeRangeDatePickerValue | null, timeZone: string) => void;
    isInvalid: boolean;
    errors: string[];
}
 
export interface RelativeRangeDatePickerStateOptions {
    value?: RelativeRangeDatePickerValue | null;
    defaultValue?: RelativeRangeDatePickerValue;
    onUpdate?: (value: RelativeRangeDatePickerValue | null, timeZone: string) => void;
    timeZone?: string;
    defaultTimeZone?: string;
    onUpdateTimeZone?: (timeZone: string) => void;
    /** The minimum allowed date that a user may select. */
    minValue?: DateTime;
    /** The maximum allowed date that a user may select. */
    maxValue?: DateTime;
    /** Callback that is called for each date of the calendar. If it returns true, then the date is unavailable. */
    isDateUnavailable?: (date: DateTime, endpoint: 'start' | 'end') => boolean;
    allowNullableValues?: boolean;
}
 
export function useRelativeRangeDatePickerState(
    props: RelativeRangeDatePickerStateOptions,
): RelativeRangeDatePickerState {
    const [value, setValue] = useControlledState(props.value, props.defaultValue ?? null);
 
    const [timeZone, setTimeZone] = useControlledState(
        props.timeZone,
        props.defaultTimeZone ?? 'default',
        props.onUpdateTimeZone,
    );
 
    const {t} = i18n.useTranslation();
    const validation = React.useMemo(
        () =>
            getRangeValidationResult(
                value,
                props.allowNullableValues,
                props.minValue,
                props.maxValue,
                props.isDateUnavailable,
                timeZone,
                t,
            ),
        [
            value,
            props.allowNullableValues,
            props.isDateUnavailable,
            props.maxValue,
            props.minValue,
            timeZone,
            t,
        ],
    );
 
    return {
        value,
        timeZone,
        setValue(v, tz) {
            setValue(v);
            setTimeZone(tz);
            Eif (value !== v || (value && timeZone !== tz)) {
                props.onUpdate?.(v, tz);
            }
        },
        ...validation,
    };
}