@eohjsc/react-native-smart-city 0.2.64 → 0.2.68

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 (52) hide show
  1. package/assets/images/Popover/Dashboard/SmartAccount.svg +5 -0
  2. package/assets/images/scan-qr-gateway.svg +14 -0
  3. package/assets/images/wifi-gateway.svg +18 -0
  4. package/assets/images/wifi.svg +3 -0
  5. package/package.json +3 -1
  6. package/src/commons/Action/ItemQuickAction.js +4 -3
  7. package/src/commons/Dashboard/MyPinnedSharedUnit/__test__/MyPinnedSharedUnit.test.js +70 -0
  8. package/src/commons/Device/HistoryChart.js +18 -18
  9. package/src/commons/Device/HorizontalBarChart.js +1 -2
  10. package/src/commons/Device/LinearChart.js +13 -3
  11. package/src/commons/UnitSummary/ConfigHistoryChart/__test__/ConfigHistoryChart.test.js +29 -0
  12. package/src/commons/UnitSummary/ConfigHistoryChart.js +4 -6
  13. package/src/configs/API.js +2 -0
  14. package/src/configs/BLE.js +3 -0
  15. package/src/iot/RemoteControl/Bluetooth.js +34 -6
  16. package/src/iot/RemoteControl/__test__/Bluetooth.test.js +1 -0
  17. package/src/iot/RemoteControl/__test__/index.mock.js +1 -0
  18. package/src/iot/RemoteControl/index.js +7 -2
  19. package/src/navigations/AddDeviceStack.js +2 -0
  20. package/src/navigations/AddGatewayStack.js +11 -0
  21. package/src/navigations/AddLGDeviceStack.js +2 -0
  22. package/src/navigations/AddMemberStack.js +2 -0
  23. package/src/navigations/AddSubUnitStack.js +2 -0
  24. package/src/navigations/AddUnitStack.js +2 -0
  25. package/src/navigations/EmergencyContactsStack.js +2 -0
  26. package/src/navigations/SharedStack.js +2 -0
  27. package/src/navigations/UnitStack.js +2 -0
  28. package/src/screens/AddCommon/SelectSubUnit.js +14 -1
  29. package/src/screens/AddNewGateway/PlugAndPlay/ConnectWifiWarning.js +190 -0
  30. package/src/screens/AddNewGateway/PlugAndPlay/FirstWarning.js +73 -0
  31. package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +154 -0
  32. package/src/screens/AddNewGateway/PlugAndPlay/__test__/FirstWarning.test.js +60 -0
  33. package/src/screens/AddNewGateway/PlugAndPlay/__test__/GatewayWifiList.test.js +35 -0
  34. package/src/screens/AddNewGateway/__test__/SetupGateway.test.js +90 -0
  35. package/src/screens/AllCamera/index.js +27 -5
  36. package/src/screens/Device/EditDevice/index.js +3 -3
  37. package/src/screens/Device/components/SensorDisplayItem.js +4 -2
  38. package/src/screens/ScanChipQR/hooks/index.js +14 -5
  39. package/src/screens/SubUnit/AddSubUnit.js +13 -25
  40. package/src/screens/SubUnit/__test__/AddSubUnit.test.js +2 -1
  41. package/src/screens/TDSGuide/index.js +5 -2
  42. package/src/screens/Unit/AddMenu.js +15 -0
  43. package/src/screens/Unit/Detail.js +16 -3
  44. package/src/screens/Unit/components/__test__/MyUnitDevice.test.js +10 -6
  45. package/src/screens/UnitSummary/components/PowerConsumption/index.js +2 -4
  46. package/src/screens/UnitSummary/components/RunningDevices/__test__/index.test.js +10 -6
  47. package/src/screens/WaterQualityGuide/index.js +2 -2
  48. package/src/utils/Apis/axios.js +2 -3
  49. package/src/utils/I18n/translations/en.json +25 -3
  50. package/src/utils/I18n/translations/vi.json +25 -3
  51. package/src/utils/Route/index.js +4 -0
  52. package/src/utils/Utils.js +0 -4
