@eohjsc/react-native-smart-city 0.2.98 → 0.3.1

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 (238) hide show
  1. package/README.md +36 -15
  2. package/package.json +5 -3
  3. package/src/commons/Action/ItemQuickAction.js +11 -2
  4. package/src/commons/Action/__test__/ItemQuickAction.test.js +11 -6
  5. package/src/commons/ActionGroup/CurtainButtonTemplate.js +10 -5
  6. package/src/commons/ActionGroup/NumberUpDownActionTemplate.js +32 -21
  7. package/src/commons/ActionGroup/OnOffSmartLock/AutoLock/__test__/index.test.js +4 -0
  8. package/src/commons/ActionGroup/OnOffSmartLock/OnOffSmartLock.js +3 -3
  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/OnOffTemplate/OnOffSimpleTemplate.js +1 -3
  13. package/src/commons/ActionGroup/OnOffTemplate/index.js +15 -45
  14. package/src/commons/ActionGroup/OptionsDropdownActionTemplate.js +1 -1
  15. package/src/commons/ActionGroup/SmartTiviActionTemplate/SmartTiviActionTemplate.js +3 -2
  16. package/src/commons/ActionGroup/StatesGridActionTemplate.js +8 -4
  17. package/src/commons/ActionGroup/TimerActionTemplate.js +2 -2
  18. package/src/commons/ActionGroup/TwoButtonTemplate/index.js +6 -7
  19. package/src/commons/ActionGroup/__test__/CurtainButtonTemplate.test.js +53 -4
  20. package/src/commons/ActionGroup/__test__/NumberUpDownTemplate.test.js +45 -48
  21. package/src/commons/ActionGroup/__test__/StatesGridActionTemplate.test.js +77 -0
  22. package/src/commons/ActionGroup/__test__/TimerActionTemplate.test.js +58 -6
  23. package/src/commons/ActionGroup/__test__/TwoButtonTemplate.test.js +49 -1
  24. package/src/commons/ActionGroup/__test__/index.test.js +137 -2
  25. package/src/commons/Automate/ItemAutomate.js +1 -3
  26. package/src/commons/Calendar/__test__/Calendar.test.js +33 -0
  27. package/src/commons/Connecting/__test__/Connecting.test.js +19 -2
  28. package/src/commons/ConnectingProcess/__test__/Connecting.test.js +136 -3
  29. package/src/commons/ConnectingProcess/index.js +12 -8
  30. package/src/commons/Dashboard/MyPinnedSharedUnit/__test__/MyPinnedSharedUnit.test.js +16 -13
  31. package/src/commons/Dashboard/MyPinnedSharedUnit/index.js +1 -1
  32. package/src/commons/Dashboard/MyUnit/__test__/MyUnit.test.js +0 -5
  33. package/src/commons/Device/ConnectedViewHeader.js +1 -1
  34. package/src/commons/Device/Hanet/ItemHanetDevice.test.js +58 -0
  35. package/src/commons/Device/HistoryChart.js +3 -3
  36. package/src/commons/Device/ItemDevice.js +15 -11
  37. package/src/commons/Device/LinearChart.js +15 -0
  38. package/src/commons/Device/SonosSpeaker/index.js +1 -1
  39. package/src/commons/Explore/__test__/CityItem.test.js +33 -54
  40. package/src/commons/FieldTemplate/ChooseUserField/ChooseFieldStyles.js +25 -0
  41. package/src/commons/FieldTemplate/ChooseUserField/ChoosePopup.js +96 -0
  42. package/src/commons/FieldTemplate/ChooseUserField/ChoosePopupStyles.js +39 -0
  43. package/src/commons/FieldTemplate/ChooseUserField/__test__/index.test.js +118 -0
  44. package/src/commons/FieldTemplate/ChooseUserField/index.js +62 -0
  45. package/src/commons/FieldTemplate/PasscodeField/PasscodeFieldStyles.js +30 -0
  46. package/src/commons/FieldTemplate/PasscodeField/__test__/index.test.js +90 -0
  47. package/src/commons/FieldTemplate/PasscodeField/index.js +43 -0
  48. package/src/commons/FieldTemplate/ScheduleField/ScheduleFieldStyles.js +13 -0
  49. package/src/commons/FieldTemplate/ScheduleField/__test__/index.test.js +179 -0
  50. package/src/commons/FieldTemplate/ScheduleField/index.js +176 -0
  51. package/src/commons/Header/HeaderCustom.js +2 -1
  52. package/src/commons/HorizontalPicker/index.js +2 -2
  53. package/src/commons/MediaPlayerDetail/Styles/MediaPlayerDetailStyles.js +0 -6
  54. package/src/commons/MediaPlayerDetail/index.js +19 -50
  55. package/src/commons/Sharing/__test__/DevicePermissionsCheckbox.test.js +0 -1
  56. package/src/commons/SubUnit/Favorites/index.js +2 -3
  57. package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +8 -35
  58. package/src/commons/SubUnit/OneTap/index.js +1 -2
  59. package/src/commons/SubUnit/ShortDetail.js +1 -2
  60. package/src/commons/SubUnit/__test__/Item.test.js +0 -1
  61. package/src/commons/Unit/SharedUnit.js +1 -0
  62. package/src/commons/Unit/__test__/SharedUnit.test.js +38 -183
  63. package/src/commons/UnitSummary/ConfigHistoryChart/index.js +2 -13
  64. package/src/commons/UnitSummary/ConfigHistoryChart.js +22 -13
  65. package/src/commons/WheelDateTimePicker/index.js +4 -3
  66. package/src/configs/API.js +85 -145
  67. package/src/configs/Constants.js +36 -1
  68. package/src/configs/SCConfig.js +2 -0
  69. package/src/context/actionType.ts +8 -1
  70. package/src/context/mockStore.ts +10 -0
  71. package/src/context/reducer.ts +38 -5
  72. package/src/hooks/Common/index.js +2 -0
  73. package/src/hooks/Common/useGGHomeDeviceConnected.js +16 -0
  74. package/src/hooks/Common/useGetIdUser.js +1 -5
  75. package/src/hooks/Common/useSensorsStatus.js +5 -8
  76. package/src/hooks/IoT/__test__/useGGHomeConnection.test.js +198 -0
  77. package/src/hooks/IoT/__test__/useRemoteControl.test.js +198 -0
  78. package/src/hooks/IoT/index.js +4 -0
  79. package/src/hooks/IoT/useGGHomeConnection.js +91 -0
  80. package/src/hooks/IoT/useRemoteControl.js +79 -0
  81. package/src/hooks/index.js +4 -0
  82. package/src/hooks/useReceiveNotifications.js +8 -4
  83. package/src/iot/Monitor.js +3 -2
  84. package/src/iot/RemoteControl/Bluetooth.js +1 -1
  85. package/src/iot/RemoteControl/GoogleHome.js +75 -49
  86. package/src/iot/RemoteControl/Internet.js +1 -1
  87. package/src/iot/RemoteControl/__test__/GoogleHome.test.js +95 -48
  88. package/src/iot/RemoteControl/__test__/Internet.test.js +18 -7
  89. package/src/iot/RemoteControl/__test__/LgThinq.test.js +36 -177
  90. package/src/iot/RemoteControl/index.js +52 -52
  91. package/src/navigations/UnitStack.js +8 -0
  92. package/src/screens/ActivityLog/__test__/index.test.js +38 -23
  93. package/src/screens/ActivityLog/hooks/__test__/index.test.js +51 -90
  94. package/src/screens/ActivityLog/hooks/index.js +1 -1
  95. package/src/screens/ActivityLog/index.js +2 -2
  96. package/src/screens/AddCommon/__test__/SelectSubUnit.test.js +13 -24
  97. package/src/screens/AddCommon/__test__/SelectUnit.test.js +9 -33
  98. package/src/screens/AddLocationMaps/index.js +5 -4
  99. package/src/screens/AddNewAction/SelectAction.js +8 -8
  100. package/src/screens/AddNewAction/SelectSensorDevices.js +2 -1
  101. package/src/screens/AddNewAction/SetupSensor.js +7 -7
  102. package/src/screens/AddNewAction/__test__/SelectAction.test.js +10 -91
  103. package/src/screens/AddNewAction/__test__/SelectSensorDevices.test.js +40 -26
  104. package/src/screens/AddNewAutoSmart/__test__/AddNewAutoSmart.test.js +3 -1
  105. package/src/screens/AddNewAutoSmart/index.js +5 -2
  106. package/src/screens/AddNewDevice/ConnectingDevices.js +3 -3
  107. package/src/screens/AddNewDevice/__test__/AddNewDevice.test.js +34 -33
  108. package/src/screens/AddNewDevice/__test__/ConnectDevices.test.js +0 -4
  109. package/src/screens/AddNewDevice/__test__/ConnectingDevices.test.js +21 -21
  110. package/src/screens/AddNewDevice/hooks/ConnectDevices.js +1 -1
  111. package/src/screens/AddNewGateway/PlugAndPlay/ConnectWifiWarning.js +23 -17
  112. package/src/screens/AddNewGateway/PlugAndPlay/GatewayWifiList.js +3 -3
  113. package/src/screens/AddNewGateway/SetupGatewayWifi.js +1 -0
  114. package/src/screens/AddNewGateway/__test__/AddNewGateway.test.js +4 -6
  115. package/src/screens/AddNewGateway/__test__/ConnectedGateway.test.js +0 -4
  116. package/src/screens/AddNewGateway/__test__/ConnectingGateway.test.js +5 -29
  117. package/src/screens/AddNewGateway/__test__/SelectGateway.test.js +0 -4
  118. package/src/screens/AddNewGateway/__test__/SetupGateway.test.js +0 -4
  119. package/src/screens/AddNewOneTap/__test__/AddNewOneTap.test.js +10 -24
  120. package/src/screens/AddNewOneTap/index.js +2 -1
  121. package/src/screens/AllCamera/index.js +4 -4
  122. package/src/screens/Automate/MultiUnits.js +8 -8
  123. package/src/screens/Automate/__test__/MultiUnits.test.js +6 -9
  124. package/src/screens/Automate/__test__/index.test.js +7 -12
  125. package/src/screens/Automate/index.js +3 -3
  126. package/src/screens/ConfirmUnitDeletion/__test__/ConfirmUnitDeletion.test.js +36 -8
  127. package/src/screens/ConfirmUnitDeletion/index.js +7 -1
  128. package/src/screens/Device/EditDevice/__test__/EditDevice.test.js +71 -22
  129. package/src/screens/Device/EditDevice/index.js +2 -2
  130. package/src/screens/Device/__test__/detail.test.js +33 -86
  131. package/src/screens/Device/components/DetailHistoryChart.js +1 -1
  132. package/src/screens/Device/components/SensorConnectStatusViewHeader.js +1 -0
  133. package/src/screens/Device/components/SensorDisplayItem.js +5 -2
  134. package/src/screens/Device/detail.js +81 -33
  135. package/src/screens/Device/hooks/useDisconnectedDevice.js +4 -4
  136. package/src/screens/Device/hooks/useFavoriteDevice.js +5 -9
  137. package/src/screens/DeviceInfo/__test__/index.test.js +0 -2
  138. package/src/screens/EditActionsList/index.js +1 -1
  139. package/src/screens/EmergencyContacts/EmergencyContactsSelectContacts.js +6 -3
  140. package/src/screens/EmergencyContacts/__test__/EmergencyContactAddNew.test.js +7 -19
  141. package/src/screens/EmergencyContacts/__test__/EmergencyContactList.test.js +18 -14
  142. package/src/screens/EmergencyContacts/__test__/EmergencyContactsSelectContacts.test.js +30 -31
  143. package/src/screens/EmergencySetting/components/DropDownItem.js +2 -2
  144. package/src/screens/EnterPassword/__test__/EnterPassword.test.js +41 -25
  145. package/src/screens/GuestInfo/__test__/index.test.js +14 -41
  146. package/src/screens/GuestInfo/components/RecurringDetail.js +1 -0
  147. package/src/screens/GuestInfo/components/TemporaryDetail.js +2 -2
  148. package/src/screens/HanetCamera/Detail.js +1 -1
  149. package/src/screens/HanetCamera/__test__/CaptureFaceID.test.js +8 -12
  150. package/src/screens/HanetCamera/__test__/Detail.test.js +27 -42
  151. package/src/screens/HanetCamera/__test__/ManageAccess.test.js +8 -5
  152. package/src/screens/HanetCamera/__test__/MemberInfo.test.js +10 -32
  153. package/src/screens/HanetCamera/components/RequestFaceIDPopup.js +3 -2
  154. package/src/screens/HanetCamera/hooks/__test__/useHanetCheckinData.test.js +43 -35
  155. package/src/screens/HanetCamera/hooks/__test__/useHanetPlaceMembers.test.js +10 -21
  156. package/src/screens/HanetCamera/hooks/useHanetCheckinData.js +11 -11
  157. package/src/screens/HanetCamera/hooks/useHanetPlaceMembers.js +11 -11
  158. package/src/screens/ManageAccess/__test__/ManageAccess.test.js +33 -22
  159. package/src/screens/ManageAccess/hooks/__test__/useManageAccess.test.js +44 -45
  160. package/src/screens/ManageAccess/hooks/index.js +7 -4
  161. package/src/screens/ManageAccess/index.js +1 -1
  162. package/src/screens/MoveToAnotherSubUnit/__test__/index.test.js +35 -12
  163. package/src/screens/MoveToAnotherSubUnit/index.js +5 -5
  164. package/src/screens/Notification/__test__/Notification.test.js +14 -25
  165. package/src/screens/Notification/__test__/NotificationItem.test.js +8 -7
  166. package/src/screens/Notification/components/NotificationItem.js +17 -20
  167. package/src/screens/Notification/index.js +9 -2
  168. package/src/screens/PlayBackCamera/Timer.js +2 -2
  169. package/src/screens/PlayBackCamera/__test__/index.test.js +87 -2
  170. package/src/screens/PlayBackCamera/index.js +22 -6
  171. package/src/screens/ScanChipQR/__test__/ScanChipQR.test.js +7 -20
  172. package/src/screens/ScanChipQR/components/QRScan/index.js +1 -0
  173. package/src/screens/ScanChipQR/hooks/index.js +15 -16
  174. package/src/screens/ScanSensorQR/__test__/ScanSensorQR.test.js +8 -24
  175. package/src/screens/ScriptDetail/__test__/index.test.js +17 -86
  176. package/src/screens/ScriptDetail/index.js +17 -12
  177. package/src/screens/SelectUnit/__test__/index.test.js +12 -55
  178. package/src/screens/SelectUnit/index.js +8 -4
  179. package/src/screens/SetSchedule/index.js +11 -10
  180. package/src/screens/SharedUnit/__test__/TabHeader.test.js +0 -2
  181. package/src/screens/Sharing/Components/SensorItem.js +10 -12
  182. package/src/screens/Sharing/InfoMemberUnit.js +1 -1
  183. package/src/screens/Sharing/SelectPermission.js +121 -77
  184. package/src/screens/Sharing/__test__/InfoMemberUnit.test.js +47 -29
  185. package/src/screens/Sharing/__test__/MemberList.test.js +13 -127
  186. package/src/screens/Sharing/__test__/MemberList2.test.js +80 -0
  187. package/src/screens/Sharing/__test__/SelectPermission.test.js +28 -38
  188. package/src/screens/Sharing/__test__/SelectUser.test.js +17 -38
  189. package/src/screens/SideMenuDetail/SideMenuDetailStyles.js +28 -0
  190. package/src/screens/SideMenuDetail/__test__/index.test.js +154 -0
  191. package/src/screens/SideMenuDetail/index.js +148 -0
  192. package/src/screens/SmartIr/components/GroupButtonByType/GroupButtonByType.js +3 -2
  193. package/src/screens/SubUnit/Detail.js +1 -2
  194. package/src/screens/SubUnit/ManageSubUnit.js +12 -7
  195. package/src/screens/SubUnit/__test__/AddSubUnit.test.js +21 -67
  196. package/src/screens/SubUnit/__test__/Detail.test.js +31 -8
  197. package/src/screens/SubUnit/__test__/EditSubUnit.test.js +21 -89
  198. package/src/screens/SubUnit/__test__/ManageSubUnit.test.js +27 -1
  199. package/src/screens/SubUnit/hooks/__test__/useManageSubUnit.test.js +48 -45
  200. package/src/screens/SubUnit/hooks/useManageSubUnit.js +7 -7
  201. package/src/screens/SyncLGDevice/__test__/AddLGDevice.test.js +14 -90
  202. package/src/screens/Unit/ChooseLocation.js +7 -14
  203. package/src/screens/Unit/Detail.js +30 -75
  204. package/src/screens/Unit/ManageUnit.js +1 -0
  205. package/src/screens/Unit/SelectAddress.js +34 -21
  206. package/src/screens/Unit/SmartAccount.js +4 -4
  207. package/src/screens/Unit/Summaries.js +17 -1
  208. package/src/screens/Unit/__test__/CheckSendEmail.test.js +24 -29
  209. package/src/screens/Unit/__test__/ChooseLocation.test.js +27 -14
  210. package/src/screens/Unit/__test__/Detail.test.js +99 -200
  211. package/src/screens/Unit/__test__/ManageUnit.test.js +18 -42
  212. package/src/screens/Unit/__test__/SelectAddress.test.js +84 -51
  213. package/src/screens/Unit/__test__/SmartAccount.test.js +17 -9
  214. package/src/screens/Unit/__test__/SmartAccountItem.test.js +0 -1
  215. package/src/screens/Unit/__test__/Summaries.test.js +100 -0
  216. package/src/screens/Unit/components/MyAllUnit/__test__/MyAllUnit.test.js +36 -0
  217. package/src/screens/Unit/components/MyAllUnit/__test__/index.test.js +54 -0
  218. package/src/screens/Unit/components/SharedUnit/index.js +1 -0
  219. package/src/screens/Unit/components/__test__/SharedUnit.test.js +31 -34
  220. package/src/screens/Unit/hook/useUnitConnectRemoteDevices.js +50 -0
  221. package/src/screens/Unit/styles.js +4 -0
  222. package/src/screens/UnitSummary/__test__/index.test.js +70 -41
  223. package/src/screens/UnitSummary/components/3PPowerConsumption/__test__/3PPowerConsumption.test.js +31 -2
  224. package/src/screens/UnitSummary/components/PowerConsumeHistoryChart/__test__/index.test.js +7 -4
  225. package/src/screens/UnitSummary/components/PowerConsumeHistoryChart/index.js +2 -13
  226. package/src/screens/UnitSummary/components/PowerConsumption/__test__/ItemPower.test.js +0 -1
  227. package/src/screens/UnitSummary/components/PowerConsumption/__test__/PowerConsumption.test.js +14 -16
  228. package/src/screens/UnitSummary/components/RunningDevices/__test__/index.test.js +11 -2
  229. package/src/screens/UnitSummary/components/RunningDevices/index.js +7 -10
  230. package/src/screens/UnitSummary/components/Temperature/index.js +4 -4
  231. package/src/screens/UnitSummary/index.js +15 -1
  232. package/src/utils/Apis/axios.js +46 -31
  233. package/src/utils/Converter/time.js +0 -18
  234. package/src/utils/I18n/translations/en.json +3 -1
  235. package/src/utils/I18n/translations/vi.json +4 -1
  236. package/src/utils/Permission/common.js +39 -0
  237. package/src/utils/Route/index.js +1 -0
  238. package/src/utils/Utils.js +11 -7
