浏览代码

Feature: Time selector is completed.

lfabl 1 周之前
父节点
当前提交
8fa2892c2b

+ 2 - 2
example/src/pages/home/index.tsx

@@ -369,9 +369,9 @@ const Home = () => {
         <DateTimePicker
             minDate={moment().subtract(2, "months").toDate()}
             maxDate={moment().add(1, "months").toDate()}
-            multipleSelectMinimumRequireMS={18000000}
+            multipleSelectMinimumRequireMS={709200000}
             multipleSelectMinimumRequiredDayCount={3}
-            multipleSelectMaximumMS={36000000}
+            multipleSelectMaximumMS={745200000}
             multipleSelectDayLimit={10}
             isWorkWithRealtime={false}
             isWorkWithSeconds={true}

+ 0 - 7
siradakiler.txt

@@ -1,10 +1,3 @@
-* saat seçim sistemi.
-    -> validation'ın yazma işlemi bittiği anda check edip değilse geriye öyleyse okey'e yönlendirme işi.
-        Ama bu durum default yapıyı da bozmamalı.
-    -> min-max hours-minutes mantığı da eklenecek.
-    -> start end den sonra ya da end start dan önce olmayacak time için.
-    -> Date değiştiğinde tarihin üzerine yazımı eklenecek.
-    -> Düz date test edilecek.
 * ay seçimi.
 * yıl seçimi.
 * hızlı filtreler.

+ 20 - 2
src/components/numericInput/index.tsx

@@ -55,6 +55,7 @@ const NumericInput: RefForwardingComponent<INumericInputRef, ITextInputProps> =
     hintTextIcon: HintTextIconProp,
     spreadBehaviour = "baseline",
     isShowHideTextButton = true,
+    isWorkWithDebouncer = false,
     isShowHintTextIcon = false,
     icon: IconComponentProp,
     hintTextContainerStyle,
@@ -104,6 +105,7 @@ const NumericInput: RefForwardingComponent<INumericInputRef, ITextInputProps> =
         type
     });
 
+    const inputDebouncer = useRef<ReturnType<typeof setTimeout>>(null);
     const inputRef = useRef<NumericInputInstance | null>(null);
 
     const styleType = type === "default" ? "neutral" : type === "question" ? "neutral" : type === "danger" ? "error" : type;
@@ -260,7 +262,10 @@ const NumericInput: RefForwardingComponent<INumericInputRef, ITextInputProps> =
             return;
         }
 
