@eohjsc/react-native-smart-city 0.7.41 → 0.7.42

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 (29) hide show
  1. package/package.json +1 -1
  2. package/src/commons/Dashboard/MyDashboardDevice/index.js +14 -12
  3. package/src/commons/Dashboard/MyUnit/index.js +4 -3
  4. package/src/commons/DateTimeRangeChange/index.js +5 -5
  5. package/src/commons/Device/HorizontalBarChart.js +11 -24
  6. package/src/commons/Device/PowerConsumptionChart.js +195 -103
  7. package/src/commons/Form/CurrencyInput.js +9 -18
  8. package/src/commons/SubUnit/Favorites/index.js +35 -10
  9. package/src/commons/SubUnit/ShortDetail.js +17 -4
  10. package/src/commons/SubUnit/__test__/Favorites.test.js +90 -0
  11. package/src/commons/SubUnit/__test__/ShortDetail.test.js +45 -2
  12. package/src/hooks/IoT/__test__/useValueEvaluation.test.js +12 -12
  13. package/src/iot/UpdateStates.js +37 -16
  14. package/src/iot/mqtt.js +23 -0
  15. package/src/screens/Device/__test__/DeviceDetail-3rdparty.test.js +16 -5
  16. package/src/screens/Device/__test__/DeviceDetail-arduino.test.js +10 -0
  17. package/src/screens/Device/__test__/DeviceDetail-modbus.test.js +37 -8
  18. package/src/screens/Device/__test__/DeviceDetail-zigbee.test.js +16 -5
  19. package/src/screens/Device/__test__/DeviceDetail.test.js +17 -6
  20. package/src/screens/Device/__test__/sensorDisplayItem.test.js +47 -11
  21. package/src/screens/Device/components/SensorDisplayItem.js +23 -5
  22. package/src/screens/Device/styles.js +4 -0
  23. package/src/screens/UnitSummary/components/3PPowerConsumption/index.js +8 -49
  24. package/src/screens/UnitSummary/components/PowerConsumption/__test__/PowerConsumption.test.js +121 -6
  25. package/src/screens/UnitSummary/components/PowerConsumption/index.js +6 -47
  26. package/src/utils/I18n/translations/en.js +1 -0
  27. package/src/utils/I18n/translations/vi.js +1 -0
  28. package/src/utils/chartHelper/index.js +53 -0
  29. package/src/utils/chartHelper/getMaxValueIndex.js +0 -11
@@ -1,24 +1,24 @@
1
1
  import MockAdapter from 'axios-mock-adapter';
2
- import React from 'react';
3
2
  import renderer, { act } from 'react-test-renderer';
4
3
 
5
- import { SCProvider } from '../../../context';
6
- import { mockSCStore } from '../../../context/mockStore';
7
- import { SensorDisplayItem } from '../components/SensorDisplayItem';
8
4
  import ActionGroup from '../../../commons/ActionGroup';
9
- import MediaPlayerDetail from '../../../commons/MediaPlayerDetail';
5
+ import DeviceAlertStatus from '../../../commons/Device/DeviceAlertStatus';
10
6
  import FlatListItems from '../../../commons/Device/FlatListItems';
11
- import VisualChart from '../components/VisualChart';
12
7
  import FooterInfo from '../../../commons/Device/FooterInfo';
13
- import Anemometer from '../../../commons/Device/WindSpeed/Anemometer';
8
+ import LabelValue from '../../../commons/Device/LabelValue';
9
+ import PowerConsumptionChart from '../../../commons/Device/PowerConsumptionChart';
14
10
  import ProgressBar from '../../../commons/Device/ProgressBar';
15
- import Compass from '../../../commons/Device/WindDirection/Compass';
16
- import DeviceAlertStatus from '../../../commons/Device/DeviceAlertStatus';
17
11
  import CurrentRainSensor from '../../../commons/Device/RainningSensor/CurrentRainSensor';
