@eohjsc/react-native-smart-city 0.7.7 → 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 (90) 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 +4 -3
  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/Device/LabelValue/__test__/LabelValue.test.js +74 -0
  15. package/src/commons/Device/LabelValue/index.js +49 -0
  16. package/src/commons/Device/LabelValue/styles.js +33 -0
  17. package/src/commons/Form/TextInputPassword.js +1 -1
  18. package/src/commons/OneTapTemplate/StatesGridActionTemplate.js +6 -2
  19. package/src/configs/API.js +12 -0
  20. package/src/configs/AccessibilityLabel.js +7 -0
  21. package/src/configs/Constants.js +1 -0
  22. package/src/hooks/Common/index.js +2 -2
  23. package/src/hooks/Common/useBlockBack.js +36 -0
  24. package/src/hooks/useMqtt.js +10 -5
  25. package/src/navigations/AddGatewayStack.js +2 -0
  26. package/src/navigations/AllGatewayStack.js +4 -0
  27. package/src/navigations/Main.js +2 -2
  28. package/src/navigations/UnitStack.js +32 -0
  29. package/src/screens/AddNewGateway/ConnectingWifiDevice.js +7 -6
  30. package/src/screens/AddNewGateway/ScanDeviceLocal.js +267 -0
  31. package/src/screens/AddNewGateway/ScanDeviceLocalStyles.js +58 -0
  32. package/src/screens/AddNewGateway/SelectDeviceSubUnit.js +10 -2
  33. package/src/screens/AddNewGateway/SelectDeviceType.js +19 -2
  34. package/src/screens/AddNewGateway/__test__/ScanDeviceLocal.test.js +475 -0
  35. package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +2 -2
  36. package/src/screens/AddNewGateway/configs/API.js +8 -0
  37. package/src/screens/AddNewGateway/hooks/useConnectDevice.js +59 -0
  38. package/src/screens/AllGateway/GatewayInfo/__test__/index.test.js +58 -1
  39. package/src/screens/AllGateway/GatewayInfo/index.js +8 -6
  40. package/src/screens/AllGateway/GatewayWifi/__test__/index.test.js +319 -0
  41. package/src/screens/AllGateway/GatewayWifi/index.js +107 -0
  42. package/src/screens/AllGateway/Successfully/__test__/index.test.js +77 -0
  43. package/src/screens/AllGateway/Successfully/index.js +66 -0
  44. package/src/screens/AllGateway/Successfully/styles.js +35 -0
  45. package/src/screens/AllGateway/components/Information/index.js +17 -1
  46. package/src/screens/AllGateway/components/RowItem/index.js +12 -1
  47. package/src/screens/AllGateway/hooks/__test__/index.test.js +18 -0
  48. package/src/screens/AllGateway/hooks/useGateway.js +13 -0
  49. package/src/screens/Automate/AddNewAction/SetupConfigCondition.js +3 -3
  50. package/src/screens/Automate/AddNewAction/SetupScriptEmail.js +79 -0
  51. package/src/screens/Automate/AddNewAction/SetupScriptReceiverEmail.js +166 -0
  52. package/src/screens/Automate/AddNewAction/Styles/SetupScriptEmailStyles.js +37 -0
  53. package/src/screens/Automate/AddNewAction/Styles/SetupScriptReceiverEmailStyles.js +79 -0
  54. package/src/screens/Automate/AddNewAction/__test__/ChooseAction.test.js +1 -1
  55. package/src/screens/Automate/AddNewAction/__test__/SetupConfigCondition.test.js +13 -5
  56. package/src/screens/Automate/AddNewAction/__test__/SetupScriptEmail.test.js +76 -0
  57. package/src/screens/Automate/AddNewAction/__test__/SetupScriptReceiverEmail.test.js +105 -0
  58. package/src/screens/Automate/EditActionsList/Styles/UpdateReceiverEmailScriptStyles.js +78 -0
  59. package/src/screens/Automate/EditActionsList/UpdateEmailScript.js +80 -0
  60. package/src/screens/Automate/EditActionsList/UpdateReceiverEmailScript.js +179 -0
  61. package/src/screens/Automate/EditActionsList/__tests__/UpdateEmailScript.test.js +81 -0
  62. package/src/screens/Automate/EditActionsList/__tests__/UpdateReceiverEmailScript.test.js +83 -0
  63. package/src/screens/Automate/EditActionsList/__tests__/index.test.js +38 -5
  64. package/src/screens/Automate/EditActionsList/index.js +59 -2
  65. package/src/screens/Automate/ScriptDetail/Components/AddActionScript.js +20 -0
  66. package/src/screens/Automate/ScriptDetail/Styles/indexStyles.js +5 -3
  67. package/src/screens/Automate/ScriptDetail/__test__/index.test.js +127 -21
  68. package/src/screens/Automate/ScriptDetail/index.js +57 -14
  69. package/src/screens/Device/__test__/sensorDisplayItem.test.js +22 -0
  70. package/src/screens/Device/components/SensorDisplayItem.js +10 -0
  71. package/src/screens/SharedUnit/index.js +2 -2
  72. package/src/screens/Sharing/SelectUser.js +47 -47
  73. package/src/screens/Sharing/__test__/SelectUser.test.js +57 -103
  74. package/src/screens/SubUnit/ManageSubUnit.js +94 -90
  75. package/src/screens/SubUnit/ManageSubUnitStyles.js +4 -6
  76. package/src/screens/SubUnit/RearrageSubUnit.js +90 -0
  77. package/src/screens/SubUnit/RearrrageSubUnitStyle.js +65 -0
  78. package/src/screens/SubUnit/__test__/ManageSubUnit.test.js +35 -19
  79. package/src/screens/SubUnit/__test__/RearrangeSubUnit.test.js +129 -0
  80. package/src/screens/SubUnit/hooks/__test__/useManageSubUnit.test.js +6 -7
  81. package/src/screens/SubUnit/hooks/useManageSubUnit.js +8 -16
  82. package/src/screens/Unit/Detail.js +2 -6
  83. package/src/screens/Unit/ManageUnit.js +1 -1
  84. package/src/utils/Functions/__test__/ShortEmail.test.js +5 -0
  85. package/src/utils/I18n/translations/en.js +46 -8
  86. package/src/utils/I18n/translations/vi.js +37 -4
  87. package/src/utils/Route/index.js +7 -0
  88. package/src/commons/Auth/__test__/AccountItem.test.js +0 -31
  89. package/src/hooks/Common/useBlockBackAndroid.js +0 -21
  90. package/src/screens/SubUnit/DetailStyles.js +0 -46
