@eohjsc/react-native-smart-city 0.2.99 → 0.3.2

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 (224) hide show
  1. package/README.md +1 -1
  2. package/package.json +6 -4
  3. package/react-native-smart-city.podspec +1 -0
  4. package/src/commons/Action/ItemQuickAction.js +11 -2
  5. package/src/commons/Action/__test__/ItemQuickAction.test.js +11 -6
  6. package/src/commons/ActionGroup/CurtainButtonTemplate.js +10 -5
  7. package/src/commons/ActionGroup/NumberUpDownActionTemplate.js +31 -20
  8. package/src/commons/ActionGroup/OnOffSmartLock/AutoLock/__test__/index.test.js +4 -0
  9. package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/ItemPasscode.js +1 -1
  10. package/src/commons/ActionGroup/OnOffSmartLock/PasscodeList/__test__/ItemPasscode.test.js +24 -0
  11. package/src/commons/ActionGroup/OnOffSmartLock/SetupGeneratePasscode/__test__/index.test.js +14 -0
  12. package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +1 -1
  13. package/src/commons/ActionGroup/SmartTiviActionTemplate/SmartTiviActionTemplate.js +3 -2
  14. package/src/commons/ActionGroup/StatesGridActionTemplate.js +8 -4
  15. package/src/commons/ActionGroup/TimerActionTemplate.js +2 -2
  16. package/src/commons/ActionGroup/TwoButtonTemplate/index.js +0 -1
  17. package/src/commons/ActionGroup/__test__/CurtainButtonTemplate.test.js +53 -4
  18. package/src/commons/ActionGroup/__test__/NumberUpDownTemplate.test.js +45 -48
  19. package/src/commons/ActionGroup/__test__/StatesGridActionTemplate.test.js +77 -0
  20. package/src/commons/ActionGroup/__test__/TimerActionTemplate.test.js +58 -6
  21. package/src/commons/ActionGroup/__test__/TwoButtonTemplate.test.js +49 -1
  22. package/src/commons/ActionGroup/__test__/index.test.js +137 -2
  23. package/src/commons/Automate/ItemAutomate.js +1 -3
  24. package/src/commons/Calendar/__test__/Calendar.test.js +33 -0
  25. package/src/commons/Connecting/__test__/Connecting.test.js +19 -2
  26. package/src/commons/ConnectingProcess/DeviceItem/DeviceItem.js +7 -3
  27. package/src/commons/ConnectingProcess/DeviceItem/DeviceItemStyles.js +8 -11
  28. package/src/commons/ConnectingProcess/__test__/Connecting.test.js +136 -3
  29. package/src/commons/ConnectingProcess/__test__/DeviceItem.test.js +3 -2
  30. package/src/commons/ConnectingProcess/index.js +72 -25
  31. package/src/commons/Dashboard/MyPinnedSharedUnit/__test__/MyPinnedSharedUnit.test.js +16 -13
  32. package/src/commons/Dashboard/MyPinnedSharedUnit/index.js +1 -1
  33. package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +0 -5
  34. package/src/commons/Device/ConnectedViewHeader.js +1 -1
  35. package/src/commons/Device/Hanet/ItemHanetDevice.test.js +58 -0
  36. package/src/commons/Device/HistoryChart.js +3 -3
  37. package/src/commons/Device/ItemDevice.js +15 -11
  38. package/src/commons/Device/LinearChart.js +15 -0
  39. package/src/commons/Device/SonosSpeaker/index.js +1 -1
  40. package/src/commons/Explore/__test__/CityItem.test.js +33 -54
  41. package/src/commons/FieldTemplate/ChooseUserField/__test__/index.test.js +19 -14
  42. package/src/commons/FieldTemplate/PasscodeField/__test__/index.test.js +0 -3
  43. package/src/commons/FieldTemplate/ScheduleField/__test__/index.test.js +0 -3
  44. package/src/commons/FieldTemplate/ScheduleField/index.js +2 -2
  45. package/src/commons/Header/HeaderCustom.js +2 -1
  46. package/src/commons/HorizontalPicker/index.js +2 -2
  47. package/src/commons/MediaPlayerDetail/Styles/MediaPlayerDetailStyles.js +0 -6
  48. package/src/commons/MediaPlayerDetail/index.js +24 -55
  49. package/src/commons/Sharing/__test__/DevicePermissionsCheckbox.test.js +0 -1
  50. package/src/commons/SubUnit/Favorites/index.js +2 -3
  51. package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +8 -35
  52. package/src/commons/SubUnit/OneTap/index.js +1 -2
  53. package/src/commons/SubUnit/ShortDetail.js +25 -9
  54. package/src/commons/SubUnit/__test__/Item.test.js +0 -1
  55. package/src/commons/SubUnit/__test__/ShortDetail.test.js +8 -1
  56. package/src/commons/Unit/SharedUnit.js +1 -0
  57. package/src/commons/Unit/__test__/SharedUnit.test.js +38 -183
  58. package/src/commons/UnitSummary/ConfigHistoryChart/index.js +2 -13
  59. package/src/commons/UnitSummary/ConfigHistoryChart.js +22 -13
  60. package/src/commons/WheelDateTimePicker/index.js +2 -2
  61. package/src/configs/API.js +85 -144
  62. package/src/configs/Constants.js +24 -0
  63. package/src/configs/SCConfig.js +2 -0
  64. package/src/context/actionType.ts +8 -0
  65. package/src/context/mockStore.ts +10 -0
  66. package/src/context/reducer.ts +38 -2
  67. package/src/hooks/Common/index.js +2 -0
  68. package/src/hooks/Common/useGGHomeDeviceConnected.js +16 -0
  69. package/src/hooks/Common/useGetIdUser.js +1 -5
  70. package/src/hooks/Common/useSensorsStatus.js +4 -4
  71. package/src/hooks/IoT/__test__/useGGHomeConnection.test.js +198 -0
  72. package/src/hooks/IoT/__test__/useRemoteControl.test.js +198 -0
  73. package/src/hooks/IoT/index.js +4 -0
  74. package/src/hooks/IoT/useGGHomeConnection.js +91 -0
  75. package/src/hooks/IoT/useRemoteControl.js +79 -0
  76. package/src/hooks/index.js +4 -0
  77. package/src/hooks/useReceiveNotifications.js +9 -5
  78. package/src/iot/Monitor.js +3 -2
  79. package/src/iot/RemoteControl/Bluetooth.js +1 -1
  80. package/src/iot/RemoteControl/GoogleHome.js +75 -49
  81. package/src/iot/RemoteControl/Internet.js +1 -1
  82. package/src/iot/RemoteControl/__test__/GoogleHome.test.js +95 -48
  83. package/src/iot/RemoteControl/__test__/Internet.test.js +18 -7
  84. package/src/iot/RemoteControl/__test__/LgThinq.test.js +36 -177
  85. package/src/iot/RemoteControl/index.js +52 -52
  86. package/src/screens/ActivityLog/__test__/index.test.js +38 -23
  87. package/src/screens/ActivityLog/hooks/__test__/index.test.js +51 -90
  88. package/src/screens/ActivityLog/hooks/index.js +1 -1
  89. package/src/screens/ActivityLog/index.js +2 -2
  90. package/src/screens/AddCommon/__test__/SelectSubUnit.test.js +13 -24
  91. package/src/screens/AddCommon/__test__/SelectUnit.test.js +9 -33
  92. package/src/screens/AddLocationMaps/index.js +5 -4
  93. package/src/screens/AddNewAction/SelectAction.js +8 -8
  94. package/src/screens/AddNewAction/SetupSensor.js +7 -7
  95. package/src/screens/AddNewAction/__test__/SelectAction.test.js +10 -91
  96. package/src/screens/AddNewAction/__test__/SelectSensorDevices.test.js +40 -26
  97. package/src/screens/AddNewDevice/ConnectingDevices.js +3 -3
  98. package/src/screens/AddNewDevice/__test__/AddNewDevice.test.js +34 -33
  99. package/src/screens/AddNewDevice/__test__/ConnectDevices.test.js +0 -4
  100. package/src/screens/AddNewDevice/__test__/ConnectingDevices.test.js +21 -21
  101. package/src/screens/AddNewDevice/hooks/ConnectDevices.js +1 -1
  102. package/src/screens/AddNewGateway/PlugAndPlay/ConnectWifiWarning.js +23 -17
  103. package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +3 -3
  104. package/src/screens/AddNewGateway/SetupGatewayWifi.js +1 -0
  105. package/src/screens/AddNewGateway/__test__/AddNewGateway.test.js +4 -6
  106. package/src/screens/AddNewGateway/__test__/ConnectedGateway.test.js +0 -4
  107. package/src/screens/AddNewGateway/__test__/ConnectingGateway.test.js +5 -29
  108. package/src/screens/AddNewGateway/__test__/SelectGateway.test.js +0 -4
  109. package/src/screens/AddNewGateway/__test__/SetupGateway.test.js +0 -4
  110. package/src/screens/AddNewOneTap/__test__/AddNewOneTap.test.js +9 -23
  111. package/src/screens/AllCamera/index.js +4 -4
  112. package/src/screens/Automate/MultiUnits.js +8 -8
  113. package/src/screens/Automate/__test__/MultiUnits.test.js +6 -9
  114. package/src/screens/Automate/__test__/index.test.js +7 -12
  115. package/src/screens/Automate/index.js +3 -3
  116. package/src/screens/ConfirmUnitDeletion/__test__/ConfirmUnitDeletion.test.js +36 -8
  117. package/src/screens/ConfirmUnitDeletion/index.js +7 -1
  118. package/src/screens/Device/EditDevice/__test__/EditDevice.test.js +71 -22
  119. package/src/screens/Device/EditDevice/index.js +2 -2
  120. package/src/screens/Device/__test__/detail.test.js +32 -85
  121. package/src/screens/Device/components/DetailHistoryChart.js +1 -1
  122. package/src/screens/Device/components/SensorConnectStatusViewHeader.js +1 -0
  123. package/src/screens/Device/components/SensorDisplayItem.js +5 -2
  124. package/src/screens/Device/detail.js +53 -22
  125. package/src/screens/Device/hooks/useDisconnectedDevice.js +4 -4
  126. package/src/screens/Device/hooks/useFavoriteDevice.js +5 -9
  127. package/src/screens/DeviceInfo/__test__/index.test.js +0 -2
  128. package/src/screens/EditActionsList/index.js +1 -1
  129. package/src/screens/EmergencyContacts/EmergencyContactsSelectContacts.js +1 -1
  130. package/src/screens/EmergencyContacts/__test__/EmergencyContactAddNew.test.js +7 -19
  131. package/src/screens/EmergencyContacts/__test__/EmergencyContactList.test.js +18 -14
  132. package/src/screens/EmergencyContacts/__test__/EmergencyContactsSelectContacts.test.js +30 -31
  133. package/src/screens/EmergencySetting/components/DropDownItem.js +2 -2
  134. package/src/screens/EnterPassword/__test__/EnterPassword.test.js +41 -25
  135. package/src/screens/GuestInfo/__test__/index.test.js +13 -40
  136. package/src/screens/HanetCamera/Detail.js +1 -1
  137. package/src/screens/HanetCamera/__test__/CaptureFaceID.test.js +8 -12
  138. package/src/screens/HanetCamera/__test__/Detail.test.js +27 -42
  139. package/src/screens/HanetCamera/__test__/ManageAccess.test.js +8 -5
  140. package/src/screens/HanetCamera/__test__/MemberInfo.test.js +10 -32
  141. package/src/screens/HanetCamera/components/RequestFaceIDPopup.js +3 -2
  142. package/src/screens/HanetCamera/hooks/__test__/useHanetCheckinData.test.js +43 -35
  143. package/src/screens/HanetCamera/hooks/__test__/useHanetPlaceMembers.test.js +10 -21
  144. package/src/screens/HanetCamera/hooks/useHanetCheckinData.js +11 -11
  145. package/src/screens/HanetCamera/hooks/useHanetPlaceMembers.js +11 -11
  146. package/src/screens/ManageAccess/__test__/ManageAccess.test.js +33 -22
  147. package/src/screens/ManageAccess/hooks/__test__/useManageAccess.test.js +44 -45
  148. package/src/screens/ManageAccess/hooks/index.js +7 -4
  149. package/src/screens/ManageAccess/index.js +1 -1
  150. package/src/screens/MoveToAnotherSubUnit/__test__/index.test.js +35 -12
  151. package/src/screens/MoveToAnotherSubUnit/index.js +5 -5
  152. package/src/screens/Notification/__test__/Notification.test.js +14 -25
  153. package/src/screens/Notification/__test__/NotificationItem.test.js +8 -7
  154. package/src/screens/Notification/components/NotificationItem.js +17 -20
  155. package/src/screens/Notification/index.js +9 -2
  156. package/src/screens/PlayBackCamera/Timer.js +2 -2
  157. package/src/screens/PlayBackCamera/__test__/index.test.js +87 -2
  158. package/src/screens/PlayBackCamera/index.js +22 -6
  159. package/src/screens/ScanChipQR/__test__/ScanChipQR.test.js +7 -20
  160. package/src/screens/ScanChipQR/hooks/index.js +15 -16
  161. package/src/screens/ScanSensorQR/__test__/ScanSensorQR.test.js +8 -24
  162. package/src/screens/ScriptDetail/__test__/index.test.js +17 -86
  163. package/src/screens/ScriptDetail/index.js +16 -11
  164. package/src/screens/SelectUnit/__test__/index.test.js +11 -54
  165. package/src/screens/SelectUnit/index.js +4 -2
  166. package/src/screens/SetSchedule/index.js +9 -9
  167. package/src/screens/SharedUnit/__test__/TabHeader.test.js +0 -2
  168. package/src/screens/Sharing/Components/SensorItem.js +10 -12
  169. package/src/screens/Sharing/InfoMemberUnit.js +1 -1
  170. package/src/screens/Sharing/SelectPermission.js +121 -76
  171. package/src/screens/Sharing/__test__/InfoMemberUnit.test.js +47 -29
  172. package/src/screens/Sharing/__test__/MemberList.test.js +13 -127
  173. package/src/screens/Sharing/__test__/MemberList2.test.js +80 -0
  174. package/src/screens/Sharing/__test__/SelectPermission.test.js +28 -38
  175. package/src/screens/Sharing/__test__/SelectUser.test.js +17 -38
  176. package/src/screens/SideMenuDetail/__test__/index.test.js +12 -23
  177. package/src/screens/SideMenuDetail/index.js +2 -3
  178. package/src/screens/SmartIr/components/GroupButtonByType/GroupButtonByType.js +3 -2
  179. package/src/screens/SubUnit/Detail.js +1 -2
  180. package/src/screens/SubUnit/ManageSubUnit.js +12 -7
  181. package/src/screens/SubUnit/__test__/AddSubUnit.test.js +21 -67
  182. package/src/screens/SubUnit/__test__/Detail.test.js +31 -8
  183. package/src/screens/SubUnit/__test__/EditSubUnit.test.js +21 -89
  184. package/src/screens/SubUnit/__test__/ManageSubUnit.test.js +27 -1
  185. package/src/screens/SubUnit/hooks/__test__/useManageSubUnit.test.js +48 -45
  186. package/src/screens/SubUnit/hooks/useManageSubUnit.js +7 -7
  187. package/src/screens/SyncLGDevice/__test__/AddLGDevice.test.js +14 -90
  188. package/src/screens/Unit/ChooseLocation.js +7 -14
  189. package/src/screens/Unit/Detail.js +30 -75
  190. package/src/screens/Unit/ManageUnit.js +1 -0
  191. package/src/screens/Unit/SelectAddress.js +34 -21
  192. package/src/screens/Unit/SmartAccount.js +4 -4
  193. package/src/screens/Unit/Summaries.js +17 -1
  194. package/src/screens/Unit/__test__/CheckSendEmail.test.js +24 -29
  195. package/src/screens/Unit/__test__/ChooseLocation.test.js +27 -14
  196. package/src/screens/Unit/__test__/Detail.test.js +99 -200
  197. package/src/screens/Unit/__test__/ManageUnit.test.js +18 -42
  198. package/src/screens/Unit/__test__/SelectAddress.test.js +84 -51
  199. package/src/screens/Unit/__test__/SmartAccount.test.js +17 -9
  200. package/src/screens/Unit/__test__/SmartAccountItem.test.js +0 -1
  201. package/src/screens/Unit/__test__/Summaries.test.js +100 -0
  202. package/src/screens/Unit/components/MyAllUnit/__test__/MyAllUnit.test.js +36 -0
  203. package/src/screens/Unit/components/MyAllUnit/__test__/index.test.js +54 -0
  204. package/src/screens/Unit/components/SharedUnit/index.js +1 -0
  205. package/src/screens/Unit/components/__test__/SharedUnit.test.js +31 -34
  206. package/src/screens/Unit/hook/useUnitConnectRemoteDevices.js +50 -0
  207. package/src/screens/Unit/styles.js +4 -0
  208. package/src/screens/UnitSummary/__test__/index.test.js +70 -41
  209. package/src/screens/UnitSummary/components/3PPowerConsumption/__test__/3PPowerConsumption.test.js +31 -2
  210. package/src/screens/UnitSummary/components/PowerConsumeHistoryChart/__test__/index.test.js +7 -4
  211. package/src/screens/UnitSummary/components/PowerConsumeHistoryChart/index.js +2 -13
  212. package/src/screens/UnitSummary/components/PowerConsumption/__test__/ItemPower.test.js +0 -1
  213. package/src/screens/UnitSummary/components/PowerConsumption/__test__/PowerConsumption.test.js +14 -16
  214. package/src/screens/UnitSummary/components/RunningDevices/__test__/index.test.js +11 -2
  215. package/src/screens/UnitSummary/components/RunningDevices/index.js +7 -10
  216. package/src/screens/UnitSummary/components/Temperature/index.js +4 -4
  217. package/src/screens/UnitSummary/components/WaterQuality/Item/index.js +10 -2
  218. package/src/screens/UnitSummary/index.js +15 -1
  219. package/src/utils/Apis/axios.js +46 -31
  220. package/src/utils/Converter/time.js +0 -18
  221. package/src/utils/I18n/translations/en.json +4 -1
  222. package/src/utils/I18n/translations/vi.json +5 -1
  223. package/src/utils/Permission/common.js +67 -0
  224. package/src/utils/Utils.js +11 -7
