@eohjsc/react-native-smart-city 0.3.71 → 0.3.72

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 (151) hide show
  1. package/index.js +0 -2
  2. package/package.json +4 -5
  3. package/src/commons/ActionGroup/OnOffSmartLock/AutoLock/index.js +1 -1
  4. package/src/commons/ActionGroup/OnOffSmartLock/OnOffSmartLock.js +2 -2
  5. package/src/commons/ActionGroup/OnOffSmartLock/OnOffSmartLockStyle.js +1 -1
  6. package/src/commons/ActionGroup/OnOffSmartLock/SetupGeneratePasscode/__test__/index.test.js +12 -11
  7. package/src/commons/ActionGroup/SliderRangeTemplate.js +2 -3
  8. package/src/commons/ActionGroup/SmartTiviActionTemplate/SmartTiviActionTemplate.js +1 -0
  9. package/src/commons/ActionGroup/TwoButtonTemplate/index.js +1 -0
  10. package/src/commons/ActionGroup/__test__/OptionsDropdownTemplate.test.js +39 -34
  11. package/src/commons/ActionGroup/__test__/SliderRangeTemplate.test.js +1 -1
  12. package/src/commons/ActionGroup/__test__/TimerActionTemplate.test.js +19 -10
  13. package/src/commons/ActionGroup/__test__/TimerActionTemplateWithutConfigValue.test.js +0 -1
  14. package/src/commons/ActionGroup/__test__/index.test.js +24 -16
  15. package/src/commons/ActionTemplate/__test__/index.test.js +5 -1
  16. package/src/commons/AlertAction/__test__/AlertAction.test.js +2 -2
  17. package/src/commons/Automate/__test__/ItemAutomate.test.js +1 -1
  18. package/src/commons/Calendar/__test__/Calendar.test.js +3 -5
  19. package/src/commons/CameraDevice/index.js +37 -22
  20. package/src/commons/Dashboard/MyPinnedSharedUnit/__test__/MyPinnedSharedUnit.test.js +3 -3
  21. package/src/commons/Dashboard/MyUnit/index.js +1 -1
  22. package/src/commons/Device/ConnectedViewHeader.js +2 -1
  23. package/src/commons/Device/DeviceAlertStatus.js +1 -1
  24. package/src/commons/Device/DisconnectedView.js +10 -14
  25. package/src/commons/Device/Emergency/__test__/EmergencyDetail.test.js +1 -1
  26. package/src/commons/Device/HorizontalBarChart.js +1 -1
  27. package/src/commons/Device/LinearChart/LinearChart.test.js +10 -4
  28. package/src/commons/Device/LinearChart.js +5 -1
  29. package/src/commons/Device/SonosSpeaker/__test__/SonosSpeaker.test.js +1 -1
  30. package/src/commons/Device/SonosSpeaker/index.js +1 -1
  31. package/src/commons/Device/WindDirection/Compass/Compass.test.js +12 -27
  32. package/src/commons/Device/WindDirection/Compass/index.js +15 -23
  33. package/src/commons/Device/WindSpeed/__test__/Anemometer.test.js +4 -4
  34. package/src/commons/Device/WindSpeed/__test__/ChartInfo.test.js +2 -2
  35. package/src/commons/Device/__test__/ConnectedViewHeader.test.js +11 -8
  36. package/src/commons/Device/__test__/DisconnectedView.test.js +8 -45
  37. package/src/commons/DisplayChecking/__test__/DisplayChecking.test.js +1 -1
  38. package/src/commons/DisplayChecking/index.js +4 -3
  39. package/src/commons/DisplayChecking/styles.js +2 -2
  40. package/src/commons/MediaPlayer/index.js +2 -1
  41. package/src/commons/MediaPlayerDetail/MediaPlayerFull.js +1 -1
  42. package/src/commons/MediaPlayerDetail/__test__/MediaPlayerDetail.test.js +0 -1
  43. package/src/commons/MediaPlayerDetail/index.js +2 -3
  44. package/src/commons/MenuActionAddnew/__test__/MenuActionAddNew.test.js +2 -1
  45. package/src/commons/MenuActionList/__test__/MenuActionList.test.js +1 -1
  46. package/src/commons/MenuActionList/index.js +8 -70
  47. package/src/commons/MenuActionList/styles.js +68 -0
  48. package/src/commons/Modal/__test__/ModalBottom.test.js +1 -10
  49. package/src/commons/OneTapTemplate/StatesGridActionTemplate.js +45 -31
  50. package/src/commons/OneTapTemplate/__test__/NumberUpDownActionTemplate.test.js +15 -13
  51. package/src/commons/OneTapTemplate/__test__/OptionsDropdownActionTemplate.test.js +12 -9
  52. package/src/commons/OneTapTemplate/__test__/StatesGridActionTemplate.test.js +19 -13
  53. package/src/commons/PreventAccess/__test__/PreventAccess.test.js +5 -5
  54. package/src/commons/PreventAccess/index.js +3 -3
  55. package/src/commons/Sharing/__test__/MemberList.test.js +17 -6
  56. package/src/commons/Sharing/__test__/RowMember.test.js +0 -2
  57. package/src/commons/SubUnit/OneTap/index.js +6 -1
  58. package/src/commons/Today/__test__/Today.test.js +3 -3
  59. package/src/commons/UnitSummary/ConfigHistoryChart/__test__/ConfigHistoryChart.test.js +1 -1
  60. package/src/configs/IOPinConstants.js +285 -0
  61. package/src/libs/react-native-parallax-scroll-view/index.js +2 -1
  62. package/src/navigations/AllGatewayStack.js +3 -3
  63. package/src/navigations/UnitStack.js +0 -6
  64. package/src/screens/ActivityLog/__test__/index.test.js +16 -22
  65. package/src/screens/ActivityLog/index.js +2 -3
  66. package/src/screens/AddNewAction/SelectAction.js +3 -0
  67. package/src/screens/AddNewAction/SetupSensor.js +3 -3
  68. package/src/screens/AddNewAction/__test__/SelectAction.test.js +12 -0
  69. package/src/screens/AddNewAction/__test__/SetupSensor.test.js +11 -24
  70. package/src/screens/AddNewGateway/PlugAndPlay/__test__/ConnectRouterGuide.test.js +0 -1
  71. package/src/screens/AddNewGateway/PlugAndPlay/__test__/FirstWarning.test.js +0 -1
  72. package/src/screens/AddNewGateway/PlugAndPlay/__test__/ZigbeeDeviceConnectGuide.test.js +0 -1
  73. package/src/screens/AddNewGateway/SetupGatewayWifiStyles.js +2 -2
  74. package/src/screens/AddNewGateway/__test__/ShareWifiPassword.test.js +22 -7
  75. package/src/screens/AllCamera/__test__/index.test.js +1 -1
  76. package/src/screens/AllCamera/index.js +1 -1
  77. package/src/screens/AllGateway/DetailConfigActionInternal/__test__/index.test.js +82 -0
  78. package/src/screens/AllGateway/DetailConfigActionInternal/index.js +84 -5
  79. package/src/screens/AllGateway/DeviceInternalDetail/__test__/index.test.js +63 -57
  80. package/src/screens/AllGateway/DeviceInternalDetail/index.js +32 -32
  81. package/src/screens/AllGateway/DeviceModbusDetail/__test__/index.test.js +40 -79
  82. package/src/screens/AllGateway/DeviceZigbeeDetail/__test__/index.test.js +36 -42
  83. package/src/screens/AllGateway/DeviceZigbeeDetail/index.js +4 -4
  84. package/src/screens/AllGateway/GatewayDetail/__test__/index.test.js +49 -61
  85. package/src/screens/AllGateway/GatewayDetail/index.js +2 -1
  86. package/src/screens/AllGateway/components/TabPaneCT/__test__/index.test.js +1 -1
  87. package/src/screens/AllGateway/components/TabPaneCT/index.js +1 -1
  88. package/src/screens/AllGateway/hooks/useGateway.js +1 -0
  89. package/src/screens/AllGateway/test-utils.js +20 -0
  90. package/src/screens/Device/__test__/detail.test.js +8 -3
  91. package/src/screens/Device/components/SensorDisplayItem.js +1 -5
  92. package/src/screens/EmergencyContacts/EmergencyContactsList.js +1 -4
  93. package/src/screens/EmergencyContacts/__test__/EmergencyContactList.test.js +32 -4
  94. package/src/screens/EmergencyContacts/__test__/EmergencyContactsSelectContacts.test.js +7 -5
  95. package/src/screens/EmergencyContacts/__test__/hooks.test.js +1 -1
  96. package/src/screens/GuestInfo/__test__/index.test.js +26 -14
  97. package/src/screens/HanetCamera/CaptureFaceID.js +1 -1
  98. package/src/screens/HanetCamera/__test__/MemberInfo.test.js +1 -5
  99. package/src/screens/HanetCamera/styles/captureFaceIDStyles.js +1 -1
  100. package/src/screens/PlayBackCamera/Timer.js +2 -3
  101. package/src/screens/PlayBackCamera/__test__/index.test.js +69 -48
  102. package/src/screens/ScanChipQR/components/QRScan/index.js +8 -8
  103. package/src/screens/SharedUnit/__test__/ShareUnit.test.js +20 -10
  104. package/src/screens/SharedUnit/index.js +19 -17
  105. package/src/screens/SmartAccount/Connecting/index.js +2 -2
  106. package/src/screens/SmartAccount/ListDevice/__test__/DeviceItem.test.js +4 -2
  107. package/src/screens/SmartAccount/ListDevice/__test__/ListDevice.test.js +17 -8
  108. package/src/screens/SmartAccount/ListDevice/index.js +1 -1
  109. package/src/screens/SmartAccount/SuccessfullyConnected/__test__/SuccessfullyConnected.test.js +9 -6
  110. package/src/screens/SmartAccount/SuccessfullyConnected/index.js +1 -0
  111. package/src/screens/SmartAccount/__test__/Connecting.test.js +2 -1
  112. package/src/screens/SmartIr/__test__/GroupButtonByType.test.js +17 -6
  113. package/src/screens/SubUnit/EditSubUnit.js +6 -6
  114. package/src/screens/SubUnit/EditSubUnitStyles.js +2 -2
  115. package/src/screens/SubUnit/__test__/AddSubUnit.test.js +5 -6
  116. package/src/screens/SubUnit/__test__/Detail.test.js +2 -3
  117. package/src/screens/SubUnit/__test__/EditSubUnit.test.js +25 -10
  118. package/src/screens/Template/EditTemplate.js +13 -3
  119. package/src/screens/Template/__test__/EditTemplate.test.js +21 -15
  120. package/src/screens/Unit/Detail.js +157 -121
  121. package/src/screens/Unit/ManageUnit.js +3 -3
  122. package/src/screens/Unit/ManageUnitStyles.js +1 -1
  123. package/src/screens/Unit/__test__/Detail.test.js +40 -20
  124. package/src/screens/Unit/__test__/ManageUnit.test.js +18 -15
  125. package/src/screens/Unit/components/AutomateScript/index.js +9 -8
  126. package/src/screens/Unit/components/Header/index.js +1 -14
  127. package/src/screens/Unit/components/__test__/AutomateScript.test.js +10 -36
  128. package/src/screens/Unit/components/__test__/Header.test.js +14 -9
  129. package/src/screens/Unit/components/__test__/MyUnitDevice.test.js +4 -5
  130. package/src/utils/Route/index.js +1 -2
  131. package/src/utils/Utils.js +62 -2
  132. package/src/commons/Explore/ActivityIndicator/index.js +0 -49
  133. package/src/commons/Explore/CityItem/index.js +0 -116
  134. package/src/commons/Explore/HeaderExplore/index.js +0 -44
  135. package/src/commons/Explore/HeaderLabel/index.js +0 -46
  136. package/src/commons/Explore/LocationItem/index.js +0 -71
  137. package/src/commons/Explore/SearchBox/__test__/SearchBox.test.js +0 -58
  138. package/src/commons/Explore/SearchBox/index.js +0 -59
  139. package/src/commons/Explore/__test__/CityItem.test.js +0 -156
  140. package/src/commons/Explore/__test__/HeaderExplore.test.js +0 -25
  141. package/src/commons/Explore/__test__/HeaderLabel.test.js +0 -33
  142. package/src/commons/Explore/__test__/LocationItem.test.js +0 -31
  143. package/src/screens/Explore/__test__/Explore.test.js +0 -43
  144. package/src/screens/Explore/index.js +0 -201
  145. package/src/screens/Unit/MyAllUnit/index.js +0 -44
  146. package/src/screens/Unit/__test__/MyAllUnit.test.js +0 -87
  147. package/src/screens/Unit/components/ListMyAllUnit/index.js +0 -162
  148. package/src/screens/Unit/components/MyAllUnit/__test__/Header.test.js +0 -117
  149. package/src/screens/Unit/components/MyAllUnit/__test__/MyAllUnit.test.js +0 -36
  150. package/src/screens/Unit/components/MyAllUnit/__test__/index.test.js +0 -54
  151. package/src/screens/Unit/components/MyAllUnit/index.js +0 -44