@@ -0,0 +1,90 @@
1
+ import React, { useState } from 'react';
2
+ import { View, TouchableOpacity } from 'react-native';
3
+ import { isEqual } from 'lodash';
4
+ import { API } from '../../configs';
5
+ import { axiosPost } from '../../utils/Apis/axios';
6
+ import styles from './RearrrageSubUnitStyle';
7
+ import Text from '../../commons/Text';
8
+ import FlatListDnD from '../../commons/FlatListDnD';
9
+ import ViewButtonBottom from '../../commons/ViewButtonBottom';
10
+ import { HeaderCustom } from '../../commons/Header';
11
+ import Rearrange from '../../../assets/images/Rearrange.svg';
12
+ import { ToastBottomHelper } from '../../utils/Utils';
13
+ import { useNavigation } from '@react-navigation/native';
14
+ import { useTranslations } from '../../hooks/Common/useTranslations';
15
+
16
+ const RearrangeSubUnit = ({ route }) => {
17
+ const { stations, unit } = route.params;
18
+ const t = useTranslations();
19
+ const { goBack } = useNavigation();
20
+ const [reorderItems, setReorderItems] = useState(stations);
21
+ const handleOnSave = async () => {
22
+ const idOrderSubUnits = reorderItems.map((i) => i.id);
23
+ const { success } = await axiosPost(API.SUB_UNIT.ORDER_SUB_UNITS(unit.id), {
24
+ id_order_sub_units: idOrderSubUnits,
25
+ });
26
+ if (success) {
27
+ ToastBottomHelper.success(t('updated_sub_unit_order'));
28
+ goBack();
29
+ }
30
+ };
31
+
32
+ const renderItem = ({ item, getIndex, drag, isActive }) => {
33
+ const index = getIndex() + 1;
34
+ return (
35
+ <View style={styles.itemWrapper}>
36
+ <TouchableOpacity
37
+ style={[
38
+ styles.border,
39
+ styles.indexWrapper,
40
+ /* istanbul ignore next */
41
+ isActive && styles.isDragging,
42
+ ]}
43
+ onPressIn={drag}
44
+ >
45
+ <Text style={styles.indexText}>{`${index}`.padStart(2, '0')}</Text>
46
+ <Rearrange />
47
+ </TouchableOpacity>
48
+ <View
49
+ style={[
50
+ styles.border,
51
+ styles.subUnitWrapper,
52
+ /* istanbul ignore next */
53
+ isActive && styles.isDragging,
54
+ ]}
55
+ >
56
+ <Text style={styles.indexText}>{item.name}</Text>
57
+ <Text style={styles.deviceText}>
58
+ {`${item.devices.length} ${t('devices').toLowerCase()}`}
59
+ </Text>
60
+ </View>
61
+ </View>
62
+ );
63
+ };
64
+
65
+ return (
66
+ <View style={styles.container}>
67
+ <HeaderCustom title={t('rearrange_sub_unit')} isShowSeparator />
68
+ <Text style={styles.hintText}>{t('rearrange_sub_unit_hint')}</Text>
69
+ <View style={styles.flatList}>
70
+ <FlatListDnD
71
+ data={reorderItems}
72
+ extraData={reorderItems}
73
+ setData={setReorderItems}
74
+ renderItem={renderItem}
75
+ />
76
+ </View>
77
+ <ViewButtonBottom
78
+ leftTitle={t('cancel')}
79
+ onLeftClick={() => goBack()}
80
+ rightTitle={t('save')}
81
+ rightDisabled={isEqual(stations, reorderItems)}
82
+ onRightClick={handleOnSave}
83
+ isPreventDoubleTouch
84
+ wrapStyle={styles.bottomButtonWrapper}
85
+ />
86
+ </View>
87
+ );
88
+ };
89
+
90
+ export default RearrangeSubUnit;
@@ -0,0 +1,65 @@
1
+ import { Colors } from '../../configs';
2
+ import { StyleSheet } from 'react-native';
3
+
4
+ export default StyleSheet.create({
5
+ container: {
6
+ flex: 1,
7
+ backgroundColor: Colors.White,
8
+ },
9
+ border: {
10
+ borderRadius: 5,
11
+ borderColor: Colors.Gray6,
12
+ borderWidth: 1,
13
+ padding: 20,
14
+ backgroundColor: Colors.White,
15
+ shadowColor: Colors.Black,
16
+ shadowOffset: {
17
+ width: 0,
18
+ height: 10,
19
+ },
20
+ shadowOpacity: 0.23,
21
+ shadowRadius: 11.27,
22
+ elevation: 4,
23
+ },
24
+ flatList: {
25
+ flex: 0.95,
26
+ marginBottom: 10,
27
+ },
28
+ isDragging: {
29
+ borderBottomWidth: 1,
30
+ borderColor: Colors.Red,
31
+ },
32
+ itemWrapper: {
33
+ flexDirection: 'row',
34
+ marginBottom: 20,
35
+ marginHorizontal: 16,
36
+ backgroundColor: Colors.White,
37
+ },
38
+ indexWrapper: {
39
+ flexDirection: 'column',
40
+ justifyContent: 'center',
41
+ alignItems: 'center',
42
+ },
43
+ subUnitWrapper: {
44
+ flex: 1,
45
+ marginLeft: 10,
46
+ justifyContent: 'center',
47
+ },
48
+ hintText: {
49
+ marginHorizontal: 16,
50
+ marginTop: 10,
51
+ },
52
+ indexText: {
53
+ fontSize: 16,
54
+ lineHeight: 24,
55
+ fontWeight: 'bold',
56
+ },
57
+ deviceText: {
58
+ fontSize: 14,
59
+ lineHeight: 20,
60
+ color: Colors.Gray7,
61
+ },
62
+ bottomButtonWrapper: {
63
+ backgroundColor: Colors.White,
64
+ },
65
+ });
@@ -22,26 +22,29 @@ const wrapComponent = (route) => (
22
22
  );
