@eohjsc/react-native-smart-city 0.2.56 → 0.2.60

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 (126) hide show
  1. package/assets/images/Map/MarkerGeolocation.svg +4 -0
  2. package/assets/images/SonosSpeaker/buttonpause-active.svg +3 -0
  3. package/assets/images/SonosSpeaker/buttonpause-notactive.svg +3 -0
  4. package/assets/images/SonosSpeaker/picture-main-notactive.svg +5 -0
  5. package/assets/images/SonosSpeaker/picture-main.svg +6 -0
  6. package/assets/images/SonosSpeaker/picture-volume.svg +3 -0
  7. package/package.json +4 -22
  8. package/src/Images/Common/buttonLeftCurtain.png +0 -0
  9. package/src/Images/Common/buttonPause-center-curtain.png +0 -0
  10. package/src/Images/Common/buttonRightCurtain.png +0 -0
  11. package/src/commons/ActionGroup/CurtainButtonTemplate.js +139 -0
  12. package/src/commons/ActionGroup/CurtainButtonTemplateStyle.js +58 -0
  13. package/src/commons/ActionGroup/__test__/CurtainButtonTemplate.test.js +72 -0
  14. package/src/commons/ActionGroup/index.js +3 -0
  15. package/src/commons/Auth/__test__/AccountList.test.js +33 -0
  16. package/src/commons/CameraDevice/index.js +2 -0
  17. package/src/commons/CardShadow/index.js +1 -1
  18. package/src/commons/CardShadow/styles.js +1 -3
  19. package/src/commons/DateTimeRangeChange/DateTimeButton.js +1 -1
  20. package/src/commons/DateTimeRangeChange/index.js +2 -2
  21. package/src/commons/Device/HistoryChart.js +21 -55
  22. package/src/commons/Device/HorizontalBarChart.js +46 -30
  23. package/src/commons/Device/LinearChart.js +0 -34
  24. package/src/commons/Device/PMSensor/PMSensorIndicatior.js +1 -1
  25. package/src/commons/Device/PMSensor/PMSensorIndicatorStyles.js +2 -1
  26. package/src/commons/Device/SonosSpeaker/__test__/SonosSpeaker.test.js +57 -0
  27. package/src/commons/Device/SonosSpeaker/index.js +88 -0
  28. package/src/commons/Device/SonosSpeaker/styles.js +57 -0
  29. package/src/commons/Form/CurrencyInput.js +169 -0
  30. package/src/commons/Form/__test__/CurrencyInput.test.js +65 -0
  31. package/src/commons/FourButtonFilterHistory/__test__/FourButtonFilterHistory.test.js +48 -0
  32. package/src/commons/FourButtonFilterHistory/index.js +72 -0
  33. package/src/commons/FourButtonFilterHistory/styles.js +22 -0
  34. package/src/commons/MediaPlayerDetail/Styles/MediaPlayerDetailStyles.js +14 -0
  35. package/src/commons/MediaPlayerDetail/index.js +204 -161
  36. package/src/commons/SearchLocation/index.js +0 -1
  37. package/src/commons/Sharing/RowMember.js +7 -2
  38. package/src/commons/Sharing/__test__/RowMember.test.js +42 -0
  39. package/src/commons/SubUnit/ShortDetail.js +12 -6
  40. package/src/commons/UnitSummary/AirQuality/SegmentedRoundDisplay/index.js +1 -1
  41. package/src/commons/UnitSummary/ConfigHistoryChart.js +2 -1
  42. package/src/configs/API.js +13 -3
  43. package/src/configs/Constants.js +14 -4
  44. package/src/configs/Images.js +3 -0
  45. package/src/configs/SCConfig.js +8 -0
  46. package/src/context/actionType.ts +5 -0
  47. package/src/context/mockStore.ts +3 -0
  48. package/src/context/reducer.ts +14 -0
  49. package/src/iot/RemoteControl/Bluetooth.js +14 -0
  50. package/src/iot/RemoteControl/index.js +0 -1
  51. package/src/navigations/UnitStack.js +42 -4
  52. package/src/screens/ActivityLog/FilterPopup.js +1 -1
  53. package/src/screens/ActivityLog/ItemLog.js +11 -2
  54. package/src/screens/ActivityLog/__test__/ItemLog.test.js +46 -0
  55. package/src/screens/ActivityLog/hooks/index.js +1 -0
  56. package/src/screens/ActivityLog/index.js +0 -1
  57. package/src/screens/AddCommon/SelectSubUnit.js +24 -2
  58. package/src/screens/AddCommon/SelectUnit.js +12 -0
  59. package/src/screens/AddLocationMaps/index.js +139 -44
  60. package/src/screens/AddLocationMaps/indexStyle.js +14 -12
  61. package/src/screens/AddNewAction/SelectAction.js +1 -0
  62. package/src/screens/Automate/MultiUnits.js +8 -8
  63. package/src/screens/Automate/__test__/MultiUnits.test.js +2 -2
  64. package/src/screens/Automate/__test__/index.test.js +2 -0
  65. package/src/screens/Automate/index.js +4 -2
  66. package/src/screens/Device/__test__/detail.test.js +3 -7
  67. package/src/screens/Device/components/SensorDisplayItem.js +10 -10
  68. package/src/screens/Device/detail.js +65 -15
  69. package/src/screens/Device/hooks/useDisconnectedDevice.js +32 -26
  70. package/src/screens/Device/styles.js +3 -3
  71. package/src/screens/EmergencySetting/__test__/DropDownItem.test.js +59 -0
  72. package/src/screens/EmergencySetting/__test__/index.test.js +27 -0
  73. package/src/screens/EmergencySetting/components/DropDownItem.js +54 -0
  74. package/src/screens/EmergencySetting/index.js +90 -0
  75. package/src/screens/EmergencySetting/styles/DropDownItem.js +38 -0
  76. package/src/screens/EmergencySetting/styles.js +19 -0
  77. package/src/screens/MoveToAnotherSubUnit/__test__/index.test.js +126 -0
  78. package/src/screens/MoveToAnotherSubUnit/index.js +88 -0
  79. package/src/screens/MoveToAnotherSubUnit/styles/MoveToAnotherSubUnitStyles.js +50 -0
  80. package/src/screens/Notification/__test__/Notification.test.js +3 -3
  81. package/src/screens/Notification/components/NotificationItem.js +3 -6
  82. package/src/screens/Notification/index.js +2 -2
  83. package/src/screens/ScriptDetail/Styles/indexStyles.js +0 -1
  84. package/src/screens/ScriptDetail/__test__/index.test.js +13 -0
  85. package/src/screens/ScriptDetail/index.js +20 -17
  86. package/src/screens/SelectUnit/index.js +2 -0
  87. package/src/screens/Sharing/MemberList.js +2 -9
  88. package/src/screens/SubUnit/AddSubUnit.js +79 -59
  89. package/src/screens/SubUnit/AddSubUnitStyles.js +0 -2
  90. package/src/screens/SubUnit/__test__/AddSubUnit.test.js +4 -3
  91. package/src/screens/TDSGuide/index.js +6 -4
  92. package/src/screens/Unit/ChooseLocation.js +96 -0
  93. package/src/screens/Unit/ChooseLocationStyles.js +26 -0
  94. package/src/screens/Unit/Detail.js +14 -2
  95. package/src/screens/Unit/ManageUnit.js +4 -5
  96. package/src/screens/Unit/SelectAddress.js +240 -0
  97. package/src/screens/Unit/SelectAddressStyles.js +48 -0
  98. package/src/screens/Unit/SmartAccountItem.js +1 -1
  99. package/src/screens/Unit/Summaries.js +5 -1
  100. package/src/screens/Unit/__test__/ChooseLocation.test.js +112 -0
  101. package/src/screens/Unit/__test__/SelectAddress.test.js +216 -0
  102. package/src/screens/Unit/components/MyUnitDevice/index.js +21 -5
  103. package/src/screens/Unit/hook/useStateAlertRemove.js +3 -1
  104. package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +2 -2
  105. package/src/screens/UnitSummary/components/PowerConsumption/index.js +3 -2
  106. package/src/screens/UnitSummary/components/WaterQuality/Item/index.js +1 -3
  107. package/src/screens/UnitSummary/index.js +3 -2
  108. package/src/screens/WaterQualityGuide/index.js +1 -0
  109. package/src/utils/Apis/axios.js +17 -5
  110. package/src/utils/I18n/translations/en.json +19 -4
  111. package/src/utils/I18n/translations/vi.json +22 -7
  112. package/src/utils/Route/index.js +4 -1
  113. package/src/utils/Utils.js +22 -2
  114. package/assets/images/AddLocationMaps/PinLocation.svg +0 -3
  115. package/assets/images/AddLocationMaps/Point.svg +0 -3
  116. package/src/commons/ThreeButtonHistory/CalendarHeader.js +0 -35
  117. package/src/commons/ThreeButtonHistory/CalendarHeaderStyles.js +0 -17
  118. package/src/commons/ThreeButtonHistory/SelectMonth.js +0 -53
  119. package/src/commons/ThreeButtonHistory/SelectMonthStyles.js +0 -29
  120. package/src/commons/ThreeButtonHistory/__test__/SelectMonth.test.js +0 -37
  121. package/src/commons/ThreeButtonHistory/__test__/ThreeButtonHistory.test.js +0 -231
  122. package/src/commons/ThreeButtonHistory/index.js +0 -281
  123. package/src/commons/ThreeButtonHistory/styles.js +0 -65
  124. package/src/screens/Unit/ManageUnit/index.js +0 -286
  125. package/src/screens/Unit/SelectLocation.js +0 -161
  126. package/src/screens/Unit/SelectLocationStyles.js +0 -114
