1
|
|
|
import React, { useState, useContext, useEffect, useRef, Fragment } from 'react'; |
2
|
|
|
import { rgbaColor, themeColors, isIterableArray } from '../../../helpers/utils'; |
3
|
|
|
import FalconCardHeader from '../../common/FalconCardHeader'; |
4
|
|
|
import { Row, Col, Card, CardBody, CustomInput } from 'reactstrap'; |
5
|
|
|
import {withTranslation} from "react-i18next"; |
6
|
|
|
import { Bar } from 'react-chartjs-2'; |
7
|
|
|
import { |
8
|
|
|
Chart as ChartJS, |
9
|
|
|
CategoryScale, |
10
|
|
|
LinearScale, |
11
|
|
|
BarElement, |
12
|
|
|
Title, |
13
|
|
|
Tooltip, |
14
|
|
|
Legend, |
15
|
|
|
LogarithmicScale |
16
|
|
|
} from 'chart.js'; |
17
|
|
|
import AppContext from '../../../context/Context'; |
18
|
|
|
|
19
|
|
|
ChartJS.register( |
20
|
|
|
CategoryScale, |
21
|
|
|
LinearScale, |
22
|
|
|
BarElement, |
23
|
|
|
Title, |
24
|
|
|
Tooltip, |
25
|
|
|
Legend, |
26
|
|
|
LogarithmicScale |
27
|
|
|
); |
28
|
|
|
|
29
|
|
|
const ChartSpacesStackBar = ({ labels, inputData, costData, title, childSpaces, t}) => { |
30
|
|
|
const [selectedLabel, setSelectedLabel] = useState('a0'); |
31
|
|
|
const [option, setOption] = useState('a0'); |
32
|
|
|
const { isDark } = useContext(AppContext); |
33
|
|
|
const chartRef = useRef(null); |
34
|
|
|
const [chartData, setChartData] = useState({ |
35
|
|
|
datasets: [] |
36
|
|
|
}); |
37
|
|
|
|
38
|
|
|
useEffect(() => { |
39
|
|
|
const chart = chartRef.current; |
40
|
|
|
let dataArray = []; |
41
|
|
|
let index = option.substring(1); |
42
|
|
|
if (chart) { |
43
|
|
|
const ctx = chart.ctx; |
44
|
|
|
const gradientFill = isDark |
45
|
|
|
? ctx.createLinearGradient(0, 0, 0, ctx.canvas.height) |
46
|
|
|
: ctx.createLinearGradient(0, 0, 0, 250); |
47
|
|
|
gradientFill.addColorStop(0, isDark ? 'rgba(44,123,229, 0.5)' : 'rgba(255, 255, 255, 0.3)'); |
48
|
|
|
gradientFill.addColorStop(1, isDark ? 'transparent' : 'rgba(255, 255, 255, 0)'); |
49
|
|
|
if (inputData['subtotals_array'] != undefined) { |
50
|
|
|
let category = t('CATEGORY Consumption UNIT', {'CATEGORY': inputData['energy_category_names'][index], 'UNIT': inputData['units'][index]}); |
51
|
|
|
let childSpaceArray = inputData['child_space_names_array'][index]; |
52
|
|
|
inputData['subtotals_array'][index].forEach((item, itemIndex) => { |
53
|
|
|
let color = rgbaColor("#"+((1<<24)*Math.random()|0).toString(16), 0.8); |
54
|
|
|
dataArray.push({ |
55
|
|
|
label: childSpaceArray[itemIndex] + " " + category, |
56
|
|
|
stack: category, |
57
|
|
|
data: item, |
58
|
|
|
backgroundColor: color, |
59
|
|
|
}) |
60
|
|
|
}) |
61
|
|
|
} |
62
|
|
|
if (costData['subtotals_array'] != undefined) { |
63
|
|
|
let category = t('CATEGORY Costs UNIT', {'CATEGORY': costData['energy_category_names'][index], 'UNIT': costData['units'][index]}); |
64
|
|
|
let childSpaceArray = costData['child_space_names_array'][index]; |
65
|
|
|
costData['subtotals_array'][index].forEach((item, itemIndex) => { |
66
|
|
|
let color = rgbaColor("#"+((1<<24)*Math.random()|0).toString(16), 0.8); |
67
|
|
|
dataArray.push({ |
68
|
|
|
label: childSpaceArray[itemIndex] + " " + category, |
69
|
|
|
stack: category, |
70
|
|
|
data: item, |
71
|
|
|
backgroundColor: color, |
72
|
|
|
}) |
73
|
|
|
}) |
74
|
|
|
} |
75
|
|
|
setChartData({ |
76
|
|
|
labels: labels, |
77
|
|
|
datasets: dataArray |
78
|
|
|
}) |
79
|
|
|
} |
80
|
|
|
}, [labels, inputData, costData, option]) |
81
|
|
|
const options = { |
82
|
|
|
scales: { |
83
|
|
|
x: { |
84
|
|
|
display: true, |
85
|
|
|
ticks: { |
86
|
|
|
fontColor: rgbaColor('#fff', 0.8), |
87
|
|
|
fontStyle: 600, |
88
|
|
|
color: isDark ? themeColors.light : themeColors.dark |
89
|
|
|
}, |
90
|
|
|
stacked: true, |
91
|
|
|
}, |
92
|
|
|
y: { |
93
|
|
|
display: true, |
94
|
|
|
gridLines: { |
95
|
|
|
color: rgbaColor('#000', 0.1) |
96
|
|
|
}, |
97
|
|
|
ticks: { |
98
|
|
|
color: isDark ? themeColors.light : themeColors.dark |
99
|
|
|
}, |
100
|
|
|
stacked: true, |
101
|
|
|
}, |
102
|
|
|
}, |
103
|
|
|
plugins:{ |
104
|
|
|
legend: { |
105
|
|
|
display: false, |
106
|
|
|
}, |
107
|
|
|
}, |
108
|
|
|
interaction: { |
109
|
|
|
intersect: false, |
110
|
|
|
mode: 'x', |
111
|
|
|
}, |
112
|
|
|
}; |
113
|
|
|
return ( |
114
|
|
|
<Fragment> |
115
|
|
|
<Card className="mb-3"> |
116
|
|
|
<FalconCardHeader title={title} className="bg-light"> |
117
|
|
|
</FalconCardHeader> |
118
|
|
|
<CardBody className="rounded-soft"> |
119
|
|
|
<Row className="text-white align-items-center no-gutters"> |
120
|
|
|
<Col> |
121
|
|
|
<h4 className="text-lightSlateGray mb-0"></h4> |
122
|
|
|
</Col> |
123
|
|
|
{isIterableArray(childSpaces) && |
124
|
|
|
<Col xs="auto" className="d-none d-sm-block"> |
125
|
|
|
<CustomInput |
126
|
|
|
id="ddd" |
127
|
|
|
type="select" |
128
|
|
|
bsSize="sm" |
129
|
|
|
className="mb-3 shadow" |
130
|
|
|
value={option} |
131
|
|
|
onChange={({ target }) => {setOption(target.value); setSelectedLabel(target.value);}} |
132
|
|
|
> |
133
|
|
|
{childSpaces.map(({ value, label }) => ( |
134
|
|
|
<option key={value} value={value}>{label}</option> |
135
|
|
|
))} |
136
|
|
|
</CustomInput> |
137
|
|
|
</Col> |
138
|
|
|
} |
139
|
|
|
</Row> |
140
|
|
|
<Bar ref={chartRef} data={chartData} width={160} height={40} options={options} /> |
141
|
|
|
</CardBody> |
142
|
|
|
</Card> |
143
|
|
|
</Fragment> |
144
|
|
|
) |
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
export default withTranslation()(ChartSpacesStackBar); |