23
23
 
24
24
  describe('Test ManageSubUnit', () => {
25
- let tree;
25
+ let tree, route, data;
26
26
  const mockedNavigate = useNavigation().navigate;
27
27
 
28
+ beforeEach(() => {
29
+ route = {
30
+ params: { unit: { id: 1, name: 'unit 1' } },
31
+ };
32
+ data = [{ id: 1, name: 'station', devices: [{ id: 1, name: 'device' }] }];
33
+ });
34
+
28
35
  afterEach(() => {
29
36
  mockedNavigate.mockClear();
30
37
  mock.reset();
31
38
  });
32
39
 
33
40
  it('render ManageSubUnit', async () => {
34
- let route = {
35
- params: { unit: { id: 1, name: 'unit 1' } },
36
- };
37
- const data = [{ id: 1, name: 'sensor' }];
38
41
  mock.onGet(API.UNIT.UNIT_DETAIL(1)).reply(200, { stations: data });
39
42
  await act(async () => {
40
43
  tree = await create(wrapComponent(route));
41
44
  });
42
45
  const instance = tree.root;
43
46
  const subUnitScrollViews = instance.findAllByType(ScrollView);
44
- expect(subUnitScrollViews).toHaveLength(2);
47
+ expect(subUnitScrollViews).toHaveLength(1);
45
48
  const rowItem = instance.findAllByType(RowItem);
46
49
  expect(rowItem).toHaveLength(1);
47
50
  await act(async () => {
@@ -49,19 +52,13 @@ describe('Test ManageSubUnit', () => {
49
52
  });
50
53
  expect(global.mockedNavigate).toHaveBeenCalledWith(Routes.UnitStack, {
51
54
  params: {
52
- station: { id: 1, name: 'sensor' },
53
- unit: {
54
- id: 1,
55
- name: 'unit 1',
56
- },
55
+ station: data[0],
56
+ unit: route.params.unit,
57
57
  },
58
- screen: 'EditSubUnit',
58
+ screen: Routes.EditSubUnit,
59
59
  });
60
60
  });
61
61
  it('ManageSubUnit add sub unit', async () => {
62
- let route = {
63
- params: { unit: { id: 1, name: 'unit 1' } },
64
- };
65
62
  await act(async () => {
66
63
  tree = await create(wrapComponent(route));
67
64
  });
@@ -76,12 +73,31 @@ describe('Test ManageSubUnit', () => {
76
73
  });
77
74
  expect(global.mockedNavigate).toHaveBeenCalledWith(Routes.AddSubUnitStack, {
78
75
  params: {
79
- unit: {
80
- id: 1,
81
- name: 'unit 1',
82
- },
76
+ unit: route.params.unit,
83
77
  },
84
78
  screen: Routes.AddSubUnit,
85
79
  });
86
80
  });
81
+ it('ManageSubUnit rearrange sub unit', async () => {
82
+ mock.onGet(API.UNIT.UNIT_DETAIL(1)).reply(200, { stations: data });
83
+ await act(async () => {
84
+ tree = await create(wrapComponent(route));
85
+ });
86
+ const instance = tree.root;
87
+ const buttonRearrangeSubUnit = instance.find(
88
+ (el) =>
89
+ el.props.accessibilityLabel === AccessibilityLabel.REARRANGE_SUB_UNIT &&
90
+ el.type === TouchableOpacity
91
+ );
92
+ await act(async () => {
93
+ buttonRearrangeSubUnit.props.onPress();
94
+ });
95
+ expect(global.mockedNavigate).toHaveBeenCalledWith(Routes.UnitStack, {
96
+ params: {
97
+ unit: route.params.unit,
98
+ stations: data,
99
+ },
100
+ screen: Routes.RearrangeSubUnit,
101
+ });
102
+ });
87
103
  });
@@ -0,0 +1,129 @@
1
+ import React from 'react';
2
+ import { create } from 'react-test-renderer';
3
+ import { act } from '@testing-library/react-hooks';
4
+ import { API } from '../../../configs';
5
+ import { ViewButtonBottom } from '../../../commons';
6
+ import { SCProvider } from '../../../context';
7
+ import { mockSCStore } from '../../../context/mockStore';
8
+ import api from '../../../utils/Apis/axios';
9
+ import RearrageSubUnit from '../RearrageSubUnit';
10
+ import MockAdapter from 'axios-mock-adapter';
11
+ import { useNavigation } from '@react-navigation/native';
12
+ import { ToastBottomHelper } from '../../../utils/Utils';
13
+ import DraggableFlatList from 'react-native-draggable-flatlist';
14
+
15
+ const mock = new MockAdapter(api.axiosInstance);
16
+
17
+ const wrapComponent = (route) => (
18
+ <SCProvider initState={mockSCStore({})}>
19
+ <RearrageSubUnit route={route} />
20
+ </SCProvider>
21
+ );
22
+
23
+ describe('Test RearrangeSubUnit', () => {
24
+ let tree, route;
25
+ const mockGoBack = useNavigation().goBack;
26
+
27
+ beforeEach(() => {
28
+ route = {
29
+ params: {
30
+ unit: { id: 1, name: 'unit 1' },
31
+ stations: [
32
+ { id: 1, name: 'station 1', devices: [{ id: 1, name: 'device 1' }] },
33
+ { id: 2, name: 'station 2', devices: [{ id: 1, name: 'device 2' }] },
34
+ ],
35
+ },
36
+ };
37
+ });
38
+ afterEach(() => {
39
+ mockGoBack.mockClear();
40
+ mock.reset();
41
+ });
42
+
43
+ it('test render RearrageSubUnit', async () => {
44
+ await act(async () => {
45
+ tree = await create(wrapComponent(route));
46
+ });
47
+
48
+ const spyToastSuccess = jest.spyOn(ToastBottomHelper, 'success');
49
+ mock.onPost(API.SUB_UNIT.ORDER_SUB_UNITS(1)).reply(200);
50
+
51
+ const instance = tree.root;
52
+ const flatListDnD = instance.findByType(DraggableFlatList);
53
+ const viewButtonBottom = instance.findByType(ViewButtonBottom);
54
+
55
+ expect(flatListDnD.props.data).toEqual(route.params.stations);
56
+
57
+ const swappedStations = [
58
+ { id: 2, name: 'station 2', devices: [{ id: 1, name: 'device 2' }] },
59
+ { id: 1, name: 'station 1', devices: [{ id: 1, name: 'device 1' }] },
60
+ ];
61
+
62
+ await act(async () => {
63
+ flatListDnD.props.onDragEnd({ data: swappedStations });
64
+ });
65
+
66
+ await act(async () => {
67
+ viewButtonBottom.props.onRightClick();
68
+ });
69
+
70
+ expect(mock.history.post).toHaveLength(1);
71
+ expect(mock.history.post[0].data).toEqual(
72
+ JSON.stringify({ id_order_sub_units: [2, 1] })
73
+ );
74
+ expect(spyToastSuccess).toHaveBeenCalledTimes(1);
75
+ expect(mockGoBack).toHaveBeenCalled();
76
+ expect(flatListDnD.props.data).toEqual(swappedStations);
77
+ });
78
+ it('test click cancel and save button is disabled', async () => {
79
+ await act(async () => {
80
+ tree = await create(wrapComponent(route));
81
+ });
82
+
83
+ const instance = tree.root;
84
+ const viewButtonBottom = instance.findByType(ViewButtonBottom);
85
+
86
+ expect(viewButtonBottom.props.rightDisabled).toEqual(true);
87
+ await act(async () => {
88
+ viewButtonBottom.props.onLeftClick();
89
+ });
90
+
91
+ expect(mockGoBack).toHaveBeenCalled();
92
+ expect(mock.history.post).toHaveLength(0);
93
+ });
94
+
95
+ it('test call api error', async () => {
96
+ await act(async () => {
97
+ tree = await create(wrapComponent(route));
98
+ });
99
+ const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
100
+ mock.onPost(API.SUB_UNIT.ORDER_SUB_UNITS(1)).reply(400);
101
+
102
+ const instance = tree.root;
103
+ const flatListDnD = instance.findByType(DraggableFlatList);
104
+ const viewButtonBottom = instance.findByType(ViewButtonBottom);
105
+
106
+ expect(flatListDnD.props.data).toEqual(route.params.stations);
107
+
108
+ const swappedStations = [
109
+ { id: 2, name: 'station 2', devices: [{ id: 1, name: 'device 2' }] },
110
+ { id: 1, name: 'station 1', devices: [{ id: 1, name: 'device 1' }] },
111
+ ];
112
+
113
+ await act(async () => {
114
+ flatListDnD.props.onDragEnd({ data: swappedStations });
115
+ });
116
+
117
+ await act(async () => {
118
+ viewButtonBottom.props.onRightClick();
119
+ });
120
+
121
+ expect(mock.history.post).toHaveLength(1);
122
+ expect(mock.history.post[0].data).toEqual(
123
+ JSON.stringify({ id_order_sub_units: [2, 1] })
124
+ );
125
+ expect(spyToastError).toHaveBeenCalledTimes(1);
126
+ expect(mockGoBack).toHaveBeenCalledTimes(0);
127
+ expect(flatListDnD.props.data).toEqual(swappedStations);
128
+ });
129
+ });
@@ -10,14 +10,13 @@ describe('Test Manage Access', () => {
10
10
  const unit = { id: 1, name: 'unit name' };
11
11
 
12
12
  it('Test init', async () => {
13
- const { result } = renderHook(() => useManageSubUnit(unit));
13
+ const { result } = renderHook(() => useManageSubUnit(unit.id));
14
14
  expect(result.current.stations).toEqual([]);
15
- expect(result.current.isLoading).toBeFalsy();
16
- expect(result.current.isRefreshing).toBeFalsy();
15
+ expect(result.current.refreshing).toBeFalsy();
17
16
  });
18
17
 
19
18
  it('Test onRefresh', async () => {
20
- const { result } = renderHook(() => useManageSubUnit(unit));
19
+ const { result } = renderHook(() => useManageSubUnit(unit.id));
21
20
  mock.onGet(API.UNIT.UNIT_DETAIL(unit?.id)).reply(200, [
22
21
  {
23
22
  id: 1,
@@ -55,15 +54,15 @@ describe('Test Manage Access', () => {
55
54
  await act(async () => {
56
55
  result.current.onRefresh();
57
56
  });
58
- expect(result.current.isRefreshing).toBeFalsy();
57
+ expect(result.current.refreshing).toBeFalsy();
59
58
  });
60
59
 
61
60
  it('Test get unit failure', async () => {
62
- const { result } = renderHook(() => useManageSubUnit(unit));
61
+ const { result } = renderHook(() => useManageSubUnit(unit.id));
63
62
  mock.onGet(API.UNIT.UNIT_DETAIL(unit?.id)).reply(400);
64
63
  await act(async () => {
65
64
  result.current.onRefresh();
66
65
  });
67
- expect(result.current.isRefreshing).toBeFalsy();
66
+ expect(result.current.refreshing).toBeFalsy();
68
67
  });
69
68
  });
@@ -2,34 +2,26 @@ import { useCallback, useState } from 'react';
2
2
  import { axiosGet } from '../../../utils/Apis/axios';
3
3
  import API from '../../../configs/API';
4
4
 
5
- export default (unit) => {
5
+ export default (unit_id) => {
6
6
  const [stations, setStations] = useState([]);
7
- const [isLoading, setIsLoading] = useState(false);
8
- const [isRefresh, setRefresh] = useState(false);
7
+ const [refreshing, setRefreshing] = useState(false);
9
8
 
10
9
  const fetchData = useCallback(async () => {
11
- setIsLoading(true);
10
+ setRefreshing(true);
12
11
  const { success, data } = await axiosGet(
13
- API.UNIT.UNIT_DETAIL(unit?.id),
12
+ API.UNIT.UNIT_DETAIL(unit_id),
14
13
  {},
15
14
  true
16
15
  );
17
16
  if (success) {
18
17
  setStations(data?.stations);
19
18
  }
20
- setIsLoading(false);
21
- }, [unit]);
22
-
23
- const onRefresh = useCallback(async () => {
24
- setRefresh(true);
25
- await fetchData();
26
- setRefresh(false);
27
- }, [fetchData]);
19
+ setRefreshing(false);
20
+ }, [unit_id]);
28
21
 
29
22
  return {
30
23
  stations,
31
- isRefresh,
32
- onRefresh,
33
- isLoading,
24
+ refreshing,
25
+ onRefresh: fetchData,
34
26
  };
35
27
  };
@@ -14,11 +14,7 @@ import Summaries from './Summaries';
14
14
 
15
15
  import Text from '../../commons/Text';
16
16
  import { API } from '../../configs';
17
- import {
18
- useBlockBackAndroid,
19
- useBoolean,
20
- useIsOwnerOfUnit,
21
- } from '../../hooks/Common';
17
+ import { useBlockBack, useBoolean, useIsOwnerOfUnit } from '../../hooks/Common';
22
18
  import { useFavorites } from './hook/useFavorites';
23
19
  import { useUnitConnectRemoteDevices } from './hook/useUnitConnectRemoteDevices';
24
20
  import { useValueEvaluations } from '../../hooks/IoT';
@@ -209,7 +205,7 @@ const UnitDetail = ({ route }) => {
209
205
  [navigate]
210
206
  );
211
207
 
212
- useBlockBackAndroid(
208
+ useBlockBack(
213
209
  isSuccessfullyConnected ? RouterHardware(Routes.Dashboard) : goBack
214
210
  );
215
211
  const user = useSCContextSelector((state) => state?.auth?.account?.user);
@@ -193,7 +193,7 @@ const ManageUnit = ({ route }) => {
193
193
  <ButtonWrapper
194
194
  onPress={goToManageSubUnit}
195
195
  title={t('manage_sub_units')}
196
- value={`${SensorNumbers} sub-units`}
196
+ value={`${SensorNumbers} ${t('sub_units').toLowerCase()}`}
197
197
  accessibilityLabel={
198
198
  AccessibilityLabel.MANAGE_UNIT_GO_TO_SUBUNIT
199
199
  }
@@ -4,3 +4,8 @@ it('Test shortEmailName function', async () => {
4
4
  const data = shortEmailName('emailExample@gmail.com');
5
5
  expect(data).toEqual('emailExample');
6
6
  });
7
+
8
+ it('Test email null', async () => {
9
+ const data = shortEmailName(null);
10
+ expect(data).toEqual('');
11
+ });
@@ -13,6 +13,7 @@ export default {
13
13
  'Please note that your personal data including records of your control of the connected devices and services ' +
14
14
  'will be shared with other members in the same unit.',
15
15
  add_user_invitation_sent: 'Invitation sent',
16
+ check: 'Check',
16
17
  cancel: 'Cancel',
17
18
  max_value: 'Max value',
18
19
  text_password: 'Password',
@@ -51,6 +52,7 @@ export default {
51
52
  text_all_locations: 'All locations',
52
53
  text_starred: 'Starred',
53
54
  text_new_unit: 'New Unit',
55
+ text_unit: 'Unit',
54
56
  text_good_morning: 'Good morning, {0}',
55
57
  text_good_afternoon: 'Good afternoon, {0}',
56
58
  text_good_evening: 'Good evening, {0}',
@@ -79,7 +81,7 @@ export default {
79
81
  text_visibility: 'Visibility',
80
82
  text_air_quality: 'Air Quality',
81
83
  sub_units: 'Sub-units',
82
- text_no_sub_unit_yet: "No sub-units yet. Tap '+’ to add new sub-units.",
84
+ text_no_sub_unit_yet: "No Sub-Units yet. Tap '+’ to add new sub-units.",
83
85
  text_no_units: 'No units',
84
86
  text_last_7_days: 'Last 7 days',
85
87
  text_average: 'Average',
@@ -411,8 +413,8 @@ export default {
411
413
  choose_on_map: 'Choose on map',
412
414
  plan_and_zoom_to_adjust: 'Plan and zoom to adjust',
413
415
  add_remote_control: 'Add remote control',
414
- manage_sub_unit: 'Manage sub-unit',
415
- remove_sub_unit: 'Remove sub-unit',
416
+ manage_sub_unit: 'Manage Sub-Unit',
417
+ remove_sub_unit: 'Remove Sub-Unit',
416
418
  text_ble_is_powered_on: 'Bluetooth is powered on',
417
419
  current_wind_speed: 'Current Wind Speed',
418
420
  history: 'History',
@@ -725,6 +727,13 @@ export default {
725
727
  title_notification: 'Subject: “Warning”',
726
728
  update_title_notification: 'Update title',
727
729
  update_message_notification: 'Update warning content',
730
+ email_content: 'E-mail content',
731
+ email_to: 'E-mail to',
732
+ subject: 'Subject',
733
+ message: 'Message...',
734
+ no_email: 'No email address',
735
+ update_title_email: 'Update title',
736
+ update_message_email: 'Update warning content',
728
737
  update_action: 'Update action',
729
738
  updated_action_order: 'Updated action order',
730
739
  message_notification:
@@ -978,7 +987,7 @@ export default {
978
987
  alert_send_error: 'Send alert fail!',
979
988
  unit_name: 'Unit name',
980
989
  location: 'Location',
981
- manage_sub_units: 'Manage Sub-units',
990
+ manage_sub_units: 'Manage Sub-Unit',
982
991
  unit_wallpaper: 'Unit Wallpaper',
983
992
  tap_to_change: 'Tap to change',
984
993
  choose_location: 'Choose location',
@@ -1041,7 +1050,7 @@ export default {
1041
1050
  rename_automate: 'Rename automate',
1042
1051
  edit_sub_unit: 'Edit Sub-unit',
1043
1052
  no_sub_unit_yet: 'No sub-unit yet.',
1044
- 'tap_+_to_add_new_sub_unit': 'Tap + to add new sub-unit.',
1053
+ 'tap_+_to_add_new_sub_unit': 'Tap + to add new Sub-Unit.',
1045
1054
  go_to_automate_scripts: 'Go to automate scripts',
1046
1055
  Script: 'Script',
1047
1056
  'One-Tap': 'One-Tap',
@@ -1065,6 +1074,7 @@ export default {
1065
1074
  send_email: 'Send e-mail',
1066
1075
  send_app_notification: 'Send app notification',
1067
1076
  delay_the_action: 'Delay the action',
1077
+ email_the_action: 'Send e-mail',
1068
1078
  wait: 'Wait',
1069
1079
  set_timeout_seconds: 'Set timeout (seconds)',
1070
1080
  update_waiting_time: 'Update waiting time (seconds)',
@@ -1160,11 +1170,32 @@ export default {
1160
1170
  connecting: 'Connecting',
1161
1171
  connect_device: 'Connect Device',
1162
1172
  connect: 'Connect',
1173
+ failed: 'Failed',
1174
+ other: 'Other',
1163
1175
  server_error: 'Server Error',
1164
1176
  add_gateway_success: 'Add gateway success',
1177
+ change_wifi: 'Change Wi-Fi',
1178
+ change_wifi_success: 'Change Wi-Fi success',
1179
+ change_wifi_failed: 'Change Wi-Fi failed',
1180
+ gateway_need_to_be_connected:
1181
+ 'Gateway needs to be connected to make Wi-Fi changes',
1165
1182
  set_network: 'Set network',
1166
- select_wifi: 'Select your wifi network',
1167
- enter_wifi_password: 'Enter wifi password',
1183
+ select_wifi: 'Select your Wi-Fi network',
1184
+ enter_wifi_password: 'Enter Wi-Fi password',
1185
+ enter_wifi_name_password: 'Enter Wi-Fi name and password',
1186
+ connect_wifi: 'Connect Wi-Fi',
1187
+ connect_to_wifi: 'Connect to Wi-Fi',
1188
+ please_enter_wifi_name: 'Please enter Wi-Fi name',
1189
+ please_enter_wifi_password: 'Please enter Wi-Fi password',
1190
+ password_must_be_at_least_8_characters:
1191
+ 'Password must be at least 8 characters',
1192
+ connection_timeout: 'Connection timeout',
1193
+ you_have_successfully_connected_wifi:
1194
+ 'You have successfully connected to the Wi-Fi name (SSID)',
1195
+ device_scaned: 'Device scaned',
1196
+ select_device_and_connect: 'Select a device and press connect',
1197
+ error_sending_data_to_local_device:
1198
+ 'Error sending data to local device. Please try again.',
1168
1199
  gateway_warning_content_1: 'To bring you good experiences, ',
1169
1200
  gateway_warning_content_2: 'your device needs a permanent wifi connection.',
1170
1201
  gateway_warning_content_3:
@@ -1302,6 +1333,8 @@ export default {
1302
1333
  zigbee: 'Zigbee',
1303
1334
  device_connect_remotely_to_the_gateway:
1304
1335
  'Device connected remotely to the gateway',
1336
+ scan: 'Scan',
1337
+ device_connected_to_local_network: 'Device connected to the local network',
1305
1338
  connect_wifi_asking:
1306
1339
  "By continuing, {appName} needs to connect to the device's Wifi. A message will appear asking you to connect.",
1307
1340
  previous: 'Previous',
@@ -1348,6 +1381,7 @@ export default {
1348
1381
  connection_methods: 'Connection methods',
1349
1382
  delete_gateway: 'Delete gateway',
1350
1383
  connection_time: 'Connection time',
1384
+ board: 'Board',
1351
1385
  device_id: 'Device id',
1352
1386
  auth_token: 'Auth token',
1353
1387
  activate_date: 'Activate date',
@@ -1486,7 +1520,11 @@ export default {
1486
1520
  uri_invalid: 'URI invalid',
1487
1521
  when_value_is: 'Activates when "{config_name}" value is',
1488
1522
  template_not_supported: 'Widget "{template}" not yet supported',
1489
- invited_user: 'Invited user {user}',
1523
+ invited_user: 'Invited user',
1490
1524
  enter_value: 'Enter value',
1491
1525
  enter_parameters: 'Enter parameters',
1526
+ rearrange_sub_unit_hint:
1527
+ 'Press and hold the number and drag to rearrange the order of the Sub-Units',
1528
+ rearrange_sub_unit: 'Rearrange Sub-Unit',
1529
+ updated_sub_unit_order: 'Updated Sub-Units order successfully!',
1492
1530
  };