@@ -32,7 +32,6 @@ import {
32
32
  import { useFavoriteDevice } from './hooks/useFavoriteDevice';
33
33
  import BottomButtonView from '../../commons/BottomButtonView';
34
34
  import Text from '../../commons/Text';
35
- import { transformDatetime } from '../../utils/Converter/time';
36
35
  import { AlertAction, ButtonPopup, MenuActionMore } from '../../commons';
37
36
  import { TESTID } from '../../configs/Constants';
38
37
 
@@ -40,7 +39,12 @@ import { usePopover } from '../../hooks/Common';
40
39
  import { useConfigGlobalState } from '../../iot/states';
41
40
  import { useNavigation } from '@react-navigation/native';
42
41
  import styles from './styles';
43
- import { useIsOwnerOfUnit, useBoolean } from '../../hooks/Common';
42
+ import {
43
+ useIsOwnerOfUnit,
44
+ useBoolean,
45
+ useGGHomeDeviceConnected,
46
+ } from '../../hooks/Common';
47
+ import { useGGHomeConnection } from '../../hooks/IoT';
44
48
  import { SensorDisplayItem } from './components/SensorDisplayItem';
45
49
  import { useSCContextSelector } from '../../context';
46
50
  import { EmergencyCountdown } from './components/EmergencyCountdown';
@@ -48,6 +52,7 @@ import { SensorConnectStatusViewHeader } from './components/SensorConnectStatusV
48
52
  import { useDisconnectedDevice } from './hooks/useDisconnectedDevice';
49
53
  import { Card } from '../../commons/CardShadow';
50
54
  import PreventAccess from '../../commons/PreventAccess';
55
+ import { notImplemented } from '../../utils/Utils';
51
56
 
52
57
  const DeviceDetail = ({ route }) => {
53
58
  const t = useTranslations();
@@ -66,8 +71,7 @@ const DeviceDetail = ({ route }) => {
66
71
  // eslint-disable-next-line no-unused-vars
67
72
  const [configValues, setConfigValues] = useConfigGlobalState('configValues');
68
73
 
69
- const { unitData, unitId, sensorData, sensorId, isGGHomeConnected } =
70
- route.params;
74
+ const { unitData, unitId, sensorData, sensorId } = route.params;
71
75
  const [unit, setUnit] = useState(unitData || { id: unitId });
72
76
  const [sensor, setSensor] = useState(sensorData || { id: sensorId });
73
77
  const [station, setStation] = useState(sensor?.station);
@@ -89,6 +93,7 @@ const DeviceDetail = ({ route }) => {
89
93
  const isBluetoothEnabled = useSCContextSelector((state) => {
90
94
  return state.app.isBluetoothEnabled;
91
95
  });
96
+ const { isConnected: isGGHomeConnected } = useGGHomeDeviceConnected(sensor);
92
97
 
93
98
  const isDeviceConnectedViaBle = useMemo(
94
99
  () =>
@@ -131,10 +136,8 @@ const DeviceDetail = ({ route }) => {
131
136
  [display.items]
132
137
  );
133
138
 
134
- const { isFavorite, addToFavorites, removeFromFavorites } = useFavoriteDevice(
135
- unit,
136
- sensor
137
- );
139
+ const { isFavorite, addToFavorites, removeFromFavorites } =
140
+ useFavoriteDevice(sensor);
138
141
 
139
142
  const currentUserId = useSelector((state) =>
140
143
  get(state, 'auth.account.user.id', 0)
@@ -159,9 +162,24 @@ const DeviceDetail = ({ route }) => {
159
162
  }
160
163
  }, [fetchUnitDetail, unitId, unitData]);
161
164
 
165
+ const { connectGoogleHome } = useGGHomeConnection();
166
+
167
+ useEffect(() => {
168
+ if (
169
+ unit.remote_control_options &&
170
+ unit.remote_control_options.googlehome?.length &&
171
+ isNetworkConnected
172
+ ) {
173
+ (async () => {
174
+ await connectGoogleHome(unit.remote_control_options.googlehome);
175
+ })();
176
+ }
177
+ // eslint-disable-next-line react-hooks/exhaustive-deps
178
+ }, [unit, isNetworkConnected]);
179
+
162
180
  const fetchSensorDetail = useCallback(async () => {
163
181
  const { success, data, resp_status } = await axiosGet(
164
- API.SENSOR.SENSOR_DETAIL(sensorId)
182
+ API.DEVICE.SENSOR_DETAIL(sensorId)
165
183
  );
166
184
  if (success) {
167
185
  setSensor(data);
@@ -187,7 +205,7 @@ const DeviceDetail = ({ route }) => {
187
205
  }
188
206
 
189
207
  const { success, data } = await axiosGet(
190
- API.SENSOR.DISPLAY(sensor?.id),
208
+ API.DEVICE.DISPLAY(sensor?.id),
191
209
  {},
192
210
  true
193
211
  );
@@ -197,10 +215,10 @@ const DeviceDetail = ({ route }) => {
197
215
  setServerDown(false);
198
216
  if (data.items.length) {
199
217
  const config = data.items[0].configuration;
200
- if (config.hasOwnProperty('max_value')) {
218
+ if (Object.prototype.hasOwnProperty.call(config, 'max_value')) {
201
219
  setMaxValue(config.max_value);
202
220
  }
203
- if (config.hasOwnProperty('device')) {
221
+ if (Object.prototype.hasOwnProperty.call(config, 'device')) {
204
222
  // for emergency
205
223
  setDeviceId(config.device.id);
206
224
  const last_event = config.device.last_event;
@@ -211,14 +229,14 @@ const DeviceDetail = ({ route }) => {
211
229
  }
212
230
  }
213
231
  }
214
- if (data.side_menu_items.length) {
232
+ if (data?.side_menu_items?.length) {
215
233
  setSideMenu(data.side_menu_items);
216
234
  }
217
235
  }
218
236
  setLoading((preState) => ({ ...preState, displayTemplate: false }));
219
237
 
220
238
  const controlResult = await axiosGet(
221
- API.SENSOR.REMOTE_CONTROL_OPTIONS(sensor?.id),
239
+ API.DEVICE.REMOTE_CONTROL_OPTIONS(sensor?.id),
222
240
  {},
223
241
  true
224
242
  );
@@ -395,7 +413,7 @@ const DeviceDetail = ({ route }) => {
395
413
  const { countUpStr } = useCountUp(lastEvent.reportedAt);
396
414
 
397
415
  useEffect(() => {
398
- if (controlOptions.bluetooth) {
416
+ if (controlOptions?.bluetooth) {
399
417
  const bluetooth = controlOptions.bluetooth;
400
418
  scanBluetoothDevices([bluetooth.address]);
401
419
  }
@@ -407,8 +425,17 @@ const DeviceDetail = ({ route }) => {
407
425
 
408
426
  const onRefresh = useCallback(() => {
409
427
  fetchDataDeviceDetail();
428
+ if (
429
+ unit.remote_control_options &&
430
+ unit.remote_control_options.googlehome?.length &&
431
+ isNetworkConnected
432
+ ) {
433
+ (async () => {
434
+ await connectGoogleHome(unit.remote_control_options.googlehome);
435
+ })();
436
+ }
410
437
  // eslint-disable-next-line react-hooks/exhaustive-deps
411
- }, [sensor, fetchDataDeviceDetail]);
438
+ }, [sensor, unit, isNetworkConnected, fetchDataDeviceDetail]);
412
439
 
413
440
  const getData = useCallback(
414
441
  (item) => {
@@ -435,6 +462,7 @@ const DeviceDetail = ({ route }) => {
435
462
  if (item.type !== 'value') {
436
463
  return;
437
464
  }
465
+
438
466
  if (!item.configuration) {
439
467
  return;
440
468
  }
@@ -452,7 +480,7 @@ const DeviceDetail = ({ route }) => {
452
480
 
453
481
  const fetchValues = async () => {
454
482
  const { success, data, resp_status } = await axiosGet(
455
- API.SENSOR.DISPLAY_VALUES_V2(sensor?.id),
483
+ API.DEVICE.DISPLAY_VALUES_V2(sensor?.id),
456
484
  {
457
485
  params: params,
458
486
  }
@@ -460,7 +488,10 @@ const DeviceDetail = ({ route }) => {
460
488
  if (success) {
461
489
  setDisplayValues(data.configs);
462
490
  setConnected(data.is_connected);
463
- transformDatetime(data, ['last_updated']);
491
+ data.last_updated = data.last_updated
492
+ ? moment(data.last_updated)
493
+ : data.last_updated;
494
+
464
495
  setLastUpdated(data.last_updated);
465
496
  } else if (resp_status >= 500) {
466
497
  setServerDown(true);
@@ -480,7 +511,7 @@ const DeviceDetail = ({ route }) => {
480
511
  useEffect(() => {
481
512
  setDisplayValues((currentDisplayValues) => {
482
513
  for (const [configId, value] of Object.entries(configValues)) {
483
- const intId = parseInt(configId);
514
+ const intId = parseInt(configId, 10);
484
515
  const index = currentDisplayValues.findIndex(
485
516
  (element) => element.id === intId
486
517
  );
@@ -604,12 +635,12 @@ const DeviceDetail = ({ route }) => {
604
635
 
605
636
  const getDataFromLocal = async () => {
606
637
  const displayData = await getLocalData(
607
- `@CACHE_REQUEST_${API.SENSOR.DISPLAY(sensor?.id)}`
638
+ `@CACHE_REQUEST_${API.DEVICE.DISPLAY(sensor?.id)}`
608
639
  );
609
640
  displayData && setDisplay(JSON.parse(displayData));
610
641
 
611
642
  const controlOptionData = await getLocalData(
612
- `@CACHE_REQUEST_${API.SENSOR.REMOTE_CONTROL_OPTIONS(sensor?.id)}`
643
+ `@CACHE_REQUEST_${API.DEVICE.REMOTE_CONTROL_OPTIONS(sensor?.id)}`
613
644
  );
614
645
  controlOptionData && setControlOptions(JSON.parse(controlOptionData));
615
646
  setLoading((preState) => ({ ...preState, displayTemplate: false }));
@@ -621,7 +652,7 @@ const DeviceDetail = ({ route }) => {
621
652
  } else if (item.doAction) {
622
653
  item.doAction();
623
654
  } else {
624
- alert(t('feature_under_development'));
655
+ notImplemented(t);
625
656
  }
626
657
  };
627
658
 
@@ -47,7 +47,7 @@ export const useDisconnectedDevice = (
47
47
  );
48
48
 
49
49
  const checkNetworkConnect = useCallback(
50
- async (isNetworkConnected, isBluetoothEnabled, serverDown) => {
50
+ async () => {
51
51
  if (!isDeviceHasBle) {
52
52
  return;
53
53
  }
@@ -72,10 +72,10 @@ export const useDisconnectedDevice = (
72
72
  }
73
73
  },
74
74
  // eslint-disable-next-line react-hooks/exhaustive-deps
75
- [isDeviceHasBle]
75
+ [isDeviceHasBle, isNetworkConnected, isBluetoothEnabled, serverDown]
76
76
  );
77
77
 
78
78
  useEffect(() => {
79
- checkNetworkConnect(isNetworkConnected, isBluetoothEnabled, serverDown);
80
- }, [isNetworkConnected, isBluetoothEnabled, checkNetworkConnect, serverDown]);
79
+ checkNetworkConnect();
80
+ }, [checkNetworkConnect]);
81
81
  };
@@ -4,7 +4,7 @@ import { SCContext, useSCContextSelector } from '../../../context';
4
4
  import { Action } from '../../../context/actionType';
5
5
  import { axiosPost } from '../../../utils/Apis/axios';
6
6
 
7
- export const useFavoriteDevice = (unit, device) => {
7
+ export const useFavoriteDevice = (device) => {
8
8
  const { setAction } = useContext(SCContext);
9
9
  const favoriteDeviceIds = useSCContextSelector(
10
10
  (state) => state.unit.favoriteDeviceIds
@@ -14,21 +14,17 @@ export const useFavoriteDevice = (unit, device) => {
14
14
 
15
15
  const addToFavorites = useCallback(async () => {
16
16
  const { success } = await axiosPost(
17
- API.SENSOR.ADD_TO_FAVOURITES(unit?.id, device?.station?.id, device?.id)
17
+ API.DEVICE.ADD_TO_FAVOURITES(device?.id)
18
18
  );
19
19
  success && setAction(Action.ADD_DEVICE_TO_FAVORITES, device.id);
20
- }, [unit, device, setAction]);
20
+ }, [device, setAction]);
21
21
 
22
22
  const removeFromFavorites = useCallback(async () => {
23
23
  const { success } = await axiosPost(
24
- API.SENSOR.REMOVE_FROM_FAVOURITES(
25
- unit?.id,
26
- device?.station?.id,
27
- device?.id
28
- )
24
+ API.DEVICE.REMOVE_FROM_FAVOURITES(device?.id)
29
25
  );
30
26
  success && setAction(Action.REMOVE_DEVICE_FROM_FAVORITES, device.id);
31
- }, [unit, device, setAction]);
27
+ }, [device, setAction]);
32
28
 
33
29
  return {
34
30
  isFavorite,
@@ -7,8 +7,6 @@ import { View } from 'react-native';
7
7
  import { SCProvider } from '../../../context';
8
8
  import { mockSCStore } from '../../../context/mockStore';
9
9
 
10
- jest.mock('axios');
11
-
12
10
  jest.mock('@react-navigation/core', () => {
13
11
  return {
14
12
  ...jest.requireActual('@react-navigation/core'),
@@ -142,7 +142,7 @@ const EditActionsList = () => {
142
142
  data={actionsList}
143
143
  renderItem={renderItem}
144
144
  keyExtractor={(item) => `draggable-item-${item.key}`}
145
- onDragEnd={({ data }) => setActionList(data)}
145
+ onDragEnd={({ data: dragData }) => setActionList(dragData)}
146
146
  extraData={actionsList}
147
147
  containerStyle={styles.containerStyle}
148
148
  />
@@ -75,7 +75,7 @@ export const EmergencyContactsSelectContacts = ({ route }) => {
75
75
  {dataContact.map((contact, index) => (
76
76
  <RowUser
77
77
  key={contact.id.toString()}
78
- testID={TESTID.EMERGENCY_SELECT_CONTACT}
78
+ testID={TESTID.EMERGENCY_SELECT_CONTACT + index}
79
79
  index={index}
80
80
  leftIcon={
81
81
  <IconOutline name={'user'} size={20} color={Colors.White} />
@@ -2,13 +2,15 @@ import React from 'react';
2
2
  import { TextInput } from 'react-native';
3
3
  import { act, create } from 'react-test-renderer';
4
4
  import { EmergencyContactsAddNew } from '../EmergencyContactsAddNew';
5
- import axios from 'axios';
5
+ import MockAdapter from 'axios-mock-adapter';
6
6
  import Toast from 'react-native-toast-message';
7
7
  import { ViewButtonBottom } from '../../../commons';
8
8
  import { TESTID } from '../../../configs/Constants';
9
9
  import { getTranslate } from '../../../utils/I18n';
10
10
  import { SCProvider } from '../../../context';
11
11
  import { mockSCStore } from '../../../context/mockStore';
12
+ import api from '../../../utils/Apis/axios';
13
+ import { API } from '../../../configs';
12
14
 
13
15
  const wrapComponent = (route) => (
14
16
  <SCProvider initState={mockSCStore({})}>
@@ -20,7 +22,7 @@ jest.mock('react-native-toast-message');
20
22
 
21
23
  const mockedGoBack = jest.fn();
22
24
 
23
- jest.mock('axios');
25
+ const mock = new MockAdapter(api.axiosInstance);
24
26
 
25
27
  jest.mock('@react-navigation/native', () => {
26
28
  return {
@@ -105,13 +107,7 @@ describe('test EmergencyContactAddNew', () => {
105
107
  });
106
108
 
107
109
  test('onSave success', async () => {
108
- const response = {
109
- status: 200,
110
- data: {},
111
- };
112
- axios.post.mockImplementation(async () => {
113
- return response;
114
- });
110
+ mock.onPost(API.EMERGENCY_BUTTON.CREATE_CONTACT()).reply(200);
115
111
 
116
112
  await act(async () => {
117
113
  tree = await create(wrapComponent(route));
@@ -127,22 +123,14 @@ describe('test EmergencyContactAddNew', () => {
127
123
  });
128
124
 
129
125
  test('onSave fail', async () => {
130
- const response = {
131
- data: {},
132
- };
133
- axios.post.mockImplementation(async () => {
134
- return response;
135
- });
136
-
137
126
  await act(async () => {
138
127
  tree = await create(wrapComponent(route));
139
128
  });
140
129
  const instance = tree.root;
141
130
  const viewButtonBottom = instance.findByType(ViewButtonBottom);
142
131
 
143
- await act(async () => {
144
- await viewButtonBottom.props.onRightClick();
145
- });
132
+ mock.onPost(API.EMERGENCY_BUTTON.CREATE_CONTACT()).reply(400);
133
+ await viewButtonBottom.props.onRightClick();
146
134
  expect(Toast.show).toHaveBeenCalledWith({
147
135
  type: 'error',
148
136
  position: 'bottom',
@@ -1,16 +1,19 @@
1
1
  import React from 'react';
2
2
  import { TouchableOpacity } from 'react-native';
3
3
  import { act, create } from 'react-test-renderer';
4
+ import MockAdapter from 'axios-mock-adapter';
5
+
4
6
  import Routes from '../../../utils/Route';
5
- import axios from 'axios';
6
7
  import { API } from '../../../configs';
7
-
8
8
  import { AlertAction } from '../../../commons';
9
9
  import { EmergencyContactsList } from '../EmergencyContactsList';
10
10
  import { TESTID } from '../../../configs/Constants';
11
11
  import { getTranslate } from '../../../utils/I18n';
12
12
  import { SCProvider } from '../../../context';
13
13
  import { mockSCStore } from '../../../context/mockStore';
14
+ import api from '../../../utils/Apis/axios';
15
+
16
+ const mock = new MockAdapter(api.axiosInstance);
14
17
 
15
18
  const wrapComponent = (route) => (
16
19
  <SCProvider initState={mockSCStore({})}>
@@ -26,12 +29,10 @@ jest.mock('@react-navigation/native', () => {
26
29
  useNavigation: () => ({
27
30
  navigate: mockedNavigate,
28
31
  }),
29
- useIsFocused: jest.fn(),
32
+ useIsFocused: () => true,
30
33
  };
31
34
  });
32
35
 
33
- jest.mock('axios');
34
-
35
36
  describe('test EmergencyContactList', () => {
36
37
  let route;
37
38
 
@@ -42,7 +43,6 @@ describe('test EmergencyContactList', () => {
42
43
  group: 1,
43
44
  },
44
45
  };
45
- axios.delete.mockClear();
46
46
  });
47
47
  let tree;
48
48
 
@@ -56,20 +56,24 @@ describe('test EmergencyContactList', () => {
56
56
  });
57
57
  const instance = tree.root;
58
58
  const alertAction = instance.findByType(AlertAction);
59
-
60
- const response = { status: 204 };
61
- axios.delete.mockImplementation(async () => {
62
- return response;
59
+ mock.onDelete(API.EMERGENCY_BUTTON.REMOVE_CONTACTS()).reply(204);
60
+ act(() => {
61
+ alertAction.props.rightButtonClick();
63
62
  });
63
+ expect(alertAction.props.visible).toBe(false);
64
+ });
64
65
 
66
+ test('handleRemove failure', async () => {
67
+ act(() => {
68
+ tree = create(wrapComponent(route));
69
+ });
70
+ const instance = tree.root;
71
+ const alertAction = instance.findByType(AlertAction);
72
+ mock.onDelete(API.EMERGENCY_BUTTON.REMOVE_CONTACTS()).reply(400);
65
73
  act(() => {
66
74
  alertAction.props.rightButtonClick();
67
75
  });
68
-
69
76
  expect(alertAction.props.visible).toBe(false);
70
- expect(axios.delete).toHaveBeenCalledWith(
71
- API.EMERGENCY_BUTTON.REMOVE_CONTACTS()
72
- );
73
77
  });
74
78
 
75
79
  test('onAddNew', async () => {
@@ -1,14 +1,18 @@
1
1
  import React from 'react';
2
2
  import { act, create } from 'react-test-renderer';
3
- import axios from 'axios';
3
+ import MockAdapter from 'axios-mock-adapter';
4
+ import Toast from 'react-native-toast-message';
5
+
4
6
  import { EmergencyContactsSelectContacts } from '../EmergencyContactsSelectContacts';
5
7
  import { TESTID } from '../../../configs/Constants';
6
8
  import { SCProvider } from '../../../context';
7
9
  import { mockSCStore } from '../../../context/mockStore';
8
10
  import { API } from '../../../configs';
9
11
  import { ViewButtonBottom } from '../../../commons';
12
+ import api from '../../../utils/Apis/axios';
13
+ import { getTranslate } from '../../../utils/I18n';
10
14
 
11
- jest.mock('axios');
15
+ const mock = new MockAdapter(api.axiosInstance);
12
16
 
13
17
  const mockedNavigate = jest.fn();
14
18
  jest.mock('@react-navigation/native', () => {
@@ -45,7 +49,6 @@ describe('test EmergencyContactsSelectContacts', () => {
45
49
  tree = create(wrapComponent(route));
46
50
  });
47
51
  const instance = tree.root;
48
-
49
52
  const rowUser = instance.findAllByProps(
50
53
  (item) => item.props.testID === TESTID.EMERGENCY_SELECT_CONTACT
51
54
  );
@@ -54,50 +57,41 @@ describe('test EmergencyContactsSelectContacts', () => {
54
57
 
55
58
  test('render emergencyContactsSelectContacts success', async () => {
56
59
  jest.useFakeTimers();
57
- const response = {
58
- status: 200,
59
- data: {
60
- data: {},
61
- },
62
- };
63
- axios.get.mockImplementation(() => Promise.resolve(response));
64
-
65
- act(() => {
66
- tree = create(wrapComponent(route));
60
+ mock.onGet(API.SHARE.UNITS_MEMBERS(1, 1)).reply(200, {
61
+ id: 1,
62
+ name: 'test',
63
+ phone_number: 1,
67
64
  });
68
65
  act(() => {
69
- jest.runOnlyPendingTimers();
66
+ tree = create(wrapComponent(route));
70
67
  });
71
- expect(axios.get).toHaveBeenCalled();
72
- expect(axios.get).toHaveBeenCalledWith(API.SHARE.UNITS_MEMBERS(1, 1), {});
68
+ const instance = tree.root;
69
+ const rowUser = instance.findAllByProps(
70
+ (item) => item.props.testID === TESTID.EMERGENCY_SELECT_CONTACT + 0
71
+ );
72
+ expect(rowUser[0]).toBeDefined();
73
73
  });
74
74
 
75
75
  test('test onSave emergencyContactsSelectContacts', async () => {
76
- const response = {
77
- status: 200,
78
- };
79
- axios.post.mockImplementation(async () => {
80
- return response;
81
- });
76
+ mock.onPost(API.EMERGENCY_BUTTON.CREATE_BATCH()).reply(200);
82
77
  act(() => {
83
78
  tree = create(wrapComponent(route));
84
79
  });
85
80
  const instance = tree.root;
86
-
87
81
  const viewButtonBottom = instance.findByType(ViewButtonBottom);
88
82
  await act(async () => {
89
83
  viewButtonBottom.props.onRightClick();
90
84
  });
91
- expect(axios.post).toHaveBeenCalled();
85
+ expect(Toast.show).toBeCalledWith({
86
+ type: 'success',
87
+ position: 'bottom',
88
+ text1: getTranslate('en', 'saving_contact_successful'),
89
+ visibilityTime: 1000,
90
+ });
92
91
  });
93
92
 
94
93
  test('test onSave emergencyContactsSelectContacts fail', async () => {
95
- const response = {
96
- status: 500,
97
- };
98
- axios.post.mockImplementation(async () => {
99
- return response;
100
- });
94
+ mock.onPost(API.EMERGENCY_BUTTON.CREATE_BATCH()).reply(500);
101
95
  act(() => {
102
96
  tree = create(wrapComponent(route));
103
97
  });
@@ -107,6 +101,11 @@ describe('test EmergencyContactsSelectContacts', () => {
107
101
  await act(async () => {
108
102
  viewButtonBottom.props.onRightClick();
109
103
  });
110
- expect(axios.post).toHaveBeenCalled();
104
+ expect(Toast.show).toBeCalledWith({
105
+ type: 'error',
106
+ position: 'bottom',
107
+ text1: getTranslate('en', 'create_contact_failed'),
108
+ visibilityTime: 1000,
109
+ });
111
110
  });
112
111
  });
@@ -34,11 +34,11 @@ const DropDownItem = ({ label, data, onSelectItem, isOpen, onOpen, index }) => {
34
34
 
35
35
  {isOpen && (
36
36
  <View style={[styles.dropDownItem]}>
37
- {data.map((item, index) => (
37
+ {data.map((item, i) => (
38
38
  <Text
39
39
  style={styles.dropDownText}
40
40
  onPress={handleSelectItem(item)}
41
- key={index}
41
+ key={i}
42
42
  testID={TESTID.DROP_DOWN_PICKER_ITEM}
43
43
  >
44
44
  {item?.label}
@@ -1,15 +1,16 @@
1
1
  import React from 'react';
2
2
  import { create, act } from 'react-test-renderer';
3
3
  import { TouchableOpacity } from 'react-native';
4
- import axios from 'axios';
4
+ import MockAdapter from 'axios-mock-adapter';
5
5
 
6
6
  import { SCProvider } from '../../../context';
7
7
  import { mockSCStore } from '../../../context/mockStore';
8
8
  import EnterPassword from '../index';
9
9
  import { TESTID } from '../../../configs/Constants';
10
10
  import { API } from '../../../configs';
11
+ import api from '../../../utils/Apis/axios';
11
12
 
12
- jest.mock('axios');
13
+ const mock = new MockAdapter(api.axiosInstance);
13
14
 
14
15
  const wrapComponent = (route) => (
15
16
  <SCProvider initState={mockSCStore({})}>
@@ -37,20 +38,11 @@ describe('Test EnterPassword', () => {
37
38
  el.type === TouchableOpacity
38
39
  );
39
40
  };
40
- const mockAxios = (response, method) => {
41
- switch (method) {
42
- case 'get':
43
- return axios.get.mockImplementation(async () => {
44
- return response;
45
- });
46
- case 'put':
47
- return axios.put.mockImplementation(async () => {
48
- return response;
49
- });
50
- default:
51
- return '';
52
- }
53
- };
41
+
42
+ beforeEach(() => {
43
+ mockNavigate.mockClear();
44
+ });
45
+
54
46
  test('test render EnterPassword button done', () => {
55
47
  const route = {
56
48
  params: { dataParams: {}, type: '' },
@@ -63,6 +55,16 @@ describe('Test EnterPassword', () => {
63
55
  expect(button).toHaveLength(1);
64
56
  });
65
57
 
58
+ test('test render EnterPassword has not params', () => {
59
+ const route = {};
60
+ act(() => {
61
+ tree = create(wrapComponent(route));
62
+ });
63
+ const instance = tree.root;
64
+ const button = buttonDone(instance);
65
+ expect(button).toHaveLength(1);
66
+ });
67
+
66
68
  test('test render EnterPassword text input password', () => {
67
69
  const route = {
68
70
  params: { dataParams: {}, type: '' },
@@ -102,11 +104,7 @@ describe('Test EnterPassword', () => {
102
104
  type: 'infoMemberUnit',
103
105
  },
104
106
  };
105
- const responsePut = {
106
- status: 200,
107
- data: { id: 1, user_id: 1 },
108
- };
109
- await mockAxios(responsePut, 'put');
107
+ mock.onPut(API.UNIT.CHANGE_OWNER(1)).reply(200, { id: 1, user_id: 1 });
110
108
  await act(async () => {
111
109
  tree = await create(wrapComponent(route));
112
110
  });
@@ -115,10 +113,28 @@ describe('Test EnterPassword', () => {
115
113
  await act(async () => {
116
114
  await button[0].props.onPress();
117
115
  });
118
- expect(axios.put).toHaveBeenCalledTimes(1);
119
- expect(axios.put).toHaveBeenCalledWith(API.UNIT.CHANGE_OWNER(1), {
120
- confirm_password: '',
121
- new_owner: 1,
116
+ expect(mockNavigate).toBeCalled();
117
+ });
118
+
119
+ test('test EnterPassword button failure', async () => {
120
+ const route = {
121
+ params: {
122
+ dataParams: {
123
+ unit_id: 1,
124
+ member: { id: 1 },
125
+ },
126
+ type: 'infoMemberUnit',
127
+ },
128
+ };
129
+ await act(async () => {
130
+ tree = await create(wrapComponent(route));
131
+ });
132
+ const instance = tree.root;
133
+ const button = buttonDone(instance);
134
+ mock.onPut(API.UNIT.CHANGE_OWNER(1)).reply(400);
135
+ await act(async () => {
136
+ await button[0].props.onPress();
122
137
  });
138
+ expect(mockNavigate).not.toBeCalled();
123
139
  });
124
140
  });