@@ -1,18 +1,17 @@
1
- import React, { memo, useState, useCallback, useRef } from 'react';
2
- import { View, ScrollView } from 'react-native';
3
- import MapView, { Marker, PROVIDER_GOOGLE } from 'react-native-maps';
1
+ import React, { memo, useState, useCallback, useRef, useEffect } from 'react';
2
+ import { View, ScrollView, TouchableOpacity } from 'react-native';
3
+ import MapView, { Marker, Circle, PROVIDER_GOOGLE } from 'react-native-maps';
4
4
  import { useNavigation } from '@react-navigation/native';
5
+ import { IconOutline, IconFill } from '@ant-design/icons-react-native';
5
6
  import { useTranslations } from '../../hooks/Common/useTranslations';
6
7
 
7
- import { Colors } from '../../configs';
8
8
  import Text from '../../commons/Text';
9
9
  import { ViewButtonBottom } from '../../commons';
10
10
  import SearchBarLocation from '../../commons/SearchLocation';
11
11
  import RowLocation from '../../commons/SearchLocation/RowLocation';
12
- import Point from '../../../assets/images/AddLocationMaps/Point.svg';
13
12
  import { axiosGet } from '../../utils/Apis/axios';
14
- import { API } from '../../configs';
15
- import { SCConfig } from '../../configs';
13
+ import { API, Colors, SCConfig } from '../../configs';
14
+ import { TESTID } from '../../configs/Constants';
16
15
  import styles from './indexStyle';
