@eohjsc/react-native-smart-city 0.2.59 → 0.2.63
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/README.md +115 -68
- package/assets/images/Map/MarkerGeolocation.svg +4 -0
- package/package.json +3 -3
- package/src/commons/ActionGroup/CurtainButtonTemplate.js +10 -2
- package/src/commons/ActionGroup/__test__/CurtainButtonTemplate.test.js +1 -1
- package/src/commons/ActionGroup/__test__/MenuActionAddSchedule.test.js +71 -0
- package/src/commons/ActionGroup/hooks/AccessScheduleDetailStyles.js +41 -0
- package/src/commons/ActionGroup/hooks/MenuActionAddSchedule.js +110 -0
- package/src/commons/ActionGroup/hooks/MenuActionAddScheduleStyle.js +69 -0
- package/src/commons/ActionGroup/hooks/RecurringDetail.js +97 -0
- package/src/commons/DateTimeRangeChange/DateTimeButton.js +7 -2
- package/src/commons/Device/HistoryChart.js +80 -81
- package/src/commons/Device/HorizontalBarChart.js +48 -31
- package/src/commons/Device/LinearChart.js +28 -1
- package/src/commons/Form/CurrencyInput.js +1 -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/ImagePicker/index.js +27 -33
- package/src/commons/MediaPlayerDetail/Styles/MediaPlayerDetailStyles.js +11 -1
- package/src/commons/MediaPlayerDetail/index.js +14 -5
- package/src/commons/SubUnit/OneTap/OneTapStyles.js +20 -1
- package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +151 -40
- package/src/commons/SubUnit/OneTap/index.js +64 -12
- package/src/commons/UnitSummary/AirQuality/index.js +9 -7
- package/src/commons/UnitSummary/ConfigHistoryChart.js +2 -1
- package/src/configs/API.js +3 -0
- package/src/configs/Constants.js +15 -0
- package/src/iot/RemoteControl/Bluetooth.js +6 -3
- package/src/iot/RemoteControl/GoogleHome.js +6 -3
- package/src/iot/RemoteControl/Internet.js +1 -0
- package/src/iot/RemoteControl/LG.js +2 -1
- package/src/iot/RemoteControl/index.js +13 -6
- package/src/navigations/SharedStack.js +11 -9
- package/src/navigations/UnitStack.js +26 -2
- package/src/screens/ActivityLog/ItemLog.js +3 -3
- package/src/screens/ActivityLog/__test__/ItemLog.test.js +5 -2
- package/src/screens/ActivityLog/hooks/index.js +2 -1
- package/src/screens/ActivityLog/index.js +0 -1
- package/src/screens/AddLocationMaps/index.js +4 -2
- package/src/screens/AddNewAction/SelectSensorDevices.js +18 -11
- package/src/screens/AddNewAction/Styles/SelectSensorDevicesStyles.js +5 -1
- package/src/screens/AddNewAction/__test__/SelectSensorDevices.test.js +6 -1
- package/src/screens/Automate/MultiUnits.js +7 -4
- package/src/screens/Automate/__test__/MultiUnits.test.js +1 -1
- package/src/screens/Automate/__test__/index.test.js +12 -0
- package/src/screens/ConfirmUnitDeletion/__test__/ConfirmUnitDeletion.test.js +61 -0
- package/src/screens/ConfirmUnitDeletion/index.js +64 -0
- package/src/screens/ConfirmUnitDeletion/styles.js +37 -0
- package/src/screens/Device/__test__/detail.test.js +3 -2
- package/src/screens/Device/detail.js +48 -15
- package/src/screens/Device/hooks/useDisconnectedDevice.js +2 -1
- 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 +92 -0
- package/src/screens/EmergencySetting/styles/DropDownItem.js +38 -0
- package/src/screens/EmergencySetting/styles.js +25 -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/ScriptDetail/Styles/indexStyles.js +0 -1
- package/src/screens/ScriptDetail/index.js +1 -0
- package/src/screens/SubUnit/AddSubUnit.js +3 -3
- package/src/screens/SubUnit/AddSubUnitStyles.js +0 -2
- package/src/screens/SubUnit/EditSubUnit.js +16 -7
- package/src/screens/SubUnit/EditSubUnitStyles.js +2 -3
- package/src/screens/SubUnit/__test__/EditSubUnit.test.js +2 -2
- package/src/screens/TDSGuide/index.js +1 -1
- package/src/screens/Unit/ChooseLocation.js +3 -7
- package/src/screens/Unit/ChooseLocationStyles.js +5 -8
- package/src/screens/Unit/Detail.js +16 -6
- package/src/screens/Unit/ManageUnit.js +20 -26
- package/src/screens/Unit/SmartAccount.js +25 -41
- package/src/screens/Unit/SmartAccountItem.js +2 -1
- package/src/screens/Unit/SmartAccountStyles.js +0 -1
- package/src/screens/Unit/__test__/ManageUnit.test.js +0 -6
- package/src/screens/Unit/__test__/SmartAccount.test.js +24 -0
- package/src/screens/Unit/__test__/SmartAccountItem.test.js +72 -0
- package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +58 -59
- package/src/screens/UnitSummary/components/PowerConsumption/index.js +26 -22
- package/src/screens/UnitSummary/components/Temperature/ItemTemperature/index.js +2 -2
- package/src/screens/UnitSummary/components/Temperature/index.js +15 -14
- package/src/screens/UnitSummary/components/UvIndex/index.js +6 -5
- package/src/screens/UnitSummary/components/WaterQuality/index.js +9 -7
- package/src/screens/UnitSummary/index.js +11 -7
- package/src/screens/WaterQualityGuide/index.js +1 -0
- package/src/utils/Apis/axios.js +4 -4
- package/src/utils/I18n/translations/en.json +20 -2
- package/src/utils/I18n/translations/vi.json +21 -2
- package/src/utils/Route/index.js +3 -0
- package/src/utils/Utils.js +4 -0
- 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 -240
- package/src/commons/ThreeButtonHistory/index.js +0 -310
- package/src/commons/ThreeButtonHistory/styles.js +0 -65
|
@@ -7,7 +7,7 @@ import Text from '../Text';
|
|
|
7
7
|
import { Colors } from '../../configs';
|
|
8
8
|
|
|
9
9
|
const DateTimeButton = memo(({ onPress, time, date, formatType, style }) => {
|
|
10
|
-
let format = 'DD.MM.YY
|
|
10
|
+
let format = 'DD.MM.YY HH:mm';
|
|
11
11
|
if (formatType === 'date') {
|
|
12
12
|
format = 'DD.MM.YY';
|
|
13
13
|
}
|
|
@@ -16,7 +16,7 @@ const DateTimeButton = memo(({ onPress, time, date, formatType, style }) => {
|
|
|
16
16
|
<Text type={'Label'} color={Colors.Gray8} style={styles.txtTime}>
|
|
17
17
|
{moment(time).format(format)}
|
|
18
18
|
</Text>
|
|
19
|
-
<IconOutline name={'calendar'}
|
|
19
|
+
<IconOutline style={styles.iconDateTime} name={'calendar'} />
|
|
20
20
|
</TouchableOpacity>
|
|
21
21
|
);
|
|
22
22
|
});
|
|
@@ -40,4 +40,9 @@ const styles = StyleSheet.create({
|
|
|
40
40
|
txtTime: {
|
|
41
41
|
marginRight: 4,
|
|
42
42
|
},
|
|
43
|
+
iconDateTime: {
|
|
44
|
+
marginBottom: 4,
|
|
45
|
+
fontSize: 16,
|
|
46
|
+
color: Colors.Gray8,
|
|
47
|
+
},
|
|
43
48
|
});
|
|
@@ -11,7 +11,7 @@ import DateTimeRangeChange from '../DateTimeRangeChange';
|
|
|
11
11
|
import HorizontalBarChart from './HorizontalBarChart';
|
|
12
12
|
import DateTimePickerModal from 'react-native-modal-datetime-picker';
|
|
13
13
|
import LinearChart from './LinearChart';
|
|
14
|
-
import
|
|
14
|
+
import FourButtonFilterHistory from '../FourButtonFilterHistory';
|
|
15
15
|
import { formatMoney } from '../../utils/Utils';
|
|
16
16
|
|
|
17
17
|
export const dateTimeType = {
|
|
@@ -33,98 +33,102 @@ const HistoryChart = memo(
|
|
|
33
33
|
endDate,
|
|
34
34
|
setEndDate,
|
|
35
35
|
setStartDate,
|
|
36
|
+
groupBy,
|
|
36
37
|
setGroupBy,
|
|
37
38
|
configuration,
|
|
38
39
|
}) => {
|
|
39
40
|
const t = useTranslations();
|
|
40
|
-
const dateNow = moment().valueOf();
|
|
41
41
|
const [chartOptions, setChartOptions] = useState({
|
|
42
42
|
index: -1,
|
|
43
43
|
showAll: true,
|
|
44
44
|
});
|
|
45
45
|
const [eventPicker, setEventPicker] = useState({
|
|
46
|
-
currentChangeTime: '',
|
|
47
46
|
showModalEnd: false,
|
|
48
47
|
showModalStart: false,
|
|
49
48
|
startTime: startDate ? startDate : moment().subtract(1, 'day').valueOf(),
|
|
50
|
-
endTime:
|
|
49
|
+
endTime: endDate ? endDate : moment().valueOf(),
|
|
51
50
|
});
|
|
52
51
|
const [price, setPrice] = useState(null);
|
|
53
52
|
|
|
54
53
|
const onStart = useCallback(() => {
|
|
55
|
-
setEventPicker({
|
|
56
|
-
...
|
|
57
|
-
currentChangeTime: 'start',
|
|
54
|
+
setEventPicker((state) => ({
|
|
55
|
+
...state,
|
|
58
56
|
showModalStart: true,
|
|
59
57
|
showModalEnd: false,
|
|
60
|
-
});
|
|
61
|
-
}, [
|
|
58
|
+
}));
|
|
59
|
+
}, []);
|
|
62
60
|
const onEnd = useCallback(() => {
|
|
63
|
-
setEventPicker({
|
|
64
|
-
...
|
|
65
|
-
currentChangeTime: 'end',
|
|
66
|
-
show: true,
|
|
61
|
+
setEventPicker((state) => ({
|
|
62
|
+
...state,
|
|
67
63
|
showModalStart: false,
|
|
68
64
|
showModalEnd: true,
|
|
69
|
-
});
|
|
70
|
-
}, [
|
|
71
|
-
const onConfirmStart = (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
65
|
+
}));
|
|
66
|
+
}, []);
|
|
67
|
+
const onConfirmStart = useCallback(
|
|
68
|
+
(date) => {
|
|
69
|
+
setEventPicker((state) => {
|
|
70
|
+
if (typeof date === 'number') {
|
|
71
|
+
onCancel();
|
|
72
|
+
return state;
|
|
73
|
+
}
|
|
74
|
+
if (moment(date).valueOf() < state.endTime) {
|
|
75
|
+
setStartDate(moment(date).valueOf());
|
|
76
|
+
return {
|
|
77
|
+
...state,
|
|
78
|
+
showModalStart: false,
|
|
79
|
+
startTime: moment(date).valueOf(),
|
|
80
|
+
};
|
|
81
|
+
} else {
|
|
82
|
+
setStartDate(moment(date).valueOf());
|
|
83
|
+
setEndDate(moment(date).add(1, 'day').valueOf());
|
|
84
|
+
return {
|
|
85
|
+
...state,
|
|
86
|
+
showModalStart: false,
|
|
87
|
+
startTime: moment(date).valueOf(),
|
|
88
|
+
endTime: moment(date).add(1, 'day').valueOf(),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
90
91
|
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
};
|
|
92
|
+
},
|
|
93
|
+
[onCancel, setStartDate, setEndDate]
|
|
94
|
+
);
|
|
95
95
|
|
|
96
|
-
const onConfirmEnd = (
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
96
|
+
const onConfirmEnd = useCallback(
|
|
97
|
+
(date) => {
|
|
98
|
+
setEventPicker((state) => {
|
|
99
|
+
if (typeof date === 'number') {
|
|
100
|
+
onCancel();
|
|
101
|
+
return state;
|
|
102
|
+
}
|
|
103
|
+
if (moment(date).valueOf() > state.startTime) {
|
|
104
|
+
setEndDate(moment(date).valueOf());
|
|
105
|
+
return {
|
|
106
|
+
...state,
|
|
107
|
+
showModalEnd: false,
|
|
108
|
+
endTime: moment(date).valueOf(),
|
|
109
|
+
};
|
|
110
|
+
} else {
|
|
111
|
+
setStartDate(moment(date).add(-1, 'day').valueOf());
|
|
112
|
+
setEndDate(moment(date).valueOf());
|
|
113
|
+
return {
|
|
114
|
+
...state,
|
|
115
|
+
showModalEnd: false,
|
|
116
|
+
startTime: moment(date).add(-1, 'day').valueOf(),
|
|
117
|
+
endTime: moment(date).valueOf(),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
107
120
|
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
currentChangeTime: 'start',
|
|
112
|
-
showModalEnd: false,
|
|
113
|
-
endTime: moment(date).valueOf(),
|
|
114
|
-
startTime: moment(date).subtract(1, 'day').valueOf(),
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
setEndDate(moment(date).valueOf());
|
|
118
|
-
};
|
|
121
|
+
},
|
|
122
|
+
[onCancel, setStartDate, setEndDate]
|
|
123
|
+
);
|
|
119
124
|
|
|
120
125
|
const onCancel = useCallback(() => {
|
|
121
|
-
setEventPicker({
|
|
122
|
-
...
|
|
123
|
-
currentChangeTime: '',
|
|
126
|
+
setEventPicker((state) => ({
|
|
127
|
+
...state,
|
|
124
128
|
showModalEnd: false,
|
|
125
129
|
showModalStart: false,
|
|
126
|
-
});
|
|
127
|
-
}, [
|
|
130
|
+
}));
|
|
131
|
+
}, []);
|
|
128
132
|
const onShowOneChart = useCallback(
|
|
129
133
|
(index) => {
|
|
130
134
|
if (index === chartOptions.index) {
|
|
@@ -152,7 +156,8 @@ const HistoryChart = memo(
|
|
|
152
156
|
return null;
|
|
153
157
|
}
|
|
154
158
|
const sum = datas[0].data.reduce((a, b) => a + b.y, 0);
|
|
155
|
-
|
|
159
|
+
const roundedSum = sum * price;
|
|
160
|
+
return roundedSum.toFixed();
|
|
156
161
|
}, [configuration, datas, chartConfig]);
|
|
157
162
|
|
|
158
163
|
const renderChart = useCallback(() => {
|
|
@@ -179,25 +184,19 @@ const HistoryChart = memo(
|
|
|
179
184
|
{t('history')}
|
|
180
185
|
</Text>
|
|
181
186
|
{configuration.type === 'horizontal_bar_chart' && (
|
|
182
|
-
<
|
|
183
|
-
|
|
184
|
-
setEndDate={setEndDate}
|
|
187
|
+
<FourButtonFilterHistory
|
|
188
|
+
groupBy={groupBy}
|
|
185
189
|
setGroupBy={setGroupBy}
|
|
186
|
-
startDate={startDate}
|
|
187
|
-
endDate={endDate}
|
|
188
190
|
/>
|
|
189
191
|
)}
|
|
190
192
|
</View>
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
formatType={formatType}
|
|
199
|
-
/>
|
|
200
|
-
)}
|
|
193
|
+
<DateTimeRangeChange
|
|
194
|
+
startTime={eventPicker.startTime}
|
|
195
|
+
onStart={onStart}
|
|
196
|
+
onEnd={onEnd}
|
|
197
|
+
endTime={eventPicker.endTime}
|
|
198
|
+
formatType={formatType}
|
|
199
|
+
/>
|
|
201
200
|
</View>
|
|
202
201
|
{configuration.config === 'power_consumption' && (
|
|
203
202
|
<View style={styles.wrapCalculateCost}>
|
|
@@ -1,34 +1,19 @@
|
|
|
1
|
-
import React, { memo, useMemo } from 'react';
|
|
1
|
+
import React, { memo, useEffect, useMemo, useState } from 'react';
|
|
2
2
|
import { View, StyleSheet } from 'react-native';
|
|
3
3
|
import HighchartsReactNative from '@highcharts/highcharts-react-native/src/HighchartsReactNative';
|
|
4
|
+
import { isEmpty } from 'lodash';
|
|
4
5
|
|
|
5
6
|
import { Colors } from '../../configs';
|
|
6
7
|
import { getMaxValueIndex } from '../../utils/chartHelper/getMaxValueIndex';
|
|
8
|
+
import { arePropsEqual } from '../../utils/Utils';
|
|
7
9
|
|
|
8
10
|
const HorizontalBarChart = memo(({ datas, config }) => {
|
|
9
|
-
const
|
|
10
|
-
return {
|
|
11
|
-
color: index % 2 === 0 ? Colors.Primary + '20' : Colors.Primary + '16',
|
|
12
|
-
y: item.y,
|
|
13
|
-
};
|
|
14
|
-
});
|
|
15
|
-
const dataX = datas[0].data.map((item) => item.x);
|
|
16
|
-
const heightChart = useMemo(() => {
|
|
17
|
-
return dataX.length > 1 ? dataX.length * 55 : 90;
|
|
18
|
-
}, [dataX]);
|
|
19
|
-
const maxY = getMaxValueIndex(dataY);
|
|
20
|
-
dataY.splice(maxY._index, 1, { ...maxY.max, color: Colors.Primary });
|
|
21
|
-
|
|
22
|
-
// eslint-disable-next-line no-unused-vars
|
|
23
|
-
const chartOptions = {
|
|
11
|
+
const [chartOptions, setChartOptions] = useState({
|
|
24
12
|
chart: {
|
|
25
13
|
type: 'bar',
|
|
26
14
|
style: {
|
|
27
15
|
fontFamily: 'Arial',
|
|
28
16
|
},
|
|
29
|
-
scrollablePlotArea: {
|
|
30
|
-
minHeight: dataY.length * 32,
|
|
31
|
-
},
|
|
32
17
|
},
|
|
33
18
|
credits: {
|
|
34
19
|
enabled: false,
|
|
@@ -37,7 +22,6 @@ const HorizontalBarChart = memo(({ datas, config }) => {
|
|
|
37
22
|
text: '',
|
|
38
23
|
},
|
|
39
24
|
xAxis: {
|
|
40
|
-
categories: dataX,
|
|
41
25
|
title: {
|
|
42
26
|
text: null,
|
|
43
27
|
},
|
|
@@ -45,14 +29,6 @@ const HorizontalBarChart = memo(({ datas, config }) => {
|
|
|
45
29
|
enabled: true,
|
|
46
30
|
},
|
|
47
31
|
},
|
|
48
|
-
series: [
|
|
49
|
-
{
|
|
50
|
-
marker: { enabled: true },
|
|
51
|
-
color: Colors.Primary + '50',
|
|
52
|
-
name: JSON.stringify(config),
|
|
53
|
-
data: dataY,
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
32
|
time: {
|
|
57
33
|
timezoneOffset: -7 * 60,
|
|
58
34
|
},
|
|
@@ -85,7 +61,7 @@ const HorizontalBarChart = memo(({ datas, config }) => {
|
|
|
85
61
|
const costStyle = valueStyle + 'font-weight:bold;';
|
|
86
62
|
|
|
87
63
|
let label = `<span style="${valueStyle}">` + `${this.y}${unit}`;
|
|
88
|
-
if (price === null || isNaN(price)) {
|
|
64
|
+
if (price === '' || price === null || isNaN(price)) {
|
|
89
65
|
return label + '</span>';
|
|
90
66
|
}
|
|
91
67
|
|
|
@@ -119,7 +95,48 @@ const HorizontalBarChart = memo(({ datas, config }) => {
|
|
|
119
95
|
shadow: false,
|
|
120
96
|
},
|
|
121
97
|
},
|
|
122
|
-
};
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const heightChart = useMemo(() => {
|
|
101
|
+
const dataX = datas[0].data.map((item) => item.x);
|
|
102
|
+
return dataX.length > 1 ? dataX.length * 55 : 90;
|
|
103
|
+
}, [datas]);
|
|
104
|
+
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
const dataY = datas[0].data.map((item, index) => {
|
|
107
|
+
return {
|
|
108
|
+
color: index % 2 === 0 ? Colors.Primary + '20' : Colors.Primary + '16',
|
|
109
|
+
y: item.y,
|
|
110
|
+
};
|
|
111
|
+
});
|
|
112
|
+
const dataX = datas[0].data.map((item) => item.x);
|
|
113
|
+
const maxY = getMaxValueIndex(dataY);
|
|
114
|
+
if (!isEmpty(maxY.max)) {
|
|
115
|
+
dataY.splice(maxY._index, 1, { ...maxY.max, color: Colors.Primary });
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
setChartOptions((options) => ({
|
|
119
|
+
...options,
|
|
120
|
+
chart: {
|
|
121
|
+
...options.chart,
|
|
122
|
+
scrollablePlotArea: {
|
|
123
|
+
minHeight: dataY.length * 32,
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
xAxis: {
|
|
127
|
+
...options.xAxis,
|
|
128
|
+
categories: dataX,
|
|
129
|
+
},
|
|
130
|
+
series: [
|
|
131
|
+
{
|
|
132
|
+
marker: { enabled: true },
|
|
133
|
+
color: Colors.Primary + '50',
|
|
134
|
+
name: JSON.stringify(config),
|
|
135
|
+
data: dataY,
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
}));
|
|
139
|
+
}, [datas, config]);
|
|
123
140
|
|
|
124
141
|
return (
|
|
125
142
|
<View style={[styles.container, { height: heightChart }]}>
|
|
@@ -129,7 +146,7 @@ const HorizontalBarChart = memo(({ datas, config }) => {
|
|
|
129
146
|
/>
|
|
130
147
|
</View>
|
|
131
148
|
);
|
|
132
|
-
});
|
|
149
|
+
}, arePropsEqual);
|
|
133
150
|
|
|
134
151
|
export default HorizontalBarChart;
|
|
135
152
|
|
|
@@ -3,6 +3,7 @@ import { StyleSheet, View } from 'react-native';
|
|
|
3
3
|
import HighchartsReactNative from '@highcharts/highcharts-react-native';
|
|
4
4
|
import moment from 'moment';
|
|
5
5
|
import { Colors } from '../../configs';
|
|
6
|
+
import { arePropsEqual } from '../../utils/Utils';
|
|
6
7
|
|
|
7
8
|
const convertData = (data = []) => {
|
|
8
9
|
let arr = [];
|
|
@@ -56,6 +57,32 @@ const chartOptions = {
|
|
|
56
57
|
},
|
|
57
58
|
minRange: 3600 * 24 * 1000,
|
|
58
59
|
},
|
|
60
|
+
plotOptions: {
|
|
61
|
+
series: {
|
|
62
|
+
events: {
|
|
63
|
+
legendItemClick: function () {
|
|
64
|
+
const { index, visible } = this;
|
|
65
|
+
const isHiding = (serie, i) => {
|
|
66
|
+
if (i === index) {
|
|
67
|
+
return visible;
|
|
68
|
+
}
|
|
69
|
+
return !serie.visible;
|
|
70
|
+
};
|
|
71
|
+
if (this.chart.series.every(isHiding)) {
|
|
72
|
+
this.chart.yAxis[0].update({
|
|
73
|
+
min: 0,
|
|
74
|
+
max: 100,
|
|
75
|
+
});
|
|
76
|
+
} else {
|
|
77
|
+
this.chart.yAxis[0].update({
|
|
78
|
+
min: undefined,
|
|
79
|
+
max: undefined,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
},
|
|
59
86
|
};
|
|
60
87
|
|
|
61
88
|
function LinearChart({ datas }) {
|
|
@@ -93,7 +120,7 @@ function LinearChart({ datas }) {
|
|
|
93
120
|
);
|
|
94
121
|
}
|
|
95
122
|
|
|
96
|
-
export default memo(LinearChart);
|
|
123
|
+
export default memo(LinearChart, arePropsEqual);
|
|
97
124
|
|
|
98
125
|
const styles = StyleSheet.create({
|
|
99
126
|
container: {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { act, create } from 'react-test-renderer';
|
|
3
|
+
import { SCProvider } from '../../../context';
|
|
4
|
+
import { mockSCStore } from '../../../context/mockStore';
|
|
5
|
+
import FourButtonFilterHistory from '../index';
|
|
6
|
+
import { TouchableOpacity } from 'react-native';
|
|
7
|
+
|
|
8
|
+
const wrapComponent = (props) => (
|
|
9
|
+
<SCProvider initState={mockSCStore({})}>
|
|
10
|
+
<FourButtonFilterHistory {...props} />
|
|
11
|
+
</SCProvider>
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
jest.mock('react', () => {
|
|
15
|
+
return {
|
|
16
|
+
...jest.requireActual('react'),
|
|
17
|
+
memo: (x) => x,
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('test', async () => {
|
|
22
|
+
const mockSetGroupBy = jest.fn();
|
|
23
|
+
let tree;
|
|
24
|
+
let props = {
|
|
25
|
+
groupBy: 'date',
|
|
26
|
+
setGroupBy: mockSetGroupBy,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
await act(async () => {
|
|
30
|
+
tree = await create(wrapComponent(props));
|
|
31
|
+
});
|
|
32
|
+
const instance = tree.root;
|
|
33
|
+
const buttons = instance.findAllByType(TouchableOpacity);
|
|
34
|
+
expect(buttons).toHaveLength(4);
|
|
35
|
+
|
|
36
|
+
const clickButton = async (index, data) => {
|
|
37
|
+
mockSetGroupBy.mockClear();
|
|
38
|
+
await act(async () => {
|
|
39
|
+
await buttons[index].props.onPress();
|
|
40
|
+
});
|
|
41
|
+
expect(mockSetGroupBy).toBeCalledWith(data);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
await clickButton(0, 'date');
|
|
45
|
+
await clickButton(1, 'week');
|
|
46
|
+
await clickButton(2, 'month');
|
|
47
|
+
await clickButton(3, 'year');
|
|
48
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import React, { memo, useCallback, useMemo } from 'react';
|
|
2
|
+
import { View, TouchableOpacity } from 'react-native';
|
|
3
|
+
import Text from '../Text';
|
|
4
|
+
import { Colors } from '../../configs';
|
|
5
|
+
import styles from './styles';
|
|
6
|
+
|
|
7
|
+
const FourButtonFilterHistory = memo(({ groupBy, setGroupBy }) => {
|
|
8
|
+
const listItem = useMemo(
|
|
9
|
+
() => [
|
|
10
|
+
{
|
|
11
|
+
title: 'D',
|
|
12
|
+
data: 'date',
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
{
|
|
16
|
+
title: 'W',
|
|
17
|
+
data: 'week',
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
{
|
|
21
|
+
title: 'M',
|
|
22
|
+
data: 'month',
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
{
|
|
26
|
+
title: 'Y',
|
|
27
|
+
data: 'year',
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
[]
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const ItemButton = memo(({ title, onPress, isSelected }) => {
|
|
34
|
+
return (
|
|
35
|
+
<TouchableOpacity
|
|
36
|
+
onPress={onPress}
|
|
37
|
+
style={[styles.button, isSelected && styles.selectedButton]}
|
|
38
|
+
>
|
|
39
|
+
<View>
|
|
40
|
+
<Text bold color={isSelected && Colors.Primary}>
|
|
41
|
+
{title}
|
|
42
|
+
</Text>
|
|
43
|
+
</View>
|
|
44
|
+
</TouchableOpacity>
|
|
45
|
+
);
|
|
46
|
+
}, []);
|
|
47
|
+
|
|
48
|
+
const onPressButton = useCallback(
|
|
49
|
+
(data) => () => {
|
|
50
|
+
setGroupBy(data);
|
|
51
|
+
},
|
|
52
|
+
[setGroupBy]
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<View style={styles.row}>
|
|
57
|
+
{listItem &&
|
|
58
|
+
listItem.map((item, index) => {
|
|
59
|
+
return (
|
|
60
|
+
<ItemButton
|
|
61
|
+
key={index}
|
|
62
|
+
title={item.title}
|
|
63
|
+
onPress={onPressButton(item.data)}
|
|
64
|
+
isSelected={item.data === groupBy}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
67
|
+
})}
|
|
68
|
+
</View>
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
export default FourButtonFilterHistory;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { StyleSheet } from 'react-native';
|
|
2
|
+
import { Colors } from '../../configs';
|
|
3
|
+
|
|
4
|
+
export default StyleSheet.create({
|
|
5
|
+
row: {
|
|
6
|
+
flexDirection: 'row',
|
|
7
|
+
alignItems: 'center',
|
|
8
|
+
backgroundColor: Colors.Gray4,
|
|
9
|
+
borderRadius: 5,
|
|
10
|
+
padding: 2,
|
|
11
|
+
},
|
|
12
|
+
button: {
|
|
13
|
+
width: 31,
|
|
14
|
+
height: 28,
|
|
15
|
+
alignItems: 'center',
|
|
16
|
+
justifyContent: 'center',
|
|
17
|
+
borderRadius: 5,
|
|
18
|
+
},
|
|
19
|
+
selectedButton: {
|
|
20
|
+
backgroundColor: Colors.White,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useCallback } from 'react';
|
|
2
2
|
import { Platform, PermissionsAndroid } from 'react-native';
|
|
3
|
-
import
|
|
3
|
+
import ImagePickerCrop from 'react-native-image-crop-picker';
|
|
4
|
+
|
|
4
5
|
import { useTranslations } from '../../hooks/Common/useTranslations';
|
|
5
6
|
|
|
6
7
|
import ButtonPopup from '../ButtonPopup';
|
|
@@ -54,34 +55,29 @@ const ImagePicker = ({
|
|
|
54
55
|
}
|
|
55
56
|
}, []);
|
|
56
57
|
|
|
57
|
-
// options info: check https://github.com/react-native-image-picker/react-native-image-picker
|
|
58
58
|
const captureImage = useCallback(
|
|
59
59
|
async (type) => {
|
|
60
60
|
let options = optionsCapture
|
|
61
61
|
? optionsCapture
|
|
62
62
|
: {
|
|
63
63
|
mediaType: type,
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
compressImageMaxWidth: 1280,
|
|
65
|
+
compressImageMaxHeight: 720,
|
|
66
|
+
compressImageQuality: 0.8,
|
|
66
67
|
};
|
|
67
68
|
|
|
68
69
|
let isCameraPermitted = await requestCameraPermission();
|
|
69
70
|
let isStoragePermitted = await requestExternalWritePermission();
|
|
70
71
|
if (isCameraPermitted && isStoragePermitted) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
setImageUrl(response);
|
|
83
|
-
setShowImagePicker(false);
|
|
84
|
-
});
|
|
72
|
+
await ImagePickerCrop.openCamera(options)
|
|
73
|
+
.then((response) => {
|
|
74
|
+
setImageUrl(response);
|
|
75
|
+
setShowImagePicker(false);
|
|
76
|
+
})
|
|
77
|
+
.catch((e) => {
|
|
78
|
+
/* eslint-disable no-console */
|
|
79
|
+
console.log('ERROR ' + e);
|
|
80
|
+
});
|
|
85
81
|
}
|
|
86
82
|
},
|
|
87
83
|
[
|
|
@@ -94,26 +90,24 @@ const ImagePicker = ({
|
|
|
94
90
|
);
|
|
95
91
|
|
|
96
92
|
const chooseFile = useCallback(
|
|
97
|
-
(type) => {
|
|
93
|
+
async (type) => {
|
|
98
94
|
let options = optionsSelect
|
|
99
95
|
? optionsSelect
|
|
100
96
|
: {
|
|
101
97
|
mediaType: type,
|
|
102
|
-
|
|
98
|
+
compressImageMaxWidth: 1280,
|
|
99
|
+
compressImageMaxHeight: 720,
|
|
100
|
+
compressImageQuality: 0.8,
|
|
103
101
|
};
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
setImageUrl(response);
|
|
115
|
-
setShowImagePicker(false);
|
|
116
|
-
});
|
|
102
|
+
await ImagePickerCrop.openPicker(options)
|
|
103
|
+
.then((response) => {
|
|
104
|
+
setImageUrl(response);
|
|
105
|
+
setShowImagePicker(false);
|
|
106
|
+
})
|
|
107
|
+
.catch((e) => {
|
|
108
|
+
/* eslint-disable no-console */
|
|
109
|
+
console.log('ERROR ' + e);
|
|
110
|
+
});
|
|
117
111
|
},
|
|
118
112
|
[setImageUrl, setShowImagePicker, optionsSelect]
|
|
119
113
|
);
|