fbi-cde/crime-data-frontend

View on GitHub
src/components/HorizontalBarChartDetails.js

Summary

Maintainability
A
0 mins
Test Coverage
import range from 'lodash.range'
import PropTypes from 'prop-types'
import React from 'react'

import Highlight from './Highlight'
import crimeTerm from '../util/glossary'
import { formatNum, formatOneDec as formatRate } from '../util/formats'
import { nationalKey } from '../util/usa'
import generateId from '../util/id'

const highlight = txt => <strong>{txt}</strong>
const borderColor = { borderColor: '#c8d3dd' }
const cellStyle = { width: 68, ...borderColor }

const getComparison = ({ place, data }) => {
  const threshold = 3
  const placeRate = data.find(d => d.place === place).rate
  const nationalRate = data.find(d => d.place === nationalKey).rate
  const diff = (placeRate / nationalRate - 1) * 100

  return Math.abs(diff) < threshold ? (
    <span>about the same (within {threshold}%) as</span>
  ) : (
    <span>{<Highlight text={`${diff > 0 ? 'higher' : 'lower'}`} />} than</span>
  )
}

const HorizontalBarChartDetails = ({
  active,
  ratePer,
  colors,
  subject,
  keys,
  since,
  until,
  onChangeYear,
  placeName
}) => {
  const handleSelectChange = e => onChangeYear(Number(e.target.value))
  const yearRange = range(since, until + 1)
  const term = crimeTerm(subject)
  const data = active.filter(d => d.crime !== 'rape-revised')
  const isNational = keys.length === 1
  const place = isNational ? nationalKey : keys.find(k => k !== nationalKey)
  const comparison = getComparison({ place, data })
  const { rate, year } = data.find(d => d.place === place) || {}
  const crimeId = `${subject}-hbar-chart-details`

  let sentence
  if (isNational) {
    sentence = (
      <span>
        In <span id="selected-year-text">{highlight(year)}</span>, the {term}{' '}
        rate was {highlight(formatRate(rate))} per {ratePer} inhabitants.
      </span>
    )
  } else {
    sentence = (
      <span>
        In <span id="selected-year-text">{highlight(year)}</span>, {placeName}’s{' '}
        {term} rate was {highlight(formatRate(rate))} per {ratePer} inhabitants.
        The rate for that year was {comparison} that of the United States.
      </span>
    )
  }

  return (
    <div className="lg-flex">
      <div className="flex-auto">
        <p className="mb2 lg-m0 lg-pr5 lg-mh-88p fs-14">{sentence}</p>
      </div>
      <div
        id={crimeId}
        className="flex-none inline-block mw-fill overflow-auto bg-blue-white rounded"
      >
        <table className="p2 sm-col-5">
          <thead className="fs-10 line-height-4 right-align">
            <tr>
              <td className="left-align">
                <label htmlFor="year-selected" className="hide">
                  Year selected
                </label>
                <select
                  className="col-12 field select select-sm select-dark fs-12"
                  id="year-selected"
                  style={{ width: 100 }}
                  onChange={handleSelectChange}
                  value={year}
                >
                  {yearRange.map((y, i) => <option key={i}>{y}</option>)}
                </select>
              </td>
              <td className="pr2 align-middle">Rate</td>
              <td className="pr2 align-middle">Total</td>
              <td className="pl2 align-middle border-left" style={borderColor}>
                Population
              </td>
            </tr>
          </thead>
          <tbody className="fs-12 bold line-height-4">
            {data.map((d, i) => (
              <tr key={i} id={generateId(`${d.place}-trend-chart-details-row`)}>
                <td
                  className="pr2 nowrap truncate align-bottom"
                  style={{ maxWidth: 125 }}
                >
                  <span
                    className="mr1 inline-block circle"
                    style={{
                      width: 8,
                      height: 8,
                      backgroundColor: colors[i] || '#000'
                    }}
                  />
                  {d.place === 'united-states' ? 'United States' : placeName}
                </td>
                <td className="pt1 pr2 align-bottom right-align">
                  <span
                    id={generateId(`${d.place}-trend-chart-details-row-rate`)}
                    className="inline-block border-bottom"
                    style={cellStyle}
                  >
                    {formatRate(d.rate)}
                  </span>
                </td>
                <td className="pt1 pr2 align-bottom right-align">
                  <span
                    id={generateId(`${d.place}-trend-chart-details-row-count`)}
                    className="inline-block border-bottom"
                    style={cellStyle}
                  >
                    {formatNum(d.count)}
                  </span>
                </td>
                <td
                  className="pt1 pl2 align-bottom right-align border-left"
                  style={borderColor}
                >
                  <span
                    id={generateId(
                      `${d.place}-trend-chart-details-row-population`
                    )}
                    className="inline-block border-bottom"
                    style={cellStyle}
                  >
                    {formatNum(d.population)}
                  </span>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  )
}

HorizontalBarChartDetails.propTypes = {
  active: PropTypes.arrayOf(PropTypes.object).isRequired,
  colors: PropTypes.arrayOf(PropTypes.string).isRequired,
  subject: PropTypes.string.isRequired,
  since: PropTypes.number.isRequired,
  until: PropTypes.number.isRequired,
  onChangeYear: PropTypes.func.isRequired,
  placeName: PropTypes.string.isRequired
}

export default HorizontalBarChartDetails