@eohjsc/react-native-smart-city 0.4.83 → 0.4.85

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 (39) hide show
  1. package/package.json +1 -1
  2. package/src/commons/Device/PMSensor/PMSensorIndicator.js +15 -8
  3. package/src/commons/Device/WaterQualitySensor/ListQualityIndicator.js +23 -15
  4. package/src/commons/Device/WaterQualitySensor/QualityIndicatorsItem.js +10 -9
  5. package/src/commons/Sharing/WrapHeaderScrollable.js +1 -1
  6. package/src/commons/SubUnit/DeviceTemplate/ConfigValue/ConfigValue.js +2 -8
  7. package/src/commons/SubUnit/DeviceTemplate/EvaluationOverConfig/EvaluationOverConfig.js +2 -10
  8. package/src/commons/SubUnit/ShortDetail.js +14 -4
  9. package/src/commons/UnitSummary/ConfigHistoryChart/index.js +4 -1
  10. package/src/hooks/IoT/useBluetoothDeviceConnected.js +2 -4
  11. package/src/iot/RemoteControl/Bluetooth.js +15 -9
  12. package/src/screens/Device/__test__/mqttDetail.test.js +20 -20
  13. package/src/screens/Device/components/SensorConnectStatusViewHeader.js +3 -3
  14. package/src/screens/Device/components/VisualChart.js +1 -1
  15. package/src/screens/Device/detail.js +13 -6
  16. package/src/screens/UnitSummary/__test__/index.test.js +2 -1
  17. package/src/screens/UnitSummary/components/3PPowerConsumption/__test__/3PPowerConsumption.test.js +37 -30
  18. package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +105 -166
  19. package/src/screens/UnitSummary/components/AirQuality/SegmentedRoundChart.js +32 -0
  20. package/src/{commons/UnitSummary → screens/UnitSummary/components}/AirQuality/__test__/index.test.js +25 -15
  21. package/src/{commons/UnitSummary → screens/UnitSummary/components}/AirQuality/index.js +55 -71
  22. package/src/{commons/UnitSummary → screens/UnitSummary/components}/AirQuality/styles.js +1 -2
  23. package/src/screens/UnitSummary/components/PowerConsumption/__test__/PowerConsumption.test.js +26 -20
  24. package/src/screens/UnitSummary/components/PowerConsumption/index.js +59 -87
  25. package/src/screens/UnitSummary/components/RunningDevices/index.js +27 -23
  26. package/src/screens/UnitSummary/components/Temperature/ItemTemperature/index.js +33 -20
  27. package/src/screens/UnitSummary/components/Temperature/index.js +52 -79
  28. package/src/screens/UnitSummary/components/UvIndex/SegmentedRoundChart.js +36 -0
  29. package/src/screens/UnitSummary/components/UvIndex/__test__/index.test.js +8 -0
  30. package/src/screens/UnitSummary/components/UvIndex/index.js +16 -72
  31. package/src/screens/UnitSummary/components/UvIndex/styles.js +48 -0
  32. package/src/screens/UnitSummary/components/WaterQuality/Item/index.js +6 -4
  33. package/src/screens/UnitSummary/components/WaterQuality/__test__/index.test.js +26 -12
  34. package/src/screens/UnitSummary/components/WaterQuality/index.js +93 -3
  35. package/src/screens/UnitSummary/index.js +1 -9
  36. package/src/utils/I18n/translations/en.js +2 -0
  37. package/src/utils/I18n/translations/vi.js +2 -0
  38. package/src/screens/UnitSummary/components/PowerConsumption/ItemPower/index.js +0 -53
  39. package/src/screens/UnitSummary/components/PowerConsumption/__test__/ItemPower.test.js +0 -20
@@ -1,5 +1,5 @@
1
1
  import React, { memo, useMemo } from 'react';
