@eohjsc/react-native-smart-city 0.3.33 → 0.3.36
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.
- package/assets/images/AddNewDevice/add-gateway-icon.svg +13 -0
- package/assets/images/AddNewDevice/add-modbus-device-icon.svg +8 -0
- package/assets/images/AddNewDevice/add-wifi-device-icon.svg +4 -0
- package/assets/images/AddNewDevice/add-zigbee-device-icon.svg +4 -0
- package/assets/images/AddNewDevice/interact-smartphone-icon.svg +14 -0
- package/assets/images/AddNewDevice/on-icon.svg +5 -0
- package/assets/images/AddNewDevice/router-connect-icon.svg +3 -0
- package/index.js +2 -0
- package/package.json +2 -1
- package/src/Images/SmartAccount/DienQuang.png +0 -0
- package/src/Images/SmartAccount/DienQuang@2x.png +0 -0
- package/src/Images/SmartAccount/DienQuang@3x.png +0 -0
- package/src/Images/SmartAccount/LG.png +0 -0
- package/src/Images/SmartAccount/LG@2x.png +0 -0
- package/src/Images/SmartAccount/LG@3x.png +0 -0
- package/src/Images/SmartAccount/Samsung.png +0 -0
- package/src/Images/SmartAccount/Samsung@2x.png +0 -0
- package/src/Images/SmartAccount/Samsung@3x.png +0 -0
- package/src/commons/Device/HorizontalBarChart.js +2 -6
- package/src/commons/SelectSubUnit/index.js +18 -18
- package/src/commons/SelectSubUnit/styles.js +0 -3
- package/src/commons/SelectUnit/index.js +2 -3
- package/src/commons/SelectUnit/styles.js +1 -2
- package/src/configs/API.js +10 -0
- package/src/configs/AccessibilityLabel.js +18 -0
- package/src/configs/Constants.js +2 -0
- package/src/configs/Images.js +2 -0
- package/src/context/actionType.ts +3 -0
- package/src/context/reducer.ts +22 -0
- package/src/navigations/AddGatewayStack.js +15 -0
- package/src/navigations/SmartAccountStack.js +52 -0
- package/src/screens/AddCommon/SelectSubUnit.js +17 -13
- package/src/screens/AddCommon/SelectUnit.js +14 -7
- package/src/screens/AddCommon/__test__/SelectSubUnit.test.js +18 -11
- package/src/screens/AddCommon/__test__/SelectUnit.test.js +13 -6
- package/src/screens/AddNewAction/SetupSensor.js +6 -0
- package/src/screens/AddNewGateway/ConnectingModbusDevice.js +0 -1
- package/src/screens/AddNewGateway/ConnectingWifiGuide.js +167 -0
- package/src/screens/AddNewGateway/ConnectingWifiGuideStyles.js +58 -0
- package/src/screens/AddNewGateway/PlugAndPlay/ConnectRouterGuide.js +49 -0
- package/src/screens/AddNewGateway/PlugAndPlay/ConnectRouterGuideStyles.js +31 -0
- package/src/screens/AddNewGateway/PlugAndPlay/FirstWarning.js +0 -5
- package/src/screens/AddNewGateway/PlugAndPlay/ZigbeeDeviceConnectGuide.js +51 -0
- package/src/screens/AddNewGateway/PlugAndPlay/__test__/FirstWarning.test.js +1 -1
- package/src/screens/AddNewGateway/ScanGatewayQR.js +23 -12
- package/src/screens/AddNewGateway/ScanModbusQR.js +75 -11
- package/src/screens/AddNewGateway/ScanWifiDeviceQR.js +19 -9
- package/src/screens/AddNewGateway/SelectDeviceSubUnit.js +26 -7
- package/src/screens/AddNewGateway/SelectDeviceType.js +145 -43
- package/src/screens/AddNewGateway/SelectDeviceTypeStyles.js +51 -0
- package/src/screens/AddNewGateway/SelectDeviceUnit.js +1 -1
- package/src/screens/AddNewGateway/SelectZigbeeGateway.js +1 -1
- package/src/screens/AddNewGateway/ShareWifiPassword.js +7 -112
- package/src/screens/AddNewGateway/__test__/ConnectingWifiGuide.test.js +224 -0
- package/src/screens/AddNewGateway/__test__/ScanGatewayQR.test.js +6 -7
- package/src/screens/AddNewGateway/__test__/ScanModbusQR.test.js +4 -6
- package/src/screens/AddNewGateway/__test__/ScanWifiDeviceQR.test.js +5 -7
- package/src/screens/AddNewGateway/__test__/SelectDeviceSubUnit.test.js +2 -1
- package/src/screens/AddNewGateway/__test__/SelectDeviceType.test.js +46 -11
- package/src/screens/AddNewGateway/__test__/SelectZigbeeGateway.test.js +1 -1
- package/src/screens/AddNewGateway/__test__/ShareWifiPassword.test.js +4 -143
- package/src/screens/EditActionsList/__tests__/index.test.js +120 -0
- package/src/screens/EditActionsList/index.js +15 -5
- package/src/screens/ScanChipQR/components/InvalidQRCode/index.js +33 -0
- package/src/screens/ScanChipQR/components/QRScan/index.js +7 -5
- package/src/screens/SharedUnit/__test__/ShareUnit.test.js +25 -0
- package/src/screens/SharedUnit/index.js +2 -0
- package/src/screens/Sharing/Components/DeviceItem.js +24 -8
- package/src/screens/Sharing/SelectPermission.js +78 -62
- package/src/screens/Sharing/__test__/SelectPermission.test.js +55 -2
- package/src/screens/SmartAccount/Connecting/index.js +171 -0
- package/src/screens/SmartAccount/Connecting/style.js +50 -0
- package/src/screens/SmartAccount/ListDevice/DeviceItem.js +45 -0
- package/src/screens/SmartAccount/ListDevice/__test__/DeviceItem.test.js +34 -0
- package/src/screens/SmartAccount/ListDevice/__test__/ListDevice.test.js +139 -0
- package/src/screens/SmartAccount/ListDevice/index.js +185 -0
- package/src/screens/SmartAccount/ListDevice/styles/DeviceItemStyles.js +70 -0
- package/src/screens/SmartAccount/ListDevice/styles/index.js +85 -0
- package/src/screens/SmartAccount/SuccessfullyConnected/DeviceItem.js +37 -0
- package/src/screens/SmartAccount/SuccessfullyConnected/DeviceItemStyles.js +49 -0
- package/src/screens/SmartAccount/SuccessfullyConnected/__test__/DeviceItem.test.js +65 -0
- package/src/screens/SmartAccount/SuccessfullyConnected/__test__/SuccessfullyConnected.test.js +88 -0
- package/src/screens/SmartAccount/SuccessfullyConnected/index.js +101 -0
- package/src/screens/SmartAccount/SuccessfullyConnected/styles.js +42 -0
- package/src/screens/SmartAccount/__test__/Connecting.test.js +86 -0
- package/src/screens/SmartAccount/__test__/SmartAccount.test.js +249 -0
- package/src/screens/SmartAccount/index.js +172 -0
- package/src/screens/SmartAccount/style.js +70 -0
- package/src/screens/SyncLGDevice/__test__/AddLGDevice.test.js +37 -10
- package/src/screens/Unit/AddMenu.js +4 -5
- package/src/screens/Unit/SmartAccount.js +8 -5
- package/src/screens/Unit/__test__/SmartAccount.test.js +8 -5
- package/src/utils/I18n/translations/en.json +35 -2
- package/src/utils/I18n/translations/vi.json +36 -2
- package/src/utils/Route/index.js +6 -0
- package/src/utils/Validation.js +4 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import renderer, { act } from 'react-test-renderer';
|
|
3
|
+
import Toast from 'react-native-toast-message';
|
|
4
|
+
import { ScrollView, TouchableOpacity } from 'react-native';
|
|
5
|
+
import { SCProvider } from '../../../context';
|
|
6
|
+
import { mockSCStore } from '../../../context/mockStore';
|
|
7
|
+
import SmartAccount from '../index';
|
|
8
|
+
import AccessibilityLabel from '../../../configs/AccessibilityLabel';
|
|
9
|
+
import TextInput from '../../../commons/Form/TextInput';
|
|
10
|
+
import _TextInputPassword from '../../../commons/Form/TextInputPassword';
|
|
11
|
+
import Routes from '../../../utils/Route';
|
|
12
|
+
|
|
13
|
+
const wrapComponent = (route) => (
|
|
14
|
+
<SCProvider initState={mockSCStore({})}>
|
|
15
|
+
<SmartAccount route={route} />
|
|
16
|
+
</SCProvider>
|
|
17
|
+
);
|
|
18
|
+
const mockedNavigate = jest.fn();
|
|
19
|
+
|
|
20
|
+
jest.mock('@react-navigation/native', () => {
|
|
21
|
+
return {
|
|
22
|
+
...jest.requireActual('@react-navigation/native'),
|
|
23
|
+
useNavigation: () => ({
|
|
24
|
+
navigate: mockedNavigate,
|
|
25
|
+
}),
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe('Test SmartAccount', () => {
|
|
30
|
+
let tree;
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
mockedNavigate.mockClear();
|
|
33
|
+
});
|
|
34
|
+
test('render SmartAccount', () => {
|
|
35
|
+
const route = {
|
|
36
|
+
params: {
|
|
37
|
+
unit_id: 1,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
act(() => {
|
|
41
|
+
tree = renderer.create(wrapComponent(route));
|
|
42
|
+
});
|
|
43
|
+
const instance = tree.root;
|
|
44
|
+
const scrollView = instance.findAllByType(ScrollView);
|
|
45
|
+
const touchDienQuang = instance.findAllByType(TouchableOpacity);
|
|
46
|
+
act(async () => {
|
|
47
|
+
touchDienQuang[1].props.onPress();
|
|
48
|
+
});
|
|
49
|
+
expect(scrollView[0]).toBeDefined();
|
|
50
|
+
expect(touchDienQuang[1]).toBeDefined();
|
|
51
|
+
expect(touchDienQuang).toBeDefined();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('render login SmartAccount', () => {
|
|
55
|
+
const route = {
|
|
56
|
+
params: {
|
|
57
|
+
unit_id: 1,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
act(() => {
|
|
61
|
+
tree = renderer.create(wrapComponent(route));
|
|
62
|
+
});
|
|
63
|
+
const instance = tree.root;
|
|
64
|
+
const touchableOpacity = instance.find(
|
|
65
|
+
(el) =>
|
|
66
|
+
el.props.accessibilityLabel ===
|
|
67
|
+
AccessibilityLabel.LOGIN_SMART_ACCOUNT && el.type === TouchableOpacity
|
|
68
|
+
);
|
|
69
|
+
act(async () => {
|
|
70
|
+
touchableOpacity.props.onPress();
|
|
71
|
+
});
|
|
72
|
+
expect(touchableOpacity).toBeDefined();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test('render handle onpress save but not select supplier item ', async () => {
|
|
76
|
+
const route = {
|
|
77
|
+
params: {
|
|
78
|
+
unitId: 1,
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
await act(async () => {
|
|
82
|
+
tree = await renderer.create(wrapComponent(route));
|
|
83
|
+
});
|
|
84
|
+
const instance = tree.root;
|
|
85
|
+
const textInput = instance.find(
|
|
86
|
+
(el) =>
|
|
87
|
+
el.props.accessibilityLabel ===
|
|
88
|
+
AccessibilityLabel.ON_CHANGE_SEARCH_SMART_ACCOUNT &&
|
|
89
|
+
el.type === TextInput
|
|
90
|
+
);
|
|
91
|
+
await act(async () => {
|
|
92
|
+
await textInput.props.onChange('eoh.dienquang@gmail.com');
|
|
93
|
+
});
|
|
94
|
+
const textInputPassWord = instance.find(
|
|
95
|
+
(el) =>
|
|
96
|
+
el.props.accessibilityLabel ===
|
|
97
|
+
AccessibilityLabel.ON_CHANGE_SEARCH_PASSWORD_SMART_ACCOUNT &&
|
|
98
|
+
el.type === _TextInputPassword
|
|
99
|
+
);
|
|
100
|
+
await act(async () => {
|
|
101
|
+
await textInputPassWord.props.onChange('1234567');
|
|
102
|
+
});
|
|
103
|
+
const touchableOpacity = instance.find(
|
|
104
|
+
(el) =>
|
|
105
|
+
el.props.accessibilityLabel ===
|
|
106
|
+
AccessibilityLabel.LOGIN_SMART_ACCOUNT && el.type === TouchableOpacity
|
|
107
|
+
);
|
|
108
|
+
act(async () => {
|
|
109
|
+
await touchableOpacity.props.onPress();
|
|
110
|
+
});
|
|
111
|
+
expect(Toast.show).toBeCalledWith({
|
|
112
|
+
type: 'error',
|
|
113
|
+
position: 'bottom',
|
|
114
|
+
text1: 'Please select a supplier',
|
|
115
|
+
text2: undefined,
|
|
116
|
+
visibilityTime: 1000,
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('render handle sync item DienQuang from screen unitDetail', async () => {
|
|
121
|
+
const route = {
|
|
122
|
+
params: {
|
|
123
|
+
unitId: 1,
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
await act(async () => {
|
|
127
|
+
tree = await renderer.create(wrapComponent(route));
|
|
128
|
+
});
|
|
129
|
+
const instance = tree.root;
|
|
130
|
+
const textInput = instance.find(
|
|
131
|
+
(el) =>
|
|
132
|
+
el.props.accessibilityLabel ===
|
|
133
|
+
AccessibilityLabel.ON_CHANGE_SEARCH_SMART_ACCOUNT &&
|
|
134
|
+
el.type === TextInput
|
|
135
|
+
);
|
|
136
|
+
await act(async () => {
|
|
137
|
+
await textInput.props.onChange('eoh.dienquang@gmail.com');
|
|
138
|
+
});
|
|
139
|
+
const textInputPassWord = instance.find(
|
|
140
|
+
(el) =>
|
|
141
|
+
el.props.accessibilityLabel ===
|
|
142
|
+
AccessibilityLabel.ON_CHANGE_SEARCH_PASSWORD_SMART_ACCOUNT &&
|
|
143
|
+
el.type === _TextInputPassword
|
|
144
|
+
);
|
|
145
|
+
await act(async () => {
|
|
146
|
+
await textInputPassWord.props.onChange('1234567');
|
|
147
|
+
});
|
|
148
|
+
const touchSupplierItem = instance.findAll(
|
|
149
|
+
(el) =>
|
|
150
|
+
el.props.accessibilityLabel ===
|
|
151
|
+
AccessibilityLabel.TOUCH_SUPPLIER_ITEM && el.type === TouchableOpacity
|
|
152
|
+
);
|
|
153
|
+
act(async () => {
|
|
154
|
+
await touchSupplierItem[0].props.onPress();
|
|
155
|
+
});
|
|
156
|
+
const touchableOpacity = instance.find(
|
|
157
|
+
(el) =>
|
|
158
|
+
el.props.accessibilityLabel ===
|
|
159
|
+
AccessibilityLabel.LOGIN_SMART_ACCOUNT && el.type === TouchableOpacity
|
|
160
|
+
);
|
|
161
|
+
act(async () => {
|
|
162
|
+
await touchableOpacity.props.onPress();
|
|
163
|
+
});
|
|
164
|
+
expect(mockedNavigate).toBeCalledWith(Routes.SmartAccountConnecting, {
|
|
165
|
+
brand: 'google_home',
|
|
166
|
+
password: '1234567',
|
|
167
|
+
unit_id: 1,
|
|
168
|
+
username: 'eoh.dienquang@gmail.com',
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test('render handle sync item DienQuang from screen dashboard', async () => {
|
|
173
|
+
const route = {
|
|
174
|
+
params: {},
|
|
175
|
+
};
|
|
176
|
+
await act(async () => {
|
|
177
|
+
tree = await renderer.create(wrapComponent(route));
|
|
178
|
+
});
|
|
179
|
+
const instance = tree.root;
|
|
180
|
+
const textInput = instance.find(
|
|
181
|
+
(el) =>
|
|
182
|
+
el.props.accessibilityLabel ===
|
|
183
|
+
AccessibilityLabel.ON_CHANGE_SEARCH_SMART_ACCOUNT &&
|
|
184
|
+
el.type === TextInput
|
|
185
|
+
);
|
|
186
|
+
await act(async () => {
|
|
187
|
+
await textInput.props.onChange('eoh.dienquang@gmail.com');
|
|
188
|
+
});
|
|
189
|
+
const textInputPassWord = instance.find(
|
|
190
|
+
(el) =>
|
|
191
|
+
el.props.accessibilityLabel ===
|
|
192
|
+
AccessibilityLabel.ON_CHANGE_SEARCH_PASSWORD_SMART_ACCOUNT &&
|
|
193
|
+
el.type === _TextInputPassword
|
|
194
|
+
);
|
|
195
|
+
await act(async () => {
|
|
196
|
+
await textInputPassWord.props.onChange('1234567');
|
|
197
|
+
});
|
|
198
|
+
const touchSupplierItem = instance.findAll(
|
|
199
|
+
(el) =>
|
|
200
|
+
el.props.accessibilityLabel ===
|
|
201
|
+
AccessibilityLabel.TOUCH_SUPPLIER_ITEM && el.type === TouchableOpacity
|
|
202
|
+
);
|
|
203
|
+
act(async () => {
|
|
204
|
+
await touchSupplierItem[0].props.onPress();
|
|
205
|
+
});
|
|
206
|
+
const touchableOpacity = instance.find(
|
|
207
|
+
(el) =>
|
|
208
|
+
el.props.accessibilityLabel ===
|
|
209
|
+
AccessibilityLabel.LOGIN_SMART_ACCOUNT && el.type === TouchableOpacity
|
|
210
|
+
);
|
|
211
|
+
act(async () => {
|
|
212
|
+
await touchableOpacity.props.onPress();
|
|
213
|
+
});
|
|
214
|
+
expect(mockedNavigate).toBeCalledWith(Routes.AddDeviceStack, {
|
|
215
|
+
screen: 'AddCommonSelectUnit',
|
|
216
|
+
params: {
|
|
217
|
+
addType: 'AddHassioDevice',
|
|
218
|
+
brand: 'google_home',
|
|
219
|
+
password: '1234567',
|
|
220
|
+
username: 'eoh.dienquang@gmail.com',
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test('render handle sync Lg', () => {
|
|
226
|
+
const route = {
|
|
227
|
+
params: {
|
|
228
|
+
unit_id: 1,
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
act(() => {
|
|
232
|
+
tree = renderer.create(wrapComponent(route));
|
|
233
|
+
});
|
|
234
|
+
const instance = tree.root;
|
|
235
|
+
const touchSupplierItem = instance.findAll(
|
|
236
|
+
(el) =>
|
|
237
|
+
el.props.accessibilityLabel ===
|
|
238
|
+
AccessibilityLabel.TOUCH_SUPPLIER_ITEM && el.type === TouchableOpacity
|
|
239
|
+
);
|
|
240
|
+
act(async () => {
|
|
241
|
+
await touchSupplierItem[1].props.onPress();
|
|
242
|
+
});
|
|
243
|
+
expect(touchSupplierItem).toBeDefined();
|
|
244
|
+
expect(mockedNavigate).toBeCalledWith(Routes.Browser, {
|
|
245
|
+
// eslint-disable-next-line max-len
|
|
246
|
+
link: 'https://qt-vn.m.lgaccount.com/emp/v2/authorize?client_id=2b85aee334f046848341547894bb7c4e&redirect_uri=app://eoh/sync-lg-device&response_type=code&state=1',
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
});
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import React, { useState, useCallback, useMemo } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Image,
|
|
4
|
+
View,
|
|
5
|
+
ScrollView,
|
|
6
|
+
TouchableOpacity,
|
|
7
|
+
Keyboard,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
|
|
10
|
+
import { HeaderCustom } from '../../commons/Header';
|
|
11
|
+
import Text from '../../commons/Text';
|
|
12
|
+
import TextInput from '../../commons/Form/TextInput';
|
|
13
|
+
import _TextInputPassword from '../../commons/Form/TextInputPassword';
|
|
14
|
+
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
15
|
+
import { useNavigation } from '@react-navigation/native';
|
|
16
|
+
import { Button } from '../../commons';
|
|
17
|
+
import { isValidPhoneNumberOrEmailAddress } from '../../utils/Validation';
|
|
18
|
+
import { ToastBottomHelper } from '../../utils/Utils';
|
|
19
|
+
import Routes from '../../utils/Route';
|
|
20
|
+
import { API, Images, SCConfig, Colors } from '../../configs';
|
|
21
|
+
import AccessibilityLabel from '../../configs/AccessibilityLabel';
|
|
22
|
+
import styles from './style';
|
|
23
|
+
|
|
24
|
+
const SmartAccount = ({ route }) => {
|
|
25
|
+
const t = useTranslations();
|
|
26
|
+
const { navigate } = useNavigation();
|
|
27
|
+
const [username, setUsername] = useState('');
|
|
28
|
+
const [usernameError, setUsernameErrorState] = useState();
|
|
29
|
+
const [password, setPassword] = useState('');
|
|
30
|
+
const [passwordError, setPasswordlErrorState] = useState();
|
|
31
|
+
const [selectItemActive, setSelectItemActive] = useState(null);
|
|
32
|
+
|
|
33
|
+
const supplierItems = useMemo(() => {
|
|
34
|
+
return [
|
|
35
|
+
{
|
|
36
|
+
name: t('dien_quang_smart'),
|
|
37
|
+
logo: Images.dienquang,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: t('lg_smart'),
|
|
41
|
+
logo: Images.lg,
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
}, [t]);
|
|
45
|
+
|
|
46
|
+
const handleSyncItemDienQuang = useCallback(() => {
|
|
47
|
+
if (route?.params?.unitId) {
|
|
48
|
+
navigate(Routes.SmartAccountConnecting, {
|
|
49
|
+
username: username,
|
|
50
|
+
password: password,
|
|
51
|
+
brand: 'google_home',
|
|
52
|
+
unit_id: route?.params?.unitId,
|
|
53
|
+
});
|
|
54
|
+
} else {
|
|
55
|
+
navigate(Routes.AddDeviceStack, {
|
|
56
|
+
screen: Routes.AddCommonSelectUnit,
|
|
57
|
+
params: {
|
|
58
|
+
username: username,
|
|
59
|
+
password: password,
|
|
60
|
+
brand: 'google_home',
|
|
61
|
+
addType: 'AddHassioDevice',
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}, [navigate, password, route?.params, username]);
|
|
66
|
+
|
|
67
|
+
const validate = useCallback(() => {
|
|
68
|
+
Keyboard.dismiss();
|
|
69
|
+
let hasError = false;
|
|
70
|
+
if (!isValidPhoneNumberOrEmailAddress(username)) {
|
|
71
|
+
setUsernameErrorState(t('please_enter_your_email_or_your_phone'));
|
|
72
|
+
hasError = true;
|
|
73
|
+
} else {
|
|
74
|
+
setUsernameErrorState('');
|
|
75
|
+
}
|
|
76
|
+
if (!password) {
|
|
77
|
+
setPasswordlErrorState(t('please_enter_your_password'));
|
|
78
|
+
hasError = true;
|
|
79
|
+
} else {
|
|
80
|
+
setPasswordlErrorState('');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!hasError) {
|
|
84
|
+
if (selectItemActive !== null) {
|
|
85
|
+
selectItemActive === 0 && handleSyncItemDienQuang();
|
|
86
|
+
}
|
|
87
|
+
if (selectItemActive === null) {
|
|
88
|
+
ToastBottomHelper.error(t('please_select_a_supplier'));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}, [handleSyncItemDienQuang, password, selectItemActive, t, username]);
|
|
92
|
+
|
|
93
|
+
const handleSelectSupplier = useCallback(
|
|
94
|
+
(index) => {
|
|
95
|
+
setSelectItemActive(index);
|
|
96
|
+
if (index === 1) {
|
|
97
|
+
navigate(Routes.Browser, {
|
|
98
|
+
link: API.IOT.LG.AUTHORIZE(
|
|
99
|
+
SCConfig.LG_CLIENT_ID,
|
|
100
|
+
SCConfig.LG_REDIRECT_URI_APP
|
|
101
|
+
),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
[navigate]
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<View style={styles.container}>
|
|
110
|
+
<HeaderCustom
|
|
111
|
+
title={t('add_new_smart_account')}
|
|
112
|
+
titleStyle={styles.title}
|
|
113
|
+
/>
|
|
114
|
+
<ScrollView contentContainerStyle={styles.scroll}>
|
|
115
|
+
<Text bold type="H4" color={Colors.Gray9} style={styles.text}>
|
|
116
|
+
{t('smart_supplier')}
|
|
117
|
+
</Text>
|
|
118
|
+
<View style={styles.logocontainer}>
|
|
119
|
+
{supplierItems.map((item, index) => (
|
|
120
|
+
<TouchableOpacity
|
|
121
|
+
style={[styles.logo]}
|
|
122
|
+
onPress={() => handleSelectSupplier(index)}
|
|
123
|
+
accessibilityLabel={AccessibilityLabel.TOUCH_SUPPLIER_ITEM}
|
|
124
|
+
>
|
|
125
|
+
<View
|
|
126
|
+
style={selectItemActive === index ? styles.borderLogo : styles}
|
|
127
|
+
>
|
|
128
|
+
<Image source={item.logo} />
|
|
129
|
+
</View>
|
|
130
|
+
<Text type="H4" color={Colors.Gray9} style={styles.logoName}>
|
|
131
|
+
{item.name}
|
|
132
|
+
</Text>
|
|
133
|
+
</TouchableOpacity>
|
|
134
|
+
))}
|
|
135
|
+
</View>
|
|
136
|
+
<TextInput
|
|
137
|
+
placeholder={t('text_email_or_phone_number')}
|
|
138
|
+
onChange={(value) => setUsername(value)}
|
|
139
|
+
errorText={usernameError}
|
|
140
|
+
value={username}
|
|
141
|
+
textInputStyle={styles.textInputStyle}
|
|
142
|
+
accessibilityLabel={AccessibilityLabel.ON_CHANGE_SEARCH_SMART_ACCOUNT}
|
|
143
|
+
/>
|
|
144
|
+
<_TextInputPassword
|
|
145
|
+
secureTextEntry={true}
|
|
146
|
+
placeholder={t('enter_password')}
|
|
147
|
+
onChange={(value) => setPassword(value)}
|
|
148
|
+
value={password}
|
|
149
|
+
errorText={passwordError}
|
|
150
|
+
returnKeyType={'done'}
|
|
151
|
+
eyeColor={true}
|
|
152
|
+
textInputStyle={styles.textInputStyle}
|
|
153
|
+
wrapInputStyle={styles.borderInputStyle}
|
|
154
|
+
errorStyle={passwordError && styles.borderErrorStyle}
|
|
155
|
+
accessibilityLabel={
|
|
156
|
+
AccessibilityLabel.ON_CHANGE_SEARCH_PASSWORD_SMART_ACCOUNT
|
|
157
|
+
}
|
|
158
|
+
/>
|
|
159
|
+
</ScrollView>
|
|
160
|
+
<View style={[styles.buttonWrap]}>
|
|
161
|
+
<Button
|
|
162
|
+
type="primary"
|
|
163
|
+
title={t('save')}
|
|
164
|
+
onPress={validate}
|
|
165
|
+
accessibilityLabel={AccessibilityLabel.LOGIN_SMART_ACCOUNT}
|
|
166
|
+
/>
|
|
167
|
+
</View>
|
|
168
|
+
</View>
|
|
169
|
+
);
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
export default SmartAccount;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { Colors } from '../../configs';
|
|
3
|
+
|
|
4
|
+
const borderCommonStyle = {
|
|
5
|
+
borderColor: Colors.White,
|
|
6
|
+
borderWidth: 0,
|
|
7
|
+
borderBottomWidth: 0.8,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default StyleSheet.create({
|
|
11
|
+
container: {
|
|
12
|
+
flex: 1,
|
|
13
|
+
backgroundColor: Colors.White,
|
|
14
|
+
},
|
|
15
|
+
title: {
|
|
16
|
+
color: Colors.Gray9,
|
|
17
|
+
},
|
|
18
|
+
scroll: {
|
|
19
|
+
padding: 16,
|
|
20
|
+
paddingBottom: 60,
|
|
21
|
+
},
|
|
22
|
+
text: {
|
|
23
|
+
lineHeight: 24,
|
|
24
|
+
},
|
|
25
|
+
logocontainer: {
|
|
26
|
+
flexDirection: 'row',
|
|
27
|
+
marginVertical: 16,
|
|
28
|
+
},
|
|
29
|
+
logo: {
|
|
30
|
+
marginRight: 16,
|
|
31
|
+
},
|
|
32
|
+
touchLogo: {
|
|
33
|
+
marginRight: 16,
|
|
34
|
+
borderColor: Colors.Green7,
|
|
35
|
+
},
|
|
36
|
+
logoName: {
|
|
37
|
+
width: 74,
|
|
38
|
+
height: 44,
|
|
39
|
+
textAlign: 'center',
|
|
40
|
+
lineHeight: 22,
|
|
41
|
+
marginTop: 4,
|
|
42
|
+
},
|
|
43
|
+
textInputStyle: {
|
|
44
|
+
borderTopWidth: 0,
|
|
45
|
+
borderRightWidth: 0,
|
|
46
|
+
borderLeftWidth: 0,
|
|
47
|
+
paddingHorizontal: 0,
|
|
48
|
+
paddingLeft: 0,
|
|
49
|
+
},
|
|
50
|
+
buttonWrap: {
|
|
51
|
+
marginHorizontal: 20,
|
|
52
|
+
flexDirection: 'row',
|
|
53
|
+
marginTop: 40,
|
|
54
|
+
position: 'absolute',
|
|
55
|
+
bottom: 32,
|
|
56
|
+
},
|
|
57
|
+
borderLogo: {
|
|
58
|
+
borderColor: Colors.Primary,
|
|
59
|
+
borderWidth: 1,
|
|
60
|
+
borderRadius: 5,
|
|
61
|
+
},
|
|
62
|
+
borderInputStyle: {
|
|
63
|
+
...borderCommonStyle,
|
|
64
|
+
borderBottomColor: Colors.Gray5,
|
|
65
|
+
},
|
|
66
|
+
borderErrorStyle: {
|
|
67
|
+
...borderCommonStyle,
|
|
68
|
+
borderBottomColor: Colors.Red,
|
|
69
|
+
},
|
|
70
|
+
});
|
|
@@ -12,6 +12,8 @@ import Routes from '../../../utils/Route';
|
|
|
12
12
|
import { SCProvider } from '../../../context';
|
|
13
13
|
import { mockSCStore } from '../../../context/mockStore';
|
|
14
14
|
import api from '../../../utils/Apis/axios';
|
|
15
|
+
import Toast from 'react-native-toast-message';
|
|
16
|
+
import { SCConfig } from '../../../configs';
|
|
15
17
|
|
|
16
18
|
const mock = new MockAdapter(api.axiosInstance);
|
|
17
19
|
|
|
@@ -174,9 +176,18 @@ describe('Test Add LG Device', () => {
|
|
|
174
176
|
access_token: 'ACCESS_TOKEN',
|
|
175
177
|
},
|
|
176
178
|
};
|
|
177
|
-
mock
|
|
179
|
+
mock
|
|
180
|
+
.onPost(
|
|
181
|
+
API.IOT.LG.GET_TOKEN(
|
|
182
|
+
SCConfig.LG_CLIENT_ID,
|
|
183
|
+
'CODE',
|
|
184
|
+
SCConfig.LG_REDIRECT_URI_APP,
|
|
185
|
+
'https://doamin.com'
|
|
186
|
+
)
|
|
187
|
+
)
|
|
188
|
+
.reply(200, responseToken.data);
|
|
178
189
|
mock.onPost(API.IOT.LG.SYNC_DEVICE()).reply(200, {});
|
|
179
|
-
const spyToastSuccess = jest.spyOn(ToastBottomHelper, 'success');
|
|
190
|
+
// const spyToastSuccess = jest.spyOn(ToastBottomHelper, 'success');
|
|
180
191
|
await act(async () => {
|
|
181
192
|
tree = await create(wrapComponent(route));
|
|
182
193
|
});
|
|
@@ -190,10 +201,14 @@ describe('Test Add LG Device', () => {
|
|
|
190
201
|
await act(async () => {
|
|
191
202
|
viewButtonBottom.props.onRightClick();
|
|
192
203
|
});
|
|
193
|
-
expect(mockedNavigate).toHaveBeenCalledWith(Routes.Dashboard);
|
|
194
204
|
|
|
195
|
-
|
|
196
|
-
|
|
205
|
+
expect(Toast.show).toBeCalledWith({
|
|
206
|
+
type: 'success',
|
|
207
|
+
position: 'bottom',
|
|
208
|
+
text1: getTranslate('en', 'lg_sync_success'),
|
|
209
|
+
visibilityTime: 1000,
|
|
210
|
+
});
|
|
211
|
+
expect(mockedNavigate).toHaveBeenCalledWith(Routes.Dashboard);
|
|
197
212
|
});
|
|
198
213
|
|
|
199
214
|
test('ViewButtonBottom onRightClick with stationId but sync failed', async () => {
|
|
@@ -206,9 +221,17 @@ describe('Test Add LG Device', () => {
|
|
|
206
221
|
},
|
|
207
222
|
};
|
|
208
223
|
mock.onGet(API.UNIT.UNIT_DETAIL(1)).reply(200, response.data);
|
|
209
|
-
mock
|
|
224
|
+
mock
|
|
225
|
+
.onPost(
|
|
226
|
+
API.IOT.LG.GET_TOKEN(
|
|
227
|
+
SCConfig.LG_CLIENT_ID,
|
|
228
|
+
'CODE',
|
|
229
|
+
SCConfig.LG_REDIRECT_URI_APP,
|
|
230
|
+
'https://doamin.com'
|
|
231
|
+
)
|
|
232
|
+
)
|
|
233
|
+
.reply(200, response.data);
|
|
210
234
|
const spyToastSuccess = jest.spyOn(ToastBottomHelper, 'success');
|
|
211
|
-
const spyToastError = jest.spyOn(ToastBottomHelper, 'error');
|
|
212
235
|
|
|
213
236
|
await act(async () => {
|
|
214
237
|
tree = await create(wrapComponent(route));
|
|
@@ -224,10 +247,14 @@ describe('Test Add LG Device', () => {
|
|
|
224
247
|
viewButtonBottom.props.onRightClick();
|
|
225
248
|
});
|
|
226
249
|
expect(spyToastSuccess).not.toBeCalled();
|
|
227
|
-
|
|
250
|
+
|
|
251
|
+
expect(Toast.show).toBeCalledWith({
|
|
252
|
+
type: 'error',
|
|
253
|
+
position: 'bottom',
|
|
254
|
+
text1: getTranslate('en', 'lg_sync_failed'),
|
|
255
|
+
visibilityTime: 1000,
|
|
256
|
+
});
|
|
228
257
|
expect(mockedNavigate).toHaveBeenCalledWith(Routes.Dashboard);
|
|
229
|
-
spyToastSuccess.mockReset();
|
|
230
|
-
spyToastSuccess.mockRestore();
|
|
231
258
|
});
|
|
232
259
|
|
|
233
260
|
test('ViewButtonBottom onRightClick with stationId but get token failed, wrong data', async () => {
|
|
@@ -49,14 +49,13 @@ const AddMenu = memo(({ unit, afterItemClick, showAdd, setHideAdd }) => {
|
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
id: 'add_smart_account',
|
|
52
|
-
route: Routes.
|
|
52
|
+
route: Routes.SmartAccountStack,
|
|
53
53
|
text: t('name_smart_account'),
|
|
54
|
-
image: <SmartAccount width={43} height={43} />,
|
|
54
|
+
image: <SmartAccount width={43} height={43} />,
|
|
55
55
|
data: {
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
screen: Routes.SmartAccount,
|
|
57
|
+
params: { unitId: unit?.id, unitName: unit?.name },
|
|
58
58
|
},
|
|
59
|
-
type: Routes.SmartAccount,
|
|
60
59
|
},
|
|
61
60
|
];
|
|
62
61
|
}, [t, unit]);
|
|
@@ -94,11 +94,14 @@ const ListSmartAccount = ({ route }) => {
|
|
|
94
94
|
|
|
95
95
|
const gotoSmartAccountDetail = useCallback(
|
|
96
96
|
(item) => {
|
|
97
|
-
navigate(Routes.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
97
|
+
navigate(Routes.SmartAccountStack, {
|
|
98
|
+
screen: Routes.ListDeviceSmartAccount,
|
|
99
|
+
params: {
|
|
100
|
+
username: item.username,
|
|
101
|
+
brand: item.brand,
|
|
102
|
+
smart_account_id: item.id,
|
|
103
|
+
unit_id: unitId,
|
|
104
|
+
},
|
|
102
105
|
});
|
|
103
106
|
},
|
|
104
107
|
[navigate, unitId]
|
|
@@ -92,11 +92,14 @@ describe('Test SmartAccount', () => {
|
|
|
92
92
|
.onDelete(API.SMART_ACCOUNT.REMOVE_SMART_ACCOUNT(response.data[0].id))
|
|
93
93
|
.reply(200);
|
|
94
94
|
await alertAction[0].props.leftButtonClick();
|
|
95
|
-
expect(mockNavigate).
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
expect(mockNavigate).toHaveBeenCalledWith(Routes.SmartAccountStack, {
|
|
96
|
+
screen: Routes.ListDeviceSmartAccount,
|
|
97
|
+
params: {
|
|
98
|
+
username: response.data[0].username,
|
|
99
|
+
brand: response.data[0].brand,
|
|
100
|
+
smart_account_id: response.data[0].id,
|
|
101
|
+
unit_id: route.params.unitId,
|
|
102
|
+
},
|
|
100
103
|
});
|
|
101
104
|
const menuActionMore = instance.findByType(MenuActionMore);
|
|
102
105
|
await act(async () => {
|
|
@@ -267,7 +267,7 @@
|
|
|
267
267
|
"notify_new_version_content": "A new version of this application is available. Please update now for the best experience.",
|
|
268
268
|
"text_update": "Update",
|
|
269
269
|
"not_available": "Not available",
|
|
270
|
-
"add_new_sub_unit": "Add new
|
|
270
|
+
"add_new_sub_unit": "Add new Sub-unit",
|
|
271
271
|
"add_sub_unit_room_name": "Name your sub-unit",
|
|
272
272
|
"add_sub_unit_wallpaper": "Wallpaper",
|
|
273
273
|
"text_create_sub_unit_success": "Create new sub-unit success!",
|
|
@@ -1007,5 +1007,38 @@
|
|
|
1007
1007
|
"no_widgets": "No Widgets",
|
|
1008
1008
|
"add_your_widget": "Add your widget in dashboard template",
|
|
1009
1009
|
"label": "Label",
|
|
1010
|
-
"
|
|
1010
|
+
"choose_type_of_device": "Choose type of device",
|
|
1011
|
+
"central_controller": "Central controller",
|
|
1012
|
+
"wifi_device": "Wifi device",
|
|
1013
|
+
"device_connect_without_gateway": "Connecting device without gateway",
|
|
1014
|
+
"modbus": "Modbus",
|
|
1015
|
+
"device_connect_directly_to_the_gateway": "Device connected directly to the gateway",
|
|
1016
|
+
"zigbee": "Zigbee",
|
|
1017
|
+
"device_connect_remotely_to_the_gateway": "Device connected remotely to the gateway",
|
|
1018
|
+
"connect_wifi_asking": "By continuing, EoH needs to connect to the device's Wifi. A message will appear asking you to connect.",
|
|
1019
|
+
"previous": "Previous",
|
|
1020
|
+
"invalid_qr_code": "Invalid QR Code",
|
|
1021
|
+
"invalid_qr_code_warning": "This device can't be added using a QR code",
|
|
1022
|
+
"retry": "Retry",
|
|
1023
|
+
"hold_and_hover_description": "Hold and hover to rearrange the module",
|
|
1024
|
+
"dien_quang_smart": "Điện Quang",
|
|
1025
|
+
"add_new_smart_account": "Add new smart account",
|
|
1026
|
+
"lg_smart": "LG",
|
|
1027
|
+
"please_enter_your_email_or_your_phone": "Please enter your email or your phone",
|
|
1028
|
+
"please_select_a_supplier": "Please select a supplier",
|
|
1029
|
+
"smart_supplier": "Smart Supplier",
|
|
1030
|
+
"text_email_or_phone_number": "Email or Phone number",
|
|
1031
|
+
"connecting_smart_account": "Connecting your account",
|
|
1032
|
+
"warning_connecting_smart_account": "Don't turn off the device or close this app during the setup process. Setup may take few minutes to complete.",
|
|
1033
|
+
"unidentified": "Unidentified",
|
|
1034
|
+
"select_all": "Select All",
|
|
1035
|
+
"turn_off_device": "Turn off device",
|
|
1036
|
+
"turn_off_device_when_scan_qr_guide": "Turn off the device you want to add new before scanning the QR code. Press ‘’OK’’ to continue.",
|
|
1037
|
+
"connect_to_router": "Connect to the Router",
|
|
1038
|
+
"connect_router_content": "Please plug in the gatewayand connect it to the router, making sure your phone and the gatewayare under the same network. Then, comfirm that the light is on and press “Next”",
|
|
1039
|
+
"turn_on_zigbee_device": "Turn on zigbee device",
|
|
1040
|
+
"turn_on_device_to_connect": "Turn on device to connect",
|
|
1041
|
+
"turn_on_zigbee_device_content": "Power ON the device and keep the device connected to the router. Make sure the end device still ON",
|
|
1042
|
+
"read_device_manual_guide": "Read Device's manual guide for more details.",
|
|
1043
|
+
"click_here_to_setup_device": "Click here to setup device"
|
|
1011
1044
|
}
|