@@ -12,7 +12,7 @@ import { get } from 'lodash';
12
12
  import { useSelector } from 'react-redux';
13
13
  import { IconFill, IconOutline } from '@ant-design/icons-react-native';
14
14
  import { Icon } from '@ant-design/react-native';
15
-
15
+ import Routes from '../../utils/Route';
16
16
  import { useCountUp } from './hooks/useCountUp';
17
17
  import { getData as getLocalData } from '../../utils/Storage';
18
18
  import { API, Colors } from '../../configs';
@@ -32,20 +32,19 @@ 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
- import {
37
- AlertAction,
38
- ButtonPopup,
39
- FullLoading,
40
- MenuActionMore,
41
- } from '../../commons';
35
+ import { AlertAction, ButtonPopup, MenuActionMore } from '../../commons';
42
36
  import { TESTID } from '../../configs/Constants';
43
- import Routes from '../../utils/Route';
37
+
44
38
  import { usePopover } from '../../hooks/Common';
45
39
  import { useConfigGlobalState } from '../../iot/states';
46
40
  import { useNavigation } from '@react-navigation/native';
47
41
  import styles from './styles';
48
- import { useIsOwnerOfUnit, useBoolean } from '../../hooks/Common';
42
+ import {
43
+ useIsOwnerOfUnit,
44
+ useBoolean,
45
+ useGGHomeDeviceConnected,
46
+ } from '../../hooks/Common';
47
+ import { useGGHomeConnection } from '../../hooks/IoT';
49
48
  import { SensorDisplayItem } from './components/SensorDisplayItem';
