@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.
- package/assets/images/Map/MarkerGeolocation.svg +4 -0
- package/assets/images/SonosSpeaker/buttonpause-active.svg +3 -0
- package/assets/images/SonosSpeaker/buttonpause-notactive.svg +3 -0
- package/assets/images/SonosSpeaker/picture-main-notactive.svg +5 -0
- package/assets/images/SonosSpeaker/picture-main.svg +6 -0
- package/assets/images/SonosSpeaker/picture-volume.svg +3 -0
- package/package.json +4 -22
- package/src/Images/Common/buttonLeftCurtain.png +0 -0
- package/src/Images/Common/buttonPause-center-curtain.png +0 -0
- package/src/Images/Common/buttonRightCurtain.png +0 -0
- package/src/commons/ActionGroup/CurtainButtonTemplate.js +139 -0
- package/src/commons/ActionGroup/CurtainButtonTemplateStyle.js +58 -0
- package/src/commons/ActionGroup/__test__/CurtainButtonTemplate.test.js +72 -0
- package/src/commons/ActionGroup/index.js +3 -0
- package/src/commons/Auth/__test__/AccountList.test.js +33 -0
- package/src/commons/CameraDevice/index.js +2 -0
- package/src/commons/CardShadow/index.js +1 -1
- package/src/commons/CardShadow/styles.js +1 -3
- package/src/commons/DateTimeRangeChange/DateTimeButton.js +1 -1
- package/src/commons/DateTimeRangeChange/index.js +2 -2
- package/src/commons/Device/HistoryChart.js +21 -55
- package/src/commons/Device/HorizontalBarChart.js +46 -30
- package/src/commons/Device/LinearChart.js +0 -34
- package/src/commons/Device/PMSensor/PMSensorIndicatior.js +1 -1
- package/src/commons/Device/PMSensor/PMSensorIndicatorStyles.js +2 -1
- package/src/commons/Device/SonosSpeaker/__test__/SonosSpeaker.test.js +57 -0
- package/src/commons/Device/SonosSpeaker/index.js +88 -0
- package/src/commons/Device/SonosSpeaker/styles.js +57 -0
- package/src/commons/Form/CurrencyInput.js +169 -0
- package/src/commons/Form/__test__/CurrencyInput.test.js +65 -0
- package/src/commons/FourButtonFilterHistory/__test__/FourButtonFilterHistory.test.js +48 -0
- package/src/commons/FourButtonFilterHistory/index.js +72 -0
- package/src/commons/FourButtonFilterHistory/styles.js +22 -0
- package/src/commons/MediaPlayerDetail/Styles/MediaPlayerDetailStyles.js +14 -0
- package/src/commons/MediaPlayerDetail/index.js +204 -161
- package/src/commons/SearchLocation/index.js +0 -1
- package/src/commons/Sharing/RowMember.js +7 -2
- package/src/commons/Sharing/__test__/RowMember.test.js +42 -0
- package/src/commons/SubUnit/ShortDetail.js +12 -6
- package/src/commons/UnitSummary/AirQuality/SegmentedRoundDisplay/index.js +1 -1
- package/src/commons/UnitSummary/ConfigHistoryChart.js +2 -1
- package/src/configs/API.js +13 -3
- package/src/configs/Constants.js +14 -4
- package/src/configs/Images.js +3 -0
- package/src/configs/SCConfig.js +8 -0
- package/src/context/actionType.ts +5 -0
- package/src/context/mockStore.ts +3 -0
- package/src/context/reducer.ts +14 -0
- package/src/iot/RemoteControl/Bluetooth.js +14 -0
- package/src/iot/RemoteControl/index.js +0 -1
- package/src/navigations/UnitStack.js +42 -4
- package/src/screens/ActivityLog/FilterPopup.js +1 -1
- package/src/screens/ActivityLog/ItemLog.js +11 -2
- package/src/screens/ActivityLog/__test__/ItemLog.test.js +46 -0
- package/src/screens/ActivityLog/hooks/index.js +1 -0
- package/src/screens/ActivityLog/index.js +0 -1
- package/src/screens/AddCommon/SelectSubUnit.js +24 -2
- package/src/screens/AddCommon/SelectUnit.js +12 -0
- package/src/screens/AddLocationMaps/index.js +139 -44
- package/src/screens/AddLocationMaps/indexStyle.js +14 -12
- package/src/screens/AddNewAction/SelectAction.js +1 -0
- package/src/screens/Automate/MultiUnits.js +8 -8
- package/src/screens/Automate/__test__/MultiUnits.test.js +2 -2
- package/src/screens/Automate/__test__/index.test.js +2 -0
- package/src/screens/Automate/index.js +4 -2
- package/src/screens/Device/__test__/detail.test.js +3 -7
- package/src/screens/Device/components/SensorDisplayItem.js +10 -10
- package/src/screens/Device/detail.js +65 -15
- package/src/screens/Device/hooks/useDisconnectedDevice.js +32 -26
- package/src/screens/Device/styles.js +3 -3
- package/src/screens/EmergencySetting/__test__/DropDownItem.test.js +59 -0
- package/src/screens/EmergencySetting/__test__/index.test.js +27 -0
- package/src/screens/EmergencySetting/components/DropDownItem.js +54 -0
- package/src/screens/EmergencySetting/index.js +90 -0
- package/src/screens/EmergencySetting/styles/DropDownItem.js +38 -0
- package/src/screens/EmergencySetting/styles.js +19 -0
- package/src/screens/MoveToAnotherSubUnit/__test__/index.test.js +126 -0
- package/src/screens/MoveToAnotherSubUnit/index.js +88 -0
- package/src/screens/MoveToAnotherSubUnit/styles/MoveToAnotherSubUnitStyles.js +50 -0
- package/src/screens/Notification/__test__/Notification.test.js +3 -3
- package/src/screens/Notification/components/NotificationItem.js +3 -6
- package/src/screens/Notification/index.js +2 -2
- package/src/screens/ScriptDetail/Styles/indexStyles.js +0 -1
- package/src/screens/ScriptDetail/__test__/index.test.js +13 -0
- package/src/screens/ScriptDetail/index.js +20 -17
- package/src/screens/SelectUnit/index.js +2 -0
- package/src/screens/Sharing/MemberList.js +2 -9
- package/src/screens/SubUnit/AddSubUnit.js +79 -59
- package/src/screens/SubUnit/AddSubUnitStyles.js +0 -2
- package/src/screens/SubUnit/__test__/AddSubUnit.test.js +4 -3
- package/src/screens/TDSGuide/index.js +6 -4
- package/src/screens/Unit/ChooseLocation.js +96 -0
- package/src/screens/Unit/ChooseLocationStyles.js +26 -0
- package/src/screens/Unit/Detail.js +14 -2
- package/src/screens/Unit/ManageUnit.js +4 -5
- package/src/screens/Unit/SelectAddress.js +240 -0
- package/src/screens/Unit/SelectAddressStyles.js +48 -0
- package/src/screens/Unit/SmartAccountItem.js +1 -1
- package/src/screens/Unit/Summaries.js +5 -1
- package/src/screens/Unit/__test__/ChooseLocation.test.js +112 -0
- package/src/screens/Unit/__test__/SelectAddress.test.js +216 -0
- package/src/screens/Unit/components/MyUnitDevice/index.js +21 -5
- package/src/screens/Unit/hook/useStateAlertRemove.js +3 -1
- package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +2 -2
- package/src/screens/UnitSummary/components/PowerConsumption/index.js +3 -2
- package/src/screens/UnitSummary/components/WaterQuality/Item/index.js +1 -3
- package/src/screens/UnitSummary/index.js +3 -2
- package/src/screens/WaterQualityGuide/index.js +1 -0
- package/src/utils/Apis/axios.js +17 -5
- package/src/utils/I18n/translations/en.json +19 -4
- package/src/utils/I18n/translations/vi.json +22 -7
- package/src/utils/Route/index.js +4 -1
- package/src/utils/Utils.js +22 -2
- package/assets/images/AddLocationMaps/PinLocation.svg +0 -3
- package/assets/images/AddLocationMaps/Point.svg +0 -3
- package/src/commons/ThreeButtonHistory/CalendarHeader.js +0 -35
- package/src/commons/ThreeButtonHistory/CalendarHeaderStyles.js +0 -17
- package/src/commons/ThreeButtonHistory/SelectMonth.js +0 -53
- package/src/commons/ThreeButtonHistory/SelectMonthStyles.js +0 -29
- package/src/commons/ThreeButtonHistory/__test__/SelectMonth.test.js +0 -37
- package/src/commons/ThreeButtonHistory/__test__/ThreeButtonHistory.test.js +0 -231
- package/src/commons/ThreeButtonHistory/index.js +0 -281
- package/src/commons/ThreeButtonHistory/styles.js +0 -65
- package/src/screens/Unit/ManageUnit/index.js +0 -286
- package/src/screens/Unit/SelectLocation.js +0 -161
- 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 {
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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:
|
|
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
|
});
|
|
@@ -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('
|
|
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('
|
|
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('
|
|
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={
|
|
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
|
|
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', '
|
|
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:
|
|
822
|
-
user:
|
|
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 {
|
|
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
|
-
<
|
|
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:
|
|
57
|
+
uri: background,
|
|
61
58
|
}}
|
|
62
|
-
|
|
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(
|
|
63
|
-
|
|
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
|
-
|
|
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:
|
|
201
|
-
user:
|
|
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
|
-
[
|
|
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}>
|
|
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="
|
|
497
|
-
mainTitle={t('
|
|
546
|
+
mainIcon={<Icon name="plus" size={16} color={Colors.Primary} />}
|
|
547
|
+
mainTitle={t('setup_my_emergency_contact')}
|
|
498
548
|
onPressMain={onSetupContacts}
|
|
499
|
-
typeMain="
|
|
549
|
+
typeMain="primaryBorder"
|
|
500
550
|
semiboldMain={false}
|
|
501
551
|
/>
|
|
502
552
|
)}
|