@eohjsc/react-native-smart-city 0.2.82 → 0.2.85

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 (99) hide show
  1. package/assets/images/Event.svg +9 -0
  2. package/assets/images/brightness.svg +12 -0
  3. package/package.json +4 -2
  4. package/src/Images/Common/SuccessfullyConnected.svg +4 -0
  5. package/src/Images/Common/eye-closed.png +0 -0
  6. package/src/Images/Common/eye-closed@2x.png +0 -0
  7. package/src/Images/Common/eye-closed@3x.png +0 -0
  8. package/src/Images/Common/eye.png +0 -0
  9. package/src/Images/Common/eye@2x.png +0 -0
  10. package/src/Images/Common/eye@3x.png +0 -0
  11. package/src/commons/ActionGroup/CurtainButtonTemplate.js +32 -21
  12. package/src/commons/ActionGroup/LightActionTemplate.js +103 -0
  13. package/src/commons/ActionGroup/LightActionTemplateStyles.js +57 -0
  14. package/src/commons/ActionGroup/NumberUpDownActionTemplate.js +8 -6
  15. package/src/commons/ActionGroup/OnOffTemplate/OnOffButtonTemplate.js +33 -31
  16. package/src/commons/ActionGroup/OnOffTemplate/index.js +11 -3
  17. package/src/commons/ActionGroup/OneBigButtonTemplate.js +10 -7
  18. package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +5 -2
  19. package/src/commons/ActionGroup/StatesGridActionTemplate.js +7 -3
  20. package/src/commons/ActionGroup/ThreeButtonTemplate.js +33 -24
  21. package/src/commons/ActionGroup/__test__/LightActionTemplate.test.js +59 -0
  22. package/src/commons/ActionGroup/__test__/OnOffTemplate.test.js +18 -6
  23. package/src/commons/ActionGroup/__test__/OneBigButtonTemplate.test.js +9 -1
  24. package/src/commons/ActionGroup/__test__/OptionsDropdownTemplate.test.js +25 -13
  25. package/src/commons/ActionGroup/__test__/index.test.js +48 -14
  26. package/src/commons/ActionGroup/index.js +3 -0
  27. package/src/commons/Automate/ItemAutomate.js +1 -1
  28. package/src/commons/Automate/ItemAutomateStyles.js +5 -1
  29. package/src/commons/CardShadow/index.js +5 -2
  30. package/src/commons/CardShadow/styles.js +2 -3
  31. package/src/commons/ConnectingProcess/DeviceItem/DeviceItem.js +16 -0
  32. package/src/commons/ConnectingProcess/DeviceItem/DeviceItemStyles.js +42 -0
  33. package/src/commons/ConnectingProcess/__test__/Connecting.test.js +27 -0
  34. package/src/commons/ConnectingProcess/__test__/DeviceItem.test.js +18 -0
  35. package/src/commons/ConnectingProcess/index.js +202 -0
  36. package/src/commons/ConnectingProcess/styles.js +69 -0
  37. package/src/commons/Device/HorizontalBarChart.js +7 -1
  38. package/src/commons/Device/ItemDevice.js +8 -5
  39. package/src/commons/Device/LinearChart.js +1 -0
  40. package/src/commons/Device/WaterQualitySensor/ListQualityIndicator.js +1 -1
  41. package/src/commons/Device/WaterQualitySensor/QualityIndicatorsItem.js +1 -1
  42. package/src/commons/EmergencyButton/AlertSendConfirm.js +2 -2
  43. package/src/commons/EmergencyButton/AlertSent.js +2 -2
  44. package/src/commons/Form/TextInputPassword.js +1 -1
  45. package/src/commons/FullLoading/index.js +35 -0
  46. package/src/commons/SubUnit/Favorites/index.js +2 -0
  47. package/src/commons/SubUnit/OneTap/ItemOneTap.js +3 -0
  48. package/src/commons/SubUnit/ShortDetail.js +7 -1
  49. package/src/commons/index.js +2 -0
  50. package/src/configs/API.js +6 -4
  51. package/src/configs/Constants.js +25 -0
  52. package/src/configs/Images.js +2 -0
  53. package/src/context/actionType.ts +2 -0
  54. package/src/context/reducer.ts +10 -0
  55. package/src/hooks/Common/useBlockBackAndroid.js +3 -1
  56. package/src/iot/RemoteControl/Internet.js +8 -1
  57. package/src/iot/RemoteControl/index.js +4 -2
  58. package/src/navigations/AddDeviceStack.js +10 -0
  59. package/src/screens/AddCommon/SelectSubUnit.js +29 -6
  60. package/src/screens/AddCommon/SelectUnit.js +24 -2
  61. package/src/screens/AddCommon/__test__/SelectSubUnit.test.js +120 -1
  62. package/src/screens/AddCommon/__test__/SelectUnit.test.js +16 -1
  63. package/src/screens/AddNewAction/SelectAction.js +46 -28
  64. package/src/screens/AddNewAutoSmart/__test__/AddNewAutoSmart.test.js +3 -3
  65. package/src/screens/AddNewAutoSmart/index.js +18 -1
  66. package/src/screens/AddNewGateway/PlugAndPlay/ConnectWifiWarning.js +55 -16
  67. package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +52 -23
  68. package/src/screens/AddNewGateway/SelectGateway.js +132 -0
  69. package/src/screens/AddNewGateway/SelectGatewayStyles.js +55 -0
  70. package/src/screens/AddNewGateway/__test__/SetupGateway.test.js +0 -52
  71. package/src/screens/Device/EditDevice/__test__/EditDevice.test.js +2 -2
  72. package/src/screens/Device/EditDevice/index.js +2 -2
  73. package/src/screens/Device/__test__/detail.test.js +18 -11
  74. package/src/screens/Device/components/SensorConnectStatusViewHeader.js +2 -2
  75. package/src/screens/Device/components/SensorDisplayItem.js +2 -2
  76. package/src/screens/Device/detail.js +64 -26
  77. package/src/screens/Device/styles.js +2 -0
  78. package/src/screens/Notification/__test__/NotificationItem.test.js +197 -15
  79. package/src/screens/Notification/components/NotificationItem.js +188 -14
  80. package/src/screens/Notification/styles/NotificationItemStyles.js +3 -3
  81. package/src/screens/ScanChipQR/__test__/ScanChipQR.test.js +10 -7
  82. package/src/screens/ScanChipQR/hooks/index.js +48 -40
  83. package/src/screens/SubUnit/AddSubUnit.js +4 -1
  84. package/src/screens/SubUnit/__test__/AddSubUnit.test.js +148 -0
  85. package/src/screens/Unit/Detail.js +33 -1
  86. package/src/screens/Unit/ManageUnit.js +1 -1
  87. package/src/screens/Unit/ManageUnitStyles.js +0 -6
  88. package/src/screens/Unit/SmartAccount.js +5 -1
  89. package/src/screens/Unit/Summaries.js +2 -2
  90. package/src/screens/Unit/__test__/CheckSendEmail.test.js +10 -0
  91. package/src/screens/Unit/__test__/Detail.test.js +10 -0
  92. package/src/screens/Unit/components/__test__/SharedUnit.test.js +21 -2
  93. package/src/screens/UnitSummary/__test__/index.test.js +3 -3
  94. package/src/screens/UnitSummary/components/RunningDevices/__test__/index.test.js +2 -2
  95. package/src/screens/UnitSummary/index.js +52 -9
  96. package/src/utils/Apis/axios.js +1 -1
  97. package/src/utils/I18n/translations/en.json +16 -0
  98. package/src/utils/I18n/translations/vi.json +16 -1
  99. package/src/utils/Route/index.js +2 -0
