import React from 'react'
import ReactApexChart from 'react-apexcharts'
import ApexCharts from 'apexcharts'
import './styles.css'

// Shared by the vanilla-js, React and Vue builds. A synthetic population model:
// as the minimum age rises, the crowd shrinks and the female share dips. Each
// dot is one person; colour is gender; the female minority nests in the centre
// of the packed blob. Dragging the slider re-buckets the data and the dots
// redistribute in place, they do not rebuild from scratch.
function countsForAge(minAge) {
  var frac = (90 - minAge) / 45 // 1 at age 45, 0 at age 90
  var total = Math.round(180 + 760 * frac)
  var femaleShare = 0.2 + 0.16 * frac
  var female = Math.round(total * femaleShare)
  return { female: female, male: total - female, total: total }
}

function readoutText(minAge) {
  var c = countsForAge(minAge)
  var pct = ((c.female / c.total) * 100).toFixed(1)
  return (
    c.total.toLocaleString() +
    ' people aged ' +
    minAge +
    '+, ' +
    c.female.toLocaleString() +
    ' female (' +
    pct +
    '%)'
  )
}

const ApexChart = () => {
  const [state, setState] = React.useState({
    series: [338, 602],
    options: {
      chart: {
        id: 'popChart',
        type: 'unit',
        height: 460,
        animations: {
          enabled: true,
          speed: 700,
        },
      },
      labels: ['Female', 'Male'],
      colors: ['#EE5A8F', '#1AA5A0'],
      legend: {
        position: 'bottom',
      },
      plotOptions: {
        unit: {
          layout: 'packed',
          sortByGroup: true,
          spacing: 1.1,
        },
      },
    },
  })

  React.useEffect(() => {
    // Reach the live instance by its chart.id, then wire the slider.
    // (countsForAge and readoutText live in the shared head script.)
    let chart
    const timer = window.setInterval(() => {
      chart = ApexCharts.getChartByID('popChart')
      if (!chart) return
      window.clearInterval(timer)

      const ageInput = document.querySelector('#age')
      const readout = document.querySelector('#readout')
      ageInput.addEventListener('input', () => {
        const minAge = parseInt(ageInput.value, 10)
        readout.textContent = readoutText(minAge)
        const c = countsForAge(minAge)
        chart.updateSeries([c.female, c.male])
      })
    }, 50)

    return () => window.clearInterval(timer)
  }, [])

  return (
    <div>
      <div className="wrap">
        <h1>Population explorer</h1>
        <p>
          One dot per person, coloured by gender, the minority packed into the
          centre.
        </p>

        <div className="chart-wrap">
          <div id="chart">
            <ReactApexChart
              options={state.options}
              series={state.series}
              type="unit"
              height={460}
            />
          </div>
        </div>

        <div className="controls">
          Minimum age:{' '}
          <span className="readout" id="readout">
            45+
          </span>
          <input type="range" id="age" min="45" max="90" step="1" value="45" />
        </div>
      </div>
    </div>
  )
}

export default ApexChart
Population Explorer - React Unit Charts | ApexCharts.js | ApexCharts.js