@eohjsc/react-native-smart-city 0.7.8 → 0.7.9

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 (85) hide show
  1. package/assets/images/AddNewDevice/add-scan-device-icon.svg +13 -0
  2. package/assets/images/Email.svg +9 -0
  3. package/assets/images/lan.svg +3 -0
  4. package/assets/images/wifi-open.svg +3 -0
  5. package/package.json +2 -1
  6. package/src/commons/ActionGroup/StatesGridActionTemplate.js +7 -3
  7. package/src/commons/ActionGroup/__test__/StatesGridActionTemplate.test.js +7 -3
  8. package/src/commons/AlertAction/index.js +1 -0
  9. package/src/commons/Auth/AccountItem.js +17 -3
  10. package/src/commons/Auth/AccountList.js +3 -7
  11. package/src/commons/ConnectWifi/__test__/ConnectWifi.test.js +373 -0
  12. package/src/commons/ConnectWifi/index.js +201 -0
  13. package/src/commons/ConnectWifi/styles.js +69 -0
  14. package/src/commons/Form/TextInputPassword.js +1 -1
  15. package/src/commons/OneTapTemplate/StatesGridActionTemplate.js +6 -2
  16. package/src/configs/API.js +12 -0
  17. package/src/configs/AccessibilityLabel.js +7 -0
  18. package/src/configs/Constants.js +1 -0
  19. package/src/hooks/Common/index.js +2 -2
  20. package/src/hooks/Common/useBlockBack.js +36 -0
  21. package/src/hooks/useMqtt.js +10 -5
  22. package/src/navigations/AddGatewayStack.js +2 -0
  23. package/src/navigations/AllGatewayStack.js +4 -0
  24. package/src/navigations/Main.js +2 -2
  25. package/src/navigations/UnitStack.js +32 -0
  26. package/src/screens/AddNewGateway/ConnectingWifiDevice.js +7 -6
  27. package/src/screens/AddNewGateway/ScanDeviceLocal.js +267 -0
  28. package/src/screens/AddNewGateway/ScanDeviceLocalStyles.js +58 -0
  29. package/src/screens/AddNewGateway/SelectDeviceSubUnit.js +10 -2
  30. package/src/screens/AddNewGateway/SelectDeviceType.js +19 -2
  31. package/src/screens/AddNewGateway/__test__/ScanDeviceLocal.test.js +475 -0
  32. package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +2 -2
  33. package/src/screens/AddNewGateway/configs/API.js +8 -0
  34. package/src/screens/AddNewGateway/hooks/useConnectDevice.js +59 -0
  35. package/src/screens/AllGateway/GatewayInfo/__test__/index.test.js +58 -1
  36. package/src/screens/AllGateway/GatewayInfo/index.js +8 -6
  37. package/src/screens/AllGateway/GatewayWifi/__test__/index.test.js +319 -0
  38. package/src/screens/AllGateway/GatewayWifi/index.js +107 -0
  39. package/src/screens/AllGateway/Successfully/__test__/index.test.js +77 -0
  40. package/src/screens/AllGateway/Successfully/index.js +66 -0
  41. package/src/screens/AllGateway/Successfully/styles.js +35 -0
  42. package/src/screens/AllGateway/components/Information/index.js +17 -1
  43. package/src/screens/AllGateway/components/RowItem/index.js +12 -1
  44. package/src/screens/AllGateway/hooks/__test__/index.test.js +18 -0
  45. package/src/screens/AllGateway/hooks/useGateway.js +13 -0
  46. package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +3 -3
  47. package/src/screens/Automate/AddNewAction/SetupScriptEmail.js +79 -0
  48. package/src/screens/Automate/AddNewAction/SetupScriptReceiverEmail.js +166 -0
  49. package/src/screens/Automate/AddNewAction/Styles/SetupScriptEmailStyles.js +37 -0
  50. package/src/screens/Automate/AddNewAction/Styles/SetupScriptReceiverEmailStyles.js +79 -0
  51. package/src/screens/Automate/AddNewAction/__test__/ChooseAction.test.js +1 -1
  52. package/src/screens/Automate/AddNewAction/__test__/SetupConfigCondition.test.js +13 -5
  53. package/src/screens/Automate/AddNewAction/__test__/SetupScriptEmail.test.js +76 -0
  54. package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverEmail.test.js +105 -0
  55. package/src/screens/Automate/EditActionsList/Styles/UpdateReceiverEmailScriptStyles.js +78 -0
  56. package/src/screens/Automate/EditActionsList/UpdateEmailScript.js +80 -0
  57. package/src/screens/Automate/EditActionsList/UpdateReceiverEmailScript.js +179 -0
  58. package/src/screens/Automate/EditActionsList/__tests__/UpdateEmailScript.test.js +81 -0
  59. package/src/screens/Automate/EditActionsList/__tests__/UpdateReceiverEmailScript.test.js +83 -0
  60. package/src/screens/Automate/EditActionsList/__tests__/index.test.js +38 -5
  61. package/src/screens/Automate/EditActionsList/index.js +59 -2
  62. package/src/screens/Automate/ScriptDetail/Components/AddActionScript.js +20 -0
  63. package/src/screens/Automate/ScriptDetail/Styles/indexStyles.js +5 -3
  64. package/src/screens/Automate/ScriptDetail/__test__/index.test.js +127 -21
  65. package/src/screens/Automate/ScriptDetail/index.js +57 -14
  66. package/src/screens/SharedUnit/index.js +2 -2
  67. package/src/screens/Sharing/SelectUser.js +47 -47
  68. package/src/screens/Sharing/__test__/SelectUser.test.js +57 -103
  69. package/src/screens/SubUnit/ManageSubUnit.js +94 -90
  70. package/src/screens/SubUnit/ManageSubUnitStyles.js +4 -6
  71. package/src/screens/SubUnit/RearrageSubUnit.js +90 -0
  72. package/src/screens/SubUnit/RearrrageSubUnitStyle.js +65 -0
  73. package/src/screens/SubUnit/__test__/ManageSubUnit.test.js +35 -19
  74. package/src/screens/SubUnit/__test__/RearrangeSubUnit.test.js +129 -0
  75. package/src/screens/SubUnit/hooks/__test__/useManageSubUnit.test.js +6 -7
  76. package/src/screens/SubUnit/hooks/useManageSubUnit.js +8 -16
  77. package/src/screens/Unit/Detail.js +2 -6
  78. package/src/screens/Unit/ManageUnit.js +1 -1
  79. package/src/utils/Functions/__test__/ShortEmail.test.js +5 -0
  80. package/src/utils/I18n/translations/en.js +46 -8
  81. package/src/utils/I18n/translations/vi.js +37 -4
  82. package/src/utils/Route/index.js +7 -0
  83. package/src/commons/Auth/__test__/AccountItem.test.js +0 -31
  84. package/src/hooks/Common/useBlockBackAndroid.js +0 -21
  85. package/src/screens/SubUnit/DetailStyles.js +0 -46
