@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.
Files changed (101) hide show
  1. package/README.md +115 -68
  2. package/assets/images/Map/MarkerGeolocation.svg +4 -0
  3. package/package.json +3 -3
  4. package/src/commons/ActionGroup/CurtainButtonTemplate.js +10 -2
  5. package/src/commons/ActionGroup/__test__/CurtainButtonTemplate.test.js +1 -1
  6. package/src/commons/ActionGroup/__test__/MenuActionAddSchedule.test.js +71 -0
  7. package/src/commons/ActionGroup/hooks/AccessScheduleDetailStyles.js +41 -0
  8. package/src/commons/ActionGroup/hooks/MenuActionAddSchedule.js +110 -0
  9. package/src/commons/ActionGroup/hooks/MenuActionAddScheduleStyle.js +69 -0
  10. package/src/commons/ActionGroup/hooks/RecurringDetail.js +97 -0
  11. package/src/commons/DateTimeRangeChange/DateTimeButton.js +7 -2
  12. package/src/commons/Device/HistoryChart.js +80 -81
  13. package/src/commons/Device/HorizontalBarChart.js +48 -31
  14. package/src/commons/Device/LinearChart.js +28 -1
  15. package/src/commons/Form/CurrencyInput.js +1 -0
  16. package/src/commons/FourButtonFilterHistory/__test__/FourButtonFilterHistory.test.js +48 -0
  17. package/src/commons/FourButtonFilterHistory/index.js +72 -0
  18. package/src/commons/FourButtonFilterHistory/styles.js +22 -0
  19. package/src/commons/ImagePicker/index.js +27 -33
  20. package/src/commons/MediaPlayerDetail/Styles/MediaPlayerDetailStyles.js +11 -1
  21. package/src/commons/MediaPlayerDetail/index.js +14 -5
  22. package/src/commons/SubUnit/OneTap/OneTapStyles.js +20 -1
  23. package/src/commons/SubUnit/OneTap/__test__/SubUnitAutomate.test.js +151 -40
  24. package/src/commons/SubUnit/OneTap/index.js +64 -12
  25. package/src/commons/UnitSummary/AirQuality/index.js +9 -7
  26. package/src/commons/UnitSummary/ConfigHistoryChart.js +2 -1
  27. package/src/configs/API.js +3 -0
  28. package/src/configs/Constants.js +15 -0
  29. package/src/iot/RemoteControl/Bluetooth.js +6 -3
  30. package/src/iot/RemoteControl/GoogleHome.js +6 -3
  31. package/src/iot/RemoteControl/Internet.js +1 -0
  32. package/src/iot/RemoteControl/LG.js +2 -1
  33. package/src/iot/RemoteControl/index.js +13 -6
  34. package/src/navigations/SharedStack.js +11 -9
  35. package/src/navigations/UnitStack.js +26 -2
  36. package/src/screens/ActivityLog/ItemLog.js +3 -3
  37. package/src/screens/ActivityLog/__test__/ItemLog.test.js +5 -2
  38. package/src/screens/ActivityLog/hooks/index.js +2 -1
  39. package/src/screens/ActivityLog/index.js +0 -1
  40. package/src/screens/AddLocationMaps/index.js +4 -2
  41. package/src/screens/AddNewAction/SelectSensorDevices.js +18 -11
  42. package/src/screens/AddNewAction/Styles/SelectSensorDevicesStyles.js +5 -1
  43. package/src/screens/AddNewAction/__test__/SelectSensorDevices.test.js +6 -1
  44. package/src/screens/Automate/MultiUnits.js +7 -4
  45. package/src/screens/Automate/__test__/MultiUnits.test.js +1 -1
  46. package/src/screens/Automate/__test__/index.test.js +12 -0
  47. package/src/screens/ConfirmUnitDeletion/__test__/ConfirmUnitDeletion.test.js +61 -0
  48. package/src/screens/ConfirmUnitDeletion/index.js +64 -0
  49. package/src/screens/ConfirmUnitDeletion/styles.js +37 -0
  50. package/src/screens/Device/__test__/detail.test.js +3 -2
  51. package/src/screens/Device/detail.js +48 -15
  52. package/src/screens/Device/hooks/useDisconnectedDevice.js +2 -1
  53. package/src/screens/Device/styles.js +3 -3
  54. package/src/screens/EmergencySetting/__test__/DropDownItem.test.js +59 -0
  55. package/src/screens/EmergencySetting/__test__/index.test.js +27 -0
  56. package/src/screens/EmergencySetting/components/DropDownItem.js +54 -0
  57. package/src/screens/EmergencySetting/index.js +92 -0
  58. package/src/screens/EmergencySetting/styles/DropDownItem.js +38 -0
  59. package/src/screens/EmergencySetting/styles.js +25 -0
  60. package/src/screens/MoveToAnotherSubUnit/__test__/index.test.js +126 -0
  61. package/src/screens/MoveToAnotherSubUnit/index.js +88 -0
  62. package/src/screens/MoveToAnotherSubUnit/styles/MoveToAnotherSubUnitStyles.js +50 -0
  63. package/src/screens/ScriptDetail/Styles/indexStyles.js +0 -1
  64. package/src/screens/ScriptDetail/index.js +1 -0
  65. package/src/screens/SubUnit/AddSubUnit.js +3 -3
  66. package/src/screens/SubUnit/AddSubUnitStyles.js +0 -2
  67. package/src/screens/SubUnit/EditSubUnit.js +16 -7
  68. package/src/screens/SubUnit/EditSubUnitStyles.js +2 -3
  69. package/src/screens/SubUnit/__test__/EditSubUnit.test.js +2 -2
  70. package/src/screens/TDSGuide/index.js +1 -1
  71. package/src/screens/Unit/ChooseLocation.js +3 -7
  72. package/src/screens/Unit/ChooseLocationStyles.js +5 -8
  73. package/src/screens/Unit/Detail.js +16 -6
  74. package/src/screens/Unit/ManageUnit.js +20 -26
  75. package/src/screens/Unit/SmartAccount.js +25 -41
  76. package/src/screens/Unit/SmartAccountItem.js +2 -1
  77. package/src/screens/Unit/SmartAccountStyles.js +0 -1
  78. package/src/screens/Unit/__test__/ManageUnit.test.js +0 -6
  79. package/src/screens/Unit/__test__/SmartAccount.test.js +24 -0
  80. package/src/screens/Unit/__test__/SmartAccountItem.test.js +72 -0
  81. package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +58 -59
  82. package/src/screens/UnitSummary/components/PowerConsumption/index.js +26 -22
  83. package/src/screens/UnitSummary/components/Temperature/ItemTemperature/index.js +2 -2
  84. package/src/screens/UnitSummary/components/Temperature/index.js +15 -14
  85. package/src/screens/UnitSummary/components/UvIndex/index.js +6 -5
  86. package/src/screens/UnitSummary/components/WaterQuality/index.js +9 -7
  87. package/src/screens/UnitSummary/index.js +11 -7
  88. package/src/screens/WaterQualityGuide/index.js +1 -0
  89. package/src/utils/Apis/axios.js +4 -4
  90. package/src/utils/I18n/translations/en.json +20 -2
  91. package/src/utils/I18n/translations/vi.json +21 -2
  92. package/src/utils/Route/index.js +3 -0
  93. package/src/utils/Utils.js +4 -0
  94. package/src/commons/ThreeButtonHistory/CalendarHeader.js +0 -35
  95. package/src/commons/ThreeButtonHistory/CalendarHeaderStyles.js +0 -17
  96. package/src/commons/ThreeButtonHistory/SelectMonth.js +0 -53
  97. package/src/commons/ThreeButtonHistory/SelectMonthStyles.js +0 -29
  98. package/src/commons/ThreeButtonHistory/__test__/SelectMonth.test.js +0 -37
  99. package/src/commons/ThreeButtonHistory/__test__/ThreeButtonHistory.test.js +0 -240
  100. package/src/commons/ThreeButtonHistory/index.js +0 -310
  101. 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 hh:mm';
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'} size={16} color={Colors.Gray8} />
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 ThreeButtonHistory from '../ThreeButtonHistory';
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: dateNow,
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
- ...eventPicker,
57
- currentChangeTime: 'start',
54
+ setEventPicker((state) => ({
55
+ ...state,
58
56
  showModalStart: true,
59
57
  showModalEnd: false,
60
- });
61
- }, [eventPicker]);
58
+ }));
59
+ }, []);
62
60
  const onEnd = useCallback(() => {
63
- setEventPicker({
64
- ...eventPicker,
65
- currentChangeTime: 'end',
66
- show: true,
61
+ setEventPicker((state) => ({
62
+ ...state,
67
63
  showModalStart: false,
68
64
  showModalEnd: true,
69
- });
70
- }, [eventPicker]);
71
- const onConfirmStart = (date) => {
72
- if (typeof date === 'number') {
73
- onCancel();
74
- return;
75
- }
76
- if (moment(date).valueOf() < eventPicker.endTime) {
77
- setEventPicker({
78
- ...eventPicker,
79
- currentChangeTime: 'start',
80
- showModalStart: false,
81
- startTime: moment(date).valueOf(),
82
- });
83
- } else {
84
- setEventPicker({
85
- ...eventPicker,
86
- currentChangeTime: 'start',
87
- showModalStart: false,
88
- startTime: moment(date).valueOf(),
89
- endTime: moment(date).add(1, 'day').valueOf(),
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
- setStartDate(moment(date).valueOf());
94
- };
92
+ },
93
+ [onCancel, setStartDate, setEndDate]
94
+ );
95
95
 
96
- const onConfirmEnd = (date) => {
97
- if (typeof date === 'number') {
98
- onCancel();
99
- return;
100
- }
101
- if (moment(date).valueOf() >= eventPicker.startTime) {
102
- setEventPicker({
103
- ...eventPicker,
104
- currentChangeTime: 'start',
105
- showModalEnd: false,
106
- endTime: moment(date).valueOf(),
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
- } else {
109
- setEventPicker({
110
- ...eventPicker,
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
- ...eventPicker,
123
- currentChangeTime: '',
126
+ setEventPicker((state) => ({
127
+ ...state,
124
128
  showModalEnd: false,
125
129
  showModalStart: false,
126
- });
127
- }, [eventPicker]);
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
- return sum * price;
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
- <ThreeButtonHistory
183
- setStartDate={setStartDate}
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
- {configuration.type !== 'horizontal_bar_chart' && (
192
- <DateTimeRangeChange
193
- startTime={eventPicker.startTime}
194
- onStart={onStart}
195
- onEnd={onEnd}
196
- endTime={eventPicker.endTime}
197
- date={dateNow}
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 dataY = datas[0].data.map((item, index) => {
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: {
@@ -136,6 +136,7 @@ const CurrencyInput = ({
136
136
  placeholder={placeholder}
137
137
  onSubmitEditing={onSubmitEditing}
138
138
  style={styles.input}
139
+ maxLength={10}
139
140
  />
140
141
  <Text
141
142
  semibold
@@ -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 { launchCamera, launchImageLibrary } from 'react-native-image-picker';
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
- quality: 1,
65
- saveToPhotos: true,
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
- launchCamera(options, (response) => {
72
- if (response.didCancel) {
73
- return;
74
- } else if (response.errorCode === 'camera_unavailable') {
75
- return;
76
- } else if (response.errorCode === 'permission') {
77
- return;
78
- } else if (response.errorCode === 'others') {
79
- return;
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
- quality: 1,
98
+ compressImageMaxWidth: 1280,
99
+ compressImageMaxHeight: 720,
100
+ compressImageQuality: 0.8,
103
101
  };
104
- launchImageLibrary(options, (response) => {
105
- if (response.didCancel) {
106
- return;
107
- } else if (response.errorCode === 'camera_unavailable') {
108
- return;
109
- } else if (response.errorCode === 'permission') {
110
- return;
111
- } else if (response.errorCode === 'others') {
112
- return;
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
  );