@@ -50,6 +50,144 @@ import {
50
50
  import PreventAccess from '../../commons/PreventAccess';
51
51
  import MediaPlayerDetail from '../../commons/MediaPlayerDetail';
52
52
 
53
+ const SubUnitDetail = ({ station, isOwner, unit, listAutomate }) => {
54
+ const { navigate } = useNavigation();
55
+ const goToPlayBack = useCallback(
56
+ (item, thumbnail) => {
57
+ navigate(Routes.PlaybackCamera, { item, thumbnail });
58
+ },
59
+ [navigate]
60
+ );
61
+ const { favoriteDevices, favoriteAutomates } = useFavorites(
62
+ unit.stations || [],
63
+ listAutomate
64
+ );
65
+
66
+ if (!station) {
67
+ return null;
68
+ }
69
+
70
+ if (station.isFavorites) {
71
+ return (
72
+ <SubUnitFavorites
73
+ isOwner={isOwner}
74
+ unit={unit}
75
+ favoriteDevices={favoriteDevices}
76
+ favoriteAutomates={favoriteAutomates}
77
+ wrapItemStyle={styles.wrapItemStyle}
78
+ />
79
+ );
80
+ }
81
+ if (station.camera_devices) {
82
+ return <CameraDevice station={station} goToPlayBack={goToPlayBack} />;
83
+ }
84
+
85
+ if (station.isOneTap) {
86
+ return (
87
+ <SubUnitAutomate
88
+ isOwner={isOwner}
89
+ listAutomate={listAutomate}
90
+ unit={unit}
91
+ wrapItemStyle={styles.wrapItemStyle}
92
+ />
93
+ );
94
+ }
95
+ return <ShortDetailSubUnit unit={unit} station={station} isOwner={isOwner} />;
96
+ };
97
+
98
+ const SubUnitList = ({
99
+ unit,
100
+ listAutomate,
101
+ isOwner,
102
+ isOneTap,
103
+ stationId,
104
+ isAddSubUnit,
105
+ isEditSubUnit,
106
+ }) => {
107
+ const t = useTranslations();
108
+
109
+ const [listMenuItem, setListMenuItem] = useState([]);
110
+ const [listStation, setListStation] = useState([]);
111
+ const [station, setStation] = useState({});
112
+ const [indexStation, setIndexStation] = useState(0);
113
+ const onSnapToItem = useCallback(
114
+ (item, index) => {
115
+ setStation(unit.stations[index]);
116
+ setIndexStation(index);
117
+ },
118
+ // eslint-disable-next-line react-hooks/exhaustive-deps
119
+ [unit, indexStation]
120
+ );
121
+
122
+ useEffect(() => {
123
+ isEditSubUnit && setIndexStation(0);
124
+ isOneTap && setIndexStation(1);
125
+ }, [isEditSubUnit, isOneTap]);
126
+
127
+ useEffect(() => {
128
+ if (listMenuItem.length && isAddSubUnit) {
129
+ setIndexStation(listMenuItem.length - 1);
130
+ }
131
+ }, [listMenuItem.length, isAddSubUnit]);
132
+
133
+ useEffect(() => {
134
+ if (!stationId) {
135
+ return;
136
+ }
137
+ for (let i = 0; i < listStation.length; i++) {
138
+ if (listStation[i]?.id === stationId) {
139
+ setIndexStation(i);
140
+ break;
141
+ }
142
+ }
143
+ }, [stationId, listStation]);
144
+
145
+ useEffect(() => {
146
+ if (unit.stations) {
147
+ let listMenu = unit.stations.map((item, index) => ({
148
+ text: item.name,
149
+ station: item,
150
+ id: item.id,
151
+ }));
152
+ setListMenuItem(listMenu);
153
+ setListStation(listMenu.concat([{ text: '' }]));
154
+ }
155
+ }, [unit.stations]);
156
+
157
+ useEffect(() => {
158
+ if (!unit?.stations || !unit.stations[indexStation]) {
159
+ return;
160
+ }
161
+ setStation(unit.stations[indexStation]);
162
+ }, [indexStation, unit.stations]);
163
+
164
+ return (
165
+ <View style={styles.container}>
166
+ <Summaries unit={unit} />
167
+ <NavBar
168
+ accessibilityLabel={AccessibilityLabel.NAVBAR_ON_SNAP_ITEM}
169
+ listStation={listStation}
170
+ listMenuItem={listMenuItem}
171
+ onSnapToItem={onSnapToItem}
172
+ indexStation={indexStation}
173
+ idLabelScrollView={AccessibilityLabel.NAV_LIST}
174
+ idLabelItem={AccessibilityLabel.SUB_UNIT_NAME}
175
+ idLabelIconBars={AccessibilityLabel.NAVBAR_ICON_BARS}
176
+ />
177
+ <SubUnitDetail
178
+ unit={unit}
179
+ station={station}
180
+ listAutomate={listAutomate}
181
+ isOwner={isOwner}
182
+ />
183
+ {!!unit.can_add && unit.stations.length === 0 && (
184
+ <View style={styles.canAdd}>
185
+ <Text style={styles.emptyUnit}>{t('text_no_sub_unit_yet')}</Text>
186
+ </View>
187
+ )}
188
+ </View>
189
+ );
190
+ };
53
191
  const UnitDetail = ({ route }) => {
54
192
  const t = useTranslations();
55
193
  const { setAction } = useContext(SCContext);
@@ -58,8 +196,8 @@ const UnitDetail = ({ route }) => {
58
196
  const {
59
197
  unitId,
60
198
  unitData,
61
- isOneTap,
62
199
  routeName,
200
+ isOneTap,
63
201
  stationId,
64
202
  isAddSubUnit,
65
203
  isEditSubUnit,
@@ -84,11 +222,7 @@ const UnitDetail = ({ route }) => {
84
222
  );
85
223
 
86
224
  const [unit, setUnit] = useState(unitData || { id: unitId });
87
- const [listMenuItem, setListMenuItem] = useState([]);
88
- const [listStation, setListStation] = useState([]);
89
225
  const [listAutomate, setListAutomate] = useState([]);
90
- const [station, setStation] = useState({});
91
- const [indexStation, setIndexStation] = useState(0);
92
226
  const [showAdd, setShowAdd, setHideAdd] = useBoolean();
93
227
  const [showPreventAccess, setShowPreventAccess, setHidePreventAccess] =
94
228
  useBoolean(false);
@@ -98,10 +232,6 @@ const UnitDetail = ({ route }) => {
98
232
  usePopover();
99
233
 
100
234
  const { isOwner } = useIsOwnerOfUnit(unit.user_id);
101
- const { favoriteDevices, favoriteAutomates } = useFavorites(
102
- unit.stations || [],
103
- listAutomate
104
- );
105
235
 
106
236
  const prepareData = useCallback(
107
237
  (rawUnitData) => {
@@ -200,83 +330,6 @@ const UnitDetail = ({ route }) => {
200
330
  }
201
331
  }, [fetchDetails, isFocused]);
202
332
 
203
- useEffect(() => {
204
- if (unit.stations) {
205
- let listMenu = unit.stations.map((item, index) => ({
206
- text: item.name,
207
- station: item,
208
- index: index,
209
- }));
210
- setStation(unit.stations[indexStation]);
211
- setListMenuItem(listMenu);
212
- setListStation(listMenu.concat([{ text: '' }]));
213
- }
214
- }, [unit, indexStation]);
215
-
216
- useEffect(() => {
217
- isEditSubUnit && setIndexStation(0);
218
- isOneTap && setIndexStation(1);
219
- }, [isEditSubUnit, isOneTap]);
220
-
221
- useEffect(() => {
222
- if (listMenuItem.length && isAddSubUnit) {
223
- setIndexStation(listMenuItem.length - 1);
224
- }
225
- }, [listMenuItem.length, isAddSubUnit]);
226
-
227
- useEffect(() => {
228
- if (!isEditSubUnit && listMenuItem.length && stationId) {
229
- const getStationCurrent = listMenuItem.filter(
230
- (item) => item?.station.id === stationId
231
- );
232
- setIndexStation(getStationCurrent[0]?.index);
233
- }
234
- // eslint-disable-next-line react-hooks/exhaustive-deps
235
- }, [listMenuItem.length, stationId]);
236
-
237
- const onSnapToItem = useCallback(
238
- (item, index) => {
239
- setStation(unit.stations[index]);
240
- setIndexStation(index);
241
- },
242
- // eslint-disable-next-line react-hooks/exhaustive-deps
243
- [unit, indexStation]
244
- );
245
-
246
- const goToPlayBack = (item, thumbnail) => () => {
247
- navigate(Routes.PlaybackCamera, { item, thumbnail });
248
- };
249
-
250
- const renderDetailSubUnit = () => {
251
- if (station?.isFavorites) {
252
- return (
253
- <SubUnitFavorites
254
- isOwner={isOwner}
255
- unit={unit}
256
- favoriteDevices={favoriteDevices}
257
- favoriteAutomates={favoriteAutomates}
258
- wrapItemStyle={styles.wrapItemStyle}
259
- />
260
- );
261
- }
262
- if (station?.camera_devices) {
263
- return <CameraDevice station={station} goToPlayBack={goToPlayBack} />;
264
- } else if (station?.isOneTap) {
265
- return (
266
- <SubUnitAutomate
267
- isOwner={isOwner}
268
- listAutomate={listAutomate}
269
- unit={unit}
270
- wrapItemStyle={styles.wrapItemStyle}
271
- />
272
- );
273
- } else if (station) {
274
- return (
275
- <ShortDetailSubUnit unit={unit} station={station} isOwner={isOwner} />
276
- );
277
- }
278
- };
279
-
280
333
  const onBack = useCallback(() => {
281
334
  navigate(isLavidaSource ? Routes.SmartHomeDashboard : routeName);
282
335
  }, [navigate, routeName, isLavidaSource]);
@@ -285,21 +338,6 @@ const UnitDetail = ({ route }) => {
285
338
  navigate(isLavidaSource ? Routes.SmartHomeDashboard : Routes.Dashboard);
286
339
  }, [isLavidaSource, navigate]);
287
340
 
288
- const renderCamera = useMemo(() => {
289
- return (
290
- isFirstOpenCamera &&
291
- isIOS && (
292
- <MediaPlayerDetail
293
- uri={Constants.URL_STREAM_CAMERA_DEMO}
294
- isPaused={false}
295
- width={1}
296
- height={1}
297
- style={styles.fakeCamera}
298
- />
299
- )
300
- );
301
- }, [isFirstOpenCamera, isIOS]);
302
-
303
341
  useEffect(() => {
304
342
  watchNotificationData(user, onRefresh);
305
343
  return () => unwatchNotificationData(user);
@@ -331,27 +369,25 @@ const UnitDetail = ({ route }) => {
331
369
  accessibilityLabel={AccessibilityLabel.UNIT_DETAIL_PARALLAX_SCROLLVIEW}
332
370
  idButtonMore={AccessibilityLabel.UNIT_DETAIL_PARALLAX_BUTTON_MORE}
333
371
  >
334
- {renderCamera}
335
-
336
- <View style={styles.container}>
337
- <Summaries unit={unit} />
338
- <NavBar
339
- accessibilityLabel={AccessibilityLabel.NAVBAR_ON_SNAP_ITEM}
340
- listStation={listStation}
341
- listMenuItem={listMenuItem}
342
- onSnapToItem={onSnapToItem}
343
- indexStation={indexStation}
344
- idLabelScrollView={AccessibilityLabel.NAV_LIST}
345
- idLabelItem={AccessibilityLabel.SUB_UNIT_NAME}
346
- idLabelIconBars={AccessibilityLabel.NAVBAR_ICON_BARS}
372
+ {isFirstOpenCamera && isIOS && (
373
+ <MediaPlayerDetail
374
+ uri={Constants.URL_STREAM_CAMERA_DEMO}
375
+ isPaused={false}
376
+ width={1}
377
+ height={1}
378
+ style={styles.fakeCamera}
347
379
  />
348
- {renderDetailSubUnit()}
349
- {!!unit.can_add && unit.stations.length === 0 && (
350
- <View style={styles.canAdd}>
351
- <Text style={styles.emptyUnit}>{t('text_no_sub_unit_yet')}</Text>
352
- </View>
353
- )}
354
- </View>
380
+ )}
381
+
382
+ <SubUnitList
383
+ unit={unit}
384
+ listAutomate={listAutomate}
385
+ isOwner={isOwner}
386
+ isOneTap={isOneTap}
387
+ stationId={stationId}
388
+ isAddSubUnit={isAddSubUnit}
389
+ isEditSubUnit={isEditSubUnit}
390
+ />
355
391
  <AddMenu
356
392
  unit={unit}
357
393
  afterItemClick={hidePopover}
@@ -23,7 +23,7 @@ const ManageUnit = ({ route }) => {
23
23
  const { unit } = route?.params || {};
24
24
  const navigation = useNavigation();
25
25
  const { isOwner } = useIsOwnerOfUnit(unit.user_id);
26
- const [showEdit, setshowEdit, setHideEdit] = useBoolean();
26
+ const [showEdit, setShowEdit, setHideEdit] = useBoolean();
27
27
  const [unitData, setUnitData] = useState({
28
28
  name: unit.name,
29
29
  address: unit.address,
@@ -161,7 +161,7 @@ const ManageUnit = ({ route }) => {
161
161
  title={t('manage_unit')}
162
162
  styleScrollView={styles.scrollView}
163
163
  >
164
- <View style={styles.wraper}>
164
+ <View style={styles.wrapper}>
165
165
  {isOwner && (
166
166
  <>
167
167
  <ButtonWrapper
@@ -172,7 +172,7 @@ const ManageUnit = ({ route }) => {
172
172
  accessibilityLabel={AccessibilityLabel.MANAGE_UNIT_CHANGE_PHOTO}
173
173
  />
174
174
  <ButtonWrapper
175
- onPress={setshowEdit}
175
+ onPress={setShowEdit}
176
176
  accessibilityLabel={AccessibilityLabel.MANAGE_UNIT_CHANGE_NAME}
177
177
  title={t('unit_name')}
178
178
  value={unitData.name}
@@ -6,7 +6,7 @@ export default StyleSheet.create({
6
6
  scrollView: {
7
7
  backgroundColor: Colors.White,
8
8
  },
9
- wraper: {
9
+ wrapper: {
10
10
  flex: 1,
11
11
  marginHorizontal: 16,
12
12
  },
@@ -86,13 +86,15 @@ describe('Test UnitDetail', () => {
86
86
  jest.clearAllTimers();
87
87
  useIsFocused.mockImplementation(() => true);
88
88
  AsyncStorage.clear();
89
- mock.resetHistory();
89
+ mock.reset();
90
+ mockedNavigate.mockReset();
90
91
  });
91
92
 
92
93
  it('render subunit camera devices', async () => {
93
94
  const unitData = {
94
95
  stations: [
95
96
  {
97
+ id: 'camera',
96
98
  camera_devices: [
97
99
  {
98
100
  configuration: {
@@ -121,7 +123,9 @@ describe('Test UnitDetail', () => {
121
123
  const instance = tree.root;
122
124
  const CameraDeviceViews = instance.findAllByType(CameraDevice);
123
125
  expect(CameraDeviceViews).toHaveLength(1);
124
- await CameraDeviceViews[0].props.goToPlayBack()();
126
+ await act(async () => {
127
+ CameraDeviceViews[0].props.goToPlayBack();
128
+ });
125
129
  expect(mockedNavigate).toBeCalledWith(Routes.PlaybackCamera, {
126
130
  item: undefined,
127
131
  thumbnail: undefined,
@@ -166,8 +170,8 @@ describe('Test UnitDetail', () => {
166
170
  refreshControl.props.onRefresh();
167
171
  });
168
172
  const instance = tree.root;
169
- const PreventAccesss = instance.findByType(PreventAccess);
170
- expect(PreventAccesss).toBeDefined();
173
+ const preventAccesses = instance.findByType(PreventAccess);
174
+ expect(preventAccesses).toBeDefined();
171
175
  });
172
176
 
173
177
  it('display unit detail when cache not change', async () => {
@@ -212,8 +216,8 @@ describe('Test UnitDetail', () => {
212
216
  tree = await renderer.create(wrapComponent(route, account));
213
217
  });
214
218
  const instance = tree.root;
215
- const PreventAccesss = instance.findByType(PreventAccess);
216
- expect(PreventAccesss).toBeDefined();
219
+ const preventAccesses = instance.findByType(PreventAccess);
220
+ expect(preventAccesses).toBeDefined();
217
221
  });
218
222
 
219
223
  it('fetch unit detail error 404', async () => {
@@ -235,8 +239,8 @@ describe('Test UnitDetail', () => {
235
239
  tree = await renderer.create(wrapComponent(route, account));
236
240
  });
237
241
  const instance = tree.root;
238
- const PreventAccesss = instance.findByType(PreventAccess);
239
- expect(PreventAccesss).toBeDefined();
242
+ const preventAccesses = instance.findByType(PreventAccess);
243
+ expect(preventAccesses).toBeDefined();
240
244
  });
241
245
 
242
246
  it('fetch unit summary has data', async () => {
@@ -245,8 +249,8 @@ describe('Test UnitDetail', () => {
245
249
  tree = await renderer.create(wrapComponent(route, account));
246
250
  });
247
251
  const instance = tree.root;
248
- const PreventAccesss = instance.findByType(PreventAccess);
249
- expect(PreventAccesss).toBeDefined();
252
+ const preventAccesses = instance.findByType(PreventAccess);
253
+ expect(preventAccesses).toBeDefined();
250
254
  });
251
255
 
252
256
  it('not fetch unit summary if not focus', async () => {
@@ -256,8 +260,8 @@ describe('Test UnitDetail', () => {
256
260
  tree = await renderer.create(wrapComponent(route, account));
257
261
  });
258
262
  const instance = tree.root;
259
- const PreventAccesss = instance.findByType(PreventAccess);
260
- expect(PreventAccesss).toBeDefined();
263
+ const preventAccesses = instance.findByType(PreventAccess);
264
+ expect(preventAccesses).toBeDefined();
261
265
  });
262
266
 
263
267
  it('fetch unit detail when refresh', async () => {
@@ -399,6 +403,7 @@ describe('Test UnitDetail', () => {
399
403
  const unitData = {
400
404
  stations: [
401
405
  {
406
+ id: 'camera',
402
407
  camera_devices: [
403
408
  {
404
409
  configuration: {
@@ -418,24 +423,30 @@ describe('Test UnitDetail', () => {
418
423
  },
419
424
  ],
420
425
  };
426
+ mock.onGet(API.UNIT.UNIT_DETAIL(1)).reply(200, unitData);
421
427
 
422
428
  await act(async () => {
423
429
  tree = await renderer.create(
424
- wrapComponent({ params: { ...route.params, unitData } }, account)
430
+ wrapComponent(
431
+ { params: { ...route.params, stationId: 'camera' } },
432
+ account
433
+ )
425
434
  );
426
435
  });
427
436
  const instance = tree.root;
437
+
438
+ await act(async () => {});
428
439
  const CameraDeviceViews = instance.findAllByType(CameraDevice);
429
- expect(CameraDeviceViews).toHaveLength(0);
440
+ expect(CameraDeviceViews).toHaveLength(1);
430
441
  const goDetailButton = tree.root.findAll(
431
442
  (el) =>
432
443
  el.props.accessibilityLabel === AccessibilityLabel.SUB_UNIT_GO_DETAIL &&
433
444
  el.type === TouchableOpacity
434
445
  );
435
446
 
436
- expect(goDetailButton).toHaveLength(1);
447
+ expect(goDetailButton).toHaveLength(2);
437
448
  await act(async () => {
438
- await goDetailButton[0].props.onPress();
449
+ await goDetailButton[1].props.onPress();
439
450
  });
440
451
  expect(mockedNavigate).toHaveBeenCalled();
441
452
  });
@@ -470,6 +481,11 @@ describe('Test UnitDetail', () => {
470
481
  isFavorites: true,
471
482
  name: 'Favorites',
472
483
  },
484
+ {
485
+ isOneTap: true,
486
+ name: 'Smart',
487
+ id: 'Smart',
488
+ },
473
489
  ],
474
490
  };
475
491
  route.params.isAddSubUnit = true;
@@ -507,10 +523,12 @@ describe('Test UnitDetail', () => {
507
523
  });
508
524
  jest.runAllTimers();
509
525
  const instance = tree.root;
510
- const PreventAccesss = instance.findByType(PreventAccess);
511
- expect(PreventAccesss).toBeDefined();
526
+ const preventAccess = instance.findByType(PreventAccess);
527
+ expect(preventAccess).toBeDefined();
512
528
  const TouchableOpacities = instance.findAllByType(TouchableOpacity);
513
- await TouchableOpacities[0].props.onPress();
529
+ await act(async () => {
530
+ await TouchableOpacities[0].props.onPress();
531
+ });
514
532
  expect(mockedNavigate).toBeCalled();
515
533
  });
516
534
 
@@ -522,7 +540,9 @@ describe('Test UnitDetail', () => {
522
540
  });
523
541
  const instance = tree.root;
524
542
  const TouchableOpacities = instance.findAllByType(TouchableOpacity);
525
- await TouchableOpacities[0].props.onPress();
543
+ await act(async () => {
544
+ await TouchableOpacities[0].props.onPress();
545
+ });
526
546
  expect(mockedNavigate).toBeCalled();
527
547
  });
528
548
  });
@@ -62,12 +62,16 @@ describe('Test Manage Unit', () => {
62
62
  mockNavigate.mockClear();
63
63
  });
64
64
 
65
- const getElement = (instance) => {
65
+ const getElement = async (instance) => {
66
66
  const changeName = instance.findAll(
67
67
  (item) =>
68
68
  item.props.accessibilityLabel ===
69
69
  AccessibilityLabel.MANAGE_UNIT_CHANGE_NAME
70
70
  );
71
+
72
+ await act(async () => {
73
+ await changeName[0].props.onPress();
74
+ });
71
75
  const changeLocation = instance.findAll(
72
76
  (item) =>
73
77
  item.props.accessibilityLabel ===
@@ -93,11 +97,7 @@ describe('Test Manage Unit', () => {
93
97
  item.props.accessibilityLabel ===
94
98
  AccessibilityLabel.MANAGE_UNIT_MODAL_RENAME_INPUT_NAME
95
99
  );
96
- const showRemove = instance.findAll(
97
- (item) =>
98
- item.props.accessibilityLabel ===
99
- AccessibilityLabel.MANAGE_UNIT_SHOW_REMOVE
100
- );
100
+
101
101
  return {
102
102
  changeName,
103
103
  changeLocation,
@@ -105,7 +105,6 @@ describe('Test Manage Unit', () => {
105
105
  imagePicker,
106
106
  modalRename,
107
107
  inputRename,
108
- showRemove,
109
108
  };
110
109
  };
111
110
 
@@ -121,7 +120,7 @@ describe('Test Manage Unit', () => {
121
120
  changePhoto,
122
121
  imagePicker,
123
122
  modalRename,
124
- } = getElement(instance);
123
+ } = await getElement(instance);
125
124
 
126
125
  expect(changeName[0]).toBeDefined();
127
126
  expect(changeLocation[0]).toBeDefined();
@@ -135,7 +134,7 @@ describe('Test Manage Unit', () => {
135
134
  tree = await create(wrapComponent(route));
136
135
  });
137
136
  const instance = tree.root;
138
- const { changeName, inputRename } = getElement(instance);
137
+ const { changeName, inputRename } = await getElement(instance);
139
138
  await act(async () => {
140
139
  await changeName[0].props.onPress();
141
140
  });
@@ -160,7 +159,12 @@ describe('Test Manage Unit', () => {
160
159
  });
161
160
 
162
161
  const instance = tree.root;
163
- const { showRemove } = getElement(instance);
162
+
163
+ const showRemove = instance.findAll(
164
+ (item) =>
165
+ item.props.accessibilityLabel ===
166
+ AccessibilityLabel.MANAGE_UNIT_SHOW_REMOVE
167
+ );
164
168
 
165
169
  await act(async () => {
166
170
  await showRemove[0].props.onPress();
@@ -178,23 +182,22 @@ describe('Test Manage Unit', () => {
178
182
  expect(mockedDispatch).not.toBeCalled();
179
183
  });
180
184
 
181
- it('rename Unit sucess', async () => {
185
+ it('rename Unit success', async () => {
182
186
  const spyToast = jest.spyOn(ToastBottomHelper, 'success');
183
187
  await act(async () => {
184
188
  tree = await create(wrapComponent(route));
185
189
  });
186
190
 
187
191
  const instance = tree.root;
188
- const { changeName, inputRename } = getElement(instance);
189
192
 
190
- await act(async () => {
191
- await changeName[0].props.onPress();
192
- });
193
+ const { inputRename } = await getElement(instance);
193
194
 
194
195
  const alertActions = instance.findAllByType(AlertAction);
195
196
  mock.onPatch(API.UNIT.MANAGE_UNIT(1)).reply(200, {});
196
197
  await act(async () => {
197
198
  await inputRename[0].props.onChange('input station');
199
+ });
200
+ await act(async () => {
198
201
  await alertActions[0].props.rightButtonClick();
199
202
  });
200
203
 
@@ -15,6 +15,13 @@ import {
15
15
  } from '../../../../configs/Constants';
16
16
  import { Colors } from '../../../../configs';
17
17
 
18
+ const iconByType = {
19
+ [AUTOMATE_TYPE.ONE_TAP]: OneTap,
20
+ [AUTOMATE_TYPE.VALUE_CHANGE]: ValueChange,
21
+ [AUTOMATE_TYPE.EVENT]: Event,
22
+ [AUTOMATE_TYPE.SCHEDULE]: Schedule,
23
+ };
24
+
18
25
  const AutomateScript = ({ automate, onPress, isSelected }) => {
19
26
  const t = useTranslations();
20
27
  const { script, type, author = '' } = automate;
@@ -27,15 +34,9 @@ const AutomateScript = ({ automate, onPress, isSelected }) => {
27
34
  const iconKit = script?.icon_kit;
28
35
  if (iconKit) {
29
36
  return <FImage source={{ uri: iconKit }} style={styles.iconSensor} />;
30
- } else if (type === AUTOMATE_TYPE.ONE_TAP) {
31
- return <OneTap />;
32
- } else if (type === AUTOMATE_TYPE.VALUE_CHANGE) {
33
- return <ValueChange />;
34
- } else if (type === AUTOMATE_TYPE.EVENT) {
35
- return <Event />;
36
- } else {
37
- return <Schedule />;
38
37
  }
38
+ const Icon = iconByType[type] || Schedule;
39
+ return <Icon />;
39
40
  };
40
41
 
41
42
  return (
@@ -16,20 +16,7 @@ import { ModalCustom } from '../../../../commons/Modal';
16
16
 
17
17
  const { width: widthScreen } = Dimensions.get('window');
18
18
 
19
- const HeaderComponent = ({
20
- hasBack,
21
- leftComponent,
22
- centerComponent,
23
- rightComponent,
24
- navigation,
25
- title,
26
- wrapStyle,
27
- goBack,
28
- dark,
29
- hideRight,
30
- fixedHeight, // when height of header is fixed
31
- style,
32
- }) => {
19
+ const HeaderComponent = ({ title, goBack, dark, hideRight, style }) => {
33
20
  const t = useTranslations();
34
21
  const popoverRef = useRef();
35
22
  const [menu, setMenu] = useState(false);