@eohjsc/react-native-smart-city 0.2.86 → 0.2.87

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/assets/images/brightnessBlack.svg +12 -0
  2. package/index.js +4 -0
  3. package/package.json +1 -1
  4. package/src/Images/SmartIr/AC.svg +14 -0
  5. package/src/Images/SmartIr/DIY.svg +3 -0
  6. package/src/Images/SmartIr/Fan.svg +10 -0
  7. package/src/Images/SmartIr/Fridge.svg +5 -0
  8. package/src/Images/SmartIr/TV.svg +10 -0
  9. package/src/Images/SmartIr/WM.svg +11 -0
  10. package/src/Images/SmartIr/index.js +7 -0
  11. package/src/commons/ActionGroup/OnOffSmartLock/AutoLock/AutoLockStyles.js +40 -0
  12. package/src/commons/ActionGroup/OnOffSmartLock/AutoLock/ButtonWrapper.js +65 -0
  13. package/src/commons/ActionGroup/OnOffSmartLock/AutoLock/ButtonWrapperStyles.js +43 -0
  14. package/src/commons/ActionGroup/OnOffSmartLock/AutoLock/__test__/index.test.js +48 -0
  15. package/src/commons/ActionGroup/OnOffSmartLock/AutoLock/index.js +57 -0
  16. package/src/commons/ActionGroup/{OnOffSmartLock.js → OnOffSmartLock/OnOffSmartLock.js} +5 -5
  17. package/src/commons/ActionGroup/{OnOffSmartLockStyle.js → OnOffSmartLock/OnOffSmartLockStyle.js} +1 -1
  18. package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/ItemPasscode.js +48 -0
  19. package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/ItemPasscodeStyles.js +42 -0
  20. package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/PasscodeListStyles.js +49 -0
  21. package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/index.js +66 -0
  22. package/src/commons/ActionGroup/OnOffSmartLock/SetupGeneratePasscode/ButtonWrapper.js +96 -0
  23. package/src/commons/ActionGroup/OnOffSmartLock/SetupGeneratePasscode/SetupGeneratePasscodeStyles.js +98 -0
  24. package/src/commons/ActionGroup/OnOffSmartLock/SetupGeneratePasscode/__test__/index.test.js +62 -0
  25. package/src/commons/ActionGroup/OnOffSmartLock/SetupGeneratePasscode/index.js +249 -0
  26. package/src/commons/ActionGroup/OnOffTemplate/index.js +4 -2
  27. package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +2 -1
  28. package/src/commons/ActionGroup/SmartTiviActionTemplate/SmartTiviActionTemplate.js +188 -186
  29. package/src/commons/ActionGroup/StatesGridActionTemplate.js +2 -1
  30. package/src/commons/ActionGroup/index.js +1 -1
  31. package/src/commons/Device/DisconnectedView.js +7 -1
  32. package/src/commons/Device/LinearChart.js +3 -40
  33. package/src/commons/Device/__test__/DisconnectedView.test.js +13 -2
  34. package/src/commons/RowItem/index.js +12 -7
  35. package/src/commons/WheelDateTimePicker/index.js +18 -4
  36. package/src/configs/API.js +1 -1
  37. package/src/configs/Colors.js +1 -0
  38. package/src/configs/Constants.js +11 -0
  39. package/src/context/mockStore.ts +1 -0
  40. package/src/iot/RemoteControl/Bluetooth.js +3 -3
  41. package/src/navigations/SmartIrStack.js +31 -0
  42. package/src/navigations/SmartLockStack.js +51 -0
  43. package/src/navigations/UnitStack.js +12 -3
  44. package/src/screens/AddCommon/__test__/SelectSubUnit.test.js +1 -1
  45. package/src/screens/AddNewGateway/PlugAndPlay/ConnectWifiWarning.js +77 -55
  46. package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +141 -27
  47. package/src/screens/AddNewGateway/PlugAndPlay/__test__/ConnectWifiWarning.test.js +58 -0
  48. package/src/screens/AddNewGateway/PlugAndPlay/__test__/GatewayWifiList.test.js +26 -2
  49. package/src/screens/Device/components/SensorConnectStatusViewHeader.js +13 -2
  50. package/src/screens/Device/detail.js +49 -10
  51. package/src/screens/Device/hooks/useDisconnectedDevice.js +21 -5
  52. package/src/screens/GuestInfo/components/AccessScheduleItem.js +9 -2
  53. package/src/screens/GuestInfo/components/RecurringDetail.js +3 -2
  54. package/src/screens/GuestInfo/components/TemporaryDetail.js +3 -2
  55. package/src/screens/GuestInfo/styles/AccessScheduleItemStyles.js +3 -0
  56. package/src/screens/Notification/__test__/NotificationItem.test.js +1 -0
  57. package/src/screens/Notification/components/NotificationItem.js +16 -0
  58. package/src/screens/SmartIr/__test__/GroupButtonByType.test.js +54 -0
  59. package/src/screens/SmartIr/__test__/SelectBrand.test.js +74 -0
  60. package/src/screens/SmartIr/__test__/SelectDeviceType.test.js +64 -0
  61. package/src/screens/SmartIr/__test__/SmartIr.test.js +1 -0
  62. package/src/screens/SmartIr/components/GroupButtonByType/GroupButtonByType.js +86 -0
  63. package/src/screens/SmartIr/components/GroupButtonByType/GroupButtonByTypeStyles.js +76 -0
  64. package/src/screens/SmartIr/components/SelectBrand.js +61 -0
  65. package/src/screens/SmartIr/components/SelectBrandStyles.js +14 -0
  66. package/src/screens/SmartIr/components/SelectDeviceType.js +96 -0
  67. package/src/screens/SmartIr/components/SelectDeviceTypeStyles.js +30 -0
  68. package/src/screens/SmartIr/index.js +8 -3
  69. package/src/screens/Unit/Detail.js +7 -3
  70. package/src/screens/Unit/components/MyUnitDevice/index.js +2 -4
  71. package/src/screens/Unit/components/__test__/MyUnitDevice.test.js +38 -9
  72. package/src/utils/I18n/translations/en.json +24 -1
  73. package/src/utils/I18n/translations/vi.json +24 -1
  74. package/src/utils/Route/index.js +9 -1