@@ -2,6 +2,7 @@ import React, { useCallback, useContext, useEffect, useState } from 'react';
2
2
  import { AppState, RefreshControl, View } from 'react-native';
3
3
  import { useIsFocused } from '@react-navigation/native';
4
4
  import { useTranslations } from '../../hooks/Common/useTranslations';
5
+ import { useNetInfo } from '@react-native-community/netinfo';
5
6
 
6
7
  import styles from './styles';
7
8
  import AddMenu from './AddMenu';
@@ -10,7 +11,12 @@ import Summaries from './Summaries';
10
11
 
11
12
  import Text from '../../commons/Text';
12
13
  import { API } from '../../configs';
13
- import { useBoolean, useIsOwnerOfUnit, usePopover } from '../../hooks/Common';
14
+ import {
15
+ useBlockBackAndroid,
16
+ useBoolean,
17
+ useIsOwnerOfUnit,
18
+ usePopover,
19
+ } from '../../hooks/Common';
14
20
  import { scanBluetoothDevices } from '../../iot/RemoteControl/Bluetooth';
15
21
  import { googleHomeConnect } from '../../iot/RemoteControl/GoogleHome';
16
22
  import { axiosPost, fetchWithCache } from '../../utils/Apis/axios';
@@ -40,6 +46,7 @@ const UnitDetail = ({ route }) => {
40
46
  unitData,
41
47
  isOneTap,
42
48
  routeName,
49
+ stationId,
43
50
  isAddSubUnit,
44
51
  isSuccessfullyConnected,
45
52
  } = route.params;