@@ -0,0 +1,319 @@
1
+ import React from 'react';
2
+ import renderer, { act } from 'react-test-renderer';
3
+ import { Alert } from 'react-native';
4
+ import { useNavigation } from '@react-navigation/native';
5
+ import mqtt from 'precompiled-mqtt/dist/mqtt.browser';
6
+
7
+ import { SCProvider } from '../../../../context';
8
+ import { mockSCStore } from '../../../../context/mockStore';
9
+ import { getTranslate } from '../../../../utils/I18n';
10
+ import Routes from '../../../../utils/Route';
11
+
12
+ import ConnectWifi from '../../../../commons/ConnectWifi';
13
+ import GatewayWifi from '../index';
14
+
15
+ jest.mock('precompiled-mqtt/dist/mqtt.browser', () => {
16
+ return {
17
+ connect: jest.fn(() => {
18
+ return {
19
+ on: jest.fn(),
20
+ subscribe: jest.fn(),
21
+ publish: jest.fn(),
22
+ end: jest.fn(),
23
+ };
24
+ }),
25
+ };
26
+ });
27
+
28
+ const wrapComponent = ({ props }) => (
29
+ <SCProvider initState={mockSCStore({})}>
30
+ <GatewayWifi {...props} />
31
+ </SCProvider>
32
+ );
33
+
34
+ describe('Test GatewayWifi', () => {
35
+ let tree;
36
+ let mockClient;
37
+
38
+ const mockNavigate = useNavigation().navigate;
39
+ const spyAlert = jest.spyOn(Alert, 'alert');
40
+
41
+ const props = {
42
+ route: {
43
+ params: {
44
+ gateway: {
45
+ mqtt_server: {
46
+ websocket_host: 'mqtt.example.com',
47
+ websocket_port: 8083,
48
+ },
49
+ code: '123456',
50
+ },
51
+ },
52
+ },
53
+ };
54
+
55
+ beforeEach(() => {
56
+ jest.useFakeTimers();
57
+ jest.spyOn(global, 'setTimeout');
58
+ jest.spyOn(global, 'clearTimeout');
59
+ mockClient = {
60
+ on: jest.fn(),
61
+ subscribe: jest.fn(),
62
+ publish: jest.fn(),
63
+ end: jest.fn(),
64
+ };
65
+ mqtt.connect.mockReturnValue(mockClient);
66
+ });
67
+
68
+ afterEach(() => {
69
+ global.setTimeout.mockRestore();
70
+ global.clearTimeout.mockRestore();
71
+ jest.clearAllMocks();
72
+ jest.useRealTimers();
73
+ });
74
+
75
+ const triggerConnect = async () => {
76
+ const connectCallback = mockClient.on.mock.calls.find(
77
+ (call) => call[0] === 'connect'
78
+ )[1];
79
+ await act(async () => {
80
+ connectCallback();
81
+ });
82
+ };
83
+
84
+ const triggerMessage = async (topic, payload) => {
85
+ const messageCallback = mockClient.on.mock.calls.find(
86
+ (call) => call[0] === 'message'
87
+ )[1];
88
+ await act(async () => {
89
+ messageCallback(topic, JSON.stringify(payload), {});
90
+ });
91
+ };
92
+
93
+ const triggerOnChangeWifi = async (wifiDetails) => {
94
+ const instance = tree.root;
95
+ const connectWifi = instance.findByType(ConnectWifi);
96
+ const onConnect = connectWifi.props.onConnect;
97
+
98
+ await act(async () => {
99
+ onConnect(wifiDetails);
100
+ });
101
+
102
+ expect(mockClient.publish).toHaveBeenCalledWith(
103
+ 'eoh/chip/123456/wifi/change',
104
+ JSON.stringify({
105
+ ssid: wifiDetails.wifiSsid,
106
+ password: wifiDetails.wifiPassword,
107
+ })
108
+ );
109
+
110
+ expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 120000);
111
+ };
112
+
113
+ it('test connects to MQTT server on mount and subscribes to topics', async () => {
114
+ await act(async () => {
115
+ tree = await renderer.create(wrapComponent({ props }));
116
+ });
117
+
118
+ expect(mqtt.connect).toHaveBeenCalledWith('wss://mqtt.example.com:8083', {
119
+ username: '123456',
120
+ password: '123456',
121
+ });
122
+ expect(mockClient.on).toHaveBeenCalledTimes(2);
123
+ expect(mockClient.on).toHaveBeenCalledWith('connect', expect.any(Function));
124
+ expect(mockClient.on).toHaveBeenCalledWith('message', expect.any(Function));
125
+
126
+ await act(async () => {
127
+ triggerConnect();
128
+ });
129
+
130
+ expect(mockClient.subscribe).toHaveBeenCalledWith(
131
+ 'eoh/chip/123456/wifi/list'
132
+ );
133
+ expect(mockClient.subscribe).toHaveBeenCalledWith(
134
+ 'eoh/chip/123456/wifi/change_result'
135
+ );
136
+ expect(mockClient.publish).toHaveBeenCalledWith(
137
+ 'eoh/chip/123456/wifi/ask',
138
+ '1'
139
+ );
140
+ });
141
+
142
+ it('test with no mqtt server', async () => {
143
+ const newProps = {
144
+ route: {},
145
+ };
146
+ await act(async () => {
147
+ tree = await renderer.create(wrapComponent({ props: newProps }));
148
+ });
149
+
150
+ const instance = tree.root;
151
+ const connectWifi = instance.findByType(ConnectWifi);
152
+ const onConnect = connectWifi.props.onConnect;
153
+
154
+ await act(async () => {
155
+ onConnect({ wifiSsid: 'NewWiFi', wifiPassword: 'NewPassword123' });
156
+ });
157
+
158
+ expect(mqtt.connect).not.toHaveBeenCalled();
159
+ expect(mockClient.on).not.toHaveBeenCalled();
160
+ expect(mockClient.subscribe).not.toHaveBeenCalled();
161
+ expect(mockClient.publish).not.toHaveBeenCalled();
162
+ expect(mockClient.end).not.toHaveBeenCalled();
163
+ });
164
+
165
+ it('test handles receiving wifi list message', async () => {
166
+ await act(async () => {
167
+ tree = await renderer.create(wrapComponent({ props }));
168
+ });
169
+
170
+ await act(async () => {
171
+ triggerConnect();
172
+ });
173
+
174
+ const wifiList = [
175
+ { ssid: 'HomeWiFi', encryption: 'WPA2/PSK' },
176
+ { ssid: 'OpenNetwork', encryption: 'OPEN' },
177
+ ];
178
+
179
+ await act(async () => {
180
+ triggerMessage('eoh/chip/123456/wifi/list', wifiList);
181
+ });
182
+
183
+ const instance = tree.root;
184
+ const connectWifi = instance.findByType(ConnectWifi);
185
+ expect(connectWifi.props.wifiList).toEqual(wifiList);
186
+ });
187
+
188
+ it('test handles successful wifi change result message', async () => {
189
+ await act(async () => {
190
+ tree = await renderer.create(wrapComponent({ props }));
191
+ });
192
+
193
+ await act(async () => {
194
+ triggerConnect();
195
+ });
196
+
197
+ await act(async () => {
198
+ triggerOnChangeWifi({
199
+ wifiSsid: 'NewWiFi',
200
+ wifiPassword: 'NewPassword123',
201
+ });
202
+ });
203
+
204
+ await act(async () => {
205
+ triggerMessage('eoh/chip/123456/wifi/change_result', { success: true });
206
+ });
207
+
208
+ expect(mockNavigate).toHaveBeenCalledWith(Routes.Successfully, {
209
+ gateway: props.route.params.gateway,
210
+ wifiName: 'NewWiFi',
211
+ });
212
+ expect(clearTimeout).toHaveBeenCalledWith(expect.any(Number));
213
+ expect(mockClient.end).not.toHaveBeenCalled();
214
+
215
+ await act(async () => {
216
+ triggerMessage('eoh/chip/123456/wifi/change_result', { success: true });
217
+ });
218
+ expect(clearTimeout).toHaveBeenCalledTimes(1);
219
+
220
+ await act(async () => {
221
+ tree.unmount();
222
+ });
223
+ expect(mockClient.end).toHaveBeenCalled();
224
+ expect(clearTimeout).toHaveBeenCalledTimes(1);
225
+ });
226
+
227
+ it('test handles failed wifi change result message', async () => {
228
+ await act(async () => {
229
+ tree = await renderer.create(wrapComponent({ props }));
230
+ });
231
+
232
+ await act(async () => {
233
+ triggerConnect();
234
+ });
235
+
236
+ await act(async () => {
237
+ triggerOnChangeWifi({
238
+ wifiSsid: 'NewWiFi',
239
+ wifiPassword: 'NewPassword123',
240
+ });
241
+ });
242
+
243
+ await act(async () => {
244
+ triggerMessage('eoh/chip/123456/wifi/change_result', { success: false });
245
+ });
246
+
247
+ expect(spyAlert).toHaveBeenCalledWith(
248
+ getTranslate('en', 'failed'),
249
+ getTranslate('en', 'change_wifi_failed')
250
+ );
251
+ expect(mockNavigate).not.toHaveBeenCalled();
252
+ expect(mockClient.end).not.toHaveBeenCalled();
253
+ });
254
+
255
+ it('test publishes wifi change on onChangeWifi and sets timeout', async () => {
256
+ await act(async () => {
257
+ tree = await renderer.create(wrapComponent({ props }));
258
+ });
259
+
260
+ await act(async () => {
261
+ triggerConnect();
262
+ });
263
+
264
+ await act(async () => {
265
+ triggerOnChangeWifi({
266
+ wifiSsid: 'NewWiFi',
267
+ wifiPassword: 'NewPassword123',
268
+ });
269
+ });
270
+
271
+ await act(async () => {
272
+ jest.runAllTimers();
273
+ });
274
+
275
+ expect(spyAlert).toHaveBeenCalledWith(
276
+ getTranslate('en', 'failed'),
277
+ getTranslate('en', 'connection_timeout')
278
+ );
279
+ });
280
+
281
+ it('test handles unmount', async () => {
282
+ await act(async () => {
283
+ tree = await renderer.create(wrapComponent({ props }));
284
+ });
285
+
286
+ await act(async () => {
287
+ triggerConnect();
288
+ });
289
+
290
+ await act(async () => {
291
+ triggerOnChangeWifi({
292
+ wifiSsid: 'NewWiFi',
293
+ wifiPassword: 'NewPassword123',
294
+ });
295
+ });
296
+
297
+ expect(mockClient.end).not.toHaveBeenCalled();
298
+ expect(clearTimeout).not.toHaveBeenCalled();
299
+
300
+ await act(async () => {
301
+ tree.unmount();
302
+ });
303
+ expect(mockClient.end).toHaveBeenCalled();
304
+ expect(clearTimeout).toHaveBeenCalledWith(expect.any(Number));
305
+ });
306
+
307
+ it('test receives change result message before connect', async () => {
308
+ await act(async () => {
309
+ renderer.create(wrapComponent({ props }));
310
+ });
311
+
312
+ await act(async () => {
313
+ triggerMessage('eoh/chip/123456/wifi/change_result', { success: true });
314
+ });
315
+
316
+ expect(mockNavigate).not.toHaveBeenCalled();
317
+ expect(spyAlert).not.toHaveBeenCalled();
318
+ });
319
+ });
@@ -0,0 +1,107 @@
1
+ import { useNavigation } from '@react-navigation/native';
2
+ import React, { memo, useCallback, useEffect, useState, useRef } from 'react';
3
+ import { Alert } from 'react-native';
4
+ import { useTranslations } from '../../../hooks/Common/useTranslations';
5
+ import { connectMqttServer } from '../../../hooks/useMqtt';
6
+ import Routes from '../../../utils/Route';
7
+ import ConnectWifi from '../../../commons/ConnectWifi';
8
+
9
+ const GatewayWifi = ({ route }) => {
10
+ const { gateway } = route?.params || {};
11
+
12
+ const t = useTranslations();
13
+ const { navigate, goBack } = useNavigation();
14
+
15
+ const mqttClientRef = useRef(null);
16
+ const timeoutIdRef = useRef(null);
17
+ const wifiNameRef = useRef(null);
18
+
19
+ const [wifiList, setWifiList] = useState([]);
20
+ const [isShowLoading, setIsShowLoading] = useState(false);
21
+
22
+ useEffect(() => {
23
+ if (!gateway?.mqtt_server) {
24
+ return;
25
+ }
26
+
27
+ const client = connectMqttServer(gateway.mqtt_server, gateway.code);
28
+
29
+ client.on('connect', () => {
30
+ client.subscribe(`eoh/chip/${gateway.code}/wifi/list`);
31
+ client.subscribe(`eoh/chip/${gateway.code}/wifi/change_result`);
32
+ client.publish(`eoh/chip/${gateway.code}/wifi/ask`, '1');
33
+ });
34
+
35
+ client.on('message', async (topic, payload) => {
36
+ if (topic === `eoh/chip/${gateway.code}/wifi/change_result`) {
37
+ if (!wifiNameRef.current) {
38
+ return;
39
+ }
40
+ if (timeoutIdRef.current) {
41
+ clearTimeout(timeoutIdRef.current);
42
+ timeoutIdRef.current = null;
43
+ }
44
+ const result = JSON.parse(payload.toString());
45
+ if (result.success) {
46
+ navigate(Routes.Successfully, {
47
+ gateway,
48
+ wifiName: wifiNameRef.current,
49
+ });
50
+ } else {
51
+ setIsShowLoading(false);
52
+ Alert.alert(t('failed'), t('change_wifi_failed'));
53
+ }
54
+ }
55
+
56
+ if (topic === `eoh/chip/${gateway.code}/wifi/list`) {
57
+ setWifiList(JSON.parse(payload.toString()));
58
+ }
59
+ });
60
+
61
+ mqttClientRef.current = client;
62
+ return () => {
63
+ client.end();
64
+ if (timeoutIdRef.current) {
65
+ clearTimeout(timeoutIdRef.current);
66
+ timeoutIdRef.current = null;
67
+ }
68
+ };
69
+ }, [gateway, t, navigate]);
70
+
71
+ const onChangeWifi = useCallback(
72
+ ({ wifiSsid, wifiPassword }) => {
73
+ if (!mqttClientRef.current) {
74
+ return;
75
+ }
76
+
77
+ timeoutIdRef.current = setTimeout(() => {
78
+ setIsShowLoading(false);
79
+ Alert.alert(t('failed'), t('connection_timeout'));
80
+ }, 120000);
81
+
82
+ mqttClientRef.current.publish(
83
+ `eoh/chip/${gateway.code}/wifi/change`,
84
+ JSON.stringify({
85
+ ssid: wifiSsid,
86
+ password: wifiPassword,
87
+ })
88
+ );
89
+
90
+ wifiNameRef.current = wifiSsid;
91
+ },
92
+ [gateway, t]
93
+ );
94
+
95
+ return (
96
+ <ConnectWifi
97
+ title={'change_wifi'}
98
+ wifiList={wifiList}
99
+ onConnect={onChangeWifi}
100
+ onGoBack={goBack}
101
+ isShowLoading={isShowLoading}
102
+ setIsShowLoading={setIsShowLoading}
103
+ />
104
+ );
105
+ };
106
+
107
+ export default memo(GatewayWifi);
@@ -0,0 +1,77 @@
1
+ import React from 'react';
2
+ import renderer, { act } from 'react-test-renderer';
3
+ import { TouchableOpacity } from 'react-native';
4
+ import { useNavigation } from '@react-navigation/native';
5
+
6
+ import { SCProvider } from '../../../../context';
7
+ import { mockSCStore } from '../../../../context/mockStore';
8
+ import AccessibilityLabel from '../../../../configs/AccessibilityLabel';
9
+ import Routes from '../../../../utils/Route';
10
+
11
+ import Successfully from '../index';
12
+
13
+ const wrapComponent = ({ props }) => (
14
+ <SCProvider initState={mockSCStore({})}>
15
+ <Successfully {...props} />
16
+ </SCProvider>
17
+ );
18
+
19
+ describe('test Successfully', () => {
20
+ let tree;
21
+
22
+ const mockNavigate = useNavigation().navigate;
23
+
24
+ const props = {
25
+ route: {
26
+ params: {
27
+ gateway: { id: 1, name: 'Gateway1' },
28
+ wifiName: 'HomeWiFi',
29
+ },
30
+ },
31
+ };
32
+
33
+ afterEach(() => {
34
+ mockNavigate.mockClear();
35
+ });
36
+
37
+ it('test navigates to GatewayInfo with correct parameters when Done is pressed', async () => {
38
+ await act(async () => {
39
+ tree = await renderer.create(wrapComponent({ props }));
40
+ });
41
+
42
+ const instance = tree.root;
43
+ const doneButton = instance.find(
44
+ (el) =>
45
+ el.props.accessibilityLabel === AccessibilityLabel.BUTTON_DONE &&
46
+ el.type === TouchableOpacity
47
+ );
48
+
49
+ await act(async () => {
50
+ doneButton.props.onPress();
51
+ });
52
+
53
+ expect(mockNavigate).toHaveBeenCalledWith(Routes.GatewayInfo, {
54
+ chipId: 1,
55
+ gatewayName: 'Gateway1',
56
+ });
57
+ });
58
+
59
+ it('test handles missing route params', async () => {
60
+ await act(async () => {
61
+ tree = await renderer.create(wrapComponent({}));
62
+ });
63
+
64
+ const instance = tree.root;
65
+ const doneButton = instance.find(
66
+ (el) =>
67
+ el.props.accessibilityLabel === AccessibilityLabel.BUTTON_DONE &&
68
+ el.type === TouchableOpacity
69
+ );
70
+
71
+ await act(async () => {
72
+ doneButton.props.onPress();
73
+ });
74
+
75
+ expect(mockNavigate).not.toHaveBeenCalled();
76
+ });
77
+ });
@@ -0,0 +1,66 @@
1
+ import React, { useCallback } from 'react';
2
+ import { TouchableOpacity, View } from 'react-native';
3
+ import { IconOutline } from '@ant-design/icons-react-native';
4
+ import { useNavigation } from '@react-navigation/native';
5
+ import { useTranslations } from '../../../hooks/Common/useTranslations';
6
+ import { Colors } from '../../../configs';
7
+ import Text from '../../../commons/Text';
8
+ import AccessibilityLabel from '../../../configs/AccessibilityLabel';
9
+ import Routes from '../../../utils/Route';
10
+ import { HeaderCustom } from '../../../commons/Header';
11
+
12
+ import styles from './styles';
13
+
14
+ const Successfully = ({ route }) => {
15
+ const { gateway, wifiName } = route?.params || {};
16
+
17
+ const t = useTranslations();
18
+ const { navigate } = useNavigation();
19
+
20
+ const onPressDone = useCallback(() => {
21
+ if (!gateway) {
22
+ return;
23
+ }
24
+ navigate(Routes.GatewayInfo, {
25
+ chipId: gateway?.id,
26
+ gatewayName: gateway?.name,
27
+ });
28
+ }, [navigate, gateway]);
29
+
30
+ return (
31
+ <View style={styles.container}>
32
+ <HeaderCustom
33
+ title={t('connect_wifi')}
34
+ isShowSeparator
35
+ isCanBack={false}
36
+ />
37
+ <View style={styles.content}>
38
+ <View style={styles.viewIconSuccess}>
39
+ <IconOutline name="check-circle" size={48} color={Colors.Green6} />
40
+ <Text
41
+ semibold
42
+ color={Colors.Black}
43
+ size={20}
44
+ style={styles.textStatus}
45
+ >
46
+ {t('successfully_connected')}
47
+ </Text>
48
+ <Text size={14} color={Colors.Gray9} style={styles.textInfo}>
49
+ {`${t('you_have_successfully_connected_wifi')}: ${wifiName}`}
50
+ </Text>
51
+ </View>
52
+ </View>
53
+ <TouchableOpacity
54
+ style={styles.btnDone}
55
+ onPress={onPressDone}
56
+ accessibilityLabel={AccessibilityLabel.BUTTON_DONE}
57
+ >
58
+ <Text semibold size={16} color={Colors.Primary}>
59
+ {t('done')}
60
+ </Text>
61
+ </TouchableOpacity>
62
+ </View>
63
+ );
64
+ };
65
+
66
+ export default Successfully;
@@ -0,0 +1,35 @@
1
+ import { StyleSheet } from 'react-native';
2
+ import { Colors } from '../../../configs';
3
+
4
+ export default StyleSheet.create({
5
+ container: {
6
+ flex: 1,
7
+ backgroundColor: Colors.White,
8
+ justifyContent: 'center',
9
+ alignItems: 'center',
10
+ },
11
+ content: {
12
+ flex: 1,
13
+ justifyContent: 'center',
14
+ alignItems: 'center',
15
+ },
16
+ btnDone: {
17
+ height: 48,
18
+ width: '100%',
19
+ alignItems: 'center',
20
+ marginTop: 100,
21
+ },
22
+ textStatus: {
23
+ marginTop: 8,
24
+ marginBottom: 16,
25
+ },
26
+ textInfo: {
27
+ textAlign: 'center',
28
+ lineHeight: 24,
29
+ marginHorizontal: 20,
30
+ },
31
+ viewIconSuccess: {
32
+ alignItems: 'center',
33
+ justifyContent: 'center',
34
+ },
35
+ });
@@ -1,9 +1,12 @@
1
1
  import React, { useCallback, memo } from 'react';