50
49
  import { useSCContextSelector } from '../../context';
51
50
  import { EmergencyCountdown } from './components/EmergencyCountdown';
@@ -53,6 +52,7 @@ import { SensorConnectStatusViewHeader } from './components/SensorConnectStatusV
53
52
  import { useDisconnectedDevice } from './hooks/useDisconnectedDevice';
54
53
  import { Card } from '../../commons/CardShadow';
55
54
  import PreventAccess from '../../commons/PreventAccess';
55
+ import { notImplemented } from '../../utils/Utils';
56
56
 
57
57
  const DeviceDetail = ({ route }) => {
58
58
  const t = useTranslations();
@@ -71,8 +71,7 @@ const DeviceDetail = ({ route }) => {
71
71
  // eslint-disable-next-line no-unused-vars
72
72
  const [configValues, setConfigValues] = useConfigGlobalState('configValues');
73
73
 
74
- const { unitData, unitId, sensorData, sensorId, isGGHomeConnected } =
75
- route.params;
74
+ const { unitData, unitId, sensorData, sensorId } = route.params;
76
75
  const [unit, setUnit] = useState(unitData || { id: unitId });
77
76
  const [sensor, setSensor] = useState(sensorData || { id: sensorId });
78
77
  const [station, setStation] = useState(sensor?.station);
@@ -87,15 +86,14 @@ const DeviceDetail = ({ route }) => {
87
86
  displayTemplate: true,
88
87
  });
89
88
  const [serverDown, setServerDown] = useState(false);
90
-
89
+ const [sideMenu, setSideMenu] = useState([]);
91
90
  const isNetworkConnected = useSCContextSelector(
92
91
  (state) => state.app.isNetworkConnected
93
92
  );
94
93
  const isBluetoothEnabled = useSCContextSelector((state) => {
95
94
  return state.app.isBluetoothEnabled;
96
95
  });
97
-
98
- const isFullLoading = useSCContextSelector((state) => state.isFullLoading);
96
+ const { isConnected: isGGHomeConnected } = useGGHomeDeviceConnected(sensor);
99
97
 
100
98
  const isDeviceConnectedViaBle = useMemo(
101
99
  () =>
@@ -138,10 +136,8 @@ const DeviceDetail = ({ route }) => {
138
136
  [display.items]
139
137
  );
140
138
 
141
- const { isFavorite, addToFavorites, removeFromFavorites } = useFavoriteDevice(
142
- unit,
143
- sensor
144
- );
139
+ const { isFavorite, addToFavorites, removeFromFavorites } =
140
+ useFavoriteDevice(sensor);
145
141
 
146
142
  const currentUserId = useSelector((state) =>
147
143
  get(state, 'auth.account.user.id', 0)
@@ -166,9 +162,24 @@ const DeviceDetail = ({ route }) => {
166
162
  }
167
163
  }, [fetchUnitDetail, unitId, unitData]);
168
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
+
169
180
  const fetchSensorDetail = useCallback(async () => {
170
181
  const { success, data, resp_status } = await axiosGet(
171
- API.SENSOR.SENSOR_DETAIL(sensorId)
182
+ API.DEVICE.SENSOR_DETAIL(sensorId)
172
183
  );
173
184
  if (success) {
174
185
  setSensor(data);
@@ -194,19 +205,20 @@ const DeviceDetail = ({ route }) => {
194
205
  }
195
206
 
196
207
  const { success, data } = await axiosGet(
197
- API.SENSOR.DISPLAY(sensor?.id),
208
+ API.DEVICE.DISPLAY(sensor?.id),
198
209
  {},
199
210
  true
200
211
  );
212
+
201
213
  if (success) {
202
214
  setDisplay(data);
203
215
  setServerDown(false);
204
216
  if (data.items.length) {
205
217
  const config = data.items[0].configuration;
206
- if (config.hasOwnProperty('max_value')) {
218
+ if (Object.prototype.hasOwnProperty.call(config, 'max_value')) {
207
219
  setMaxValue(config.max_value);
208
220
  }
209
- if (config.hasOwnProperty('device')) {
221
+ if (Object.prototype.hasOwnProperty.call(config, 'device')) {
210
222
  // for emergency
211
223
  setDeviceId(config.device.id);
212
224
  const last_event = config.device.last_event;
@@ -217,11 +229,14 @@ const DeviceDetail = ({ route }) => {
217
229
  }
218
230
  }
219
231
  }
232
+ if (data?.side_menu_items?.length) {
233
+ setSideMenu(data.side_menu_items);
234
+ }
220
235
  }
221
236
  setLoading((preState) => ({ ...preState, displayTemplate: false }));
222
237
 
223
238
  const controlResult = await axiosGet(
224
- API.SENSOR.REMOTE_CONTROL_OPTIONS(sensor?.id),
239
+ API.DEVICE.REMOTE_CONTROL_OPTIONS(sensor?.id),
225
240
  {},
226
241
  true
227
242
  );
@@ -312,6 +327,19 @@ const DeviceDetail = ({ route }) => {
312
327
  text: t('activity_log'),
313
328
  });
314
329
  }
330
+
331
+ sideMenu.forEach((el) => {
332
+ menuItems.push({
333
+ route: Routes.SideMenuDetail,
334
+ data: {
335
+ unit,
336
+ sensor,
337
+ side_menu: el,
338
+ },
339
+ text: el.name,
340
+ });
341
+ });
342
+
315
343
  menuItems.push({
316
344
  route: Routes.DeviceInfo,
317
345
  text: t('device_info'),
@@ -328,6 +356,13 @@ const DeviceDetail = ({ route }) => {
328
356
  text: t('auto_lock'),
329
357
  });
330
358
  }
359
+ menuItems.push({
360
+ route: Routes.SmartLockStack,
361
+ data: {
362
+ screen: Routes.SetupGeneratePasscode,
363
+ },
364
+ text: t('setup_generate_passcode'),
365
+ });
331
366
  if (isOwner && isShowSetUpSmartLock) {
332
367
  menuItems.push({
333
368
  route: Routes.SmartLockStack,
@@ -368,6 +403,7 @@ const DeviceDetail = ({ route }) => {
368
403
  sensor,
369
404
  unit,
370
405
  sensorName,
406
+ sideMenu,
371
407
  station,
372
408
  emergencyDeviceId,
373
409
  addToFavorites,
@@ -377,7 +413,7 @@ const DeviceDetail = ({ route }) => {
377
413
  const { countUpStr } = useCountUp(lastEvent.reportedAt);
378
414
 
379
415
  useEffect(() => {
380
- if (controlOptions.bluetooth) {
416
+ if (controlOptions?.bluetooth) {
381
417
  const bluetooth = controlOptions.bluetooth;
382
418
  scanBluetoothDevices([bluetooth.address]);
383
419
  }
@@ -389,8 +425,17 @@ const DeviceDetail = ({ route }) => {
389
425
 
390
426
  const onRefresh = useCallback(() => {
391
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
+ }
392
437
  // eslint-disable-next-line react-hooks/exhaustive-deps
393
- }, [sensor, fetchDataDeviceDetail]);
438
+ }, [sensor, unit, isNetworkConnected, fetchDataDeviceDetail]);
394
439
 
395
440
  const getData = useCallback(
396
441
  (item) => {
@@ -417,6 +462,7 @@ const DeviceDetail = ({ route }) => {
417
462
  if (item.type !== 'value') {
418
463
  return;
419
464
  }
465
+
420
466
  if (!item.configuration) {
421
467
  return;
422
468
  }
@@ -434,7 +480,7 @@ const DeviceDetail = ({ route }) => {
434
480
 
435
481
  const fetchValues = async () => {
436
482
  const { success, data, resp_status } = await axiosGet(
437
- API.SENSOR.DISPLAY_VALUES_V2(sensor?.id),
483
+ API.DEVICE.DISPLAY_VALUES_V2(sensor?.id),
438
484
  {
439
485
  params: params,
440
486
  }
@@ -442,7 +488,10 @@ const DeviceDetail = ({ route }) => {
442
488
  if (success) {
443
489
  setDisplayValues(data.configs);
444
490
  setConnected(data.is_connected);
445
- transformDatetime(data, ['last_updated']);
491
+ data.last_updated = data.last_updated
492
+ ? moment(data.last_updated)
493
+ : data.last_updated;
494
+
446
495
  setLastUpdated(data.last_updated);
447
496
  } else if (resp_status >= 500) {
448
497
  setServerDown(true);
@@ -462,7 +511,7 @@ const DeviceDetail = ({ route }) => {
462
511
  useEffect(() => {
463
512
  setDisplayValues((currentDisplayValues) => {
464
513
  for (const [configId, value] of Object.entries(configValues)) {
465
- const intId = parseInt(configId);
514
+ const intId = parseInt(configId, 10);
466
515
  const index = currentDisplayValues.findIndex(
467
516
  (element) => element.id === intId
468
517
  );
@@ -580,19 +629,18 @@ const DeviceDetail = ({ route }) => {
580
629
  })}
581
630
  </Card>
582
631
  )}
583
- {isFullLoading && <FullLoading />}
584
632
  </SensorConnectStatusViewHeader>
585
633
  );
586
634
  };
587
635
 
588
636
  const getDataFromLocal = async () => {
589
637
  const displayData = await getLocalData(
590
- `@CACHE_REQUEST_${API.SENSOR.DISPLAY(sensor?.id)}`
638
+ `@CACHE_REQUEST_${API.DEVICE.DISPLAY(sensor?.id)}`
591
639
  );
592
640
  displayData && setDisplay(JSON.parse(displayData));
593
641
 
594
642
  const controlOptionData = await getLocalData(
595
- `@CACHE_REQUEST_${API.SENSOR.REMOTE_CONTROL_OPTIONS(sensor?.id)}`
643
+ `@CACHE_REQUEST_${API.DEVICE.REMOTE_CONTROL_OPTIONS(sensor?.id)}`
596
644
  );
597
645
  controlOptionData && setControlOptions(JSON.parse(controlOptionData));
598
646
  setLoading((preState) => ({ ...preState, displayTemplate: false }));
@@ -604,7 +652,7 @@ const DeviceDetail = ({ route }) => {
604
652
  } else if (item.doAction) {
605
653
  item.doAction();
606
654
  } else {
607
- alert(t('feature_under_development'));
655
+ notImplemented(t);
608
656
  }
609
657
  };
610
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
  />
@@ -1,5 +1,5 @@
1
1
  import React, { useCallback, useEffect, useState } from 'react';
2
- import { SafeAreaView, StyleSheet, View } from 'react-native';
2
+ import { SafeAreaView, StyleSheet, View, Platform } from 'react-native';
3
3
  import { IconOutline } from '@ant-design/icons-react-native';
4
4
  import { useNavigation } from '@react-navigation/native';
5
5
  import { useTranslations } from '../../hooks/Common/useTranslations';
@@ -71,11 +71,11 @@ export const EmergencyContactsSelectContacts = ({ route }) => {
71
71
  return (
72
72
  <SafeAreaView style={styles.container}>
73
73
  <WrapHeaderScrollable title={t('select_contacts')} loading={loading}>
74
- <Section type={'border'}>
74
+ <Section type={'border'} style={styles.section}>
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} />
@@ -116,6 +116,9 @@ const styles = StyleSheet.create({
116
116
  flex: 1,
117
117
  backgroundColor: Colors.Gray2,
118
118
  },
119
+ section: {
120
+ marginTop: Platform.OS === 'ios' ? 40 : 0,
121
+ },
119
122
  buttonRemove: {
120
123
  height: 40,
121
124
  width: 40,
@@ -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}