@eohjsc/react-native-smart-city 0.4.84 → 0.4.86
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/Notify.svg +9 -0
- package/package.json +1 -1
- package/src/commons/Automate/ItemAutomate.js +6 -1
- package/src/commons/Device/PMSensor/PMSensorIndicator.js +15 -8
- package/src/commons/Device/WaterQualitySensor/ListQualityIndicator.js +23 -15
- package/src/commons/Device/WaterQualitySensor/QualityIndicatorsItem.js +10 -9
- package/src/commons/MenuActionAddnew/index.js +6 -0
- package/src/commons/Sharing/WrapHeaderScrollable.js +1 -1
- package/src/commons/SubUnit/DeviceTemplate/ConfigValue/ConfigValue.js +2 -8
- package/src/commons/SubUnit/DeviceTemplate/EvaluationOverConfig/EvaluationOverConfig.js +2 -10
- package/src/commons/SubUnit/OneTap/ItemOneTap.js +4 -3
- package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +14 -1
- package/src/commons/SubUnit/ShortDetail.js +14 -4
- package/src/configs/API.js +10 -0
- package/src/configs/AccessibilityLabel.js +3 -0
- package/src/navigations/UnitStack.js +10 -2
- package/src/screens/Automate/AddNewAction/SetupScriptNotify.js +92 -0
- package/src/screens/Automate/AddNewAction/Styles/SetupScriptNotifyStyles.js +57 -0
- package/src/screens/Automate/AddNewAction/__test__/SetupConfigCondition.test.js +13 -0
- package/src/screens/Automate/AddNewAction/__test__/SetupScriptNotify.test.js +84 -0
- package/src/screens/Automate/EditActionsList/__tests__/index.test.js +15 -4
- package/src/screens/Automate/EditActionsList/index.js +130 -72
- package/src/screens/Automate/ScriptDetail/Components/AddActionScript.js +168 -0
- package/src/screens/Automate/ScriptDetail/__test__/index.test.js +75 -6
- package/src/screens/Automate/ScriptDetail/index.js +147 -84
- package/src/screens/Device/__test__/mqttDetail.test.js +20 -20
- package/src/screens/Device/detail.js +1 -3
- package/src/screens/Sharing/{MemberList.js → UnitMemberList.js} +4 -4
- package/src/screens/Sharing/__test__/{MemberList.test.js → UnitMemberList.test.js} +2 -2
- package/src/screens/UnitSummary/__test__/index.test.js +2 -1
- package/src/screens/UnitSummary/components/3PPowerConsumption/__test__/3PPowerConsumption.test.js +37 -30
- package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +105 -166
- package/src/screens/UnitSummary/components/AirQuality/SegmentedRoundChart.js +32 -0
- package/src/{commons/UnitSummary → screens/UnitSummary/components}/AirQuality/__test__/index.test.js +25 -15
- package/src/{commons/UnitSummary → screens/UnitSummary/components}/AirQuality/index.js +55 -71
- package/src/{commons/UnitSummary → screens/UnitSummary/components}/AirQuality/styles.js +1 -2
- package/src/screens/UnitSummary/components/PowerConsumption/__test__/PowerConsumption.test.js +26 -20
- package/src/screens/UnitSummary/components/PowerConsumption/index.js +59 -87
- package/src/screens/UnitSummary/components/RunningDevices/index.js +27 -23
- package/src/screens/UnitSummary/components/Temperature/ItemTemperature/index.js +33 -20
- package/src/screens/UnitSummary/components/Temperature/index.js +52 -79
- package/src/screens/UnitSummary/components/UvIndex/SegmentedRoundChart.js +36 -0
- package/src/screens/UnitSummary/components/UvIndex/__test__/index.test.js +8 -0
- package/src/screens/UnitSummary/components/UvIndex/index.js +16 -72
- package/src/screens/UnitSummary/components/UvIndex/styles.js +48 -0
- package/src/screens/UnitSummary/components/WaterQuality/Item/index.js +6 -4
- package/src/screens/UnitSummary/components/WaterQuality/__test__/index.test.js +26 -12
- package/src/screens/UnitSummary/components/WaterQuality/index.js +93 -3
- package/src/screens/UnitSummary/index.js +1 -9
- package/src/utils/I18n/translations/en.js +16 -1
- package/src/utils/I18n/translations/vi.js +15 -1
- package/src/utils/Route/index.js +1 -0
- package/src/screens/UnitSummary/components/PowerConsumption/ItemPower/index.js +0 -53
- package/src/screens/UnitSummary/components/PowerConsumption/__test__/ItemPower.test.js +0 -20
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
2
|
import { StyleSheet, View } from 'react-native';
|
|
3
3
|
import { useTranslations } from '../../../../hooks/Common/useTranslations';
|
|
4
4
|
|
|
@@ -10,84 +10,76 @@ import SvgHumidity from '../../../../../assets/images/Device/humidity.svg';
|
|
|
10
10
|
import SvgRain from '../../../../../assets/images/Device/rain-outline.svg';
|
|
11
11
|
import SvgTemperature from '../../../../../assets/images/Device/temperature.svg';
|
|
12
12
|
import SvgWind from '../../../../../assets/images/Device/wind.svg';
|
|
13
|
+
import { useWatchConfigs } from '../../../../hooks/IoT';
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
-
return [
|
|
16
|
-
{
|
|
17
|
-
id: '0',
|
|
18
|
-
svgMain: <SvgTemperature />,
|
|
19
|
-
title: `${t('text_temperature')}`,
|
|
20
|
-
value: `${summaryDetail.tempValue || t('loading')}`,
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
id: '1',
|
|
24
|
-
svgMain: <SvgHumidity />,
|
|
25
|
-
title: `${t('text_humidity')}`,
|
|
26
|
-
value: `${summaryDetail.humiValue || t('loading')}`,
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
id: '2',
|
|
30
|
-
svgMain: <SvgWind />,
|
|
31
|
-
title: `${t('text_wind')}`,
|
|
32
|
-
value: summaryDetail.windValue || t('loading'),
|
|
33
|
-
des: `${t('text_win_direction')}: ${
|
|
34
|
-
summaryDetail.windDirection || t('loading')
|
|
35
|
-
}`,
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
id: '3',
|
|
39
|
-
svgMain: <SvgRain />,
|
|
40
|
-
title: `${t('text_rain')}`,
|
|
41
|
-
value: summaryDetail.rainValue || t('loading'),
|
|
42
|
-
},
|
|
43
|
-
];
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const Temperature = memo(({ summaryDetail }) => {
|
|
15
|
+
const Temperature = ({ summaryDetail }) => {
|
|
47
16
|
const t = useTranslations();
|
|
48
|
-
const { listConfigs } = summaryDetail;
|
|
17
|
+
const { listConfigs, windDirection } = summaryDetail;
|
|
18
|
+
const { temp, humi, rain, rain_duration, wind, wind_direction } =
|
|
19
|
+
listConfigs || {};
|
|
20
|
+
useWatchConfigs([temp, humi, rain, rain_duration, wind, wind_direction]);
|
|
49
21
|
|
|
50
|
-
const showBoxHistory =
|
|
51
|
-
return !!listConfigs;
|
|
52
|
-
}, [listConfigs]);
|
|
22
|
+
const showBoxHistory = !!listConfigs;
|
|
53
23
|
|
|
54
24
|
const dataTemperature = useMemo(
|
|
55
|
-
() =>
|
|
56
|
-
|
|
25
|
+
() => [
|
|
26
|
+
{
|
|
27
|
+
id: temp,
|
|
28
|
+
svgMain: <SvgTemperature />,
|
|
29
|
+
title: `${t('text_temperature')}`,
|
|
30
|
+
measure: '°C',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: humi,
|
|
34
|
+
svgMain: <SvgHumidity />,
|
|
35
|
+
title: `${t('text_humidity')}`,
|
|
36
|
+
measure: '%',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: wind,
|
|
40
|
+
svgMain: <SvgWind />,
|
|
41
|
+
title: `${t('text_wind')}`,
|
|
42
|
+
des: `${t('text_win_direction')}: ${windDirection || t('loading')}`,
|
|
43
|
+
measure: 'm/s',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: rain,
|
|
47
|
+
svgMain: <SvgRain />,
|
|
48
|
+
title: `${t('text_rain')}`,
|
|
49
|
+
measure: '',
|
|
50
|
+
custom_get_value: {
|
|
51
|
+
1: t('rainy'),
|
|
52
|
+
0: t('no_rain'),
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
[humi, rain, windDirection, t, temp, wind]
|
|
57
57
|
);
|
|
58
58
|
|
|
59
|
-
const configs = useMemo(
|
|
60
|
-
|
|
59
|
+
const configs = useMemo(
|
|
60
|
+
() => [
|
|
61
61
|
{
|
|
62
|
-
id:
|
|
62
|
+
id: temp,
|
|
63
63
|
title: t('text_temperature'),
|
|
64
64
|
color: Colors.Blue10,
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
|
-
id:
|
|
67
|
+
id: humi,
|
|
68
68
|
title: t('text_humidity'),
|
|
69
69
|
color: Colors.Red6,
|
|
70
70
|
},
|
|
71
|
-
]
|
|
72
|
-
|
|
71
|
+
],
|
|
72
|
+
[humi, temp, t]
|
|
73
|
+
);
|
|
74
|
+
|
|
73
75
|
return (
|
|
74
76
|
<>
|
|
75
77
|
<Section type={'border'}>
|
|
76
78
|
<Today style={styles.textIndoor} />
|
|
77
79
|
<View style={styles.boxTemperature}>
|
|
78
|
-
{dataTemperature.map((item
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return (
|
|
82
|
-
<ItemTemperature
|
|
83
|
-
title={title}
|
|
84
|
-
value={value}
|
|
85
|
-
des={des}
|
|
86
|
-
svgMain={svgMain}
|
|
87
|
-
key={index.toString()}
|
|
88
|
-
/>
|
|
89
|
-
);
|
|
90
|
-
})}
|
|
80
|
+
{dataTemperature.map((item) => (
|
|
81
|
+
<ItemTemperature {...item} key={item.id} />
|
|
82
|
+
))}
|
|
91
83
|
</View>
|
|
92
84
|
</Section>
|
|
93
85
|
{showBoxHistory && (
|
|
@@ -97,7 +89,7 @@ const Temperature = memo(({ summaryDetail }) => {
|
|
|
97
89
|
)}
|
|
98
90
|
</>
|
|
99
91
|
);
|
|
100
|
-
}
|
|
92
|
+
};
|
|
101
93
|
|
|
102
94
|
export default Temperature;
|
|
103
95
|
|
|
@@ -110,23 +102,4 @@ const styles = StyleSheet.create({
|
|
|
110
102
|
flexWrap: 'wrap',
|
|
111
103
|
justifyContent: 'space-between',
|
|
112
104
|
},
|
|
113
|
-
rowAverage: {
|
|
114
|
-
flexDirection: 'row',
|
|
115
|
-
alignItems: 'center',
|
|
116
|
-
marginBottom: 16,
|
|
117
|
-
paddingHorizontal: 16,
|
|
118
|
-
},
|
|
119
|
-
txtAverage: {
|
|
120
|
-
marginRight: 20,
|
|
121
|
-
},
|
|
122
|
-
boxLastDay: {
|
|
123
|
-
paddingVertical: 24,
|
|
124
|
-
borderRadius: 20,
|
|
125
|
-
backgroundColor: Colors.White,
|
|
126
|
-
borderWidth: 1,
|
|
127
|
-
borderColor: Colors.Gray4,
|
|
128
|
-
marginTop: 16,
|
|
129
|
-
marginBottom: 25,
|
|
130
|
-
paddingHorizontal: 0,
|
|
131
|
-
},
|
|
132
105
|
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React, { memo, useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
import styles from './styles';
|
|
4
|
+
|
|
5
|
+
import { useTranslations } from '../../../../hooks/Common/useTranslations';
|
|
6
|
+
import { useConfigGlobalState } from '../../../../iot/states';
|
|
7
|
+
import SegmentedRoundDisplay from '../../../../commons/UnitSummary/AirQuality/SegmentedRoundDisplay';
|
|
8
|
+
|
|
9
|
+
const SegmentedRoundChart = memo(({ data }) => {
|
|
10
|
+
const t = useTranslations();
|
|
11
|
+
|
|
12
|
+
const { id, uv_color, uv_level } = data || {};
|
|
13
|
+
const [configValues] = useConfigGlobalState('configValues');
|
|
14
|
+
|
|
15
|
+
const renderAir = useCallback(() => {
|
|
16
|
+
const getValue = configValues?.[id]?.value ?? '--';
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<SegmentedRoundDisplay
|
|
20
|
+
filledArcColor={uv_color}
|
|
21
|
+
value={getValue}
|
|
22
|
+
valueText={getValue}
|
|
23
|
+
totalValue={10}
|
|
24
|
+
style={styles.segment}
|
|
25
|
+
pos={[0, 2, 4, 6, 8, '10+']}
|
|
26
|
+
title={uv_level}
|
|
27
|
+
boxTitle
|
|
28
|
+
textHeader={t('UV Index')}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
}, [configValues, id, t, uv_color, uv_level]);
|
|
32
|
+
|
|
33
|
+
return renderAir();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export default SegmentedRoundChart;
|
|
@@ -9,6 +9,14 @@ import api from '../../../../../utils/Apis/axios';
|
|
|
9
9
|
|
|
10
10
|
new MockAdapter(api.axiosInstance);
|
|
11
11
|
|
|
12
|
+
jest.mock('@react-navigation/native', () => {
|
|
13
|
+
return {
|
|
14
|
+
...jest.requireActual('@react-navigation/native'),
|
|
15
|
+
useRoute: jest.fn(),
|
|
16
|
+
useFocusEffect: (func) => func(),
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
|
|
12
20
|
const wrapComponent = (data) => (
|
|
13
21
|
<SCProvider initState={mockSCStore({})}>
|
|
14
22
|
<UvIndex {...data} />
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { memo, useMemo } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { View } from 'react-native';
|
|
3
3
|
import { IconOutline } from '@ant-design/icons-react-native';
|
|
4
4
|
import { useTranslations } from '../../../../hooks/Common/useTranslations';
|
|
5
5
|
|
|
@@ -7,45 +7,35 @@ import { Colors } from '../../../../configs';
|
|
|
7
7
|
import Text from '../../../../commons/Text';
|
|
8
8
|
import { Section, Today } from '../../../../commons';
|
|
9
9
|
import VisualChart from '../../../Device/components/VisualChart';
|
|
10
|
-
import
|
|
10
|
+
import SegmentedRoundChart from './SegmentedRoundChart';
|
|
11
|
+
import { useWatchConfigs } from '../../../../hooks/IoT';
|
|
12
|
+
import styles from './styles';
|
|
11
13
|
|
|
12
14
|
const UvIndex = memo(({ summaryDetail }) => {
|
|
13
15
|
const t = useTranslations();
|
|
14
|
-
const {
|
|
16
|
+
const {
|
|
17
|
+
listConfigs = {},
|
|
18
|
+
uv_id,
|
|
19
|
+
uv_color,
|
|
20
|
+
uv_level,
|
|
21
|
+
advices = [],
|
|
22
|
+
uv_value,
|
|
23
|
+
} = summaryDetail;
|
|
24
|
+
const { uv } = listConfigs;
|
|
15
25
|
const showBoxHistory = useMemo(() => {
|
|
16
26
|
return !!uv_id;
|
|
17
27
|
}, [uv_id]);
|
|
18
|
-
|
|
19
|
-
let valueRefined = summaryDetail.uv_value;
|
|
20
|
-
if (summaryDetail.uv_value < 0) {
|
|
21
|
-
valueRefined = 0;
|
|
22
|
-
} else if (summaryDetail.uv_value > 10) {
|
|
23
|
-
valueRefined = 10;
|
|
24
|
-
}
|
|
28
|
+
useWatchConfigs([uv]);
|
|
25
29
|
|
|
26
30
|
const configs = useMemo(() => {
|
|
27
31
|
return [{ id: uv_id, title: t('text_uv_index'), color: Colors.Blue10 }];
|
|
28
32
|
}, [t, uv_id]);
|
|
29
|
-
|
|
33
|
+
const data = { id: uv, uv_color, uv_level, uv_value: uv_value };
|
|
30
34
|
return (
|
|
31
35
|
<>
|
|
32
36
|
<Section type={'border'}>
|
|
33
37
|
<Today />
|
|
34
|
-
<
|
|
35
|
-
filledArcColor={summaryDetail.uv_color}
|
|
36
|
-
value={valueRefined}
|
|
37
|
-
valueText={
|
|
38
|
-
summaryDetail.uv_value !== undefined
|
|
39
|
-
? summaryDetail.uv_value
|
|
40
|
-
: t('loading')
|
|
41
|
-
}
|
|
42
|
-
totalValue={10}
|
|
43
|
-
style={styles.segment}
|
|
44
|
-
pos={[0, 2, 4, 6, 8, '10+']}
|
|
45
|
-
title={summaryDetail.uv_level}
|
|
46
|
-
boxTitle
|
|
47
|
-
textHeader={t('UV Index')}
|
|
48
|
-
/>
|
|
38
|
+
<SegmentedRoundChart data={data} />
|
|
49
39
|
<View style={styles.boxHealth}>
|
|
50
40
|
<IconOutline name="alert" size={20} style={styles.iconMargin} />
|
|
51
41
|
<Text
|
|
@@ -83,49 +73,3 @@ const UvIndex = memo(({ summaryDetail }) => {
|
|
|
83
73
|
});
|
|
84
74
|
|
|
85
75
|
export default UvIndex;
|
|
86
|
-
|
|
87
|
-
const styles = StyleSheet.create({
|
|
88
|
-
box: {
|
|
89
|
-
paddingHorizontal: 16,
|
|
90
|
-
paddingVertical: 24,
|
|
91
|
-
borderRadius: 20,
|
|
92
|
-
backgroundColor: Colors.White,
|
|
93
|
-
borderWidth: 1,
|
|
94
|
-
borderColor: Colors.Gray4,
|
|
95
|
-
marginBottom: 16,
|
|
96
|
-
},
|
|
97
|
-
textIndoor: {
|
|
98
|
-
color: Colors.Gray9,
|
|
99
|
-
fontSize: 20,
|
|
100
|
-
marginBottom: 4,
|
|
101
|
-
},
|
|
102
|
-
segment: {
|
|
103
|
-
marginTop: 36,
|
|
104
|
-
alignSelf: 'center',
|
|
105
|
-
},
|
|
106
|
-
boxHealth: {
|
|
107
|
-
flexDirection: 'row',
|
|
108
|
-
marginTop: 24,
|
|
109
|
-
alignItems: 'center',
|
|
110
|
-
marginBottom: 12,
|
|
111
|
-
},
|
|
112
|
-
boxDot: {
|
|
113
|
-
width: 8,
|
|
114
|
-
height: 8,
|
|
115
|
-
borderRadius: 4,
|
|
116
|
-
backgroundColor: Colors.Yellow6,
|
|
117
|
-
marginRight: 8,
|
|
118
|
-
marginTop: 6,
|
|
119
|
-
},
|
|
120
|
-
boxContentHealth: {
|
|
121
|
-
flexDirection: 'row',
|
|
122
|
-
marginBottom: 8,
|
|
123
|
-
marginRight: 21,
|
|
124
|
-
},
|
|
125
|
-
iconMargin: {
|
|
126
|
-
marginRight: 8,
|
|
127
|
-
},
|
|
128
|
-
textTitle: {
|
|
129
|
-
lineHeight: 28,
|
|
130
|
-
},
|
|
131
|
-
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { Colors } from '../../../../configs';
|
|
3
|
+
|
|
4
|
+
export default StyleSheet.create({
|
|
5
|
+
box: {
|
|
6
|
+
paddingHorizontal: 16,
|
|
7
|
+
paddingVertical: 24,
|
|
8
|
+
borderRadius: 20,
|
|
9
|
+
backgroundColor: Colors.White,
|
|
10
|
+
borderWidth: 1,
|
|
11
|
+
borderColor: Colors.Gray4,
|
|
12
|
+
marginBottom: 16,
|
|
13
|
+
},
|
|
14
|
+
textIndoor: {
|
|
15
|
+
color: Colors.Gray9,
|
|
16
|
+
fontSize: 20,
|
|
17
|
+
marginBottom: 4,
|
|
18
|
+
},
|
|
19
|
+
segment: {
|
|
20
|
+
marginTop: 36,
|
|
21
|
+
alignSelf: 'center',
|
|
22
|
+
},
|
|
23
|
+
boxHealth: {
|
|
24
|
+
flexDirection: 'row',
|
|
25
|
+
marginTop: 24,
|
|
26
|
+
alignItems: 'center',
|
|
27
|
+
marginBottom: 12,
|
|
28
|
+
},
|
|
29
|
+
boxDot: {
|
|
30
|
+
width: 8,
|
|
31
|
+
height: 8,
|
|
32
|
+
borderRadius: 4,
|
|
33
|
+
backgroundColor: Colors.Yellow6,
|
|
34
|
+
marginRight: 8,
|
|
35
|
+
marginTop: 6,
|
|
36
|
+
},
|
|
37
|
+
boxContentHealth: {
|
|
38
|
+
flexDirection: 'row',
|
|
39
|
+
marginBottom: 8,
|
|
40
|
+
marginRight: 21,
|
|
41
|
+
},
|
|
42
|
+
iconMargin: {
|
|
43
|
+
marginRight: 8,
|
|
44
|
+
},
|
|
45
|
+
textTitle: {
|
|
46
|
+
lineHeight: 28,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
@@ -6,12 +6,12 @@ import { useNavigation } from '@react-navigation/native';
|
|
|
6
6
|
import Text from '../../../../../commons/Text';
|
|
7
7
|
import { Colors, Constants } from '../../../../../configs';
|
|
8
8
|
import Route from '../../../../../utils/Route';
|
|
9
|
+
import { useConfigGlobalState } from '../../../../../iot/states';
|
|
9
10
|
|
|
10
11
|
const width_item = (Constants.width - 48) / 2;
|
|
11
12
|
|
|
12
|
-
const Item = memo((
|
|
13
|
-
const
|
|
14
|
-
|
|
13
|
+
const Item = memo(({ id, svgMain, title, measure, des, color, waterType }) => {
|
|
14
|
+
const [configValues] = useConfigGlobalState('configValues');
|
|
15
15
|
const navigation = useNavigation();
|
|
16
16
|
const goToDetail = () => {
|
|
17
17
|
navigation.navigate(Route.WaterQualityGuide, { waterType });
|
|
@@ -33,7 +33,9 @@ const Item = memo((props) => {
|
|
|
33
33
|
)}
|
|
34
34
|
</View>
|
|
35
35
|
<Text size={24} color={color || Colors.Gray9} style={styles.textValue}>
|
|
36
|
-
{value
|
|
36
|
+
{configValues[id]?.value !== undefined
|
|
37
|
+
? `${configValues[id].value} ${measure}`
|
|
38
|
+
: '--'}
|
|
37
39
|
</Text>
|
|
38
40
|
<Text color={Colors.Gray8}>{des}</Text>
|
|
39
41
|
<View style={styles.boxSvg}>
|
|
@@ -8,8 +8,19 @@ import { SCProvider } from '../../../../../context';
|
|
|
8
8
|
import { mockSCStore } from '../../../../../context/mockStore';
|
|
9
9
|
import MockAdapter from 'axios-mock-adapter';
|
|
10
10
|
import api from '../../../../../utils/Apis/axios';
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
new MockAdapter(api.axiosInstance);
|
|
13
|
+
const mockNavigate = jest.fn();
|
|
14
|
+
jest.mock('@react-navigation/native', () => {
|
|
15
|
+
return {
|
|
16
|
+
...jest.requireActual('@react-navigation/native'),
|
|
17
|
+
useRoute: jest.fn(),
|
|
18
|
+
useNavigation: () => ({
|
|
19
|
+
navigate: mockNavigate,
|
|
20
|
+
}),
|
|
21
|
+
useFocusEffect: (func) => func(),
|
|
22
|
+
};
|
|
23
|
+
});
|
|
13
24
|
|
|
14
25
|
const wrapComponent = (data) => (
|
|
15
26
|
<SCProvider initState={mockSCStore({})}>
|
|
@@ -19,19 +30,22 @@ const wrapComponent = (data) => (
|
|
|
19
30
|
|
|
20
31
|
describe('Test WaterQualityGuide', () => {
|
|
21
32
|
let data;
|
|
22
|
-
const mockedNavigate = useNavigation().navigate;
|
|
23
|
-
|
|
24
33
|
beforeEach(() => {
|
|
25
34
|
Date.now = jest.fn(() => new Date('2021-01-24T12:00:00.000Z'));
|
|
26
|
-
|
|
35
|
+
mockNavigate.mockClear();
|
|
27
36
|
data = {
|
|
28
37
|
summaryDetail: {
|
|
29
38
|
ph_id: 1,
|
|
30
|
-
tur_id:
|
|
31
|
-
clo_id:
|
|
39
|
+
tur_id: 2,
|
|
40
|
+
clo_id: 3,
|
|
32
41
|
tur_value: 1,
|
|
33
42
|
tur_color: '',
|
|
34
43
|
tur_status: '',
|
|
44
|
+
listConfigs: {
|
|
45
|
+
ph: 1,
|
|
46
|
+
tur: 2,
|
|
47
|
+
clo: 3,
|
|
48
|
+
},
|
|
35
49
|
},
|
|
36
50
|
};
|
|
37
51
|
});
|
|
@@ -69,24 +83,24 @@ describe('Test WaterQualityGuide', () => {
|
|
|
69
83
|
await act(async () => {
|
|
70
84
|
buttons[0].props.onPress();
|
|
71
85
|
});
|
|
72
|
-
expect(
|
|
73
|
-
expect(
|
|
86
|
+
expect(mockNavigate).toHaveBeenCalledTimes(1);
|
|
87
|
+
expect(mockNavigate).toHaveBeenCalledWith(Routes.WaterQualityGuide, {
|
|
74
88
|
waterType: 'turbidity',
|
|
75
89
|
});
|
|
76
90
|
|
|
77
91
|
await act(async () => {
|
|
78
92
|
buttons[1].props.onPress();
|
|
79
93
|
});
|
|
80
|
-
expect(
|
|
81
|
-
expect(
|
|
94
|
+
expect(mockNavigate).toHaveBeenCalledTimes(2);
|
|
95
|
+
expect(mockNavigate).toHaveBeenCalledWith(Routes.WaterQualityGuide, {
|
|
82
96
|
waterType: 'ph',
|
|
83
97
|
});
|
|
84
98
|
|
|
85
99
|
await act(async () => {
|
|
86
100
|
buttons[2].props.onPress();
|
|
87
101
|
});
|
|
88
|
-
expect(
|
|
89
|
-
expect(
|
|
102
|
+
expect(mockNavigate).toHaveBeenCalledTimes(3);
|
|
103
|
+
expect(mockNavigate).toHaveBeenCalledWith(Routes.WaterQualityGuide, {
|
|
90
104
|
waterType: 'clo',
|
|
91
105
|
});
|
|
92
106
|
});
|
|
@@ -5,14 +5,101 @@ import { Today, Section } from '../../../../commons';
|
|
|
5
5
|
import Text from '../../../../commons/Text';
|
|
6
6
|
import VisualChart from '../../../Device/components/VisualChart';
|
|
7
7
|
import Item from './Item';
|
|
8
|
+
import { useWatchConfigs } from '../../../../hooks/IoT';
|
|
8
9
|
|
|
9
10
|
const WaterQuality = memo(({ summaryDetail }) => {
|
|
10
11
|
const t = useTranslations();
|
|
11
|
-
const {
|
|
12
|
+
const {
|
|
13
|
+
ph_id,
|
|
14
|
+
tur_id,
|
|
15
|
+
clo_id,
|
|
16
|
+
clo_status,
|
|
17
|
+
ph_status,
|
|
18
|
+
tur_status,
|
|
19
|
+
ph_color,
|
|
20
|
+
clo_color,
|
|
21
|
+
tur_color,
|
|
22
|
+
listConfigs = {},
|
|
23
|
+
} = summaryDetail;
|
|
24
|
+
const { ph, clo, tur, temp } = listConfigs;
|
|
25
|
+
useWatchConfigs([ph, clo, tur, temp]);
|
|
26
|
+
|
|
12
27
|
const showBoxHistory = useMemo(() => {
|
|
13
28
|
return ph_id || tur_id || clo_id ? true : false;
|
|
14
29
|
}, [ph_id, tur_id, clo_id]);
|
|
15
30
|
|
|
31
|
+
const createDataItem = (
|
|
32
|
+
id,
|
|
33
|
+
color,
|
|
34
|
+
title,
|
|
35
|
+
measure,
|
|
36
|
+
des,
|
|
37
|
+
waterType,
|
|
38
|
+
svgMain
|
|
39
|
+
) => ({
|
|
40
|
+
id,
|
|
41
|
+
color,
|
|
42
|
+
title,
|
|
43
|
+
measure,
|
|
44
|
+
des,
|
|
45
|
+
waterType,
|
|
46
|
+
svgMain,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const datas = useMemo(() => {
|
|
50
|
+
const data = [];
|
|
51
|
+
|
|
52
|
+
if (tur) {
|
|
53
|
+
data.push(
|
|
54
|
+
createDataItem(
|
|
55
|
+
tur,
|
|
56
|
+
tur_color,
|
|
57
|
+
t('Turbidity'),
|
|
58
|
+
'°C',
|
|
59
|
+
tur_status,
|
|
60
|
+
'turbidity',
|
|
61
|
+
''
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
if (ph) {
|
|
66
|
+
data.push(
|
|
67
|
+
createDataItem(ph, ph_color, t('pH'), 'pH', ph_status, 'ph', '')
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
if (clo) {
|
|
71
|
+
data.push(
|
|
72
|
+
createDataItem(
|
|
73
|
+
clo,
|
|
74
|
+
clo_color,
|
|
75
|
+
t('Chlorine residual'),
|
|
76
|
+
'mg/l',
|
|
77
|
+
clo_status,
|
|
78
|
+
'clo',
|
|
79
|
+
''
|
|
80
|
+
)
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
if (temp) {
|
|
84
|
+
data.push(
|
|
85
|
+
createDataItem(temp, '', t('Water temperature'), '°C', '', null, '')
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
return data;
|
|
89
|
+
}, [
|
|
90
|
+
clo,
|
|
91
|
+
clo_color,
|
|
92
|
+
clo_status,
|
|
93
|
+
ph,
|
|
94
|
+
ph_color,
|
|
95
|
+
ph_status,
|
|
96
|
+
t,
|
|
97
|
+
temp,
|
|
98
|
+
tur,
|
|
99
|
+
tur_color,
|
|
100
|
+
tur_status,
|
|
101
|
+
]);
|
|
102
|
+
|
|
16
103
|
const configs = useMemo(() => {
|
|
17
104
|
return [
|
|
18
105
|
{ id: ph_id, title: 'pH', color: 'red' },
|
|
@@ -26,7 +113,10 @@ const WaterQuality = memo(({ summaryDetail }) => {
|
|
|
26
113
|
<Today style={styles.textIndoor} />
|
|
27
114
|
<Text style={styles.overall}>{t('water_quality_overall')}</Text>
|
|
28
115
|
<View style={styles.boxWaterQuality}>
|
|
29
|
-
|
|
116
|
+
{datas.map((item) => (
|
|
117
|
+
<Item {...item} key={item.id} />
|
|
118
|
+
))}
|
|
119
|
+
{/* <Item
|
|
30
120
|
title={t('Turbidity')}
|
|
31
121
|
value={summaryDetail.tur_value}
|
|
32
122
|
color={summaryDetail.tur_color}
|
|
@@ -55,7 +145,7 @@ const WaterQuality = memo(({ summaryDetail }) => {
|
|
|
55
145
|
value={summaryDetail.temp_value}
|
|
56
146
|
des={''}
|
|
57
147
|
svgMain={''}
|
|
58
|
-
/>
|
|
148
|
+
/> */}
|
|
59
149
|
</View>
|
|
60
150
|
</Section>
|
|
61
151
|
{showBoxHistory && (
|
|
@@ -11,8 +11,8 @@ import { API, Colors } from '../../configs';
|
|
|
11
11
|
import Routes from '../../utils/Route';
|
|
12
12
|
import { axiosGet } from '../../utils/Apis/axios';
|
|
13
13
|
import { title_height } from '../../commons/HeaderAni';
|
|
14
|
+
import AirQuality from './components/AirQuality';
|
|
14
15
|
import WrapHeaderScrollable from '../../commons/Sharing/WrapHeaderScrollable';
|
|
15
|
-
import AirQuality from '../../commons/UnitSummary/AirQuality';
|
|
16
16
|
import PowerConsumption from './components/PowerConsumption';
|
|
17
17
|
import ThreePhasePowerConsumption from './components/3PPowerConsumption';
|
|
18
18
|
import RunningDevices from './components/RunningDevices';
|
|
@@ -127,14 +127,6 @@ const UnitSummary = memo(({ route }) => {
|
|
|
127
127
|
useEffect(() => {
|
|
128
128
|
setLoading(true);
|
|
129
129
|
fetchSummaryDetail();
|
|
130
|
-
|
|
131
|
-
if (summary?.screen !== Routes.RunningDevices) {
|
|
132
|
-
const autoUpdate = setInterval(() => {
|
|
133
|
-
fetchSummaryDetail();
|
|
134
|
-
}, 10000); // fetch each 10 second
|
|
135
|
-
|
|
136
|
-
return () => clearInterval(autoUpdate);
|
|
137
|
-
}
|
|
138
130
|
}, [fetchSummaryDetail, summary?.screen]);
|
|
139
131
|
|
|
140
132
|
const onRefresh = useCallback(() => {
|
|
@@ -94,6 +94,8 @@ export default {
|
|
|
94
94
|
text_temperature: 'Temperature',
|
|
95
95
|
text_wind: 'Wind',
|
|
96
96
|
text_rain: 'Rain',
|
|
97
|
+
rainy: 'Rainy',
|
|
98
|
+
no_rain: 'No rain',
|
|
97
99
|
text_win_direction: 'Direction',
|
|
98
100
|
text_good: 'Good',
|
|
99
101
|
text_moderate: 'Moderate',
|
|
@@ -717,6 +719,11 @@ export default {
|
|
|
717
719
|
ok_and_got_it: 'Ok',
|
|
718
720
|
notify_back: 'Are you sure to go back?',
|
|
719
721
|
notifications: 'Notifications',
|
|
722
|
+
notification: 'Notification',
|
|
723
|
+
send_notification: 'Send Notification',
|
|
724
|
+
title_notification: 'Subject: “Warning”',
|
|
725
|
+
message_notification:
|
|
726
|
+
'Warning content: "The temperature in the office is high, please check."',
|
|
720
727
|
promotions: 'Promotions',
|
|
721
728
|
news: 'News',
|
|
722
729
|
system: 'System',
|
|
@@ -1008,9 +1015,11 @@ export default {
|
|
|
1008
1015
|
action: 'action',
|
|
1009
1016
|
power: 'Power',
|
|
1010
1017
|
actions_list: 'Actions list',
|
|
1011
|
-
|
|
1018
|
+
delete_action: 'Delete action?',
|
|
1012
1019
|
message_delete_action:
|
|
1013
1020
|
'Are you sure you want to delete action of \n{actionName} in {stationName}?',
|
|
1021
|
+
message_delete_notify:
|
|
1022
|
+
'Are you sure you want to remove sending notifications?',
|
|
1014
1023
|
add_script: 'Add Script',
|
|
1015
1024
|
delete_script: 'Delete Script',
|
|
1016
1025
|
title_delete_script: 'Delete script "{scriptName}"?',
|
|
@@ -1037,6 +1046,12 @@ export default {
|
|
|
1037
1046
|
update_smart: 'Update Smart',
|
|
1038
1047
|
automate: 'Automate',
|
|
1039
1048
|
smart: 'Smart',
|
|
1049
|
+
enable_this_script: 'Enable this script',
|
|
1050
|
+
this_script_has_been_disabled: 'This script has been disabled',
|
|
1051
|
+
control_device: 'Control device',
|
|
1052
|
+
send_email: 'Send e-mail',
|
|
1053
|
+
send_app_notification: 'Send app notification',
|
|
1054
|
+
delay_the_action: 'Delay the action',
|
|
1040
1055
|
end_device_not_support_script:
|
|
1041
1056
|
// eslint-disable-next-line max-len
|
|
1042
1057
|
'This device does not support installing "{not_support}" scripts, but you can use "{support}" scripts to perform the desired setup.',
|