2
2
  import { TouchableOpacity, View, Image, FlatList } from 'react-native';
3
+ import { useNavigation } from '@react-navigation/native';
4
+ import Routes from '../../../../utils/Route';
3
5
  import { Colors, SCConfig } from '../../../../configs';
4
6
  import t from '../../../../hooks/Common/useTranslations';
5
7
  import { Text, HeaderCustom } from '../../../../commons';
6
8
  import Images from '../../../../configs/Images';
9
+ import { ToastBottomHelper } from '../../../../utils/Utils';
7
10
  import { AccessibilityLabel } from '../../../../configs/Constants';
8
11
  import styles from './styles';
9
12
  import RowItem from '../RowItem';
@@ -12,12 +15,23 @@ const Information = ({
12
15
  listInformation,
13
16
  handleDeleteGateway,
14
17
  handleConnectionMethods,
18
+ gatewayDetail,
15
19
  isDevice = false,
16
20
  title = t('gateway_information'),
17
21
  isModbus,
18
22
  buttonBackStyles,
19
23
  methodsConnection,
20
24
  }) => {
25
+ const { navigate } = useNavigation();
26
+
27
+ const handleChangeWifi = useCallback(() => {
28
+ if (!gatewayDetail?.is_connected) {
29
+ ToastBottomHelper.error(t('gateway_need_to_be_connected'));
30
+ return;
31
+ }
32
+ navigate(Routes.GatewayWifi, { gateway: gatewayDetail });
33
+ }, [navigate, gatewayDetail]);
34
+
21
35
  const renderItem = useCallback(
22
36
  ({ item, index }) => {
23
37
  return (
@@ -26,10 +40,12 @@ const Information = ({
26
40
  subTitle={item?.data}
27
41
  key={index}
28
42
  isShowCopy={item?.id === 5 && !isModbus}
43
+ isShowChangeWifi={item?.id === 3 && !isModbus}
44
+ handleChangeWifi={handleChangeWifi}
29
45
  />
30
46
  );
31
47
  },
32
- [isModbus]
48
+ [isModbus, handleChangeWifi]
33
49
  );
34
50
 
35
51
  return (
@@ -1,6 +1,7 @@
1
1
  import React, { memo, useCallback, useMemo } from 'react';
2
2
  import { TouchableOpacity, View } from 'react-native';
3
3
  import Clipboard from '@react-native-clipboard/clipboard';
4
+ import { IconOutline } from '@ant-design/icons-react-native';
4
5
 
5
6
  import t from '../../../../hooks/Common/useTranslations';
6
7
  import FileCopy from '../../../../Images/DevMode/file_copy.svg';
@@ -14,6 +15,8 @@ const RowItem = ({
14
15
  subTitle = '--',
15
16
  isShowCopy = false,
16
17
  onRowOne = false,
18
+ isShowChangeWifi = false,
19
+ handleChangeWifi,
17
20
  }) => {
18
21
  const handleCopy = useCallback(() => {
19
22
  Clipboard?.setString(subTitle);
@@ -39,9 +42,17 @@ const RowItem = ({
39
42
  <FileCopy />
40
43
  </TouchableOpacity>
41
44
  )}
45
+ {!!isShowChangeWifi && (
46
+ <TouchableOpacity
47
+ onPress={handleChangeWifi}
48
+ accessibilityLabel={AccessibilityLabel.CHANGE_WIFI}
49
+ >
50
+ <IconOutline name="edit" size={25} />
51
+ </TouchableOpacity>
52
+ )}
42
53
  </>
43
54
  );
44
- }, [handleCopy, isShowCopy, subTitle]);
55
+ }, [handleCopy, handleChangeWifi, isShowCopy, isShowChangeWifi, subTitle]);
45
56
 
46
57
  return (
47
58
  <View