@eohjsc/react-native-smart-city 0.3.92 → 0.3.94

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 (87) hide show
  1. package/package.json +5 -1
  2. package/src/commons/ActionGroup/SliderRangeTemplate.js +2 -2
  3. package/src/commons/AlertAction/index.js +5 -0
  4. package/src/commons/BottomButtonView/index.js +22 -4
  5. package/src/commons/Button/index.js +5 -0
  6. package/src/commons/Device/ConnectedViewHeader.js +0 -1
  7. package/src/commons/Device/Emergency/EmergencyDetail.js +4 -2
  8. package/src/commons/Device/Emergency/__test__/EmergencyDetail.test.js +4 -2
  9. package/src/commons/Device/ProgressBar/index.js +3 -1
  10. package/src/commons/Device/ProgressBar/styles.js +1 -4
  11. package/src/commons/Device/WindSpeed/Anemometer/index.js +1 -1
  12. package/src/commons/Header/HeaderCustom.js +8 -18
  13. package/src/commons/SubUnit/OneTap/ItemOneTap.js +84 -129
  14. package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +74 -39
  15. package/src/commons/SubUnit/OneTap/index.js +24 -4
  16. package/src/commons/ViewButtonBottom/index.js +32 -4
  17. package/src/configs/API.js +4 -0
  18. package/src/configs/AccessibilityLabel.js +1 -0
  19. package/src/configs/BLE.js +1 -0
  20. package/src/context/actionType.ts +2 -1
  21. package/src/context/mockStore.ts +1 -0
  22. package/src/context/reducer.ts +12 -1
  23. package/src/hooks/Explore/useKeyboardAnimated.js +10 -4
  24. package/src/hooks/IoT/useBluetoothConnection.js +14 -26
  25. package/src/hooks/useMqtt.js +95 -0
  26. package/src/iot/Monitor.js +2 -1
  27. package/src/iot/RemoteControl/Bluetooth.js +56 -19
  28. package/src/iot/RemoteControl/__test__/Bluetooth.test.js +140 -0
  29. package/src/iot/mqtt.js +233 -0
  30. package/src/navigations/UnitStack.js +11 -3
  31. package/src/screens/AddLocationMaps/index.js +18 -16
  32. package/src/screens/AddLocationMaps/indexStyle.js +3 -0
  33. package/src/screens/AddNewGateway/ConnectingDevice.js +7 -0
  34. package/src/screens/AddNewGateway/RenameNewDevices.js +2 -2
  35. package/src/screens/AddNewGateway/SelectDeviceType.js +67 -9
  36. package/src/screens/AddNewGateway/__test__/ConnectingZigbeeDevice.test.js +35 -0
  37. package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +183 -29
  38. package/src/screens/Automate/AddNewAction/NewActionWrapper.js +3 -6
  39. package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +29 -29
  40. package/src/screens/Automate/AddNewAction/__test__/SetupSensor.test.js +45 -39
  41. package/src/screens/Automate/AddNewAutoSmart/AddAutomationTypeSmart.js +25 -0
  42. package/src/screens/{AddNewAutoSmart/index.js → Automate/AddNewAutoSmart/AddTypeSmart.js} +16 -51
  43. package/src/screens/Automate/AddNewAutoSmart/AddUnknownTypeSmart.js +29 -0
  44. package/src/screens/{AddNewAutoSmart → Automate/AddNewAutoSmart}/__test__/AddNewAutoSmart.test.js +11 -11
  45. package/src/screens/{AddNewAutoSmart → Automate/AddNewAutoSmart}/styles/AddNewAutoSmartStyles.js +1 -1
  46. package/src/screens/Automate/Components/InputNameStyles.js +1 -1
  47. package/src/screens/Automate/EditActionsList/__tests__/index.test.js +11 -25
  48. package/src/screens/Automate/EditActionsList/index.js +32 -33
  49. package/src/screens/Automate/MultiUnits.js +29 -19
  50. package/src/screens/Automate/ScriptDetail/__test__/index.test.js +78 -5
  51. package/src/screens/Automate/ScriptDetail/index.js +38 -10
  52. package/src/screens/Automate/Styles/MultiUnitsStyles.js +1 -1
  53. package/src/screens/Automate/__test__/MultiUnits.test.js +64 -7
  54. package/src/screens/Automate/__test__/index.test.js +45 -11
  55. package/src/screens/Automate/index.js +53 -38
  56. package/src/screens/Device/__test__/detail.test.js +1 -1
  57. package/src/screens/Device/__test__/mqttDetail.test.js +599 -0
  58. package/src/screens/Device/components/SensorDisplayItem.js +1 -7
  59. package/src/screens/Device/detail.js +64 -30
  60. package/src/screens/Device/hooks/__test__/useEvaluateValue.test.js +24 -1
  61. package/src/screens/Device/hooks/useDeviceWatchConfigControl.js +13 -3
  62. package/src/screens/SelectUnit/__test__/index.test.js +8 -13
  63. package/src/screens/Sharing/InfoMemberUnit.js +2 -2
  64. package/src/screens/Sharing/MemberList.js +28 -7
  65. package/src/screens/Sharing/__test__/InfoMemberUnit.test.js +32 -18
  66. package/src/screens/Sharing/__test__/MemberList.test.js +37 -4
  67. package/src/screens/SmartAccount/__test__/SmartAccount.test.js +8 -4
  68. package/src/screens/SmartAccount/index.js +8 -9
  69. package/src/screens/SmartAccount/style.js +8 -7
  70. package/src/screens/Unit/AddMenu.js +42 -19
  71. package/src/screens/Unit/Detail.js +4 -19
  72. package/src/screens/Unit/Summaries.js +6 -17
  73. package/src/screens/Unit/__test__/AddMenu.test.js +68 -15
  74. package/src/screens/Unit/__test__/Summaries.test.js +2 -2
  75. package/src/screens/Unit/components/AutomateScript/index.js +1 -1
  76. package/src/utils/FactoryGateway.js +525 -0
  77. package/src/utils/I18n/translations/en.js +1409 -0
  78. package/src/utils/I18n/translations/vi.js +1411 -0
  79. package/src/utils/I18n/translations.ts +2 -2
  80. package/src/utils/Permission/backend.js +7 -0
  81. package/src/utils/Route/index.js +2 -1
  82. package/src/utils/Utils.js +11 -0
  83. package/src/commons/Device/SensorConnectedStatus.js +0 -56
  84. package/src/commons/Device/__test__/SensorConnectedStatus.test.js +0 -29
  85. package/src/screens/Sharing/__test__/MemberList2.test.js +0 -74
  86. package/src/utils/I18n/translations/en.json +0 -1138
  87. package/src/utils/I18n/translations/vi.json +0 -1136