18
- import LabelValue from '../../../commons/Device/LabelValue';
12
+ import Compass from '../../../commons/Device/WindDirection/Compass';
13
+ import Anemometer from '../../../commons/Device/WindSpeed/Anemometer';
14
+ import MediaPlayerDetail from '../../../commons/MediaPlayerDetail';
19
15
  import Text from '../../../commons/Text';
20
- import SmartIr from '../../SmartIr';
16
+ import { SCProvider } from '../../../context';
17
+ import { mockSCStore } from '../../../context/mockStore';
21
18
  import api from '../../../utils/Apis/axios';
19
+ import SmartIr from '../../SmartIr';
20
+ import { SensorDisplayItem } from '../components/SensorDisplayItem';
21
+ import VisualChart from '../components/VisualChart';
22
22
 
23
23
  const mockIncrementReviewTrigger = jest.fn();
24
24
  const mockAskReview = jest.fn();
@@ -484,4 +484,40 @@ describe('Test SensorDisplayItem', () => {
484
484
  const labels = instance.findAllByType(Text);
485
485
  expect(labels[0].props.children).toEqual('Label');
486
486
  });
487
+
488
+ it('test render power_consume', async () => {
489
+ const item = {
490
+ id: 10452,
491
+ order: 0,
492
+ template: 'summary',
493
+ configuration: {
494
+ template: 'power_consume',
495
+ configs: [
496
+ {
497
+ id: 78,
498
+ color: 'green',
499
+ },
500
+ ],
501
+ aggregation_period: 'month',
502
+ },
503
+ label: 'Power Consume',
504
+ is_configuration_ready: true,
505
+ };
506
+
507
+ const sensor = {
508
+ name: 'Sensor name',
509
+ is_managed_by_backend: false,
510
+ };
511
+
512
+ await act(async () => {
513
+ tree = await renderer.create(wrapComponent({ item, sensor }));
514
+ });
515
+ const instance = tree.root;
516
+ const powerConsumptionChart = instance.findAllByType(PowerConsumptionChart);
517
+ expect(powerConsumptionChart).toHaveLength(1);
518
+ expect(powerConsumptionChart[0].props.label).toEqual('Power Consume');
519
+ expect(powerConsumptionChart[0].props.powerConfigId).toEqual(78);
520
+ expect(powerConsumptionChart[0].props.defaultPeriod).toEqual('month');
521
+ expect(powerConsumptionChart[0].props.color).toEqual('green');
522
+ });
487
523
  });
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useState } from 'react';
1
+ import { useCallback, useState } from 'react';
2
2
  import { View } from 'react-native';
3
3
  import ActionGroup from '../../../commons/ActionGroup';
4
4
  import DeviceAlertStatus from '../../../commons/Device/DeviceAlertStatus';
@@ -6,16 +6,17 @@ import EmergencyButton from '../../../commons/Device/Emergency/EmergencyButton';
6
6
  import EmergencyDetail from '../../../commons/Device/Emergency/EmergencyDetail';
7
7
  import FlatListItems from '../../../commons/Device/FlatListItems';
8
8
  import FooterInfo from '../../../commons/Device/FooterInfo';
9
+ import LabelValue from '../../../commons/Device/LabelValue';
9
10
  import PMSensorIndicator from '../../../commons/Device/PMSensor/PMSensorIndicator';
11
+ import PowerConsumptionChart from '../../../commons/Device/PowerConsumptionChart';
10
12
  import ProgressBar from '../../../commons/Device/ProgressBar';
11
- import LabelValue from '../../../commons/Device/LabelValue';
12
13
  import CurrentRainSensor from '../../../commons/Device/RainningSensor/CurrentRainSensor';
13
14
  import ListQualityIndicator from '../../../commons/Device/WaterQualitySensor/ListQualityIndicator';
14
15
  import Compass from '../../../commons/Device/WindDirection/Compass';
15
16
  import Anemometer from '../../../commons/Device/WindSpeed/Anemometer';