17
16
  import Routes from '../../utils/Route';
18
17
 
@@ -25,6 +24,8 @@ const initialRegion = {
25
24
  const DEFAULT_LATITUDE = 10.7974046; // EoH center
26
25
  const DEFAULT_LONGITUDE = 106.7035663;
27
26
 
27
+ navigator.geolocation = require('@react-native-community/geolocation');
28
+
28
29
  const AddLocationMaps = memo(() => {
29
30
  const t = useTranslations();
30
31
  const { goBack, navigate } = useNavigation();
@@ -87,33 +88,75 @@ const AddLocationMaps = memo(() => {
87
88
  );
88
89
  }, []);
89
90
 
90
- const onPressRowLocation = useCallback(
91
- async (item) => {
92
- setInput(item.description);
93
- setSearchData([]);
94
- const body = {
95
- params: {
96
- place_id: item.place_id,
97
- key: SCConfig.GOOGLE_MAP_API_KEY,
98
- },
99
- };
91
+ const onPressRowLocation = useCallback(async (item) => {
92
+ setInput(item.description);
93
+ setSearchData([]);
94
+ const body = {
95
+ params: {
96
+ place_id: item.place_id,
97
+ key: SCConfig.GOOGLE_MAP_API_KEY,
98
+ },
99
+ };
100
100
 
101
- const { success, data } = await axiosGet(
102
- API.EXTERNAL.GOOGLE_MAP.GET_LAT_LNG_BY_PLACE_ID,
103
- body
104
- );
105
- if (success) {
106
- const { location } = data.result.geometry;
107
- animateToRegion(location.lat, location.lng);
108
- setSearchedLocation({
109
- description: item.description,
110
- latitude: location.lat,
111
- longitude: location.lng,
112
- });
113
- }
114
- },
115
- [animateToRegion]
116
- );
101
+ const { success, data } = await axiosGet(
102
+ API.EXTERNAL.GOOGLE_MAP.GET_LAT_LNG_BY_PLACE_ID,
103
+ body
104
+ );
105
+ if (success) {
106
+ const { location } = data.result.geometry;
107
+ setSearchedLocation({
108
+ description: item.description,
109
+ latitude: location.lat,
110
+ longitude: location.lng,
111
+ });
112
+ }
113
+ }, []);
114
+
115
+ const getCurrentPosition = useCallback(() => {
116
+ navigator.geolocation.getCurrentPosition(
117
+ async (position) => {
118
+ const currentLatitude = JSON.stringify(position.coords.latitude);
119
+ const currentLongitude = JSON.stringify(position.coords.longitude);
120
+ const { success, data } = await axiosGet(
121
+ API.EXTERNAL.GOOGLE_MAP.GET_LOCATION_FROM_LAT_LNG,
122
+ {
123
+ params: {
124
+ latlng: `${currentLatitude},${currentLongitude}`,
125
+ key: SCConfig.GOOGLE_MAP_API_KEY,
126
+ },
127
+ }
128
+ );
129
+ if (success && data.results.length > 0) {
130
+ const result = data.results[0];
131
+ setInput(result.formatted_address);
132
+ setSearchedLocation({
133
+ description: result.formatted_address,
134
+ latitude: result.geometry.location.lat,
135
+ longitude: result.geometry.location.lng,
136
+ });
137
+ }
138
+ },
139
+ (error) => {},
140
+ {}
141
+ );
142
+ }, []);
143
+
144
+ const chooseOnMap = useCallback(() => {
145
+ navigate(Routes.UnitStack, {
146
+ screen: Routes.ChooseLocation,
147
+ params: {
148
+ location: searchedLocation,
149
+ setAddress: setInput,
150
+ setLocation: setSearchedLocation,
151
+ },
152
+ });
153
+ }, [navigate, searchedLocation, setInput, setSearchedLocation]);
154
+
155
+ useEffect(() => {
156
+ if (searchedLocation) {
157
+ animateToRegion(searchedLocation.latitude, searchedLocation.longitude);
158
+ }
159
+ }, [animateToRegion, searchedLocation]);
117
160
 
118
161
  return (
119
162
  <View style={styles.container}>
@@ -130,6 +173,45 @@ const AddLocationMaps = memo(() => {
130
173
  {searchData.map((item) => (
131
174
  <RowLocation item={item} onPress={onPressRowLocation} />
132
175
  ))}
176
+ {searchData.length === 0 && (
177
+ <>
178
+ <TouchableOpacity
179
+ onPress={getCurrentPosition}
180
+ style={styles.button}
181
+ testID={TESTID.BUTTON_YOUR_LOCATION}
182
+ >
183
+ <IconOutline name="aim" size={27} color={Colors.Primary} />
184
+ <Text
185
+ type="Body"
186
+ color={Colors.Gray9}
187
+ style={styles.text}
188
+ bold
189
+ >
190
+ {t('your_location')}
191
+ </Text>
192
+ </TouchableOpacity>
193
+ <View style={styles.separated} />
194
+ <TouchableOpacity
195
+ onPress={chooseOnMap}
196
+ style={styles.button}
197
+ testID={TESTID.BUTTON_CHOOSE_ON_MAP}
198
+ >
199
+ <IconFill
200
+ name="environment"
201
+ size={27}
202
+ color={Colors.Primary}
203
+ />
204
+ <Text
205
+ type="Body"
206
+ color={Colors.Gray9}
207
+ style={styles.text}
208
+ bold
209
+ >
210
+ {t('choose_on_map')}
211
+ </Text>
212
+ </TouchableOpacity>
213
+ </>
214
+ )}
133
215
  </ScrollView>
134
216
  </View>
135
217
  <View style={styles.mapContainer}>
@@ -145,17 +227,30 @@ const AddLocationMaps = memo(() => {
145
227
  followUserLocation={true}
146
228
  >
147
229
  {searchedLocation && (
148
- <Marker
149
- coordinate={{
150
- latitude: searchedLocation.latitude,
151
- longitude: searchedLocation.longitude,
152
- }}
153
- tracksViewChanges={false}
154
- >
155
- <View style={styles.pointCircle}>
156
- <Point />
157
- </View>
158
- </Marker>
230
+ <>
231
+ <Circle
232
+ center={{
233
+ latitude: searchedLocation.latitude,
234
+ longitude: searchedLocation.longitude,
235
+ }}
236
+ radius={300}
237
+ fillColor={Colors.BlueTransparent5}
238
+ strokeColor={Colors.Blue10}
239
+ />
240
+ <Marker
241
+ coordinate={{
242
+ latitude: searchedLocation.latitude,
243
+ longitude: searchedLocation.longitude,
244
+ }}
245
+ tracksViewChanges={false}
246
+ >
247
+ <IconFill
248
+ name="environment"
249
+ size={27}
250
+ color={Colors.Blue10}
251
+ />
252
+ </Marker>
253
+ </>
159
254
  )}
160
255
  </MapView>
161
256
  </View>
@@ -36,23 +36,25 @@ export default StyleSheet.create({
36
36
  right: 0,
37
37
  bottom: 0,
38
38
  },
39
- pointCircle: {
40
- flex: 1,
41
- alignItems: 'center',
42
- justifyContent: 'center',
43
- width: 109,
44
- height: 109,
45
- borderRadius: 50,
46
- backgroundColor: Colors.BlueTransparent5,
47
- borderWidth: 1,
48
- borderColor: Colors.Blue10,
49
- },
50
39
  searchLocation: {
51
40
  paddingVertical: 8,
52
41
  },
53
42
  searchData: {
54
43
  paddingHorizontal: 26,
55
44
  width: '100%',
56
- maxHeight: 100,
45
+ maxHeight: 120,
46
+ },
47
+ button: {
48
+ flexDirection: 'row',
49
+ alignItems: 'center',
50
+ padding: 16,
51
+ },
52
+ separated: {
53
+ height: 1,
54
+ backgroundColor: Colors.Gray3,
55
+ marginHorizontal: 16,
56
+ },
57
+ text: {
58
+ marginLeft: 12,
57
59
  },
58
60
  });
@@ -178,6 +178,7 @@ const SelectAction = memo(({ route }) => {
178
178
  isAutomateTab,
179
179
  isCreateNewAction,
180
180
  isMultiUnits,
181
+ automate,
181
182
  });
182
183
  }
183
184
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -24,10 +24,10 @@ const MultiUnits = () => {
24
24
  const idUser = useGetIdUser();
25
25
  const { navigate } = useNavigation();
26
26
  const { params = {} } = useRoute();
27
- const { isMultiUnits = false, unitName = '', unit } = params;
27
+ const { isMultiUnits = false, unitName = '', unit, isOwner } = params;
28
28
  const [data, setData] = useState([]);
29
29
  // eslint-disable-next-line react-hooks/exhaustive-deps
30
- const tabName = useMemo(() => [t('Scenario'), t('automation')], []);
30
+ const tabName = useMemo(() => [t('smart'), t('automation')], []);
31
31
  const [tabActive, setTabActive] = useState(tabName[0]);
32
32
 
33
33
  const getData = useCallback(
@@ -52,14 +52,14 @@ const MultiUnits = () => {
52
52
  setTabActive(tab);
53
53
  };
54
54
 
55
- const onPressItem = (item) => () => {
55
+ const onPressItem = (item, isOwner) => () => {
56
56
  navigate(Routes.UnitStack, {
57
57
  screen: Routes.ScriptDetail,
58
58
  params: {
59
59
  id: item?.id,
60
60
  name: item?.script?.name,
61
61
  type: item?.type,
62
- havePermission: idUser === item?.user,
62
+ havePermission: isOwner || idUser === item?.user,
63
63
  unit,
64
64
  isMultiUnits,
65
65
  automate: item,
@@ -72,7 +72,7 @@ const MultiUnits = () => {
72
72
  screen: Routes.AddNewAutoSmart,
73
73
  params: {
74
74
  type:
75
- tabActive === t('Scenario')
75
+ tabActive === t('smart')
76
76
  ? AUTOMATE_TYPE.ONE_TAP_ONLY
77
77
  : AUTOMATE_TYPE.VALUE_CHANGE,
78
78
  unit: { id: unit?.id },
@@ -109,7 +109,7 @@ const MultiUnits = () => {
109
109
 
110
110
  const renderContent = useMemo(() => {
111
111
  const listItems = data.filter((item) =>
112
- tabActive === t('Scenario')
112
+ tabActive === t('smart')
113
113
  ? item?.type === AUTOMATE_TYPE.ONE_TAP
114
114
  : item?.type !== AUTOMATE_TYPE.ONE_TAP
115
115
  );
@@ -128,13 +128,13 @@ const MultiUnits = () => {
128
128
  <View style={styles.wrapItem}>
129
129
  {newListItems.map((item, index) => (
130
130
  <ItemOneTap
131
- isOwner={idUser === item?.user}
131
+ isOwner={isOwner}
132
132
  automate={item}
133
133
  wrapSyles={[
134
134
  styles.wrapAutomateItem,
135
135
  index % 2 === 0 && styles.marginRigt8,
136
136
  ]}
137
- onPressItem={onPressItem(item)}
137
+ onPressItem={onPressItem(item, isOwner)}
138
138
  />
139
139
  ))}
140
140
  <ItemAddNew
@@ -152,7 +152,7 @@ describe('Test MultiUnits', () => {
152
152
  });
153
153
  });
154
154
 
155
- it('Test is multi unit and current is Scenario tab', async () => {
155
+ it('Test is multi unit and current is smart tab', async () => {
156
156
  const response = {
157
157
  status: 200,
158
158
  data: [
@@ -201,7 +201,7 @@ describe('Test MultiUnits', () => {
201
201
  });
202
202
  useState.mockImplementationOnce(() => [response.data, mockSetState]);
203
203
  useState.mockImplementationOnce(() => [
204
- getTranslate('en', 'Scenario'),
204
+ getTranslate('en', 'smart'),
205
205
  mockSetState,
206
206
  ]);
207
207
  await act(() => {
@@ -215,6 +215,7 @@ describe('Test Automate', () => {
215
215
  isMultiUnits: true,
216
216
  unitName: '',
217
217
  unit: { id: undefined },
218
+ isOwner: true,
218
219
  });
219
220
 
220
221
  mockedNavigate.mockClear();
@@ -226,6 +227,7 @@ describe('Test Automate', () => {
226
227
  isMultiUnits: false,
227
228
  unitName: 'La Vida',
228
229
  unit: { id: 3 },
230
+ isOwner: false,
229
231
  });
230
232
  });
231
233
  });
@@ -87,11 +87,12 @@ const Automate = () => {
87
87
  });
88
88
  };
89
89
 
90
- const onPressArrowRight = (isMultiUnits, unitName, unitId) => () => {
90
+ const onPressArrowRight = (isMultiUnits, unitName, unitId, isOwner) => () => {
91
91
  navigate(Routes.MultiUnits, {
92
92
  isMultiUnits,
93
93
  unitName,
94
94
  unit: { id: unitId },
95
+ isOwner,
95
96
  });
96
97
  };
97
98
 
@@ -128,7 +129,8 @@ const Automate = () => {
128
129
  onPress={onPressArrowRight(
129
130
  type === UNIT_TYPES.MULTI,
130
131
  unit_name,
131
- unit_id
132
+ unit_id,
133
+ isOwner
132
134
  )}
133
135
  style={styles.arrowRightButton}
134
136
  testID={TESTID.ICON_ARROW_RIGHT}
@@ -239,11 +239,6 @@ describe('test DeviceDetail', () => {
239
239
  );
240
240
  expect(sensorDisplayItem.length).toEqual(2);
241
241
 
242
- const itemMediaPlayer = instance.find(
243
- (el) => el.props.testID === TESTID.DEVICE_DETAIL_MEDIA_PLAYER
244
- );
245
- expect(itemMediaPlayer).toBeDefined();
246
-
247
242
  const itemActionGroup = instance.find(
248
243
  (el) => el.props.testID === TESTID.DEVICE_DETAIL_ACTION_GROUP
249
244
  );
@@ -817,9 +812,10 @@ describe('test DeviceDetail', () => {
817
812
  expect(mockedNavigate).toHaveBeenCalledWith(Routes.ActivityLog, {
818
813
  id: route.params.sensor.id,
819
814
  type: 'action',
815
+ share: route.params.unit,
820
816
  filterEnabled: {
821
- date: false,
822
- user: false,
817
+ date: true,
818
+ user: Boolean(route.params.unit.id),
823
819
  },
824
820
  });
825
821
  });
@@ -2,11 +2,8 @@ import React, { useCallback } from 'react';
2
2
  import { View } from 'react-native';
3
3
  import ActionGroup from '../../../commons/ActionGroup';
4
4
  import { Card } from '../../../commons/CardShadow';
5
- import MediaPlayer from '../../../commons/MediaPlayer';
6
- import { Device } from '../../../configs';
7
5
  import { TESTID } from '../../../configs/Constants';
8
6
  import { useTranslations } from '../../../hooks/Common/useTranslations';
9
- import { standardizeCameraScreenSize } from '../../../utils/Utils';
10
7
  import { DetailHistoryChart } from './DetailHistoryChart';
11
8
  import { sendRemoteCommand } from '../../../iot/RemoteControl';
12
9
  import CurrentRainSensor from '../../../commons/Device/RainningSensor/CurrentRainSensor';
@@ -20,8 +17,11 @@ import ListQualityIndicator from '../../../commons/Device/WaterQualitySensor/Lis
20
17
  import EmergencyDetail from '../../../commons/Device/Emergency/EmergencyDetail';
21
18
  import EmergencyButton from '../../../commons/Device/Emergency/EmergencyButton';
22
19
  import FooterInfo from '../../../commons/Device/FooterInfo';
20
+ import MediaPlayerDetail from '../../../commons/MediaPlayerDetail';
21
+ import { standardizeCameraScreenSize } from '../../../utils/Utils';
22
+ import { Device } from '../../../configs';
23
23
 
24
- const { standardizeHeight, standardizeWidth } = standardizeCameraScreenSize(
24
+ const { standardizeWidth, standardizeHeight } = standardizeCameraScreenSize(
25
25
  Device.screenWidth - 32
26
26
  );
27
27
 
@@ -51,15 +51,15 @@ export const SensorDisplayItem = ({
51
51
  return (
52
52
  <Card title={t('camera')}>
53
53
  <View style={styles.mediaContainer}>
54
- <MediaPlayer
55
- testID={TESTID.DEVICE_DETAIL_MEDIA_PLAYER}
54
+ <MediaPlayerDetail
56
55
  uri={item.configuration.uri}
57
- style={{ height: standardizeHeight }}
58
- ratioWidth={standardizeWidth - 32}
59
56
  thumbnail={{
60
- uri: item.configuration.preview_uri,
57
+ uri: background,
61
58
  }}
62
- background={{ uri: background }}
59
+ key={`camera-device-${item.configuration.id}`}
60
+ cameraName={item.configuration.name}
61
+ width={standardizeWidth - 32}
62
+ height={standardizeHeight - 16}
63
63
  />
64
64
  </View>
65
65
  </Card>
@@ -59,8 +59,11 @@ const DeviceDetail = ({ route }) => {
59
59
  internet: {},
60
60
  });
61
61
  // eslint-disable-next-line no-unused-vars
62
- const [loading, setLoading] = useState(false);
63
- const [isConnected, setConnected] = useState(true);
62
+ const [loading, setLoading] = useState({
63
+ isConnected: true,
64
+ displayTemplate: true,
65
+ });
66
+ const [isConnected, setConnected] = useState(false);
64
67
  const [lastUpdated, setLastUpdated] = useState(null);
65
68
  const [lastEvent, setLastEvent] = useState({ id: 0, reportedAt: 0 });
66
69
  const [maxValue, setMaxValue] = useState(60);
@@ -79,7 +82,21 @@ const DeviceDetail = ({ route }) => {
79
82
  [sensor]
80
83
  );
81
84
 
82
- useDisconnectedDevice(isConnected, sensorName);
85
+ const isDeviceHasBle = useMemo(() => {
86
+ const action = display.items.filter((item) => item.type === 'action');
87
+ if (action.length === 0) {
88
+ return false;
89
+ }
90
+
91
+ return action.some((item) => {
92
+ const { configuration } = item?.configuration;
93
+ return JSON.stringify(configuration).includes(
94
+ '"command_prefer_over_bluetooth":true'
95
+ );
96
+ });
97
+ }, [display]);
98
+
99
+ useDisconnectedDevice(sensorName, isDeviceHasBle);
83
100
 
84
101
  const netInfo = useNetInfo();
85
102
 
@@ -148,6 +165,7 @@ const DeviceDetail = ({ route }) => {
148
165
  }
149
166
  }
150
167
  }
168
+ setLoading((preState) => ({ ...preState, displayTemplate: false }));
151
169
 
152
170
  const controlResult = await axiosGet(
153
171
  API.SENSOR.REMOTE_CONTROL_OPTIONS(sensor.id),
@@ -196,9 +214,10 @@ const DeviceDetail = ({ route }) => {
196
214
  data: {
197
215
  id: sensor.id,
198
216
  type: 'action',
217
+ share: unit,
199
218
  filterEnabled: {
200
- date: false,
201
- user: false,
219
+ date: true,
220
+ user: Boolean(unit.id),
202
221
  },
203
222
  },
204
223
  text: t('activity_log'),
@@ -219,6 +238,11 @@ const DeviceDetail = ({ route }) => {
219
238
  data: { unit, sensor },
220
239
  text: t('manage_access'),
221
240
  });
241
+ menuItems.push({
242
+ text: t('move_to_another_sub_unit'),
243
+ route: Routes.MoveToAnotherSubUnit,
244
+ data: { unit, sensor, station },
245
+ });
222
246
  }
223
247
  if (isShowSetupEmergencyContact) {
224
248
  menuItems.push({
@@ -255,15 +279,15 @@ const DeviceDetail = ({ route }) => {
255
279
  return [...menuItems];
256
280
  }, [
257
281
  display.items,
282
+ isOwner,
283
+ isShowSetupEmergencyContact,
258
284
  t,
259
285
  isFavourite,
260
- emergencyDeviceId,
261
- isShowSetupEmergencyContact,
262
286
  sensor,
263
- setSensorName,
264
287
  sensorName,
265
- isOwner,
266
288
  unit,
289
+ station,
290
+ emergencyDeviceId,
267
291
  addToFavorites,
268
292
  removeFromFavorites,
269
293
  ]);
@@ -339,11 +363,14 @@ const DeviceDetail = ({ route }) => {
339
363
  transformDatetime(data, ['last_updated']);
340
364
  setLastUpdated(data.last_updated);
341
365
  }
366
+ setLoading((preState) => ({ ...preState, isConnected: false }));
342
367
  };
343
368
  if (sensor.is_managed_by_backend && !sensor.is_other_device) {
344
369
  const updateInterval = setInterval(() => fetchValues(), 5000);
345
370
  fetchValues();
346
371
  return () => clearInterval(updateInterval);
372
+ } else {
373
+ setLoading((preState) => ({ ...preState, isConnected: false }));
347
374
  }
348
375
  }, [sensor, display]);
349
376
 
@@ -429,6 +456,7 @@ const DeviceDetail = ({ route }) => {
429
456
  `@CACHE_REQUEST_${API.SENSOR.REMOTE_CONTROL_OPTIONS(sensor.id)}`
430
457
  );
431
458
  controlOptionData && setControlOptions(JSON.parse(controlOptionData));
459
+ setLoading((preState) => ({ ...preState, displayTemplate: false }));
432
460
  };
433
461
 
434
462
  const onItemMenuClicked = (item) => {
@@ -453,6 +481,10 @@ const DeviceDetail = ({ route }) => {
453
481
  showPopoverWithRef(refMenuAction);
454
482
  }, [showPopoverWithRef, refMenuAction]);
455
483
 
484
+ const onPressSetting = useCallback(() => {
485
+ navigation.navigate(Routes.EmergencySetting);
486
+ }, [navigation]);
487
+
456
488
  const HeaderRight = useMemo(
457
489
  () => (
458
490
  <View style={styles.headerRight}>
@@ -467,6 +499,13 @@ const DeviceDetail = ({ route }) => {
467
499
  <IconOutline name="star" size={25} />
468
500
  )}
469
501
  </TouchableOpacity>
502
+
503
+ {isShowSetupEmergencyContact && (
504
+ <TouchableOpacity style={styles.button} onPress={onPressSetting}>
505
+ <Icon name="setting" size={25} color={Colors.Black} />
506
+ </TouchableOpacity>
507
+ )}
508
+
470
509
  <TouchableOpacity
471
510
  style={styles.button}
472
511
  onPress={handleShowMenuAction}
@@ -477,7 +516,14 @@ const DeviceDetail = ({ route }) => {
477
516
  </TouchableOpacity>
478
517
  </View>
479
518
  ),
480
- [isFavourite, addToFavorites, removeFromFavorites, handleShowMenuAction]
519
+ [
520
+ isFavourite,
521
+ removeFromFavorites,
522
+ addToFavorites,
523
+ isShowSetupEmergencyContact,
524
+ onPressSetting,
525
+ handleShowMenuAction,
526
+ ]
481
527
  );
482
528
 
483
529
  return (
@@ -486,17 +532,21 @@ const DeviceDetail = ({ route }) => {
486
532
  title={sensorName}
487
533
  headerAniStyle={styles.header}
488
534
  rightComponent={HeaderRight}
489
- loading={loading}
490
535
  onRefresh={onRefresh}
491
536
  >
492
- <View style={styles.wrapTemplate}>{renderSensorConnected()}</View>
537
+ <View style={styles.wrapTemplate}>
538
+ {loading.displayTemplate === false &&
539
+ loading.isConnected === false &&
540
+ netInfo.isConnected !== null &&
541
+ renderSensorConnected()}
542
+ </View>
493
543
  {isShowSetupEmergencyContact && canManageSubUnit && (
494
544
  <BottomButtonView
495
545
  style={styles.bottomButtonEmergencyContact}
496
- mainIcon={<Icon name="phone" size={24} color={Colors.Gray9} />}
497
- mainTitle={t('emergency_contacts')}
546
+ mainIcon={<Icon name="plus" size={16} color={Colors.Primary} />}
547
+ mainTitle={t('setup_my_emergency_contact')}
498
548
  onPressMain={onSetupContacts}
499
- typeMain="CardShadow"
549
+ typeMain="primaryBorder"
500
550
  semiboldMain={false}
501
551
  />
502
552
  )}