@@ -47,6 +54,13 @@ const UnitDetail = ({ route }) => {
47
54
  const isFocused = useIsFocused();
48
55
  const { stateData, setAction } = useContext(SCContext);
49
56
  const { navigate } = useNavigation();
57
+ const RouterHardware = useCallback(
58
+ (routeHardware) => () => {
59
+ navigate(routeHardware);
60
+ },
61
+ [navigate]
62
+ );
63
+ useBlockBackAndroid(RouterHardware(Routes.Dashboard));
50
64
  const user = useSCContextSelector((state) => state?.auth?.account?.user);
51
65
  const isLavidaSource = useSCContextSelector(
52
66
  (state) => state.app.isLavidaSource
@@ -62,6 +76,7 @@ const UnitDetail = ({ route }) => {
62
76
  automates: [],
63
77
  });
64
78
  const [isGGHomeConnected, setIsGGHomeConnected] = useState(false);
79
+ const [isNetworkConnected, setIsNetworkConnected] = useState(true);
65
80
  const [station, setStation] = useState({});
66
81
  const [indexStation, setIndexStation] = useState(0);
67
82
  const [showAdd, setShowAdd, setHideAdd] = useBoolean();
@@ -73,6 +88,8 @@ const UnitDetail = ({ route }) => {
73
88
 
74
89
  const { isOwner } = useIsOwnerOfUnit(unit.user_id);
75
90
 
91
+ const netInfo = useNetInfo();
92
+
76
93
  const handleFullScreen = (data) => {
77
94
  setIsFullScreen(!isFullScreen);
78
95
  setDataFullScreen(data);
@@ -175,6 +192,10 @@ const UnitDetail = ({ route }) => {
175
192
  };
176
193
  }, [handleAppStateChange]);
177
194
 
195
+ useEffect(() => {
196
+ setIsNetworkConnected(netInfo.isConnected);
197
+ }, [netInfo.isConnected]);
198
+
178
199
  const handleGoogleHomeConnect = useCallback(
179
200
  async (options) => {
180
201
  let isConnected = await googleHomeConnect(options); // this may wrong if have multiple connection
@@ -260,6 +281,15 @@ const UnitDetail = ({ route }) => {
260
281
  }
261
282
  }, [listMenuItem.length, isAddSubUnit]);
262
283
 
284
+ useEffect(() => {
285
+ if (listMenuItem.length && stationId) {
286
+ const getStationCurrent = listMenuItem.filter(
287
+ (item) => item?.station.id === stationId
288
+ );
289
+ setIndexStation(getStationCurrent[0]?.index);
290
+ }
291
+ }, [listMenuItem, listMenuItem.length, stationId]);
292
+
263
293
  const onSnapToItem = useCallback(
264
294
  (item, index) => {
265
295
  setStation(unit.stations[index]);
@@ -281,6 +311,7 @@ const UnitDetail = ({ route }) => {
281
311
  isOwner={isOwner}
282
312
  favorites={favorites}
283
313
  wrapItemStyle={styles.wrapItemStyle}
314
+ isNetworkConnected={isNetworkConnected}
284
315
  isGGHomeConnected={isGGHomeConnected}
285
316
  />
286
317
  );
@@ -307,6 +338,7 @@ const UnitDetail = ({ route }) => {
307
338
  <ShortDetailSubUnit
308
339
  unit={unit}
309
340
  station={station}
341
+ isNetworkConnected={isNetworkConnected}
310
342
  isGGHomeConnected={isGGHomeConnected}
311
343
  />
312
344
  );
@@ -36,7 +36,7 @@ const ButtonWrapper = ({
36
36
  <TouchableOpacity
37
37
  onPress={onPress}
38
38
  testID={testId}
39
- style={!icon ? styles.buttonWrapper : styles.buttonWrapperAvatar}
39
+ style={styles.buttonWrapper}
40
40
  >
41
41
  <View style={styles.buttonInfo}>
42
42
  {!icon ? (
@@ -16,12 +16,6 @@ export default StyleSheet.create({
16
16
  borderBottomWidth: 0.5,
17
17
  borderBottomColor: Colors.Gray6,
18
18
  },
19
- buttonWrapperAvatar: {
20
- paddingTop: 14,
21
- paddingBottom: 24,
22
- borderBottomWidth: 0.5,
23
- borderBottomColor: Colors.Gray7,
24
- },
25
19
  buttonInfo: {
26
20
  flex: 1,
27
21
  flexDirection: 'row',
@@ -15,7 +15,7 @@ import { useNavigation } from '@react-navigation/native';
15
15
  import { axiosDelete, axiosGet } from '../../utils/Apis/axios';
16
16
  import { SmartAccountItem } from './SmartAccountItem';
17
17
  import { usePopover, useBoolean } from '../../hooks/Common';
18
- import { MenuActionMore, AlertAction } from '../../commons';
18
+ import { MenuActionMore, AlertAction, FullLoading } from '../../commons';
19
19
  import { useTranslations } from '../../hooks/Common/useTranslations';
20
20
  import { useStateAlertRemove } from '../Unit/hook/useStateAlertRemove';
21
21
  import { ToastBottomHelper } from '../../utils/Utils';
@@ -26,6 +26,7 @@ const ListSmartAccount = ({ route }) => {
26
26
  const [data, setData] = useState([]);
27
27
  const smartAccountRef = useRef(null);
28
28
  const { navigate } = useNavigation();
29
+ const [loadingRemoveItem, setLoadingRemoveItem] = useState(false);
29
30
 
30
31
  const getAllSmartAccounts = useCallback(async () => {
31
32
  const { success, data } = await axiosGet(
@@ -70,6 +71,7 @@ const ListSmartAccount = ({ route }) => {
70
71
 
71
72
  const deleteSmartAccount = useCallback(async () => {
72
73
  hideAlertAction();
74
+ setLoadingRemoveItem(true);
73
75
  if (!smartAccountRef?.current) {
74
76
  return;
75
77
  }
@@ -81,6 +83,7 @@ const ListSmartAccount = ({ route }) => {
81
83
  ToastBottomHelper.success(t('removed_successfully'));
82
84
  getAllSmartAccounts();
83
85
  }
86
+ setLoadingRemoveItem(false);
84
87
  }, [getAllSmartAccounts, hideAlertAction, t]);
85
88
 
86
89
  const listMenuItem = useMemo(() => {
@@ -142,6 +145,7 @@ const ListSmartAccount = ({ route }) => {
142
145
  hideComplete={releaseLockShowing}
143
146
  />
144
147
  </WrapHeaderScrollable>
148
+ {loadingRemoveItem && <FullLoading />}
145
149
  </View>
146
150
  );
147
151
  };
@@ -34,8 +34,8 @@ const Summaries = memo(({ unit }) => {
34
34
  const goToSummary = useCallback(
35
35
  (summary) => {
36
36
  navigation.navigate(Routes.UnitSummary, {
37
- summary,
38
- unit,
37
+ summaryData: summary,
38
+ unitData: unit,
39
39
  });
40
40
  },
41
41
  [navigation, unit]
@@ -26,6 +26,16 @@ jest.mock('../../../iot/RemoteControl/GoogleHome', () => ({
26
26
 
27
27
  jest.mock('axios');
28
28
 
29
+ jest.mock('@react-native-community/netinfo', () => {
30
+ return {
31
+ useNetInfo: () => {
32
+ return {
33
+ isConnected: true,
34
+ };
35
+ },
36
+ };
37
+ });
38
+
29
39
  const wrapComponent = (route, unitData, account) => (
30
40
  <SCProvider initState={mockSCStore({})}>
31
41
  <UnitDetail
@@ -62,6 +62,16 @@ jest.mock('home-assistant-js-websocket', () => {
62
62
  };
63
63
  });
64
64
 
65
+ jest.mock('@react-native-community/netinfo', () => {
66
+ return {
67
+ useNetInfo: () => {
68
+ return {
69
+ isConnected: true,
70
+ };
71
+ },
72
+ };
73
+ });
74
+
65
75
  jest.mock('axios');
66
76
 
67
77
  describe('Test UnitDetail', () => {
@@ -12,10 +12,15 @@ import { mockSCStore } from '../../../../context/mockStore';
12
12
 
13
13
  jest.mock('axios');
14
14
 
15
+ const mockRenewItem = jest.fn();
15
16
  const wrapComponent = (item, navigation) => (
16
17
  <SCProvider initState={mockSCStore({})}>
17
- <SharedUnit item={item} navigation={navigation} />
18
- );
18
+ <SharedUnit
19
+ item={item}
20
+ navigation={navigation}
21
+ renewItem={mockRenewItem}
22
+ index={0}
23
+ />
19
24
  </SCProvider>
20
25
  );
21
26
 
@@ -55,6 +60,13 @@ describe('Test SharedUnit', () => {
55
60
 
56
61
  test('test create SharedUnit unit is not pin, not star', async () => {
57
62
  const navigation = useNavigation();
63
+ const response = {
64
+ status: 200,
65
+ success: true,
66
+ };
67
+ axios.post.mockImplementation(async () => {
68
+ return response;
69
+ });
58
70
 
59
71
  await act(async () => {
60
72
  tree = await create(wrapComponent(item, navigation));
@@ -100,6 +112,13 @@ describe('Test SharedUnit', () => {
100
112
  const navigation = useNavigation();
101
113
  item.is_pin = true;
102
114
  item.is_star = true;
115
+ const response = {
116
+ status: 200,
117
+ success: true,
118
+ };
119
+ axios.post.mockImplementation(async () => {
120
+ return response;
121
+ });
103
122
 
104
123
  await act(async () => {
105
124
  tree = await create(wrapComponent(item, navigation));
@@ -43,10 +43,10 @@ describe('Test UnitSummary', () => {
43
43
  Date.now = jest.fn(() => new Date('2021-01-24T12:00:00.000Z'));
44
44
  route = {
45
45
  params: {
46
- unit: {
46
+ unitData: {
47
47
  id: 1,
48
48
  },
49
- summary: {
49
+ summaryData: {
50
50
  id: 1,
51
51
  name: '',
52
52
  screen: Routes.AirQuality,
@@ -155,7 +155,7 @@ describe('Test UnitSummary', () => {
155
155
 
156
156
  list_value.forEach((value, index) => {
157
157
  test(`create Unit Summarty Detail ${value}`, async () => {
158
- route.params.summary.screen = value;
158
+ route.params.summaryData.screen = value;
159
159
  await act(async () => {
160
160
  tree = await create(wrapComponent(route));
161
161
  });
@@ -113,10 +113,10 @@ describe('test RunningDevices', () => {
113
113
  });
114
114
  expect(mockedNavigate).toBeCalledWith('DeviceDetail', {
115
115
  isGGHomeConnected: false,
116
- sensor: summaryDetail.devices[0],
116
+ sensorData: summaryDetail.devices[0],
117
117
  station: 'station',
118
118
  title: undefined,
119
- unit: unit,
119
+ unitData: unit,
120
120
  });
121
121
  });
122
122
  });
@@ -23,15 +23,17 @@ import { timeDifference } from '../../utils/Converter/time';
23
23
 
24
24
  const UnitSummary = memo(({ route }) => {
25
25
  const t = useTranslations();
26
- const { unit, summary } = route.params;
26
+ const { unitData, unitId, summaryData, summaryId } = route.params;
27
27
  const [summaryDetail, setSummaryDetail] = useState({});
28
+ const [unit, setUnit] = useState(unitData || { id: unitId });
29
+ const [summary, setSummary] = useState(summaryData || { id: summaryId });
28
30
 
29
31
  const [loading, setLoading] = useState(false);
30
32
  const [lastUpdated, setLastUpdated] = useState();
31
33
  const navigation = useNavigation();
32
34
 
33
35
  const getComponentAndGuide = useCallback(() => {
34
- switch (summary.screen) {
36
+ switch (summary?.screen) {
35
37
  case Routes.AirQuality:
36
38
  return {
37
39
  guideName: Routes.AQIGuide,
@@ -66,12 +68,17 @@ const UnitSummary = memo(({ route }) => {
66
68
  return {
67
69
  componentName: ThreePhasePowerConsumption,
68
70
  };
71
+ default:
72
+ return {
73
+ guideName: null,
74
+ componentName: null,
75
+ };
69
76
  }
70
- }, [summary.screen]);
77
+ }, [summary?.screen]);
71
78
 
72
79
  const fetchSummaryDetail = useCallback(async () => {
73
80
  const { success, data } = await axiosGet(
74
- API.UNIT.UNIT_SUMMARY_DETAIL(unit.id, summary.id),
81
+ API.UNIT.UNIT_SUMMARY_DETAIL(unit?.id, summary?.id),
75
82
  {},
76
83
  true
77
84
  );
@@ -80,7 +87,41 @@ const UnitSummary = memo(({ route }) => {
80
87
  setSummaryDetail(data.data);
81
88
  setLastUpdated(data.data.last_updated);
82
89
  }
83
- }, [summary.id, unit.id]);
90
+ }, [summary?.id, unit?.id]);
91
+
92
+ const fetchUnitDetail = useCallback(async () => {
93
+ const { success, data } = await axiosGet(
94
+ API.UNIT.UNIT_DETAIL(unit?.id),
95
+ {},
96
+ true
97
+ );
98
+ if (success) {
99
+ setUnit(data);
100
+ }
101
+ }, [unit.id]);
102
+
103
+ const fetchUnitSummary = useCallback(async () => {
104
+ const { success, data } = await axiosGet(
105
+ API.UNIT.UNIT_SUMMARY(unit?.id),
106
+ {}
107
+ );
108
+ if (success) {
109
+ const newData = data.filter((item) => item.id === summaryId);
110
+ setSummary(newData[0] || {});
111
+ }
112
+ }, [summaryId, unit?.id]);
113
+
114
+ useEffect(() => {
115
+ if (!unitData && unitId) {
116
+ fetchUnitDetail();
117
+ }
118
+ }, [fetchUnitDetail, unitData, unitId]);
119
+
120
+ useEffect(() => {
121
+ if (!summaryData && summaryId) {
122
+ fetchUnitSummary();
123
+ }
124
+ }, [fetchUnitSummary, summaryData, summaryId]);
84
125
 
85
126
  useEffect(() => {
86
127
  setLoading(true);
@@ -99,8 +140,8 @@ const UnitSummary = memo(({ route }) => {
99
140
  }, [fetchSummaryDetail]);
100
141
 
101
142
  const UnitSummaryDetail = getComponentAndGuide();
102
- const ComponentName = UnitSummaryDetail.componentName;
103
- const GuideName = UnitSummaryDetail.guideName;
143
+ const ComponentName = UnitSummaryDetail?.componentName;
144
+ const GuideName = UnitSummaryDetail?.guideName;
104
145
 
105
146
  const lastUpdatedStr = lastUpdated
106
147
  ? `${t('last_updated')} ${timeDifference(moment(), moment(lastUpdated))}`
@@ -109,7 +150,7 @@ const UnitSummary = memo(({ route }) => {
109
150
  return (
110
151
  <View style={[styles.container]}>
111
152
  <WrapHeaderScrollable
112
- title={summary.name}
153
+ title={summary?.name}
113
154
  subTitle={lastUpdatedStr}
114
155
  rightComponent={
115
156
  GuideName ? (
@@ -130,7 +171,9 @@ const UnitSummary = memo(({ route }) => {
130
171
  loading={loading}
131
172
  onRefresh={onRefresh}
132
173
  >
133
- <ComponentName summaryDetail={summaryDetail} unit={unit} />
174
+ {ComponentName && (
175
+ <ComponentName summaryDetail={summaryDetail} unit={unit} />
176
+ )}
134
177
  </WrapHeaderScrollable>
135
178
  </View>
136
179
  );
@@ -153,7 +153,7 @@ export async function axiosDelete(...options) {
153
153
  }
154
154
  const convertFilenameImage = (filename) => {
155
155
  const filenameConverted = filename?.replace(/HEIC/g, 'jpg');
156
- return filename || filenameConverted;
156
+ return filenameConverted || filename;
157
157
  };
158
158
  export function createFormData(data, list_file_field) {
159
159
  const formData = new FormData();
@@ -186,6 +186,7 @@
186
186
  "explanation": "Do everything with just one button",
187
187
  "value_change": "Value change",
188
188
  "schedule": "Schedule",
189
+ "event": "Event",
189
190
  "setup_the_conditions": "Setup the conditions",
190
191
  "setup_the_schedule": "Setup the Schedule",
191
192
  "des_launch_one_tap": "Quick button create at the dashboard",
@@ -275,7 +276,11 @@
275
276
  "manage_unit": "Manage unit",
276
277
  "text_bad": "Bad",
277
278
  "text_select_a_unit": "Select a unit",
279
+ "text_select_sub_unit": "Select sub unit",
280
+ "text_select_a_gateway": "Select a gateway",
278
281
  "text_select_a_unit_desc": "Select a unit you want to add new members",
282
+ "select_a_sub_unit_want_add_device": "Then, select a sub-unit that you want to add this device in",
283
+ "text_select_a_unit_have_device": "First, select a unit that has this device",
279
284
  "text_select_permissions": "Select permissions",
280
285
  "text_select_permissions_desc": "Select permissions will be grant",
281
286
  "text_read_config": "Read configs",
@@ -668,11 +673,21 @@
668
673
  "text_notification_content_pay_fine_successfully": "Your violation **%{booking}** has been paid successfully.",
669
674
  "text_notification_content_pay_fine_and_extend_successfully": "Your violation **%{booking_id_old}** has been paid successfully. The new parking session **%{booking_id_new}** is now extended until **%{leave_time}**.",
670
675
  "text_notification_content_stop_violation_free_parking_zone": "Free parking zone. You have an unpaid violation. Please complete your fine.",
676
+ "text_notification_content_air_quality_high": "The Air Quality index at **%{unit_name}** is **%{status}**. Wear a mask and reduce outdoor exercise.",
677
+ "text_notification_content_uv_index_high": "The UV index at **%{unit_name}** is **%{status}**. Reduce time in the sun and protect your skin, eye.",
678
+ "text_notification_content_pH_index_high": "The pH index at **%{unit_name}** is **%{status}**. Water is not safe to drink.",
679
+ "text_notification_content_clo_high": "The Chlorine residual at **%{unit_name}** is **%{status}**. Water is not safe to drink.",
680
+ "text_notification_content_turbility_high": "The Turbility at **%{unit_name}** is **%{status}**. Water is not safe to drink.",
681
+ "text_notification_content_smoke": "Smoke appears in **%{unit_name}**. Please check your home and call the rescue team if there is a fire.",
682
+ "text_notification_content_fire": "There is a fire at **%{unit_name}**, Please move out of the house immediately and call the rescue team.",
671
683
  "text_notification_content_remove_unit_to_owner": "Unit **%{unit_name}** has been removed successfully.",
672
684
  "text_notification_content_remove_unit_to_member": "Unit **%{unit_name}** has been removed by **%{unit_owner_name}**. You cannot access to this unit anymore.",
673
685
  "text_notification_content_remove_member": "You were remove from **%{unit_name}** by **%{unit_owner_name}**. You cannot access to this unit anymore.",
674
686
  "text_notification_content_member_leave_unit": "**%{member_name}** has left **%{unit_name}**.",
675
687
  "text_notification_content_rename_unit": "Unit **%{old_unit_name}** has been renamed to **%{new_unit_name}** by **%{owner_name}**.",
688
+ "text_notification_content_divice_disconnect": "**%{device_name}** at **%{unit_name}**: **%{sub_unit_name}** has been disconnected. Please check and reconnect.",
689
+ "text_notification_content_rename_sub_unit": "Sub-unit **%{old_sub_unit_name}**: **%{unit_name}** has been renamed to **%{new_sub_unit_name}** by **%{unti_owner_name}**.",
690
+ "text_notification_content_update_address": "New address of **%{unit_name}** has been updated by **%{unit_owner_name}** to **%{unit_address}**.",
676
691
  "this_spot_does_not_exsit": "This spot does not exist",
677
692
  "please_scan_again_or_contact_the_parking_manager": "Please scan again or contact the parking manager",
678
693
  "this_spot_does_not_support_to_scan": "This spot does not support to scan",
@@ -881,6 +896,7 @@
881
896
  "connecting_gateway_warning_2": "A message will appear asking you to connect.",
882
897
  "remove_account": "Remove Account",
883
898
  "text_sub_unit_not_have_device": "You don't have sub-unit with a device to control",
899
+ "brightness": "Brightness",
884
900
  "tap_to_add_new_schedule": "Tap + to add new schedule",
885
901
  "confirmation": "Confirmation",
886
902
  "enter_yes_to_perform": "You need to enter 'YES' to perform this action",
@@ -46,6 +46,7 @@
46
46
  "setup_the_conditions": "Cài đặt điều kiện",
47
47
  "setup_the_schedule": "Cài đặt thời gian ",
48
48
  "schedule": "Lịch trình",
49
+ "event": "Sự kiện",
49
50
  "des_launch_one_tap": "Tạo nút nhanh trên trang tổng quan",
50
51
  "active_list": "Danh sách hành động",
51
52
  "filtering": "Đang sục rửa",
@@ -310,7 +311,11 @@
310
311
  "manage_unit": "Quản lý địa điểm",
311
312
  "text_bad": "Xấu",
312
313
  "text_select_a_unit": "Chọn một địa điểm",
314
+ "text_select_sub_unit": "Chọn đơn vị",
315
+ "text_select_a_gateway": "Chọn một gateway",
313
316
  "text_select_a_unit_desc": "Chọn 1 địa điểm bạn muốn thêm thành viên",
317
+ "text_select_a_unit_have_device": "Đầu tiên, chọn một địa điểm có thiết bị này",
318
+ "select_a_sub_unit_want_add_device": "Sau đó, chọn một đơn vị con mà bạn muốn thêm thiết bị này vào",
314
319
  "text_select_permissions": "Chọn hành động",
315
320
  "text_select_permissions_desc": "Chọn các hành động cho phép",
316
321
  "text_read_config": "Thông số đọc",
@@ -676,11 +681,21 @@
676
681
  "text_notification_content_pay_fine_successfully": "Đỗ xe vi phạm **%{booking}** của bạn đã được thanh toán.",
677
682
  "text_notification_content_pay_fine_and_extend_successfully": "Đỗ xe vi phạm **%{oldbooking}** của bạn đã được thanh toán thành công. Phiên đỗ xe mới **%{newbooking}** sẽ kết thúc vào lúc **%{time}**.",
678
683
  "text_notification_content_stop_violation_free_parking_zone": "Thời gian đậu xe miễn phí. Bạn có một vi phạm chưa được thanh toán. Vui lòng hoàn thành tiền phạt của bạn.",
684
+ "text_notification_content_air_quality_high": "Chỉ số AQI tại **%{unit_name}** đang ở mức **%{status}**. Đeo khẩu trang và giảm các hoạt động ngoài trời để bảo vệ sức khoẻ của bạn.",
685
+ "text_notification_content_uv_index_high": "Chỉ số UV tại **%{unit_name}** đang ở mức **%{status}**. Giảm thời gian ngoài trời và bảo vệ da, mắt khỏi ánh nắng mặt trời.",
686
+ "text_notification_content_pH_index_high": "Độ pH của nước tại **%{unit_name}** đang ở mức **%{status}**. Nước không đảm bảo an toàn để uống.",
687
+ "text_notification_content_clo_high": "Độ clo của nước tại **%{unit_name}** đang ở mức **%{status}**. Nước không đảm bảo an toàn để uống.",
688
+ "text_notification_content_turbility_high": "Độ đục của nước tại **%{unit_name}** đang ở mức **%{status}**. Nước không đảm bảo an toàn để uống.",
689
+ "text_notification_content_smoke": "Xuất hiện khói tại **%{unit_name}**. Vui lòng kiểm tra nhà của bạn và gọi cho đội cứu hộ nếu xảy ra hỏa hoạn.",
690
+ "text_notification_content_fire": "Có đám cháy tại **%{unit_name}**, Vui lòng di chuyển ra khỏi nhà ngay lập tức và gọi cho đội cứu hộ.",
679
691
  "text_notification_content_remove_unit_to_owner": "Địa điểm **%{unit_name}** vừa được xoá thành công.",
680
692
  "text_notification_content_remove_unit_to_member": "Địa điểm **%{unit_name}** vừa được xoá bởi **%{unit_owner_name}**. Bạn không thể truy cập vào địa điểm này được nữa.",
681
693
  "text_notification_content_remove_member": "Bạn vừa được xoá khỏi **%{unit_name}** bởi **%{unit_owner_name}**. Bạn không thể truy cập vào địa điểm này được nữa.",
682
694
  "text_notification_content_member_leave_unit": "**%{member_name}** vừa rời khỏi **%{unit_name}**.",
683
695
  "text_notification_content_rename_unit": "Địa điểm **%{old_unit_name}** vừa được đổi tên thành **%{new_unit_name}** bởi **%{owner_name}**.",
696
+ "text_notification_content_divice_disconnect": "**%{device_name}** tại **%{unit_name}**: **%{sub_unit_name}** vừa bị mất kết nối. Vui lòng kiểm tra và kết nối lại.",
697
+ "text_notification_content_rename_sub_unit": "Khu vực **%{old_sub_unit_name}**: **%{unit_name}** vừa được đổi tên thành **%{new_sub_unit_name}** bởi **%{unti_owner_name}**.",
698
+ "text_notification_content_update_address": "Địa chỉ mới của **%{unit_name}** vừa được cập nhật bởi **%{unit_owner_name}** thành **%{unit_address}**.",
684
699
  "this_spot_does_not_exsit": "Vị trí đỗ này không tồn tại",
685
700
  "please_scan_again_or_contact_the_parking_manager": "Vui lòng quét lại hoặc liên hệ với người quản lý bãi đậu xe",
686
701
  "this_spot_does_not_support_to_scan": "Vị trí đỗ này không hỗ trợ quét",
@@ -883,7 +898,6 @@
883
898
  "add_gateway_success": "Thêm gateway thành công",
884
899
  "tap_to_add_new_schedule": "Nhấn + để thêm lịch trình mới",
885
900
  "remove_account": "Xóa tài khoản",
886
- "text_subunit_not_have_device": "Bạn không có khu vực nào có thiết bị để điều khiển",
887
901
  "choose_at_least_one": "Vui lòng chọn ít nhất 1 thiết bị.",
888
902
  "confirmation": "Xác Nhận",
889
903
  "enter_yes_to_perform": "Bạn cần nhập 'YES' để thực hiện hành động này",
@@ -893,6 +907,7 @@
893
907
  "curtain_closes": "Rèm đóng",
894
908
  "schedule_name": "Tên lịch trình",
895
909
  "enter_name": "Nhập tên",
910
+ "brightness": "Độ sáng",
896
911
  "name_smart_account": "Smart Account",
897
912
  "location_permission_required_wifi_title": "Quyền vị trí là bắt buộc đối với kết nối WiFi",
898
913
  "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.",
@@ -55,6 +55,8 @@ const Routes = {
55
55
  AddSubUnit: 'AddSubUnit',
56
56
  AddCommonSelectUnit: 'AddCommonSelectUnit',
57
57
  AddCommonSelectSubUnit: 'AddCommonSelectSubUnit',
58
+ AddGatewaySelectGateway: 'AddGatewaySelectGateway',
59
+ ConnectingProcess: 'ConnectingProcess',
58
60
  UnitMemberList: 'UnitMemberList',
59
61
  SharingSelectPermission: 'SharingSelectPermission',
60
62
  SharingInviteMembers: 'SharingInviteMembers',