import React from 'react'
import ReactApexChart from 'react-apexcharts'
import './styles.css'
import 'apexcharts/features/trellis'
// Four departments by four quarters: the 2-D grid IS the shape of the
// question. Reading across a row is "this department over the year"; down a
// column is "this quarter across departments"; both are one glance, where a
// pivot table is arithmetic and a 16-group column chart is soup.
//
// Marketing was formed in Q2, so (Marketing, Q1) has no data: the default
// `emptyPanels: 'placeholder'` keeps the slot as a REAL panel on the same
// shared scale (so the grid never lies about geometry) with a quiet label.
//
// Deterministic monthly hours so the e2e snapshot is stable.
function mulberry32(seed) {
return function () {
seed |= 0
seed = (seed + 0x6d2b79f5) | 0
var t = Math.imul(seed ^ (seed >>> 15), 1 | seed)
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t
return ((t ^ (t >>> 14)) >>> 0) / 4294967296
}
}
var DEPTS = [
{ name: 'Engineering', base: 610 },
{ name: 'Sales', base: 380 },
{ name: 'Support', base: 290 },
{ name: 'Marketing', base: 170 },
]
var QUARTERS = ['Q1', 'Q2', 'Q3', 'Q4']
function monthlyHours(seed, base) {
var rand = mulberry32(seed)
var out = []
for (var m = 0; m < 3; m++) {
out.push({
x: 'M' + (m + 1),
y: Math.round(base * (0.85 + rand() * 0.3)),
})
}
return out
}
var deptSeries = []
DEPTS.forEach(function (d, di) {
QUARTERS.forEach(function (q, qi) {
if (d.name === 'Marketing' && q === 'Q1') return // formed in Q2
deptSeries.push({
name: 'Hours',
dept: d.name,
quarter: q,
data: monthlyHours(di * 17 + qi * 5 + 3, d.base),
})
})
})
const ApexChart = () => {
const [state, setState] = React.useState({
series: deptSeries,
options: {
chart: {
id: 'deptQuarterTrellis',
type: 'bar',
height: 560,
animations: {
enabled: false,
},
},
trellis: {
row: 'dept',
column: 'quarter',
gap: 12,
},
colors: ['#2563EB'],
plotOptions: {
bar: {
columnWidth: '55%',
borderRadius: 3,
},
},
xaxis: {
type: 'category',
},
yaxis: {
labels: {
formatter: function (val) {
return Math.round(val) + 'h'
},
},
},
dataLabels: {
enabled: false,
},
},
})
return (
<div>
<div className="wrap">
<h1>Delivery hours, department by quarter</h1>
<p className="lead">
Across a row: one department's year. Down a column: one quarter's
whole org. The empty slot is honest: Marketing did not exist in Q1,
and the placeholder keeps that cell on the same scale instead of
collapsing the grid.
</p>
<div className="chart-wrap">
<div id="chart">
<ReactApexChart
options={state.options}
series={state.series}
type="bar"
height={560}
/>
</div>
</div>
<div className="note">
Two facet keys make a fixed grid: <code>trellis.row: 'dept'</code> and
<code>trellis.column: 'quarter'</code>, every (row, column)
combination in row-major order, column labels drawn once across the
top and row labels once down the left. Missing combinations follow
<code>emptyPanels</code>: <code>'placeholder'</code> (default) mounts
a real panel on the shared scale with a quiet label,{' '}
<code>'skip'</code>
leaves a tinted blank, <code>'hide'</code> leaves nothing. A 2-D grid
never re-columns responsively; panels shrink instead, so the grid's
meaning survives any width. Trellis is a premium feature; without a
license it renders with a trial watermark.
</div>
</div>
</div>
)
}
export default ApexChart