Department by Quarter in JavaScript

Using ApexCharts with JavaScript

This Department by Quarter example uses ApexCharts.js directly in JavaScript, with no wrapper component.

Install it with npm install apexcharts, then mount the chart with new ApexCharts(element, options).render().

JavaScript installation guide
// 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),
    })
  })
})

var options = {
  series: deptSeries,
  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,
  },
}

var chart = new ApexCharts(document.querySelector('#chart'), options)
chart.render()