@@ -14,13 +14,19 @@ import AddZigbeeDeviceIcon from '../../../assets/images/AddNewDevice/add-zigbee-
14
14
  import styles from './SelectDeviceTypeStyles';
15
15
  import AccessibilityLabel from '../../configs/AccessibilityLabel';
16
16
  import { DEVICE_TYPE } from '../../configs/Constants';
17
+ import { useBackendPermission } from '../../utils/Permission/backend';
18
+ import { axiosGet } from '../../utils/Apis/axios';
19
+ import API from '../../configs/API';
20
+ import { ToastBottomHelper } from '../../utils/Utils';
17
21
 
18
22
  const SelectDeviceGrid = ({ options, onSelect }) => {
19
23
  const [selectIndexes, setSelectIndexes] = useState();
20
24
  const onSelectOption = useCallback(
21
25
  (value) => () => {
26
+ if (onSelect(value) === false) {
27
+ return;
28
+ }
22
29
  setSelectIndexes(value);
23
- onSelect(value);
24
30
  },
25
31
  [onSelect]
26
32
  );
@@ -51,17 +57,33 @@ const SelectDeviceGrid = ({ options, onSelect }) => {
51
57
  );
52
58
  };
53
59
 
60
+ const getPermissionCode = (deviceType) => {
61
+ switch (deviceType) {
62
+ case 'gateway_qr':
63
+ return 'plug_and_play_gateway';
64
+ case 'wifi_device_qr':
65
+ return 'plug_and_play_wifi';
66
+ case 'modbus_device_qr':
67
+ return 'plug_and_play_modbus';
68
+ case 'zigbee':
69
+ default:
70
+ return 'plug_and_play_zigbee';
71
+ }
72
+ };
73
+
54
74
  const SelectDeviceType = ({ route }) => {
55
75
  const t = useTranslations();
56
76
  const { unit, subUnit } = route?.params || {};
57
77
  const { navigate, goBack } = useNavigation();
78
+ const [unitCountSummary, setUnitCountSummary] = useState();
58
79
  const [addType, setAddType] = useState();
59
80
  const [selectedAddType, setSelectedAddType] = useState();
81
+ const permissions = useBackendPermission();
60
82
 
61
83
  const listDeviceType = useMemo(() => {
62
84
  const list = [
63
85
  {
64
- id: 1,
86
+ id: 'gateway_qr',
65
87
  image: <AddGatewayIcon width={60} height={60} />,
66
88
  route: Routes.ScanGatewayQR,
67
89
  data: {
@@ -71,7 +93,7 @@ const SelectDeviceType = ({ route }) => {
71
93
  subtitle: t('central_controller'),
72
94
  },
73
95
  {
74
- id: 2,
96
+ id: 'wifi_device_qr',
75
97
  image: <AddWifiDeviceIcon width={60} height={60} />,
76
98
  route: subUnit?.id
77
99
  ? Routes.ScanWifiDeviceQR
@@ -85,7 +107,7 @@ const SelectDeviceType = ({ route }) => {
85
107
  subtitle: t('device_connect_without_gateway'),
86
108
  },
87
109
  {
88
- id: 3,
110
+ id: 'modbus_device_qr',
89
111
  image: <AddModbusDeviceIcon width={60} height={60} />,
90
112
  route: subUnit?.id ? Routes.ScanModbusQR : Routes.SelectDeviceSubUnit,
91
113
  data: {
@@ -97,7 +119,7 @@ const SelectDeviceType = ({ route }) => {
97
119
  subtitle: t('device_connect_directly_to_the_gateway'),
98
120
  },
99
121
  {
100
- id: 4,
122
+ id: 'zigbee',
101
123
  image: <AddZigbeeDeviceIcon width={60} height={60} />,
102
124
  route: subUnit?.id
103
125
  ? Routes.ConnectRouterGuide
@@ -111,19 +133,43 @@ const SelectDeviceType = ({ route }) => {
111
133
  subtitle: t('device_connect_remotely_to_the_gateway'),
112
134
  },
113
135
  ];
114
- if (!!subUnit?.id) {
136
+ if (subUnit?.id) {
115
137
  list.shift();
116
138
  }
117
139
  return list;
118
140
  }, [unit, t, subUnit]);
119
141
 
120
142
  const onRight = useCallback(() => {
121
- if (selectedAddType?.route && selectedAddType?.data) {
122
- navigate(selectedAddType?.route, selectedAddType?.data);
143
+ if (!selectedAddType?.route) {
144
+ return;
123
145
  }
146
+
147
+ navigate(selectedAddType?.route, selectedAddType?.data);
124
148
  }, [navigate, selectedAddType?.data, selectedAddType?.route]);
125
149
 
126
150
  const handleOnSelect = (itemSelect) => {
151
+ const needPermission = getPermissionCode(itemSelect);
152
+ if (!permissions?.[needPermission]) {
153
+ ToastBottomHelper.error(t(`no_permission_${needPermission}`));
154
+ return false;
155
+ }
156
+
157
+ if (['gateway_qr', 'wifi_device_qr'].includes(itemSelect)) {
158
+ if (permissions?.max_chips_per_unit <= unitCountSummary?.total_chips) {
159
+ ToastBottomHelper.error(t('reach_max_chips_per_unit'));
160
+ return false;
161
+ }
162
+ }
163
+
164
+ if (['wifi_device_qr', 'modbus_device_qr', 'zigbee'].includes(itemSelect)) {
165
+ if (
166
+ permissions?.max_configs_per_unit <= unitCountSummary?.total_configs
167
+ ) {
168
+ ToastBottomHelper.error(t('reach_max_configs_per_unit'));
169
+ return false;
170
+ }
171
+ }
172
+
127
173
  setAddType(itemSelect);
128
174
  };
129
175
 
@@ -131,6 +177,18 @@ const SelectDeviceType = ({ route }) => {
131
177
  setSelectedAddType(listDeviceType.find((item) => item.id === addType));
132
178
  }, [addType, listDeviceType]);
133
179
 
180
+ useEffect(() => {
181
+ const fetchCountSummary = async () => {
182
+ const { success, data } = await axiosGet(API.DEV_MODE.GATEWAY.COUNT(), {
183
+ unit: unit?.id,
184
+ });
185
+ if (success) {
186
+ setUnitCountSummary(data);
187
+ }
188
+ };
189
+ fetchCountSummary();
190
+ }, [unit?.id]);
191
+
134
192
  return (
135
193
  <View style={styles.container}>
136
194
  <HeaderCustom title={t('choose_type_of_device')} isShowSeparator />
@@ -141,7 +199,7 @@ const SelectDeviceType = ({ route }) => {
141
199
  leftTitle={t('cancel')}
142
200
  onLeftClick={goBack}
143
201
  rightTitle={t('text_next')}
144
- rightDisabled={!addType}
202
+ rightDisabled={!unitCountSummary || !addType}
145
203
  onRightClick={onRight}
146
204
  />
147
205
  </View>
@@ -121,4 +121,39 @@ describe('Test connecting modbus device', () => {
121
121
  sensorId: 1,
122
122
  });
123
123
  });
124
+
125
+ it('receive sensor from channel after rejoin zigbee', async () => {
126
+ mock.onPost().reply(200, {});
127
+ await act(async () => {
128
+ tree = await create(wrapComponent(route));
129
+ });
130
+ const channels = getPusher().channels;
131
+ let channel;
132
+ for (const key in channels) {
133
+ if (key.indexOf('cache-') === 0) {
134
+ channel = channels[key];
135
+ }
136
+ }
137
+ await act(async () => {
138
+ await channel.trigger('progress', {
139
+ data: { sensor: { id: 1, name: 'sensor' }, type: 'rejoin' },
140
+ });
141
+ });
142
+ await act(async () => {
143
+ await channel.trigger('progress', { success: 1 });
144
+ });
145
+ expect(mockedNavigate).toHaveBeenCalledWith(Routes.RenameNewDevices, {
146
+ addDeviceType: undefined,
147
+ unit: {
148
+ id: 1,
149
+ },
150
+ subUnit: {
151
+ id: 2,
152
+ station: 'Station 2',
153
+ },
154
+ chipId: 3,
155
+ sensorId: 1,
156
+ isRejoin: true,
157
+ });
158
+ });
124
159
  });
@@ -8,36 +8,30 @@ import Routes from '../../../utils/Route';
8
8
  import { TouchableOpacity } from 'react-native';
9
9
  import AccessibilityLabel from '../../../configs/AccessibilityLabel';
10
10
  import { ViewButtonBottom } from '../../../commons';
11
-
12
- const wrapComponent = (route) => (
13
- <SCProvider initState={mockSCStore({})}>
11
+ import { useNavigation } from '@react-navigation/native';
12
+ import MockAdapter from 'axios-mock-adapter';
13
+ import api from '../../../utils/Apis/axios';
14
+ import API from '../../../configs/API';
15
+ import { ToastBottomHelper } from '../../../utils/Utils';
16
+ import { getTranslate } from '../../../utils/I18n';
17
+ const wrapComponent = (route, storeData = {}) => (
18
+ <SCProvider initState={mockSCStore(storeData)}>
14
19
  <SelectDeviceType route={route} />
15
20
  </SCProvider>
16
21
  );
17
22
 
18
- const mockedNavigate = jest.fn();
19
- const mockedGoBack = jest.fn();
20
-
21
- jest.mock('@react-navigation/native', () => {
22
- return {
23
- ...jest.requireActual('@react-navigation/native'),
24
- useNavigation: () => ({
25
- navigate: mockedNavigate,
26
- goBack: mockedGoBack,
27
- }),
28
- useIsFocused: () => true,
29
- };
30
- });
23
+ const mock = new MockAdapter(api.axiosInstance);
31
24
 
32
25
  describe('Test select device type', () => {
33
26
  let tree;
34
27
  let route;
35
28
 
36
- afterEach(() => {
37
- mockedNavigate.mockClear();
38
- });
29
+ const mockedNavigate = useNavigation().navigate;
30
+ const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
39
31
 
40
32
  beforeEach(() => {
33
+ spyToastError.mockClear();
34
+ mockedNavigate.mockClear();
41
35
  route = {
42
36
  params: {
43
37
  unitId: 1,
@@ -81,9 +75,9 @@ describe('Test select device type', () => {
81
75
  expect(deviceTypeItems).toHaveLength(3);
82
76
  });
83
77
 
84
- const selectDeviceType = async (index) => {
78
+ const selectDeviceType = async (index, storeData = {}) => {
85
79
  await act(async () => {
86
- tree = await create(wrapComponent(route));
80
+ tree = await create(wrapComponent(route, storeData));
87
81
  });
88
82
  const instance = tree.root;
89
83
  const deviceTypeItems = instance.findAll(
@@ -99,24 +93,184 @@ describe('Test select device type', () => {
99
93
  await act(async () => {
100
94
  submitButton.props.onRightClick();
101
95
  });
102
-
103
- expect(mockedNavigate).toBeCalled();
104
96
  };
105
97
 
106
98
  it('select modbus', async () => {
107
- await selectDeviceType(0);
108
- expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.ScanGatewayQR);
99
+ await selectDeviceType(2, {
100
+ auth: {
101
+ account: {
102
+ user: {
103
+ permissions: {
104
+ plug_and_play_modbus: true,
105
+ },
106
+ },
107
+ },
108
+ },
109
+ });
110
+ expect(mockedNavigate).toBeCalled();
111
+ expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.SelectDeviceSubUnit);
109
112
  });
113
+
110
114
  it('select zigbee', async () => {
111
- await selectDeviceType(1);
115
+ await selectDeviceType(3, {
116
+ auth: {
117
+ account: {
118
+ user: {
119
+ permissions: {
120
+ plug_and_play_zigbee: true,
121
+ },
122
+ },
123
+ },
124
+ },
125
+ });
126
+ expect(mockedNavigate).toBeCalled();
112
127
  expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.SelectDeviceSubUnit);
113
128
  });
129
+
130
+ it('select zigbee reach limit', async () => {
131
+ mock.onGet(API.DEV_MODE.GATEWAY.COUNT()).reply(200, {
132
+ total_chips: 1,
133
+ total_configs: 1,
134
+ });
135
+ await selectDeviceType(3, {
136
+ auth: {
137
+ account: {
138
+ user: {
139
+ permissions: {
140
+ max_chips_per_unit: 1,
141
+ max_configs_per_unit: 1,
142
+ plug_and_play_zigbee: true,
143
+ },
144
+ },
145
+ },
146
+ },
147
+ });
148
+ expect(mockedNavigate).not.toBeCalled();
149
+ expect(spyToastError).toBeCalledWith(
150
+ getTranslate('en', 'reach_max_configs_per_unit')
151
+ );
152
+ });
153
+
114
154
  it('select gateway', async () => {
115
- await selectDeviceType(2);
116
- expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.SelectDeviceSubUnit);
155
+ await selectDeviceType(0, {
156
+ auth: {
157
+ account: {
158
+ user: {
159
+ permissions: {
160
+ plug_and_play_gateway: true,
161
+ },
162
+ },
163
+ },
164
+ },
165
+ });
166
+ expect(mockedNavigate).toBeCalled();
167
+ expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.ScanGatewayQR);
168
+ });
169
+
170
+ it('select gateway reach limit', async () => {
171
+ mock.onGet(API.DEV_MODE.GATEWAY.COUNT()).reply(200, {
172
+ total_chips: 1,
173
+ total_configs: 1,
174
+ });
175
+ await selectDeviceType(0, {
176
+ auth: {
177
+ account: {
178
+ user: {
179
+ permissions: {
180
+ max_chips_per_unit: 1,
181
+ plug_and_play_gateway: true,
182
+ },
183
+ },
184
+ },
185
+ },
186
+ });
187
+ expect(mockedNavigate).not.toBeCalled();
188
+ expect(spyToastError).toBeCalledWith(
189
+ getTranslate('en', 'reach_max_chips_per_unit')
190
+ );
191
+ });
192
+
193
+ it('select gateway without permission', async () => {
194
+ await selectDeviceType(0, {
195
+ auth: {
196
+ account: {
197
+ user: {
198
+ permissions: {
199
+ plug_and_play_gateway: false,
200
+ },
201
+ },
202
+ },
203
+ },
204
+ });
205
+ expect(spyToastError).toBeCalledWith(
206
+ getTranslate('en', 'no_permission_plug_and_play_gateway')
207
+ );
208
+ });
209
+
210
+ it('select zigbee without permission', async () => {
211
+ await selectDeviceType(3, {
212
+ auth: {
213
+ account: {
214
+ user: {
215
+ permissions: {
216
+ plug_and_play_zigbee: false,
217
+ },
218
+ },
219
+ },
220
+ },
221
+ });
222
+ expect(spyToastError).toBeCalledWith(
223
+ getTranslate('en', 'no_permission_plug_and_play_zigbee')
224
+ );
117
225
  });
226
+
227
+ it('select wifi without permission', async () => {
228
+ await selectDeviceType(1, {
229
+ auth: {
230
+ account: {
231
+ user: {
232
+ permissions: {
233
+ plug_and_play_wifi: false,
234
+ },
235
+ },
236
+ },
237
+ },
238
+ });
239
+ expect(spyToastError).toBeCalledWith(
240
+ getTranslate('en', 'no_permission_plug_and_play_wifi')
241
+ );
242
+ });
243
+
244
+ it('select modbus without permission', async () => {
245
+ await selectDeviceType(2, {
246
+ auth: {
247
+ account: {
248
+ user: {
249
+ permissions: {
250
+ plug_and_play_modbus: false,
251
+ },
252
+ },
253
+ },
254
+ },
255
+ });
256
+ expect(spyToastError).toBeCalledWith(
257
+ getTranslate('en', 'no_permission_plug_and_play_modbus')
258
+ );
259
+ });
260
+
118
261
  it('select wifi', async () => {
119
- await selectDeviceType(3);
262
+ await selectDeviceType(1, {
263
+ auth: {
264
+ account: {
265
+ user: {
266
+ permissions: {
267
+ plug_and_play_wifi: true,
268
+ },
269
+ },
270
+ },
271
+ },
272
+ });
273
+ expect(mockedNavigate).toBeCalled();
120
274
  expect(mockedNavigate.mock.calls[0][0]).toEqual(Routes.SelectDeviceSubUnit);
121
275
  });
122
276
  });
@@ -1,5 +1,5 @@
1
1
  import React, { useCallback, useMemo } from 'react';
2
- import { KeyboardAvoidingView, Platform, TouchableOpacity } from 'react-native';
2
+ import { TouchableOpacity, View } from 'react-native';
3
3
 
4
4
  import styles from './Styles/SelectActionStyles';
5
5
  import WrapHeaderScrollable from '../../../commons/Sharing/WrapHeaderScrollable';
@@ -32,10 +32,7 @@ const NewActionWrapper = ({ name, children, canNext, onNext, nextTitle }) => {
32
32
  );
33
33
 
34
34
  return (
35
- <KeyboardAvoidingView
36
- behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
37
- style={styles.wrap}
38
- >
35
+ <View style={styles.wrap}>
39
36
  <WrapHeaderScrollable
40
37
  title={name}
41
38
  headerAniStyle={styles.headerAniStyle}
@@ -49,7 +46,7 @@ const NewActionWrapper = ({ name, children, canNext, onNext, nextTitle }) => {
49
46
  onPressMain={onNext}
50
47
  typeMain={canNext ? 'primary' : 'disabled'}
51
48
  />
52
- </KeyboardAvoidingView>
49
+ </View>
53
50
  );
54
51
  };
55
52
 
@@ -7,11 +7,11 @@ import { Colors, Images } from '../../../configs';
7
7
  import { useTranslations } from '../../../hooks/Common/useTranslations';
8
8
  import { ModalCustom } from '../../../commons/Modal';
9
9
  import Text from '../../../commons/Text';
10
- import { HorizontalPicker } from '../../../commons';
11
10
  import { setStatusBarPreview } from '../../../hooks/Common/useStatusBar';
12
11
  import Routes from '../../../utils/Route';
13
12
  import NewActionWrapper from './NewActionWrapper';
14
13
  import _TextInput from '../../../commons/Form/TextInput';
14
+ import { ToastBottomHelper } from '../../../utils/Utils';
15
15
 
16
16
  const SetupConfigCondition = () => {
17
17
  const t = useTranslations();
@@ -22,7 +22,7 @@ const SetupConfigCondition = () => {
22
22
 
23
23
  const [isShowModal, setIsShowModal] = useState(false);
24
24
  const [itemActiveModal, setItemActiveModal] = useState(defaultCondition);
25
- const [value, setValue] = useState(defaultCondition?.value);
25
+ const [value, setValue] = useState(defaultCondition?.value || '');
26
26
 
27
27
  const hasNoValueEvaluation = !item?.evaluate_configuration;
28
28
 
@@ -68,6 +68,27 @@ const SetupConfigCondition = () => {
68
68
  };
69
69
 
70
70
  const onSave = useCallback(() => {
71
+ const conditionValue = parseFloat(itemActiveModal?.value);
72
+ if (isNaN(conditionValue)) {
73
+ ToastBottomHelper.error(t('value_must_be_a_number'));
74
+ return;
75
+ }
76
+
77
+ if (['<', '>', '='].includes(itemActiveModal?.condition)) {
78
+ if (item.range_min !== null && conditionValue < item.range_min) {
79
+ ToastBottomHelper.error(
80
+ t('value_must_be_greater_than_min', { min: item.range_min })
81
+ );
82
+ return;
83
+ }
84
+ if (item.range_max !== null && conditionValue > item.range_max) {
85
+ ToastBottomHelper.error(
86
+ t('value_must_be_less_than_max', { max: item.range_max })
87
+ );
88
+ return;
89
+ }
90
+ }
91
+
71
92
  navigate({
72
93
  name: Routes.ChooseConfig,
73
94
  merge: true,
@@ -78,7 +99,7 @@ const SetupConfigCondition = () => {
78
99
  },
79
100
  },
80
101
  });
81
- }, [item.id, itemActiveModal, navigate]);
102
+ }, [item.id, item.range_max, item.range_min, itemActiveModal, navigate, t]);
82
103
 
83
104
  useEffect(() => {
84
105
  !hasNoValueEvaluation && setValue(1);
@@ -98,12 +119,9 @@ const SetupConfigCondition = () => {
98
119
  );
99
120
  }, [isShowModal]);
100
121
 
101
- const onChangeValue = useCallback((v) => {
102
- const newValue = parseInt(v, 10);
103
- if (!isNaN(newValue)) {
104
- setValue(newValue);
105
- setItemActiveModal((prev) => ({ ...prev, value: newValue }));
106
- }
122
+ const onChangeValue = useCallback((newValue) => {
123
+ setValue(newValue);
124
+ setItemActiveModal((prev) => ({ ...prev, value: newValue }));
107
125
  }, []);
108
126
 
109
127
  return (
@@ -136,7 +154,8 @@ const SetupConfigCondition = () => {
136
154
  <_TextInput
137
155
  textInputStyle={styles.value}
138
156
  wrapStyle={styles.wrapValue}
139
- value={value?.toString()}
157
+ value={value}
158
+ keyboardType={'numeric'}
140
159
  onChange={onChangeValue}
141
160
  />
142
161
  </View>
@@ -144,25 +163,6 @@ const SetupConfigCondition = () => {
144
163
  {item?.unit}
145
164
  </Text>
146
165
  </View>
147
- <HorizontalPicker
148
- minimum={item?.range_min}
149
- maximum={item?.range_max}
150
- segmentSpacing={8}
151
- segmentWidth={8}
152
- step={
153
- item?.decimal_behind
154
- ? 1 / Math.pow(10, item?.decimal_behind)
155
- : 1
156
- }
157
- normalHeight={4}
158
- normalWidth={4}
159
- stepHeight={12}
160
- stepWidth={12}
161
- stepColor={Colors.Gray6}
162
- normalColor={Colors.Gray6}
163
- onChangeValue={onChangeValue}
164
- value={value}
165
- />
166
166
  </>
167
167
  )}
168
168
  </NewActionWrapper>