-        const isValid = validation ? validation(newValue) : true;
+        const isValid = validation ? validation(newValue, (text) => {
+            if (onChangeText) onChangeText(newValue);
+            setValue(text);
+        }) : true;
 
         if (!isValid) {
             setSelection({
@@ -525,7 +530,20 @@ const NumericInput: RefForwardingComponent<INumericInputRef, ITextInputProps> =
             onSelectionChange={(e) => setSelection(e.nativeEvent.selection)}
             secureTextEntry={variant === "hidden" && hideValue}
             underlineColorAndroid="rgba(255,255,255,0)"
-            onChangeText={handleTextChange}
+            onChangeText={(text) => {
+                if(isWorkWithDebouncer) {
+                    if(inputDebouncer.current) {
+                        clearTimeout(inputDebouncer.current);
+                        inputDebouncer.current = null;
+                    }
+
+                    inputDebouncer.current = setTimeout(() => {{
+                        handleTextChange(text);
+                    }}, 550);
+                } else {
+                    handleTextChange(text);
+                }
+            }}
             placeholder={placeholder}
             allowFontScaling={false}
             editable={!isDisabled}

+ 5 - 1
src/components/numericInput/type.ts

@@ -68,11 +68,15 @@ interface INumericInputProps extends TextInputProps {
     };
     spreadBehaviour?: NumericInputSpreadBehaviour;
     onChangeText?: (value: string) => void;
-    validation?: (text: string) => boolean;
+    validation?: (
+        text: string,
+        setText: (text: string) => void
+    ) => boolean;
     isAutoKeyboardDismissOnBlur?: boolean;
     hintTextContainerStyle?: ViewStyle;
     contentContainerStyle?: ViewStyle;
     isShowHideTextButton?: boolean;
+    isWorkWithDebouncer?: boolean;
     hideTextIconStyle?: ViewStyle;
     rightIconOnPress?: () => void;
     hintTextIcon?: NCoreUIKitIcon;

+ 39 - 32
src/components/timeSelector/components/timeInput/index.tsx

@@ -1,6 +1,5 @@
 import {
-    type FC,
-    useRef
+    type FC
 } from "react";
 import {
     TouchableOpacity
@@ -39,8 +38,6 @@ const TimeInput: FC<TimeInputCombinedProps> = ({
         radiuses
     } = NCoreUIKitTheme.useContext();
 
-    const inputDebouncer = useRef<ReturnType<typeof setTimeout>>(null);
-
     const {
         container: containerDynamicStyle,
         input: inputDynamicStyle
@@ -57,10 +54,10 @@ const TimeInput: FC<TimeInputCombinedProps> = ({
     >
         <NumericInput
             {...props}
-            validation={(text) => {
+            validation={(text, setText) => {
                 let resp = true;
 
-                if(props.validation && !props.validation(text)) {
+                if(props.validation && !props.validation(text, setText)) {
                     return false;
                 }
 
@@ -68,24 +65,29 @@ const TimeInput: FC<TimeInputCombinedProps> = ({
 
                 if(timeType === "hours") {
                     if(num < 0) {
+                        setText("0");
                         resp = false;
                     }
 
                     if(isWorkWith24HoursFormat) {
                         if(num > 23) {
+                            setText("23");
                             resp = false;
                         }
                     } else {
                         if(num > 11) {
+                            setText("11");
                             resp = false;
                         }
                     }
                 } else {
                     if(num < 0) {
+                        setText("0");
                         resp = false;
                     }
 
                     if(num > 59) {
+                        setText("59");
                         resp = false;
                     }
                 }
@@ -103,14 +105,20 @@ const TimeInput: FC<TimeInputCombinedProps> = ({
                         if(nDRV) {
                             const nDRVMoment = moment(nDRV[rangeType as "start" | "end"]);
 
-                            if(minDate && nDRVMoment.isBefore(minDate)) resp = false;
-
-                            if(maxDate && nDRVMoment.isAfter(maxDate)) resp = false;
+                            if(minDate && nDRVMoment.isBefore(minDate)) {
+                                setText(moment(minDate).get(timeType).toString());
+                                resp = false;
+                            }
 
+                            if(maxDate && nDRVMoment.isAfter(maxDate)) {
+                                setText(moment(maxDate).get(timeType).toString());
+                                resp = false;
+                            }
+                            console.log("x:", resp);
                             if(rangeValidation && !rangeValidation({
                                 rangeType: rangeType as "start" | "end",
                                 dateRangeValue: nDRV
-                            })) {
+                            }, setText)) {
                                 resp = false;
                             }
                         }
@@ -119,37 +127,36 @@ const TimeInput: FC<TimeInputCombinedProps> = ({
                             [timeType]: Number(text)
                         });
 
-                        if(minDate && nDV && moment(nDV).isBefore(minDate)) resp = false;
+                        if(minDate && nDV && moment(nDV).isBefore(minDate)) {
+                            setText(moment(minDate).get(timeType).toString());
+                            resp = false;
+                        }
 
-                        if(maxDate && nDV && moment(nDV).isAfter(maxDate)) resp = false;
+                        if(maxDate && nDV && moment(nDV).isAfter(maxDate)) {
+                            setText(moment(maxDate).get(timeType).toString());
+                            resp = false;
+                        }
                     }
                 }
 
                 return resp;
             }}
             onChangeText={(text) => {
-                if(inputDebouncer.current) {
-                    clearTimeout(inputDebouncer.current);
-                    inputDebouncer.current = null;
-                }
-
-                inputDebouncer.current = setTimeout(() => {{
-                    if(variant === "range") {
-                        const updateTime: UpdateDateRangeType = {
-                            rangeType: rangeType as "start" | "end"
-                        };
+                if(variant === "range") {
+                    const updateTime: UpdateDateRangeType = {
+                        rangeType: rangeType as "start" | "end"
+                    };
 
-                        updateTime[timeType] = Number(text);
+                    updateTime[timeType] = Number(text);
 
-                        const nDRV = setDateRangeValue(updateTime);
-                        selectMultipleObject(nDRV);
-                    } else {
-                        const nDV = setDateValue({
-                            [timeType]: Number(text)
-                        });
-                        selectObject(nDV);
-                    }
-                }}, 500);
+                    const nDRV = setDateRangeValue(updateTime);
+                    selectMultipleObject(nDRV);
+                } else {
+                    const nDV = setDateValue({
+                        [timeType]: Number(text)
+                    });
+                    selectObject(nDV);
+                }
             }}
             inputStyle={[
                 stylesheet.input,

+ 5 - 2
src/components/timeSelector/components/timeInput/type.ts

@@ -26,8 +26,11 @@ interface ITimeInputProps {
     rangeValidation?: (props: {
         dateRangeValue: DateTimePickerDateRange;
         rangeType: TimeInputRangeType;
-    }) => boolean;
-    validation?: (text: string) => boolean;
+    }, setText: (text: string) => void) => boolean;
+    validation?: (
+        text: string,
+        setText: (text: string) => void
+    ) => boolean;
     selectObject: (date?: Date) => void;
     dateRange?: DateTimePickerDateRange;
     isWorkWith24HoursFormat: boolean;

+ 32 - 4
src/components/timeSelector/index.tsx

@@ -18,7 +18,8 @@ import stylesheet, {
 import TimeInput from "./components/timeInput";
 import {
     NCoreUIKitLocalize,
-    NCoreUIKitTheme
+    NCoreUIKitTheme,
+    NCoreUIKitToast
 } from "../../core/hooks";
 import type {
     DateTimePickerDateRange
@@ -128,12 +129,39 @@ const TimeSelector = ({
         dateRangeValue: DateTimePickerDateRange;
         rangeType: TimeInputRangeType;
     }) => {
-        if(dateRange?.start && (rangeType === "end" || dateRange.end)) {
-            if(multipleSelectMinimumRequireMS && Math.abs(moment(rangeType === "end" ? dateRangeValue[rangeType] : dateRange.end).diff(dateRange.start, "milliseconds")) > multipleSelectMinimumRequireMS) {
+        const start = rangeType === "start" ? dateRangeValue[rangeType] : dateRange?.start;
+        const end = rangeType === "end" ? dateRangeValue[rangeType] : dateRange?.end;
+
+        if(start && end) {
+            if(multipleSelectMinimumRequireMS && Math.abs(moment(end).diff(start, "milliseconds")) < multipleSelectMinimumRequireMS) {
+                NCoreUIKitToast.open({
+                    title: localize("selected-start-and-end-times-cannot-be-less-than-x-times-apart", [
+                        moment.duration(multipleSelectMinimumRequireMS).humanize()
+                    ])
+                });
+                return false;
+            }
+
+            if(multipleSelectMaximumMS && Math.abs(moment(end).diff(start, "milliseconds")) > multipleSelectMaximumMS) {
+                NCoreUIKitToast.open({
+                    title: localize("selected-start-and-end-times-cannot-exceed-x-intervals", [
+                        moment.duration(multipleSelectMaximumMS).humanize()
+                    ])
+                });
+                return false;
+            }
+
+            if(moment(end).isBefore(start)) {
+                NCoreUIKitToast.open({
+                    title: localize("selected-end-time-cannot-before-from-start-time")
+                });
                 return false;
             }
 
-            if(multipleSelectMaximumMS && Math.abs(moment(rangeType === "end" ? dateRangeValue[rangeType] : dateRange.end).diff(dateRange.start, "milliseconds")) < multipleSelectMaximumMS) {
+            if(moment(start).isAfter(end)) {
+                NCoreUIKitToast.open({
+                    title: localize("selected-start-time-cannot-after-then-end-time")
+                });
                 return false;
             }
         }

+ 10 - 2
src/variants/locales/default.json

@@ -3,9 +3,13 @@
         "locale": "tr-TR",
         "isRTL": false,
         "translations": {
+            "selected-start-and-end-times-cannot-be-less-than-x-times-apart": "Seçilen başlangıç ve bitiş zamanı {{0}} aralığından az olamaz.",
+            "selected-start-and-end-times-cannot-exceed-x-intervals": "Seçilen başlangıç ve bitiş zamanı {{0}} aralığından çok olamaz.",
             "minimum-selection-number-of-days-required-not-provided": "Minimum seçilmesi gereken gün sayısını karşılamıyor.",
-            "selected-end-date-cannot-before-from-start-date": "Seçilen başlangıç tarihi, bitiş tarihinden sonra olamaz.",
-            "selected-start-date-cannot-after-then-end-date": "Seçilen bitiş tarihi, başlangıç tarihinden önce olamaz.",
+            "selected-start-time-cannot-after-then-end-time": "Seçilen başlangıç zamanı, başlangıç zamanından sonra olamaz.",
+            "selected-start-date-cannot-after-then-end-date": "Seçilen başlangıç tarihi, başlangıç tarihinden sonra olamaz.",
+            "selected-end-time-cannot-before-from-start-time": "Seçilen bitiş zamanı, başlangıç zamanından önce olamaz.",
+            "selected-end-date-cannot-before-from-start-date": "Seçilen bitiş tarihi, başlangıç tarihinden önce olamaz.",
             "maximum-selection-number-of-days-limit-exceeds": "Maksimum seçilebilen gün sınırını aşıyor.",
             "maximum-selection-limit-has-been-reached": "Maksimum seçim limitine ulaşıldı.",
             "minimum-a-item-selection-required": "Minimum 1 öğe seçimi gereklidir.",
@@ -99,8 +103,12 @@
         "isRTL": false,
         "translations": {
             "minimum-selection-number-of-days-required-not-provided": "It does not meet the minimum number of days required for selection.",
+            "selected-start-and-end-times-cannot-be-less-than-x-times-apart": "Selected start and end times cannot be less than {{0}}.",
+            "selected-start-and-end-times-cannot-exceed-x-intervals": "selected start and end times cannot exceed {{0}} intervals.",
             "maximum-selection-number-of-days-limit-exceeds": "It exceeds the maximum number of days that can be selected.",
+            "selected-end-time-cannot-before-from-start-time": "Selected end time cannot before from start time.",
             "selected-end-date-cannot-before-from-start-date": "Selected end date cannot before from start date.",
+            "selected-start-time-cannot-after-then-end-time": "Selected start time cannot after then end time.",
             "selected-start-date-cannot-after-then-end-date": "Selected start date cannot after then end date.",
             "maximum-selection-limit-has-been-reached": "Maximum selection limit has been reached.",
             "minimum-a-item-selection-required": "Minimum 1 item selection required.",