16
17
  import MediaPlayerDetail from '../../../commons/MediaPlayerDetail';
17
- import IFrame from '../../../commons/Widgets/IFrame/IFrame';
18
18
  import Text from '../../../commons/Text';
19
+ import IFrame from '../../../commons/Widgets/IFrame/IFrame';
19
20
  import { Device } from '../../../configs';
20
21
  import { AccessibilityLabel, WIDGET_TYPE } from '../../../configs/Constants';
21
22
  import { useSCContextSelector } from '../../../context';
@@ -47,14 +48,12 @@ export const SensorDisplayItem = ({
47
48
  const { configuration = {}, id: idTemplate, label } = item;
48
49
  const { type, template, uri, id, name, title, value_evaluation } =
49
50
  configuration;
50
-
51
51
  const sendRemoteCommand = useRemoteControl(bluetoothDevice);
52
52
  const [processing, setProcessing] = useState(false);
53
53
  // eslint-disable-next-line no-unused-vars
54
54
  const [configValues, setConfigValues] = useConfigGlobalState('configValues');
55
55
 
56
56
  const evaluateValue = useEvaluateValue();
57
-
58
57
  const checkConfigValue = (configValue) => {
59
58
  if (configValue === null || configValue === undefined) {
60
59
  return false;
@@ -322,6 +321,25 @@ export const SensorDisplayItem = ({
322
321
  return <FooterInfo data={configuration} />;
323
322
  case 'smart_ir':
324
323
  return <SmartIr item={item} />;
324
+ case 'summary':
325
+ switch (item?.configuration?.template) {
326
+ case 'power_consume':
327
+ return (
328
+ <View>
329
+ {configuration?.configs[0]?.id && (
330
+ <PowerConsumptionChart
331
+ label={label}
332
+ powerConfigId={configuration?.configs[0]?.id}
333
+ defaultPeriod={configuration?.aggregation_period}
334
+ color={configuration?.configs[0]?.color}
335
+ style={styles.powerConsumption}
336
+ />
337
+ )}
338
+ </View>
339
+ );
340
+ default:
341
+ return null;
342
+ }
325
343
  default:
326
344
  break;
327
345
  }
@@ -110,4 +110,8 @@ export default StyleSheet.create({
110
110
  color: Colors.Black,
111
111
  marginHorizontal: 20,
112
112
  },
113
+ powerConsumption: {
114
+ marginHorizontal: 16,
115
+ marginBottom: 8,
116
+ },
113
117
  });
@@ -1,17 +1,15 @@
1
- import React, { memo, useCallback, useMemo, useState } from 'react';
2
- import { View, StyleSheet } from 'react-native';
3
- import Text from '../../../../commons/Text';
4
- import { API, Colors } from '../../../../configs';
5
- import moment from 'moment';
1
+ import { memo, useMemo } from 'react';
2
+ import { StyleSheet, View } from 'react-native';
6
3
  import { Section, Today } from '../../../../commons';
7
- import ListQualityIndicator from '../../../../commons/Device/WaterQualitySensor/ListQualityIndicator';
8
4
  import PMSensorIndicator from '../../../../commons/Device/PMSensor/PMSensorIndicator';
9
- import VisualChart from '../../../Device/components/VisualChart';
10
- import { useTranslations } from '../../../../hooks/Common/useTranslations';
11
5
  import PowerConsumptionChart from '../../../../commons/Device/PowerConsumptionChart';
12
- import { axiosGet } from '../../../../utils/Apis/axios';
6
+ import ListQualityIndicator from '../../../../commons/Device/WaterQualitySensor/ListQualityIndicator';
7
+ import Text from '../../../../commons/Text';
8
+ import { Colors } from '../../../../configs';
13
9
  import { AccessibilityLabel } from '../../../../configs/Constants';
10
+ import { useTranslations } from '../../../../hooks/Common/useTranslations';
14
11
  import { useWatchConfigs } from '../../../../hooks/IoT';
12
+ import VisualChart from '../../../Device/components/VisualChart';
15
13
 
16
14
  const ThreePhasePowerConsumption = memo(({ summaryDetail }) => {
17
15
  const t = useTranslations();
@@ -114,36 +112,6 @@ const ThreePhasePowerConsumption = memo(({ summaryDetail }) => {
114
112
  return !!listConfigs;
115
113
  }, [listConfigs]);
116
114
 
117
- const [groupBy, setGroupBy] = useState('date');
118
- const [getData, setData] = useState({});
119
- const [chartConfig, setChartConfig] = useState({
120
- unit: 'kWh',
121
- price: '',
122
- });
123
-
124
- const fetchData = useCallback(
125
- async (startDate, endDate) => {
126
- let params = new URLSearchParams();
127
- params.append('config', total_power);
128
- params.append('group_by', groupBy);
129
- if (groupBy === 'date') {
130
- params.append('date_from', moment(startDate).format('YYYY-MM-DD'));
131
- params.append('date_to', moment(endDate).format('YYYY-MM-DD'));
132
- }
133
- const { success, data } = await axiosGet(
134
- API.VALUE_CONSUME.DISPLAY_HISTORY(),
135
- {
136
- params,
137
- },
138
- true
139
- );
140
- if (success) {
141
- setData(data);
142
- }
143
- },
144
- [groupBy, total_power]
145
- );
146
-
147
115
  const dataTotal = useMemo(() => {
148
116
  return total_power
149
117
  ? [
@@ -186,16 +154,7 @@ const ThreePhasePowerConsumption = memo(({ summaryDetail }) => {
186
154
  </Text>
187
155
 
188
156
  <PMSensorIndicator data={dataTotal} style={styles.styleTotalPower} />
189
- {total_power && (
190
- <PowerConsumptionChart
191
- onChangeDate={fetchData}
192
- datas={getData}
193
- chartConfig={chartConfig}
194
- setChartConfig={setChartConfig}
195
- groupBy={groupBy}
196
- setGroupBy={setGroupBy}
197
- />
198
- )}
157
+ {total_power && <PowerConsumptionChart powerConfigId={total_power} />}
199
158
  </Section>
200
159
  </>
201
160
  );
@@ -1,15 +1,17 @@
1
- import React from 'react';
2
- import renderer, { act, create } from 'react-test-renderer';
3
1
  import MockAdapter from 'axios-mock-adapter';
2
+ import renderer, { act, create } from 'react-test-renderer';
4
3
 
5
- import { AccessibilityLabel } from '../../../../../configs/Constants';
6
- import { API, Colors } from '../../../../../configs';
4
+ import moment from 'moment';
5
+ import { Today } from '../../../../../commons';
6
+ import DateTimeRangeChange from '../../../../../commons/DateTimeRangeChange';
7
+ import PowerConsumptionChart from '../../../../../commons/Device/PowerConsumptionChart';
7
8
  import ListQualityIndicator from '../../../../../commons/Device/WaterQualitySensor/ListQualityIndicator';
8
- import PowerConsumption from '../index';
9
+ import { API, Colors } from '../../../../../configs';
10
+ import { AccessibilityLabel } from '../../../../../configs/Constants';
9
11
  import { SCProvider } from '../../../../../context';
10
12
  import { mockSCStore } from '../../../../../context/mockStore';
11
13
  import api from '../../../../../utils/Apis/axios';
12
- import { Today } from '../../../../../commons';
14
+ import PowerConsumption from '../index';
13
15
 
14
16
  const mock = new MockAdapter(api.axiosInstance);
15
17
 
@@ -193,4 +195,117 @@ describe('Test PowerConsumption', () => {
193
195
  const listQualityIndicator = instance.findByType(ListQualityIndicator);
194
196
  expect(listQualityIndicator.props.data).toEqual([]);
195
197
  });
198
+
199
+ it('render PowerConsumption with total sum is 0', async () => {
200
+ const summaryDetail = {
201
+ listConfigs: {
202
+ total_power: 207,
203
+ },
204
+ };
205
+
206
+ const data = [
207
+ {
208
+ config: 207,
209
+ data: [
210
+ { x: 'Fri-14.06', y: 0 },
211
+ { x: 'Sat-15.06', y: 0 },
212
+ ],
213
+ },
214
+ ];
215
+ mock.onGet(API.VALUE_CONSUME.DISPLAY_HISTORY()).reply(200, data);
216
+ await act(async () => {
217
+ tree = await create(wrapComponent(summaryDetail));
218
+ });
219
+ const instance = tree.root;
220
+
221
+ const input_calculate_cost = instance.find(
222
+ (el) =>
223
+ el.props.accessibilityLabel === AccessibilityLabel.INPUT_CALCULATE_COST
224
+ );
225
+ await act(async () => {
226
+ input_calculate_cost.props.onChangeText('1000');
227
+ });
228
+ const button_calculate_cost = instance.find(
229
+ (el) =>
230
+ el.props.accessibilityLabel === AccessibilityLabel.BUTTON_CALCULATE_COST
231
+ );
232
+ await act(async () => {
233
+ button_calculate_cost.props.onPress();
234
+ });
235
+ const totalPrice = instance.find(
236
+ (el) => el.props.accessibilityLabel === AccessibilityLabel.TOTAL_PRICE
237
+ );
238
+ expect(totalPrice.props.children).toEqual('0 đ');
239
+ });
240
+
241
+ it('render PowerConsumption with empty data array', async () => {
242
+ const summaryDetail = {
243
+ listConfigs: {
244
+ total_power: 207,
245
+ },
246
+ };
247
+
248
+ mock.onGet(API.VALUE_CONSUME.DISPLAY_HISTORY()).reply(200, []);
249
+ await act(async () => {
250
+ tree = await create(wrapComponent(summaryDetail));
251
+ });
252
+ const instance = tree.root;
253
+
254
+ const input_calculate_cost = instance.find(
255
+ (el) =>
256
+ el.props.accessibilityLabel === AccessibilityLabel.INPUT_CALCULATE_COST
257
+ );
258
+ await act(async () => {
259
+ input_calculate_cost.props.onChangeText('1000');
260
+ });
261
+ const button_calculate_cost = instance.find(
262
+ (el) =>
263
+ el.props.accessibilityLabel === AccessibilityLabel.BUTTON_CALCULATE_COST
264
+ );
265
+ await act(async () => {
266
+ button_calculate_cost.props.onPress();
267
+ });
268
+
269
+ const totalPrice = instance.find(
270
+ (el) => el.props.accessibilityLabel === AccessibilityLabel.TOTAL_PRICE
271
+ );
272
+ expect(totalPrice.props.children).toEqual('0 đ');
273
+ });
274
+
275
+ it('cover selectStart and selectEnd in PowerConsumptionChart', async () => {
276
+ const summaryDetail = {
277
+ listConfigs: {
278
+ total_power: 207,
279
+ },
280
+ };
281
+
282
+ mock.onGet(API.VALUE_CONSUME.DISPLAY_HISTORY()).reply(200, []);
283
+ await act(async () => {
284
+ tree = await create(wrapComponent(summaryDetail));
285
+ });
286
+ const instance = tree.root;
287
+
288
+ const powerConsumptionChart = instance.findByType(PowerConsumptionChart);
289
+ const dateTimeRangeChange =
290
+ powerConsumptionChart.findByType(DateTimeRangeChange);
291
+ expect(dateTimeRangeChange).toBeDefined();
292
+
293
+ const newStartDate = moment().subtract(10, 'days');
294
+ const newEndDate = moment().subtract(1, 'days');
295
+
296
+ await act(async () => {
297
+ dateTimeRangeChange.props.selectStart(newStartDate);
298
+ });
299
+ await act(async () => {
300
+ dateTimeRangeChange.props.selectEnd(newEndDate);
301
+ });
302
+
303
+ // Check if the component still renders correctly after date changes
304
+ expect(
305
+ powerConsumptionChart.findByType(DateTimeRangeChange).props.startTime
306
+ ).toEqual(newStartDate);
307
+ expect(
308
+ powerConsumptionChart.findByType(DateTimeRangeChange).props.endTime
309
+ ).toEqual(newEndDate);
310
+ });
196
311
  });
@@ -1,18 +1,16 @@
1
- import React, { memo, useMemo, useState, useCallback } from 'react';
1
+ import { memo, useCallback, useMemo } from 'react';
2
2
  import { StyleSheet } from 'react-native';
3
3
  import { useTranslations } from '../../../../hooks/Common/useTranslations';
4
- import moment from 'moment';
5
4
 
6
- import { API, Colors } from '../../../../configs';
7
- import Text from '../../../../commons/Text';
8
5
  import { Section, Today } from '../../../../commons';
9
- import ListQualityIndicator from '../../../../commons/Device/WaterQualitySensor/ListQualityIndicator';
10
6
  import PMSensorIndicator from '../../../../commons/Device/PMSensor/PMSensorIndicator';
11
7
  import PowerConsumptionChart from '../../../../commons/Device/PowerConsumptionChart';
8
+ import ListQualityIndicator from '../../../../commons/Device/WaterQualitySensor/ListQualityIndicator';
9
+ import Text from '../../../../commons/Text';
10
+ import { Colors } from '../../../../configs';
12
11
  import { AccessibilityLabel } from '../../../../configs/Constants';
13
- import { axiosGet } from '../../../../utils/Apis/axios';
14
- import VisualChart from '../../../Device/components/VisualChart';
15
12
  import { useWatchConfigs } from '../../../../hooks/IoT';
13
+ import VisualChart from '../../../Device/components/VisualChart';
16
14
 
17
15
  const PowerConsumption = memo(({ summaryDetail }) => {
18
16
  const t = useTranslations();
@@ -21,16 +19,9 @@ const PowerConsumption = memo(({ summaryDetail }) => {
21
19
  listConfigs || {};
22
20
  useWatchConfigs([volt, current, active_power, power_factor, total_power]);
23
21
 
24
- const [groupBy, setGroupBy] = useState('date');
25
- const [getData, setData] = useState([]);
26
- const [chartConfig, setChartConfig] = useState({
27
- unit: 'kWh',
28
- price: '',
29
- });
30
22
  const showBoxHistory = useMemo(() => {
31
23
  return !!listConfigs;
32
24
  }, [listConfigs]);
33
-
34
25
  const createDataItem = useCallback(
35
26
  (id, color, title, measure) => ({
36
27
  id,
@@ -80,29 +71,6 @@ const PowerConsumption = memo(({ summaryDetail }) => {
80
71
  : [];
81
72
  }, [createDataItem, total_power]);
82
73
 
83
- const fetchData = useCallback(
84
- async (startDate, endDate) => {
85
- let params = new URLSearchParams();
86
- params.append('config', total_power);
87
- params.append('group_by', groupBy);
88
- if (groupBy === 'date') {
89
- params.append('date_from', moment(startDate).format('YYYY-MM-DD'));
90
- params.append('date_to', moment(endDate).format('YYYY-MM-DD'));
91
- }
92
- const { success, data } = await axiosGet(
93
- API.VALUE_CONSUME.DISPLAY_HISTORY(),
94
- {
95
- params,
96
- },
97
- true
98
- );
99
- if (success) {
100
- setData(data);
101
- }
102
- },
103
- [groupBy, total_power]
104
- );
105
-
106
74
  return (
107
75
  <>
108
76
  <Section type={'border'}>
@@ -123,16 +91,7 @@ const PowerConsumption = memo(({ summaryDetail }) => {
123
91
  </Text>
124
92
 
125
93
  <PMSensorIndicator data={dataTotal} style={styles.styleTotalPower} />
126
- {total_power && (
127
- <PowerConsumptionChart
128
- onChangeDate={fetchData}
129
- datas={getData}
130
- chartConfig={chartConfig}
131
- setChartConfig={setChartConfig}
132
- groupBy={groupBy}
133
- setGroupBy={setGroupBy}
134
- />
135
- )}
94
+ {total_power && <PowerConsumptionChart powerConfigId={total_power} />}
136
95
  </Section>
137
96
  </>
138
97
  );
@@ -529,6 +529,7 @@ export default {
529
529
  saved_vehicle: 'Saved Vehicle',
530
530
  set_a_number: 'Set a number',
531
531
  text_total_power_consumption: 'Total Power Consumption',
532
+ power_consumption_chart: 'Power Consumption Chart',
532
533
  input_price_to_calculate_electricity_cost:
533
534
  'Input price to calculate electricity cost',
534
535
  calculate_cost: 'Calculate cost',
@@ -590,6 +590,7 @@ export default {
590
590
  save_this_vehicle: 'Lưu và đặt phương tiện mặc định',
591
591
  saved_vehicle: 'Phương tiện đã lưu',
592
592
  text_total_power_consumption: 'Tổng điện năng tiêu thụ',
593
+ power_consumption_chart: 'Biểu đồ điện năng tiêu thụ',
593
594
  input_price_to_calculate_electricity_cost:
594
595
  'Nhập số tiền để tính giá tiền điện đã sử dụng',
595
596
  calculate_cost: 'Tính giá điện',
@@ -0,0 +1,53 @@
1
+ export const getMaxValueIndex = (data) => {
2
+ let max = {};
3
+ let _index = 0;
4
+ for (let i = 0; i < data.length; i++) {
5
+ if (max.y == null || data[i].y > max.y) {
6
+ max = { ...data[i] };
7
+ _index = i;
8
+ }
9
+ }
10
+ return { _index, max };
11
+ };
12
+
13
+ export const createDataLabelFormatter = () => {
14
+ return `function () {
15
+ const { unit, price } = JSON.parse(this.series.name || '{}');
16
+
17
+ // Re-define formatMoney for WebView scope since this function is stringified
18
+ const _formatMoney = (number) => {
19
+ const formatNumber = number.toFixed();
20
+ return (
21
+ parseInt(formatNumber, 10)
22
+ .toFixed(0)
23
+ .toString()
24
+ .replace(/(\\d)(?=(\\d\\d\\d)+(?!\\d))/g, '$1.') + 'đ'
25
+ );
26
+ };
27
+
28
+ // Hardcode Primary color or access it if available.
29
+ const Colors = { Primary: '#00979D' };
30
+
31
+ const textColor =
32
+ this.color === Colors.Primary
33
+ ? this.y === 0
34
+ ? '#262626'
35
+ : '#FFFFFF'
36
+ : '#262626';
37
+
38
+ const valueStyle = "color:" + textColor + ";font-weight:normal;font-size:12px;";
39
+ const costStyle = valueStyle + 'font-weight:bold;';
40
+ const label = "<span style=\\"" + valueStyle + "\\">" + this.y + (unit || '') + "</span>";
41
+
42
+ if (price === '' || price === null || isNaN(price)) {
43
+ return label;
44
+ }
45
+
46
+ return (
47
+ label +
48
+ "<span style=\\"" + costStyle + "\\">" + "/" +
49
+ _formatMoney(this.y * price) +
50
+ "</span></span>"
51
+ );
52
+ }`;
53
+ };
@@ -1,11 +0,0 @@
1
- export const getMaxValueIndex = (data) => {
2
- let max = {};
3
- let _index = 0;
4
- for (let i = 0; i < data.length; i++) {
5
- if (!max.y || data[i].y > max.y) {
6
- max = { ...data[i] };
7
- _index = i;
8
- }
9
- }
10
- return { _index, max };
11
- };