2
- import { StyleSheet, View } from 'react-native';
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 SegmentedRoundDisplay from '../../../../commons/UnitSummary/AirQuality/SegmentedRoundDisplay';
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 { uv_id } = summaryDetail;
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
- const advices = summaryDetail.advices ? summaryDetail.advices : [];
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
- <SegmentedRoundDisplay
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((props) => {
13
- const { svgMain, title, des, value, color, waterType } = props;
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
- import { useNavigation } from '@react-navigation/native';
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
- mockedNavigate.mockReset();
35
+ mockNavigate.mockClear();
27
36
  data = {
28
37
  summaryDetail: {
29
38
  ph_id: 1,
30
- tur_id: 1,
31
- clo_id: 1,
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(mockedNavigate).toHaveBeenCalledTimes(1);
73
- expect(mockedNavigate).toHaveBeenCalledWith(Routes.WaterQualityGuide, {
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(mockedNavigate).toHaveBeenCalledTimes(2);
81
- expect(mockedNavigate).toHaveBeenCalledWith(Routes.WaterQualityGuide, {
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(mockedNavigate).toHaveBeenCalledTimes(3);
89
- expect(mockedNavigate).toHaveBeenCalledWith(Routes.WaterQualityGuide, {
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 { ph_id, tur_id, clo_id } = summaryDetail;
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
- <Item
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',
@@ -179,6 +179,8 @@ export default {
179
179
  text_temperature: 'Nhiệt độ',
180
180
  text_wind: 'Gió',
181
181
  text_rain: 'Mưa',
182
+ rainy: 'Có mưa',
183
+ no_rain: 'Không mưa',
182
184
  text_win_direction: 'Hướng gió',
183
185
  text_good: 'Tốt',
184
186
  text_moderate: 'Trung bình',
@@ -1,53 +0,0 @@
1
- import React, { memo } from 'react';
2
- import { View, StyleSheet } from 'react-native';
3
-
4
- import Text from '../../../../../commons/Text';
5
- import { Colors } from '../../../../../configs';
6
-
7
- const ItemPower = memo((props) => {
8
- const { svg, title, des, time, value } = props;
9
- return (
10
- <View style={styles.container}>
11
- {svg}
12
- <View style={styles.content}>
13
- <View style={styles.boxInfo}>
14
- <Text size={16} color={Colors.Gray9} style={styles.textMarginBottom}>
15
- {title}
16
- </Text>
17
- <Text size={14} color={Colors.Gray8} style={styles.textMarginBottom}>
18
- {des}
19
- </Text>
20
- <Text size={14} color={Colors.Gray8}>
21
- {time}
22
- </Text>
23
- </View>
24
- <Text size={14} color={Colors.Gray8}>
25
- {value}
26
- </Text>
27
- </View>
28
- </View>
29
- );
30
- });
31
-
32
- export default ItemPower;
33
-
34
- const styles = StyleSheet.create({
35
- container: {
36
- flexDirection: 'row',
37
- paddingTop: 16,
38
- },
39
- content: {
40
- flexDirection: 'row',
41
- paddingBottom: 16,
42
- flex: 1,
43
- marginLeft: 16,
44
- borderBottomWidth: 1,
45
- borderBottomColor: Colors.Gray4,
46
- },
47
- boxInfo: {
48
- flex: 1,
49
- },
50
- textMarginBottom: {
51
- marginBottom: 4,
52
- },
53
- });
@@ -1,20 +0,0 @@
1
- import React from 'react';
2
- import { act, create } from 'react-test-renderer';
3
- import Text from '../../../../../commons/Text';
4
- import ItemPower from '../ItemPower';
5
-
6
- describe('test ItemPower', () => {
7
- it('render', async () => {
8
- let tree;
9
- let data = { svg: '', title: 'Title item', des: '', time: '', value: '' };
10
-
11
- await act(async () => {
12
- tree = await create(<ItemPower {...data} />);
13
- });
14
-
15
- const instance = tree.root;
16
- const texts = instance.findAllByType(Text);
17
- expect(texts).toHaveLength(4);
18
- expect(texts[0].props.children).toEqual('Title item');
19
- });
20
- });