@@ -0,0 +1,66 @@
1
+ import React, { memo, useCallback, useMemo } from 'react';
2
+ import { SafeAreaView, TextInput, View, TouchableOpacity } from 'react-native';
3
+ import { IconOutline } from '@ant-design/icons-react-native';
4
+ import { useNavigation } from '@react-navigation/native';
5
+
6
+ import Text from '../../../Text';
7
+ import { HeaderCustom } from '../../../Header';
8
+ import t from '../../../../hooks/Common/useTranslations';
9
+ import { Colors } from '../../../../configs';
10
+ import Routes from '../../../../utils/Route';
11
+ import styles from './PasscodeListStyles';
12
+
13
+ const PasscodeList = memo(() => {
14
+ const navigation = useNavigation();
15
+ const dataPasscodeList = useMemo(
16
+ () => [
17
+ { code: 123361, name: 'Do Loi' },
18
+ { code: 128232, name: 'Phuong Nam' },
19
+ { code: 123651, name: 'Jhonny Tam' },
20
+ ],
21
+ []
22
+ );
23
+
24
+ const handleClickButton = useCallback(
25
+ (item) => () => {
26
+ navigation.navigate(Routes.SmartLockStack, {
27
+ screen: Routes.ItemPasscode,
28
+ params: {
29
+ item,
30
+ },
31
+ });
32
+ },
33
+ [navigation]
34
+ );
35
+ return (
36
+ <SafeAreaView style={styles.container}>
37
+ <HeaderCustom title={t('passcode_list')} />
38
+ <View style={styles.wrap}>
39
+ <View style={styles.searchBox}>
40
+ <View>
41
+ <IconOutline name="search" size={24} style={styles.search} />
42
+ </View>
43
+ <TextInput
44
+ placeholder={t('search')}
45
+ placeholderTextColor={Colors.Gray8}
46
+ style={styles.textSearchInput}
47
+ />
48
+ </View>
49
+ {dataPasscodeList.map((item) => (
50
+ <TouchableOpacity
51
+ onPress={handleClickButton(item)}
52
+ style={styles.buttonWrapper}
53
+ >
54
+ <View>
55
+ <Text style={styles.textCode}>{item.code}</Text>
56
+ <Text style={styles.textName}>{item.name}</Text>
57
+ </View>
58
+ <IconOutline name="right" size={20} color={Colors.Gray8} />
59
+ </TouchableOpacity>
60
+ ))}
61
+ </View>
62
+ </SafeAreaView>
63
+ );
64
+ });
65
+
66
+ export default PasscodeList;
@@ -0,0 +1,96 @@
1
+ import React, { memo } from 'react';
2
+ import { IconOutline } from '@ant-design/icons-react-native';
3
+ import { Text, TouchableOpacity, View } from 'react-native';
4
+
5
+ import { RadioCircle } from '../../..';
6
+ import { Colors } from '../../../../configs';
7
+ import styles from './SetupGeneratePasscodeStyles';
8
+
9
+ const ButtonWrapper = memo(
10
+ ({
11
+ testID,
12
+ textHeadline,
13
+ textMinutes,
14
+ value,
15
+ isButtonChooseUser,
16
+ isButtonSetTime,
17
+ valueTime,
18
+ isButtonDuration,
19
+ onPressSetTime,
20
+ onPressSetMinute,
21
+ valueMinute,
22
+ isSelectCircle,
23
+ onPressSelectCircle,
24
+ }) => {
25
+ const textMinutesCapitalized =
26
+ textMinutes?.charAt(0).toUpperCase() + textMinutes?.slice(1);
27
+ const boxNotSelect = { ...styles.boxSetTime, ...styles.boxSetTimeDuration };
28
+ return (
29
+ <View
30
+ testID={testID}
31
+ style={
32
+ !isButtonDuration
33
+ ? styles.buttonWrapper
34
+ : { ...styles.buttonWrapper, ...styles.rowWrapperSchedule }
35
+ }
36
+ >
37
+ {!isButtonDuration ? (
38
+ <Text style={styles.textHeadLine}>{textHeadline}</Text>
39
+ ) : (
40
+ <TouchableOpacity
41
+ onPress={onPressSelectCircle}
42
+ style={styles.wrapDuration}
43
+ >
44
+ <View style={styles.circleDuration}>
45
+ <RadioCircle active={isSelectCircle} />
46
+ </View>
47
+ <Text style={styles.textDuration}>{textHeadline}</Text>
48
+ </TouchableOpacity>
49
+ )}
50
+ {isButtonChooseUser && (
51
+ <TouchableOpacity style={styles.buttonValue}>
52
+ <Text style={styles.value}>{value}</Text>
53
+ <IconOutline name="right" size={20} color={Colors.Gray8} />
54
+ </TouchableOpacity>
55
+ )}
56
+ {isButtonSetTime && (
57
+ <TouchableOpacity onPress={onPressSetTime} style={styles.boxSetTime}>
58
+ <Text style={styles.textBoxSetTime}>{valueTime}</Text>
59
+ </TouchableOpacity>
60
+ )}
61
+ {isButtonDuration && (
62
+ <View style={styles.wrapDuration}>
63
+ <TouchableOpacity
64
+ disabled={!isSelectCircle}
65
+ onPress={onPressSetMinute}
66
+ style={isSelectCircle ? styles.boxSetTime : boxNotSelect}
67
+ >
68
+ <Text
69
+ style={
70
+ isSelectCircle
71
+ ? styles.textDurationNotSelect
72
+ : styles.textTimeDuration
73
+ }
74
+ >
75
+ {valueMinute}
76
+ </Text>
77
+ </TouchableOpacity>
78
+ <View style={isSelectCircle ? styles.boxSetTime : boxNotSelect}>
79
+ <Text
80
+ style={
81
+ isSelectCircle
82
+ ? styles.textDurationNotSelect
83
+ : styles.textTimeDuration
84
+ }
85
+ >
86
+ {textMinutesCapitalized}
87
+ </Text>
88
+ </View>
89
+ </View>
90
+ )}
91
+ </View>
92
+ );
93
+ }
94
+ );
95
+
96
+ export default ButtonWrapper;
@@ -0,0 +1,98 @@
1
+ import { Colors } from '../../../../configs';
2
+ import { StyleSheet } from 'react-native';
3
+ import { getBottomSpace } from 'react-native-iphone-x-helper';
4
+
5
+ export default StyleSheet.create({
6
+ container: {
7
+ flex: 1,
8
+ backgroundColor: Colors.White,
9
+ },
10
+ scrollview: {
11
+ flex: 1,
12
+ marginHorizontal: 16,
13
+ },
14
+ buttonWrapper: {
15
+ flexDirection: 'row',
16
+ justifyContent: 'space-between',
17
+ alignItems: 'center',
18
+ borderBottomWidth: 0.5,
19
+ borderBottomColor: Colors.Gray3,
20
+ paddingTop: 24,
21
+ paddingBottom: 24,
22
+ },
23
+ rowWrapperSchedule: {
24
+ borderBottomWidth: 0,
25
+ },
26
+ buttonValue: {
27
+ flex: 1,
28
+ flexDirection: 'row',
29
+ justifyContent: 'flex-end',
30
+ alignItems: 'center',
31
+ },
32
+ value: {
33
+ marginRight: 20,
34
+ fontSize: 14,
35
+ color: Colors.Gray8,
36
+ },
37
+ textHeadLine: {
38
+ fontSize: 16,
39
+ color: Colors.Gray9,
40
+ fontWeight: 'bold',
41
+ },
42
+ textDuration: {
43
+ fontSize: 16,
44
+ color: Colors.Gray9,
45
+ marginLeft: 7,
46
+ },
47
+ boxSetTime: {
48
+ flexDirection: 'row',
49
+ justifyContent: 'center',
50
+ alignItems: 'center',
51
+ height: 36,
52
+ width: 78,
53
+ borderRadius: 5,
54
+ borderWidth: 1,
55
+ borderColor: Colors.Green7,
56
+ marginLeft: 3,
57
+ },
58
+ boxSetTimeDuration: {
59
+ borderColor: Colors.Gray6,
60
+ },
61
+ textBoxSetTime: {
62
+ fontSize: 18,
63
+ color: Colors.Green7,
64
+ fontWeight: '500',
65
+ },
66
+ textTimeDuration: {
67
+ fontSize: 18,
68
+ color: Colors.Gray6,
69
+ fontWeight: '500',
70
+ },
71
+ textDurationNotSelect: {
72
+ fontSize: 18,
73
+ color: Colors.Primary,
74
+ fontWeight: '500',
75
+ },
76
+ circleDuration: {
77
+ marginTop: 6,
78
+ },
79
+ wrapDuration: {
80
+ flexDirection: 'row',
81
+ justifyContent: 'center',
82
+ alignSelf: 'center',
83
+ },
84
+ wrap: {
85
+ paddingBottom: 100,
86
+ },
87
+ viewBottomFixed: {
88
+ position: 'absolute',
89
+ bottom: 0,
90
+ left: 0,
91
+ right: 0,
92
+ paddingBottom: getBottomSpace() > 0 ? getBottomSpace() : 32,
93
+ paddingTop: 29,
94
+ backgroundColor: Colors.White,
95
+ borderColor: Colors.ShadownTransparent,
96
+ borderTopWidth: 1,
97
+ },
98
+ });
@@ -0,0 +1,62 @@
1
+ import React from 'react';
2
+ import { act, create } from 'react-test-renderer';
3
+
4
+ import SetupGeneratePasscode from '../index';
5
+ import { mockSCStore } from '../../../../../context/mockStore';
6
+ import { TESTID } from '../../../../../configs/Constants';
7
+ import { SCProvider } from '../../../../../context';
8
+
9
+ const mockNavigate = jest.fn();
10
+ jest.mock('@react-navigation/native', () => {
11
+ return {
12
+ ...jest.requireActual('@react-navigation/native'),
13
+ useRoute: jest.fn(),
14
+ useNavigation: () => ({
15
+ navigate: mockNavigate,
16
+ }),
17
+ };
18
+ });
19
+
20
+ const wrapComponent = () => (
21
+ <SCProvider initState={mockSCStore({})}>
22
+ <SetupGeneratePasscode />
23
+ </SCProvider>
24
+ );
25
+
26
+ describe('Test SetupGeneratePasscode', () => {
27
+ let tree;
28
+
29
+ beforeEach(() => {
30
+ mockNavigate.mockClear();
31
+ });
32
+
33
+ const getElement = (instance) => {
34
+ const changeName = instance.findAll(
35
+ (item) => item.props.testID === TESTID.GENERATE_PASSCODE_CHOOSE_USER
36
+ );
37
+ const changeTime = instance.findAll(
38
+ (item) => item.props.testID === TESTID.GENERATE_PASSCODE_SET_TIME
39
+ );
40
+ const changeDuration = instance.findAll(
41
+ (item) => item.props.testID === TESTID.GENERATE_PASSCODE_SET_DURATION
42
+ );
43
+ return {
44
+ changeName,
45
+ changeTime,
46
+ changeDuration,
47
+ };
48
+ };
49
+
50
+ test('render SetupGeneratePasscode', async () => {
51
+ await act(async () => {
52
+ tree = create(wrapComponent());
53
+ });
54
+
55
+ const instance = tree.root;
56
+ const { changeName, changeTime, changeDuration } = getElement(instance);
57
+
58
+ expect(changeName[0]).toBeDefined();
59
+ expect(changeTime[0]).toBeDefined();
60
+ expect(changeDuration[0]).toBeDefined();
61
+ });
62
+ });
@@ -0,0 +1,249 @@
1
+ import React, { memo, useCallback, useMemo, useState } from 'react';
2
+ import { SafeAreaView, View, ScrollView } from 'react-native';
3
+ import { useTranslations } from '../../../../hooks/Common/useTranslations';
4
+
5
+ import Text from '../../../Text';
6
+ import { HeaderCustom } from '../../../Header';
7
+ import { useBoolean } from '../../../../hooks/Common';
8
+ import WheelDateTimePicker from '../../../WheelDateTimePicker';
9
+ import RecurringDetail from '../../../../screens/GuestInfo/components/RecurringDetail';
10
+ import TemporaryDetail from '../../../../screens/GuestInfo/components/TemporaryDetail';
11
+ import AccessScheduleItem from '../../../../screens/GuestInfo/components/AccessScheduleItem';
12
+ import BottomButtonView from '../../../BottomButtonView';
13
+ import { ACCESS_SCHEDULE } from '../../../../screens/GuestInfo/constant';
14
+ import { TESTID } from '../../../../configs/Constants';
15
+ import ButtonWrapper from './ButtonWrapper';
16
+ import moment from 'moment';
17
+ import styles from './SetupGeneratePasscodeStyles';
18
+
19
+ const SetupGeneratePasscode = memo(() => {
20
+ const t = useTranslations();
21
+ const [accessSchedule, setAccessSchedule] = useState('always');
22
+ const [isSelectCircle, setIsSelectCircle] = useState(false);
23
+ const [showTimePicker, setShowTimePicker, setHideTimePicker] = useBoolean();
24
+ const [
25
+ showTimePickerMinute,
26
+ setShowTimePickerMinute,
27
+ setHideTimePickerMinute,
28
+ ] = useBoolean();
29
+ const [lockShowing, releaseLockShowing, acquireLockShowing] =
30
+ useBoolean(true);
31
+
32
+ const [stateDateTimePicker, setStateDateTimePicker] = useState({
33
+ isVisible: false,
34
+ mode: 'time',
35
+ defaultValue: moment().valueOf(),
36
+ setter: null,
37
+ });
38
+ const [recurringTimeStart, setRecurringTimeStart] = useState(
39
+ '2022-03-08T17:00:00.551Z'
40
+ );
41
+ const [recurringTimeEnd, setRecurringTimeEnd] = useState(
42
+ '2022-03-08T17:00:00.902Z'
43
+ );
44
+ const [recurringTimeRepeat, setRecurringTimeRepeat] = useState(
45
+ '2022-03-08T17:00:00.902Z'
46
+ );
47
+ const [temporaryTimeStart, setTemporaryTimeStart] = useState(
48
+ '2022-03-08T17:00:00.902Z'
49
+ );
50
+ const [temporaryTimeEnd, setTemporaryTimeEnd] = useState(
51
+ '2022-03-08T17:00:00.902Z'
52
+ );
53
+
54
+ const [time, setTime] = useState(
55
+ '22-10-2019'.time_repeat
56
+ ? moment(22 - 10 - 2019, 'HH:mm:ss')
57
+ : moment().second(0)
58
+ );
59
+
60
+ const [minute, setMinute] = useState(0);
61
+
62
+ const onTimePicked = useCallback(
63
+ (timeData) => {
64
+ setTime(moment(timeData));
65
+ },
66
+ [setTime]
67
+ );
68
+
69
+ const onMinutePicked = useCallback((timeData) => {
70
+ const date = new Date(moment(timeData));
71
+ const minutes = date.getMinutes();
72
+ setMinute(minutes);
73
+ }, []);
74
+
75
+ const onShowSetDateTime = useCallback(
76
+ (currentValue, setter, mode) => {
77
+ releaseLockShowing();
78
+ setStateDateTimePicker((state) => ({
79
+ ...state,
80
+ isVisible: true,
81
+ mode: mode,
82
+ defaultValue: currentValue,
83
+ setter: setter,
84
+ }));
85
+ },
86
+ [releaseLockShowing]
87
+ );
88
+
89
+ const onHideSetDateTime = useCallback(() => {
90
+ acquireLockShowing();
91
+ setStateDateTimePicker((state) => ({
92
+ ...state,
93
+ isVisible: false,
94
+ }));
95
+ }, [setStateDateTimePicker, acquireLockShowing]);
96
+
97
+ const onDateTimePicked = useCallback(
98
+ (timeData) => {
99
+ const setter = stateDateTimePicker.setter;
100
+ setter && setter(moment(timeData));
101
+ },
102
+ [stateDateTimePicker]
103
+ );
104
+
105
+ const listAccessSchedule = useMemo(
106
+ () => [
107
+ {
108
+ text: t(`${ACCESS_SCHEDULE.ALWAYS}`),
109
+ value: ACCESS_SCHEDULE.ALWAYS,
110
+ detail: () => <></>,
111
+ },
112
+ {
113
+ text: t(`${ACCESS_SCHEDULE.RECURRING}`),
114
+ value: ACCESS_SCHEDULE.RECURRING,
115
+ detail: () => (
116
+ <RecurringDetail
117
+ onShowSetDateTime={onShowSetDateTime}
118
+ recurringTimeStart={recurringTimeStart}
119
+ recurringTimeEnd={recurringTimeEnd}
120
+ recurringTimeRepeat={recurringTimeRepeat}
121
+ setRecurringTimeStart={setRecurringTimeStart}
122
+ setRecurringTimeEnd={setRecurringTimeEnd}
123
+ setRecurringTimeRepeat={setRecurringTimeRepeat}
124
+ />
125
+ ),
126
+ },
127
+ {
128
+ text: t(`${ACCESS_SCHEDULE.TEMPORARY}`),
129
+ value: ACCESS_SCHEDULE.TEMPORARY,
130
+ detail: () => (
131
+ <TemporaryDetail
132
+ onShowSetDateTime={onShowSetDateTime}
133
+ temporaryTimeStart={temporaryTimeStart}
134
+ temporaryTimeEnd={temporaryTimeEnd}
135
+ setTemporaryTimeStart={setTemporaryTimeStart}
136
+ setTemporaryTimeEnd={setTemporaryTimeEnd}
137
+ />
138
+ ),
139
+ },
140
+ ],
141
+ [
142
+ onShowSetDateTime,
143
+ recurringTimeEnd,
144
+ recurringTimeRepeat,
145
+ recurringTimeStart,
146
+ t,
147
+ temporaryTimeEnd,
148
+ temporaryTimeStart,
149
+ ]
150
+ );
151
+
152
+ const handleSetTime = useCallback(() => {
153
+ setShowTimePicker();
154
+ setStateDateTimePicker((state) => ({
155
+ ...state,
156
+ mode: 'time',
157
+ }));
158
+ }, [setShowTimePicker]);
159
+
160
+ const handleSetMinute = useCallback(() => {
161
+ setShowTimePickerMinute();
162
+ setStateDateTimePicker((state) => ({
163
+ ...state,
164
+ mode: 'minute',
165
+ }));
166
+ }, [setShowTimePickerMinute]);
167
+
168
+ const handleSelectCircle = useCallback(() => {
169
+ setIsSelectCircle(!isSelectCircle);
170
+ }, [isSelectCircle]);
171
+
172
+ return (
173
+ <SafeAreaView style={styles.container}>
174
+ <HeaderCustom
175
+ title={t('setup_generate_passcode')}
176
+ titleStyle={styles.title}
177
+ isShowSeparator
178
+ />
179
+ <ScrollView
180
+ showsVerticalScrollIndicator={false}
181
+ showsHorizontalScrollIndicator={false}
182
+ style={styles.scrollview}
183
+ >
184
+ <View style={styles.wrap}>
185
+ <ButtonWrapper
186
+ textHeadline={t('choose_user')}
187
+ value={'Name'}
188
+ isButtonChooseUser
189
+ testID={TESTID.GENERATE_PASSCODE_CHOOSE_USER}
190
+ />
191
+ <ButtonWrapper
192
+ textHeadline={t('set_time')}
193
+ valueTime={time.format('HH:mm')}
194
+ onPressSetTime={handleSetTime}
195
+ isButtonSetTime
196
+ testID={TESTID.GENERATE_PASSCODE_SET_TIME}
197
+ />
198
+ <ButtonWrapper
199
+ textHeadline={t('duration')}
200
+ textMinutes={t('minutes')}
201
+ valueMinute={minute}
202
+ onPressSetMinute={handleSetMinute}
203
+ onPressSelectCircle={handleSelectCircle}
204
+ isButtonDuration
205
+ isSelectCircle={isSelectCircle}
206
+ testID={TESTID.GENERATE_PASSCODE_SET_DURATION}
207
+ />
208
+ <View>
209
+ <Text style={styles.textHeadLine}>{t('access_schedule')}</Text>
210
+ {listAccessSchedule.map((item, index) => (
211
+ <AccessScheduleItem
212
+ key={index}
213
+ item={item}
214
+ isSelected={item.value === accessSchedule}
215
+ onSelect={setAccessSchedule}
216
+ isSetupGeneratePasscode
217
+ />
218
+ ))}
219
+ </View>
220
+ </View>
221
+ </ScrollView>
222
+ <WheelDateTimePicker
223
+ mode={stateDateTimePicker.mode}
224
+ isVisible={showTimePicker}
225
+ defaultValue={time.valueOf()}
226
+ onCancel={setHideTimePicker}
227
+ onPicked={onTimePicked}
228
+ />
229
+ <WheelDateTimePicker
230
+ mode={stateDateTimePicker.mode}
231
+ isVisible={showTimePickerMinute}
232
+ defaultValue={minute.valueOf()}
233
+ onCancel={setHideTimePickerMinute}
234
+ onPicked={onMinutePicked}
235
+ />
236
+ <WheelDateTimePicker
237
+ mode={stateDateTimePicker.mode}
238
+ isVisible={stateDateTimePicker.isVisible && lockShowing}
239
+ defaultValue={stateDateTimePicker.defaultValue}
240
+ onPicked={onDateTimePicked}
241
+ onCancel={onHideSetDateTime}
242
+ onHide={releaseLockShowing}
243
+ />
244
+ <BottomButtonView style={styles.viewBottomFixed} mainTitle={t('done')} />
245
+ </SafeAreaView>
246
+ );
247
+ });
248
+
249
+ export default SetupGeneratePasscode;
@@ -34,14 +34,16 @@ const OnOffTemplate = memo(({ actionGroup, doAction, sensor }) => {
34
34
  }
35
35
  if (action_on_data && action_off_data) {
36
36
  if (isOn) {
37
- const actionName = `${
37
+ let actionName = `${
38
38
  sensor?.name
39
39
  } ${actionGroup?.title?.toLowerCase()} off`;
40
+ actionName = actionName.replace(/\s+/g, ' ').trim();
40
41
  doAction(action_off_data, null, actionName);
41
42
  } else {
42
- const actionName = `${
43
+ let actionName = `${
43
44
  sensor?.name
44
45
  } ${actionGroup?.title?.toLowerCase()} on`;
46
+ actionName = actionName.replace(/\s+/g, ' ').trim();
45
47
  doAction(action_on_data, null, actionName);
46
48
  }
47
49
  }
@@ -56,7 +56,8 @@ const OptionsDropdownActionTemplate = ({ actionGroup, doAction, sensor }) => {
56
56
  const onDone = useCallback(() => {
57
57
  const newOption = options[selectedIndex];
58
58
  const value = getOptionValue(newOption);
59
- const actionName = `${sensor?.name} ${title?.toLowerCase()} ${value}`;
59
+ let actionName = `${sensor?.name} ${title?.toLowerCase()} ${value}`;
60
+ actionName = actionName.replace(/\s+/g, ' ').trim();
60
61
  doAction(action_data, value, actionName);
61
62
  if (sensor?.is_managed_by_backend) {
62
63
  configuration.config && watchMultiConfigs([configuration.config]);