import { useImperativeHandle, forwardRef, useEffect, useState, type Ref, useRef } from "react"; import { TouchableOpacity, View } from "react-native"; import type IDateTimePickerProps from "./type"; import type { DateTimePickerDateRange, DateTimePickerType, IDateTimePickerRef } from "./type"; import stylesheet, { getDateTimePickerType, useStyles } from "./stylesheet"; import { NCoreUIKitLocalize, NCoreUIKitTheme } from "../../core/hooks"; import { type NCoreUIKitIcon } from "../../types"; import type { IBottomSheetRef } from "../bottomSheet/type"; import type ITextProps from "../text/type"; import { type RRule as RRuleType, RRule } from "rrule"; import moment from "moment"; import { BadgeQuestionMarkIcon, BadgeSuccessIcon, BadgeDangerIcon, BadgeAlertIcon, BadgeInfoIcon, CleanIcon } from "../../assets/svg"; import { uuid } from "../../utils"; import Text from "../text"; import DateTimeSheet from "../dateTimeSheet"; import { parseRRuleConfig } from "../../helpers"; const DateTimePickerTypeIcon: Record, NCoreUIKitIcon> = { "question": BadgeQuestionMarkIcon, "success": BadgeSuccessIcon, "warning": BadgeAlertIcon, "danger": BadgeDangerIcon, "info": BadgeInfoIcon }; const DateTimePicker = ({ renderLoadingIcon : LoadingIconComponentProp, rightIcon: RightIconComponentProp, localeBasedFirstDayOfWeek = true, hintTextIcon: HintTextIconProp, spreadBehaviour = "baseline", customDateTimeSheetLocalize, isShowTodayIndicator = true, titleFormat = "DD MMM YYYY", isShowDateTimeTools = true, isShowHintTextIcon = false, isWorkWithRealtime = true, dayOfWeekLength = "short", customDateTimeSheetTheme, pickerType = "date-time", icon: IconComponentProp, hintTextContainerStyle, removeSelectValidation, isCleanEnabled = false, contentContainerStyle, subTitle = "Optional", isSearchable = false, onFocus: onFocusProp, isRequired = false, isDisabled = false, onBlur: onBlurProp, dateTimeSheetProps, variant = "single", hintTextIconStyle, initialDateRange, type = "default", selectValidation, initialDateRule, dateRangeTitle, customLocalize, rightIconStyle, isShowSubTitle, cleanIconStyle, maxChoice = -1, contentStyle, initialDate, customTheme, placeholder, isOptional, customKey, minChoice, iconStyle, onChange, hintText, onCancel, maxDate, minDate, style, title, onOk }: IDateTimePickerProps, ref: Ref) => { const { inlineSpaces, typography, radiuses, borders, spaces, colors } = NCoreUIKitTheme.useContext(customTheme); const { rruleConfig, localize } = NCoreUIKitLocalize.useContext(customLocalize); const bottomSheetRef = useRef(null); const dateTimePickerKey = useRef(customKey ? customKey : uuid()); const currentType = getDateTimePickerType({ type }); const styleType = type === "default" ? "neutral" : type === "question" ? "neutral" : type === "danger" ? "error" : type; const [ isActive, setIsActive ] = useState(false); const [ isLoading, setIsLoading ] = useState(false); const [ tempDate, setTempDate ] = useState(initialDate); const [ date, setDate ] = useState(initialDate); const [ tempDateRule, setTempDateRule ] = useState(initialDateRule); const [ dateRule, setDateRule ] = useState(initialDateRule); const [ dateRange, setDateRange ] = useState(initialDateRange); const [ tempDateRange, setTempDateRange ] = useState(initialDateRange); const mainDateRange = isWorkWithRealtime ? dateRange : tempDateRange; const mainDateRule = isWorkWithRealtime ? dateRule : tempDateRule; const mainDate = isWorkWithRealtime ? date : tempDate; const { contentContainer: contentContainerDynamicStyle, titleContainer: titleContainerDynamicStyle, hintTextIcon: hintTextIconDynamicStyle, contentText: contentTextDynamicStyle, cleanButton: cleanButtonDynamicStyle, rightIcon: rightIconDynamicStyle, container: containerDynamicStyle, hintText: hintTextDynamicStyle, required: requiredDynamicStyle, subTitle: subTitleDynamicStyle, overlay: overlayDynamicStyle, content: contentDynamicStyle, title: titleDynamicStyle, icon: iconDynamicStyle } = useStyles({ icon: IconComponentProp ? true : false, spreadBehaviour, inlineSpaces, isSearchable, currentType, isDisabled, isActive, radiuses, borders, spaces, colors, title, type }); useImperativeHandle( ref, () => ({ setDateRange: (dateRange) => { if(isWorkWithRealtime) { setDateRange(dateRange); } else { setTempDateRange(dateRange); } }, setDateRule: (dateRule) => { if(isWorkWithRealtime) { setDateRule(dateRule); } else { setTempDateRule(dateRule); } }, setDate: (date) => { if(isWorkWithRealtime) { setDate(date); } else { setTempDate(date); } }, getValue: () => { return { dateRange, dateRule, date }; }, cancel, clean, focus, blur, ok }), [ dateRange, dateRule, date ] ); useEffect(() => { if(isActive) { if(onFocus) onFocus(); } else { if(!isWorkWithRealtime) { setTempDateRange(undefined); setTempDateRule(undefined); setTempDate(undefined); } if(onBlur) onBlur(); } }, [ isActive ]); useEffect(() => { if(onChange) { onChange({ dateRange, dateRule, date }); } }, [ tempDateRange, tempDateRule, dateRange, dateRule, tempDate, date ]); const titleProps: ITextProps = { color: currentType.titleColor, variant: "bodyLargeSize" }; const iconProps: NCoreUIKit.IconCallbackProps = { size: Number(typography.labelLargeSize.fontSize) + 6, color: currentType.iconColor }; if(isDisabled) { iconProps.color = "disabled"; } const blur = () => { setIsActive(false); }; const focus = () => { if(!isWorkWithRealtime) { setTempDateRange(dateRange); setTempDateRule(dateRule); setTempDate(date); } setIsActive(true); }; const cancel = () => { if(!isWorkWithRealtime) { bottomSheetRef.current?.close(() => { blur(); }); if(onCancel) { onCancel({ dateRange, dateRule, date }); } } }; const ok = () => { if(!isWorkWithRealtime) { setDateRange(tempDateRange); setDateRule(tempDateRule); setDate(tempDate); bottomSheetRef.current?.close(() => { blur(); }); if(onOk) { onOk({ dateRange, dateRule, date }); } } }; const clean = () => { setDateRange(undefined); setDateRule(undefined); setDate(undefined); setTempDateRange(undefined); setTempDateRule(undefined); setTempDate(undefined); }; const selectDateRule = (selectedDateRule?: RRule) => { if(variant === "rrule") { if(selectedDateRule && selectedDateRule !== dateRule) { if(selectValidation) { if(selectValidation({ dateRule: selectedDateRule })) { if(isWorkWithRealtime) { setDateRule(selectedDateRule); } else { setTempDateRule(selectedDateRule); } } } else { if(isWorkWithRealtime) { setDateRule(selectedDateRule); } else { setTempDateRule(selectedDateRule); } } } else { if(removeSelectValidation) { if(removeSelectValidation({ dateRule })) { setTempDateRule(undefined); setDateRule(undefined); } } else { setTempDateRule(undefined); setDateRule(undefined); } } } }; const selectMultipleObject = (selectedDateRange?: { start?: Date; end?: Date; }) => { if(variant === "range") { if(selectedDateRange) { if(selectValidation) { if(selectValidation({ dateRule })) { if(isWorkWithRealtime) { setDateRange({ start: selectedDateRange.start, end: selectedDateRange.end }); } else { setTempDateRange({ start: selectedDateRange.start, end: selectedDateRange.end }); } } } else { if(isWorkWithRealtime) { setDateRange({ start: selectedDateRange.start, end: selectedDateRange.end }); } else { setTempDateRange({ start: selectedDateRange.start, end: selectedDateRange.end }); } } } else { if(removeSelectValidation) { if(removeSelectValidation({ dateRange: selectedDateRange })) { setTempDateRange(undefined); setDateRange(undefined); } } else { setTempDateRange(undefined); setDateRange(undefined); } } } }; const selectObject = (selectedDate?: Date) => { if(variant === "single") { if(selectedDate === date) { if(removeSelectValidation) { if(removeSelectValidation({ date })) { if(isWorkWithRealtime) { setDate(undefined); } else { setTempDate(undefined); } } } else { if(isWorkWithRealtime) { setDate(undefined); } else { setTempDate(undefined); } } } else { if(selectValidation) { if(selectValidation({ date })) { if(isWorkWithRealtime) { setDate(selectedDate); } else { setTempDate(selectedDate); } } } else { if(isWorkWithRealtime) { setDate(selectedDate); } else { setTempDate(selectedDate); } } } } }; const onFocus = () => { if(onFocusProp) onFocusProp(); }; const onBlur = () => { if(onBlurProp) onBlurProp(); }; const renderCleanButton = () => { if(isDisabled) { return null; } if(!isCleanEnabled) { return null; } if(variant === "rrule") { if(!mainDateRule) return null; } else if(variant === "range") { if(!dateRange) return null; } else { if(!date) return null; } return { setDateRange(undefined); setDateRule(undefined); setDate(undefined); setTempDateRange(undefined); setTempDateRule(undefined); setTempDate(undefined); }} > ; }; const renderIcon = () => { if (!IconComponentProp) { return null; } return ; }; const renderRightIcon = () => { if (!RightIconComponentProp) { return null; } if(isCleanEnabled) { return null; } if(variant === "rrule") { if(!mainDateRule) return null; } else if(variant === "range") { if(!mainDateRange) return null; } else { if(!mainDate) return null; } return ; }; const renderHintIcon = () => { if(!isShowHintTextIcon) { return null; } if(HintTextIconProp) { return ; } const CurrentHintIcon = DateTimePickerTypeIcon[type === "default" ? "question" : type]; return ; }; const renderHintText = () => { if (!hintText) { return null; } return {renderHintIcon()} {hintText} ; }; const renderRequired = () => { if(!isRequired) { return null; } return *; }; const renderSubtitle = () => { if(!isShowSubTitle && !isOptional) { return null; } return ( {isOptional ? localize("is-optional") : subTitle} ) ; }; const renderTitle = () => { if (!title) { return null; } return { if(!isDisabled) { focus(); } }} > {renderRequired()} {title} {renderSubtitle()} ; }; const renderDateValue = () => { if(!date) { return {placeholder ? placeholder : localize("select-any-date")} ; } return {moment(date).format(titleFormat)} ; }; const renderDateRangeValue = () => { if(!dateRange) { return {placeholder ? placeholder : localize("select-any-date")} ; } if(dateRangeTitle) { return dateRangeTitle(dateRange); } return {moment(dateRange.start).format(titleFormat)} - {moment(dateRange.end).format(titleFormat)} ; }; const renderDateRuleValue = () => { if(!dateRule) { return {placeholder ? placeholder : localize("select-any-date")} ; } return {dateRule.toText(undefined, parseRRuleConfig(rruleConfig))} ; }; const renderValue = () => { if(variant === "rrule") { return renderDateRuleValue(); } if(variant === "range") { return renderDateRangeValue(); } return renderDateValue(); }; const renderContent = () => { return {renderValue()} ; }; const renderOverlay = () => { return ; }; return {renderTitle()} { if(!isDisabled) { focus(); } }} > {renderOverlay()} {renderIcon()} {renderContent()} {renderCleanButton()} {renderRightIcon()} {renderHintText()} ; }; export default forwardRef(DateTimePicker);