// Shared by the vanilla-js, React and Vue builds.
//
// Levels are FETCHED, not inlined, which is how a real dashboard works: the
// root is small, and each child is a request. A fake backend stands in for the
// API so the demo is self-contained and deterministic.
var BACKEND = {
  '2023-q': [
    { x: 'Q1', y: 21 },
    { x: 'Q2', y: 28 },
    { x: 'Q3', y: 24 },
    { x: 'Q4', y: 27 },
  ],
  '2024-q': [
    { x: 'Q1', y: 33 },
    { x: 'Q2', y: 41 },
    { x: 'Q3', y: 36 },
    { x: 'Q4', y: 40 },
  ],
  '2025-q': [
    { x: 'Q1', y: 44 },
    { x: 'Q2', y: 52 },
    { x: 'Q3', y: 48 },
    { x: 'Q4', y: 56 },
  ],
}

// Flipped by the checkbox, so the failure path is demonstrable rather than
// described. A failed fetch must leave the chart exactly where it was.
var failNext = false

function fakeFetch(id) {
  return new Promise(function (resolve, reject) {
    window.setTimeout(function () {
      if (failNext) {
        reject(new Error('Request failed (simulated)'))
        return
      }
      var rows = BACKEND[id]
      if (!rows) {
        reject(new Error('No level "' + id + '"'))
        return
      }
      resolve({ id: id, name: id.replace('-q', ' by quarter'), data: rows })
    }, 700)
  })
}

function setStatus(text, isError) {
  var el = document.querySelector('#status')
  if (!el) return
  el.textContent = text || ''
  el.className = isError ? 'status error' : 'status'
}

var options = {
  series: [
    {
      name: 'Revenue',
      data: [
        { x: '2023', y: 100, drilldown: '2023-q' },
        { x: '2024', y: 150, drilldown: '2024-q' },
        { x: '2025', y: 200, drilldown: '2025-q' },
      ],
    },
  ],
  chart: {
    id: 'asyncDrill',
    type: 'bar',
    height: 400,
    toolbar: {
      show: false,
    },
  },
  plotOptions: {
    bar: {
      distributed: true,
      columnWidth: '50%',
      borderRadius: 6,
      borderRadiusApplication: 'end',
    },
  },
  legend: {
    show: false,
  },
  dataLabels: {
    enabled: false,
  },
  drilldown: {
    enabled: true,
    // Deliberately empty: every level below the root comes from onDrillDown.
    series: [],
    breadcrumb: {
      show: true,
      rootLabel: 'All years',
    },
    loading: {
      show: true,
    },
    cache: true,
  },
}

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

// BACKEND, fakeFetch, failNext and setStatus live in the shared head script.
chart.updateOptions({
  drilldown: {
    onDrillDown: function (ctx) {
      setStatus('Fetching ' + ctx.id + '...')
      return fakeFetch(ctx.id)
    },
  },
})

chart.addEventListener('drillDownEnd', function () {
  setStatus('')
})
chart.addEventListener('drillDownError', function (info) {
  setStatus(String(info.error && info.error.message), true)
})

document.querySelector('#up').addEventListener('click', function () {
  chart.drillUp()
})
document.querySelector('#clear-cache').addEventListener('click', function () {
  chart.clearDrilldownCache()
  setStatus('Cache cleared - the next drill will refetch.')
})
document.querySelector('#fail').addEventListener('change', function (e) {
  failNext = e.target.checked
})
Async Drilldown Column - JavaScript Column Charts | ApexCharts.js | ApexCharts.js