@@ -59,7 +59,7 @@ const AllCamera = () => {
59
59
  navigate(Routes.PlaybackCamera, { item, thumbnail });
60
60
  };
61
61
 
62
- const CameraItem = ({ item }) => {
62
+ const CameraItem = ({ item, width, height }) => {
63
63
  return (
64
64
  <View style={styles.wrap}>
65
65
  {!!item && (
@@ -74,6 +74,8 @@ const AllCamera = () => {
74
74
  amount={amount}
75
75
  handleFullScreen={handleFullScreen}
76
76
  goToPlayBack={goToPlayBack(item, thumbnail)}
77
+ width={width}
78
+ height={height}
77
79
  />
78
80
  )}
79
81
  </View>
@@ -88,12 +90,32 @@ const AllCamera = () => {
88
90
  ) : amount === 4 ? (
89
91
  <>
90
92
  <View style={styles.row}>
91
- <CameraItem key={item?.id} item={item[0]} />
92
- <CameraItem key={item?.id} item={item[1]} />
93
+ <CameraItem
94
+ key={item?.id}
95
+ item={item[0]}
96
+ width={188}
97
+ height={112}
98
+ />
99
+ <CameraItem
100
+ key={item?.id}
101
+ item={item[1]}
102
+ width={188}
103
+ height={112}
104
+ />
93
105
  </View>
94
106
  <View style={styles.row}>
95
- <CameraItem key={item?.id} item={item[2]} />
96
- <CameraItem key={item?.id} item={item[3]} />
107
+ <CameraItem
108
+ key={item?.id}
109
+ item={item[2]}
110
+ width={188}
111
+ height={112}
112
+ />
113
+ <CameraItem
114
+ key={item?.id}
115
+ item={item[3]}
116
+ width={188}
117
+ height={112}
118
+ />
97
119
  </View>
98
120
  </>
99
121
  ) : (
@@ -23,7 +23,7 @@ const EditDevice = memo(() => {
23
23
  const navigation = useNavigation();
24
24
  const { params = {} } = useRoute();
25
25
  const { sensor, setSensorNameDetail, sensorNameDetail } = params;
26
- const [inputName, setInputName] = useState('');
26
+ const [inputName, setInputName] = useState(sensorNameDetail || '');
27
27
  const [sensorName, setSensorName] = useState(sensorNameDetail || '');
28
28
  const { stateAlertAction, hideAlertAction, onShowRename, onShowDelete } =
29
29
  useEditDevice();
@@ -130,8 +130,8 @@ const EditDevice = memo(() => {
130
130
  >
131
131
  {!stateAlertAction.isDelete && (
132
132
  <_TextInput
133
- onChange={(text) => setInputName(text)}
134
- defaultValue={sensorName}
133
+ onChange={setInputName}
134
+ value={inputName}
135
135
  textInputStyle={styles.textInputStyle}
136
136
  wrapStyle={styles.textInputWrapStyle}
137
137
  selectionColor={Colors.Primary}
@@ -20,6 +20,7 @@ import FooterInfo from '../../../commons/Device/FooterInfo';
20
20
  import MediaPlayerDetail from '../../../commons/MediaPlayerDetail';
21
21
  import { standardizeCameraScreenSize } from '../../../utils/Utils';
22
22
  import { Device } from '../../../configs';
23
+ import { useSCContextSelector } from '../../../context';
23
24
 
24
25
  const { standardizeWidth, standardizeHeight } = standardizeCameraScreenSize(
25
26
  Device.screenWidth - 32
@@ -37,11 +38,12 @@ export const SensorDisplayItem = ({
37
38
  background,
38
39
  }) => {
39
40
  const t = useTranslations();
41
+ const userId = useSCContextSelector((state) => state.auth.account.user.id);
40
42
  const doAction = useCallback(
41
43
  (action, data) => {
42
- sendRemoteCommand(sensor, action, data);
44
+ sendRemoteCommand(sensor, action, data, userId);
43
45
  },
44
- [sensor]
46
+ [sensor, userId]
45
47
  );
46
48
  if (item.configuration.type === 'compass') {
47
49
  setShowWindDirection(true);
@@ -17,7 +17,7 @@ const useChipScan = (route) => {
17
17
  const { success, data: new_chip } = await axiosPost(
18
18
  API.UNIT.CHIP_SCAN(unit_id),
19
19
  {
20
- imei: imei,
20
+ imei: imei || body.imei,
21
21
  qr_code: body.imei,
22
22
  phone: phoneNumber,
23
23
  name: chipName,
@@ -27,10 +27,19 @@ const useChipScan = (route) => {
27
27
  }
28
28
  );
29
29
  if (success) {
30
- navigation.navigate(Routes.ConnectingGateway, {
31
- new_chip,
32
- ...route.params,
33
- });
30
+ if (new_chip.is_wifi) {
31
+ navigation.navigate(Routes.ConnectWifiWarning, {
32
+ wifi_ssid: new_chip.wifi_ssid,
33
+ wifi_pass: new_chip.wifi_pass,
34
+ chip_id: new_chip.id,
35
+ unit_id: unit_id,
36
+ });
37
+ } else {
38
+ navigation.navigate(Routes.ConnectingGateway, {
39
+ new_chip,
40
+ ...route.params,
41
+ });
42
+ }
34
43
  } else {
35
44
  navigation.goBack();
36
45
  }
@@ -13,7 +13,6 @@ import {
13
13
  SafeAreaView,
14
14
  } from 'react-native';
15
15
  import { useNavigation } from '@react-navigation/native';
16
- import ImageResizer from 'react-native-image-resizer';
17
16
  import { useTranslations } from '../../hooks/Common/useTranslations';
18
17
 
19
18
  import { API, Colors } from '../../configs';
@@ -26,26 +25,6 @@ import { ToastBottomHelper } from '../../utils/Utils';
26
25
  import { TESTID } from '../../configs/Constants';
27
26
  import styles from './AddSubUnitStyles';
28
27
 
29
- const MAX_FILE_SIZE_BYTES = 1.5 * 1024 * 1024; // 1.5mb
30
-
31
- const prepareImageToUpload = async (image) => {
32
- if (!image || image.size < MAX_FILE_SIZE_BYTES) {
33
- return image;
34
- }
35
- const result = await ImageResizer.createResizedImage(
36
- image.path,
37
- 1280,
38
- 1280,
39
- 'JPEG',
40
- 70
41
- );
42
- return {
43
- fileName: result?.name,
44
- type: 'image/jpeg',
45
- uri: result?.uri,
46
- };
47
- };
48
-
49
28
  const AddSubUnit = ({ route }) => {
50
29
  const t = useTranslations();
51
30
  const { navigate, goBack } = useNavigation();
@@ -56,6 +35,13 @@ const AddSubUnit = ({ route }) => {
56
35
  const [showImagePicker, setShowImagePicker] = useState(false);
57
36
  let awaitCreate = useRef(false);
58
37
 
38
+ const cleanData = () => {
39
+ setRoomName('');
40
+ setWallpaper('');
41
+ setImageUrl('');
42
+ awaitCreate.current = false;
43
+ };
44
+
59
45
  const goDone = useCallback(async () => {
60
46
  if (isAddUnit) {
61
47
  if (!awaitCreate.current) {
@@ -65,7 +51,6 @@ const AddSubUnit = ({ route }) => {
65
51
  address: location,
66
52
  background: wallpaper,
67
53
  };
68
- dataObj.background = await prepareImageToUpload(dataObj.background);
69
54
  const formData = createFormData(dataObj, ['background']);
70
55
  const { success, data } = await axiosPost(
71
56
  API.UNIT.CREATE_UNIT(),
@@ -82,6 +67,7 @@ const AddSubUnit = ({ route }) => {
82
67
  routeName: Routes.DashboardStack,
83
68
  },
84
69
  });
70
+ cleanData();
85
71
  } else {
86
72
  awaitCreate.current = false;
87
73
  ToastBottomHelper.error(t('text_create_unit_fail'));
@@ -91,9 +77,8 @@ const AddSubUnit = ({ route }) => {
91
77
  if (!awaitCreate.current) {
92
78
  awaitCreate.current = true;
93
79
  const dataObj = { name: roomName, background: wallpaper };
94
- dataObj.background = await prepareImageToUpload(dataObj.background);
95
80
  const formData = createFormData(dataObj, ['background']);
96
- const { success, data } = await axiosPost(
81
+ const { success } = await axiosPost(
97
82
  API.SUB_UNIT.CREATE_SUB_UNIT(unit.id),
98
83
  formData,
99
84
  {
@@ -115,10 +100,12 @@ const AddSubUnit = ({ route }) => {
115
100
  screen: Routes.UnitDetail,
116
101
  params: {
117
102
  unitId: unit.id,
118
- unitData: data,
103
+ unitData: unit,
119
104
  isAddSubUnit: true,
105
+ routeName: Routes.DashboardStack,
120
106
  },
121
107
  });
108
+ cleanData();
122
109
  } else {
123
110
  awaitCreate.current = false;
124
111
  ToastBottomHelper.error(t('text_create_sub_unit_fail'));
@@ -188,6 +175,7 @@ const AddSubUnit = ({ route }) => {
188
175
  textInputStyle={styles.roomName}
189
176
  wrapStyle={styles.textInput}
190
177
  selectionColor={Colors.Primary}
178
+ value={roomName}
191
179
  />
192
180
 
193
181
  {isAddUnit && (
@@ -161,7 +161,8 @@ describe('Test AddSubUnit', () => {
161
161
  screen: Routes.UnitDetail,
162
162
  params: {
163
163
  unitId: route.params.unit.id,
164
- unitData: response.data,
164
+ unitData: route.params.unit,
165
+ routeName: 'DashboardStack',
165
166
  isAddSubUnit: true,
166
167
  },
167
168
  });
@@ -22,12 +22,12 @@ const TDSGuide = memo(() => {
22
22
  >
23
23
  {t('what_is_tds_title')}
24
24
  </Text>
25
- <Text type="Body">{t('what_is_tds_text')}</Text>
25
+ <Text style={styles.tdsText}>{t('what_is_tds_text')}</Text>
26
26
  <Text type="H3" semibold style={styles.titlePadding}>
27
27
  {t('tds_guidlines_title')}
28
28
  </Text>
29
29
  <>
30
- <Text type="Body">
30
+ <Text style={styles.tdsText}>
31
31
  {t('tds_guidlines_text_1')}
32
32
  {'\n'}
33
33
  {'\n'}
@@ -56,4 +56,7 @@ const styles = StyleSheet.create({
56
56
  paddingTop: 20,
57
57
  paddingBottom: 10,
58
58
  },
59
+ tdsText: {
60
+ fontSize: 15,
61
+ },
59
62
  });
@@ -4,6 +4,7 @@ import { useTranslations } from '../../hooks/Common/useTranslations';
4
4
  import Routes from '../../utils/Route';
5
5
  import AddSubUnitIcon from '../../../assets/images/Popover/Dashboard/AddSubUnit.svg';
6
6
  import AddDeviceIcon from '../../../assets/images/Popover/Dashboard/AddDevice.svg';
7
+ import SmartAccount from '../../../assets/images/Popover/Dashboard/SmartAccount.svg';
7
8
  import AddMemberIcon from '../../../assets/images/Popover/Dashboard/AddMember.svg';
8
9
  import { useNavigation } from '@react-navigation/native';
9
10
 
@@ -50,6 +51,20 @@ const AddMenu = memo(({ unit, afterItemClick, showAdd, setHideAdd }) => {
50
51
  image: <AddDeviceIcon width={43} height={43} />, // TODO change icon
51
52
  data: { screen: Routes.SetupGatewayWifi, params: { unit_id: unit.id } },
52
53
  },
54
+ {
55
+ id: 5,
56
+ route: Routes.AddGatewayStack,
57
+ text: t('gateway') + ' Wifi',
58
+ image: <AddDeviceIcon width={43} height={43} />,
59
+ data: { screen: Routes.FirstWarning, params: { unit_id: unit.id } },
60
+ },
61
+ {
62
+ id: 6,
63
+ route: Routes.SmartAccount,
64
+ text: t('name_smart_account'),
65
+ image: <SmartAccount width={43} height={43} />, // TODO change icon
66
+ type: Routes.SmartAccount,
67
+ },
53
68
  ];
54
69
  }, [t, unit]);
55
70
 
@@ -30,7 +30,16 @@ import { AUTOMATE_TYPE } from '../../configs/Constants';
30
30
 
31
31
  const UnitDetail = ({ route }) => {
32
32
  const t = useTranslations();
33
- const { unitId, unitData, isOneTap, routeName, isAddSubUnit } = route.params;
33
+
34
+ const {
35
+ unitId,
36
+ unitData,
37
+ isOneTap,
38
+ routeName,
39
+ isAddSubUnit,
40
+ isSuccessfullyConnected,
41
+ } = route.params;
42
+
34
43
  const isFocused = useIsFocused();
35
44
  const { stateData, setAction } = useContext(SCContext);
36
45
  const { navigate } = useNavigation();
@@ -253,7 +262,7 @@ const UnitDetail = ({ route }) => {
253
262
  };
254
263
 
255
264
  const renderDetailSubUnit = () => {
256
- if (station.isFavorites) {
265
+ if (station?.isFavorites) {
257
266
  return (
258
267
  <SubUnitFavorites
259
268
  unit={unit}
@@ -296,6 +305,10 @@ const UnitDetail = ({ route }) => {
296
305
  navigate(routeName);
297
306
  }, [navigate, routeName]);
298
307
 
308
+ const Dashboard = useCallback(() => {
309
+ navigate(Routes.Dashboard);
310
+ }, [navigate]);
311
+
299
312
  return (
300
313
  <WrapParallaxScrollView
301
314
  uriImg={unit.background}
@@ -308,7 +321,7 @@ const UnitDetail = ({ route }) => {
308
321
  onAdd={setShowAdd}
309
322
  onMore={showPopoverWithRef}
310
323
  hideRightPlus={!isOwner}
311
- onBack={routeName && onBack}
324
+ onBack={(isSuccessfullyConnected && Dashboard) || (routeName && onBack)}
312
325
  >
313
326
  <View style={styles.container}>
314
327
  <Summaries unit={unit} />
@@ -1,17 +1,23 @@
1
1
  import React from 'react';
2
2
  import { View } from 'react-native';
3
3
  import { act, create } from 'react-test-renderer';
4
+ import { SCProvider } from '../../../../context';
5
+ import { mockSCStore } from '../../../../context/mockStore';
4
6
  import MyUnitDevice from '../MyUnitDevice';
5
7
 
8
+ const wrapComponent = (sensor) => (
9
+ <SCProvider initState={mockSCStore({})}>
10
+ <MyUnitDevice sensor={sensor} />
11
+ </SCProvider>
12
+ );
13
+
6
14
  describe('Test MyUnitDevice', () => {
7
15
  let tree;
8
16
 
9
17
  it('Test render with status', async () => {
10
18
  await act(() => {
11
19
  tree = create(
12
- <MyUnitDevice
13
- sensor={{ status: 'Ok', name: 'Test', station_name: '' }}
14
- />
20
+ wrapComponent({ status: 'Ok', name: 'Test', station_name: '' })
15
21
  );
16
22
  });
17
23
  const instance = tree.root;
@@ -21,9 +27,7 @@ describe('Test MyUnitDevice', () => {
21
27
 
22
28
  it('Test render without status', async () => {
23
29
  await act(() => {
24
- tree = create(
25
- <MyUnitDevice sensor={{ name: 'Test', station_name: '' }} />
26
- );
30
+ tree = create(wrapComponent({ name: 'Test', station_name: '' }));
27
31
  });
28
32
  const instance = tree.root;
29
33
  const Views = instance.findAllByType(View);
@@ -77,10 +77,8 @@ const PowerConsumption = memo(({ summaryDetail }) => {
77
77
  const dataTotal = [];
78
78
  dataTotal.push(totalPower);
79
79
 
80
- const [startDate, setStartDate] = useState(
81
- moment().subtract(6, 'days').valueOf()
82
- );
83
- const [endDate, setEndDate] = useState(moment().valueOf());
80
+ const [startDate, setStartDate] = useState(moment().subtract(6, 'days'));
81
+ const [endDate, setEndDate] = useState(moment());
84
82
  const [groupBy, setGroupBy] = useState('date');
85
83
  const [getData, setData] = useState([]);
86
84
  const [chartConfig, setChartConfig] = useState({
@@ -3,6 +3,14 @@ import { act, create } from 'react-test-renderer';
3
3
  import RunningDevices from '..';
4
4
  import { TouchableOpacity } from 'react-native';
5
5
  import ItemDevice from '../../../../../commons/Device/ItemDevice';
6
+ import { mockSCStore } from '../../../../../context/mockStore';
7
+ import { SCProvider } from '../../../../../context';
8
+
9
+ const wrapComponent = (unit, summaryDetail) => (
10
+ <SCProvider initState={mockSCStore({})}>
11
+ <RunningDevices unit={unit} summaryDetail={summaryDetail} />
12
+ </SCProvider>
13
+ );
6
14
 
7
15
  const mockedNavigate = jest.fn();
8
16
 
@@ -55,9 +63,7 @@ describe('test RunningDevices', () => {
55
63
  };
56
64
 
57
65
  await act(async () => {
58
- tree = await create(
59
- <RunningDevices unit={unit} summaryDetail={summaryDetail} />
60
- );
66
+ tree = await create(wrapComponent(unit, summaryDetail));
61
67
  });
62
68
  const instance = tree.root;
63
69
  const texts = instance.findAllByType(ItemDevice);
@@ -95,9 +101,7 @@ describe('test RunningDevices', () => {
95
101
  };
96
102
 
97
103
  await act(async () => {
98
- tree = await create(
99
- <RunningDevices unit={unit} summaryDetail={summaryDetail} />
100
- );
104
+ tree = await create(wrapComponent(unit, summaryDetail));
101
105
  });
102
106
  const instance = tree.root;
103
107
  const texts = instance.findAllByType(ItemDevice);
@@ -450,9 +450,9 @@ const styles = StyleSheet.create({
450
450
  position: 'absolute',
451
451
  fontSize: 20,
452
452
  transform: [{ rotate: '90deg' }],
453
- left: -28,
453
+ left: -40,
454
454
  bottom: 8,
455
- width: 115,
455
+ width: 150,
456
456
  height: 28,
457
457
  textAlign: 'center',
458
458
  },
@@ -2,7 +2,6 @@ import axios from 'axios';
2
2
  import { deleteData, getData, storeData } from '../Storage';
3
3
  import { ToastBottomHelper } from '../Utils';
4
4
  import NetInfo from '@react-native-community/netinfo';
5
- import { Platform } from 'react-native';
6
5
 
7
6
  export const replaceParams = (apiURL, params) => {
8
7
  let _result = apiURL;
@@ -166,9 +165,9 @@ export function createFormData(data, list_file_field) {
166
165
  }
167
166
 
168
167
  formData.append(key, {
169
- uri: Platform.OS === 'ios' ? item.sourceURL : item.path,
170
- type: item.mime,
171
168
  name: item.filename || item.path?.split('/').pop(),
169
+ type: item.mime,
170
+ uri: item.path,
172
171
  });
173
172
  return;
174
173
  }
@@ -240,8 +240,10 @@
240
240
  "invalid_phone_number": "Invalid phone number",
241
241
  "Found bluetooth %{name} for remote control": "Found bluetooth %{name} for remote control",
242
242
  "Sending command via bluetooth": "Sending command via bluetooth",
243
- "Command is sent to device via bluetooth": "Command is sent to device via bluetooth",
244
- "Command is fail to send via bluetooth": "Command is fail to send via bluetooth",
243
+ "command_is_sent_to_device_via_bluetooth": "Command is sent to device via bluetooth",
244
+ "command_is_fail_to_send_via_bluetooth": "Command is fail to send via bluetooth",
245
+ "control_device_via_bluetooth_successfully": "Control device via bluetooth successfully",
246
+ "control_device_via_bluetooth_failed": "Control device via bluetooth failed",
245
247
  "Sending command via internet": "Sending command via internet",
246
248
  "Command is sent to device via internet": "Command is sent to device via internet",
247
249
  "Command is fail to send via internet": "Command is fail to send via internet",
@@ -856,6 +858,21 @@
856
858
  "volume": "Volume",
857
859
  "this_notification_will_be_updated_soon": "This notification will be updated soon",
858
860
  "text_submit": "Submit",
861
+ "connecting": "Connecting",
862
+ "connect_device": "Connect Device",
863
+ "connect": "Connect",
864
+ "server_error": "Server Error",
865
+ "add_gateway_success": "Add gateway success",
866
+ "set_network": "Set network",
867
+ "select_wifi": "Select your wifi network",
868
+ "enter_wifi_password": "Enter wifi password",
869
+ "gateway_warning_content_1": "To bring you good experiences, ",
870
+ "gateway_warning_content_2": "your device needs a permanent wifi connection.",
871
+ "gateway_warning_content_3": "In the next steps, you will be instructed to connect to wifi for the device. ",
872
+ "gateway_warning_content_4": "To give you a good experience, you need to know the name and password of the wifi network and make sure the device is placed in a good location.",
873
+ "warning_beta_test_feature": "This feature is in beta test, not official yet",
874
+ "connecting_gateway_warning_1": "By continuing, EoH needs to connect to the device's wifi.",
875
+ "connecting_gateway_warning_2": "A message will appear asking you to connect.",
859
876
  "remove_account": "Remove Account",
860
877
  "text_sub_unit_not_have_device": "You don't have sub-unit with a device to control",
861
878
  "tap_to_add_new_schedule": "Tap + to add new schedule",
@@ -866,5 +883,10 @@
866
883
  "curtain_opens": "Curtain opens",
867
884
  "curtain_closes": "Curtain closes",
868
885
  "schedule_name": "Schedule name",
869
- "enter_name": "Enter name"
886
+ "enter_name": "Enter name",
887
+ "name_smart_account": "Smart Account",
888
+ "location_permission_required_wifi_title": "Location permission is required for WiFi connections",
889
+ "location_permission_required_wifi_message": "This app needs location permission as this is required to scan for wifi networks.",
890
+ "deny": "DENY",
891
+ "allow": "ALLOW"
870
892
  }
@@ -276,8 +276,10 @@
276
276
  "invalid_phone_number": "Số điện thoại không hợp lệ.",
277
277
  "Found bluetooth %{name} for remote control": "Tìm thấy thiết bị điều khiển bluetooth %{name}",
278
278
  "Sending command via bluetooth": "Đang gởi lệnh thông qua bluetooth",
279
- "Command is sent to device via bluetooth": "Lệnh được gởi tới thiết bị thông qua bluetooth",
280
- "Command is fail to send via bluetooth": "Không thế gởi tới thiết bị thông qua bluetooth",
279
+ "command_is_sent_to_device_via_bluetooth": "Lệnh được gởi tới thiết bị thông qua bluetooth",
280
+ "command_is_fail_to_send_via_bluetooth": "Không thế gởi tới thiết bị thông qua bluetooth",
281
+ "control_device_via_bluetooth_successfully": "Điều khiển thiết bị qua bluetooth thành công",
282
+ "control_device_via_bluetooth_failed": "Điều khiển thiết bị qua bluetooth thất bại",
281
283
  "Sending command via internet": "Đang gởi lệnh thông qua internet",
282
284
  "Command is sent to device via internet": "Lệnh được gởi tới thiết bị thông qua internet",
283
285
  "Command is fail to send via internet": "Không thế gởi tới thiết bị thông qua internet",
@@ -857,6 +859,21 @@
857
859
  "volume": "Âm lượng",
858
860
  "this_notification_will_be_updated_soon": "Thông báo này sẽ sớm được cập nhật",
859
861
  "text_submit": "Xác nhận",
862
+ "connecting": "Đang kết nối",
863
+ "connect_device": "Kết nối thiết bị",
864
+ "connect": "Kết nối",
865
+ "server_error": "Lỗi hệ thống",
866
+ "set_network": "Chọn mạng",
867
+ "select_wifi": "Chọn mạng wifi của bạn",
868
+ "enter_wifi_password": "Nhập mật khẩu wifi",
869
+ "gateway_warning_content_1": "Để mang đến cho bạn những trải nghiệm tốt, ",
870
+ "gateway_warning_content_2": "thiết bị cần kết nối wifi thường trực.",
871
+ "gateway_warning_content_3": "Trong các bước tiếp theo, bạn sẽ được hướng dẫn kết nối wifi cho thiết bị. ",
872
+ "gateway_warning_content_4": "Bạn cần biết tên và mật khẩu của mạng wifi và đảm bảo thiết bị được đặt ở vị trí tốt.",
873
+ "warning_beta_test_feature": "Tính năng này đang ở giai đoạn beta test, chưa phải bản chính thức.",
874
+ "connecting_gateway_warning_1": "Bằng việc tiếp tục, EoH cần kết nối với Wifi của thiết bị.",
875
+ "connecting_gateway_warning_2": "Một thông báo sẽ hiện lên và yêu cầu bạn kết nối.",
876
+ "add_gateway_success": "Thêm gateway thành công",
860
877
  "tap_to_add_new_schedule": "Nhấn + để thêm lịch trình mới",
861
878
  "remove_account": "Xóa tài khoản",
862
879
  "text_subunit_not_have_device": "Bạn không có khu vực nào có thiết bị để điều khiển",
@@ -868,5 +885,10 @@
868
885
  "curtain_opens": "Rèm mở",
869
886
  "curtain_closes": "Rèm đóng",
870
887
  "schedule_name": "Tên lịch trình",
871
- "enter_name": "Nhập tên"
888
+ "enter_name": "Nhập tên",
889
+ "name_smart_account": "Smart Account",
890
+ "location_permission_required_wifi_title": "Quyền vị trí là bắt buộc đối với kết nối WiFi",
891
+ "location_permission_required_wifi_message": "Ứng dụng này cần có quyền định vị vì ứng dụng này được yêu cầu để quét các mạng Wi-Fi.",
892
+ "deny": "Từ chối",
893
+ "allow": "Cho phép"
872
894
  }
@@ -121,7 +121,11 @@ const Routes = {
121
121
  ListDeviceSmartAccount: 'ListDeviceSmartAccount',
122
122
  SmartAccountConnecting: 'SmartAccountConnecting',
123
123
  EmergencySetting: 'EmergencySetting',
124
+ FirstWarning: 'FirstWarning',
125
+ ConnectWifiWarning: 'ConnectWifiWarning',
126
+ GatewayWifiList: 'GatewayWifiList',
124
127
  ConfirmUnitDeletion: 'ConfirmUnitDeletion',
128
+ SmartAccount: 'SmartAccount',
125
129
  };
126
130
 
127
131
  export default Routes;
@@ -120,10 +120,6 @@ export const removeFromString = (str, index) => {
120
120
  return str.substr(0, index) + str.substr(index + 1);
121
121
  };
122
122
 
123
- export const arePropsEqual = (prevProps, nextProps) => {
124
- return JSON.stringify(prevProps) === JSON.stringify(nextProps);
125
- };
126
-
127
123
  export default {
128
124
  validateEmail,
129
125
  isObjectEmpty,