src/containers/SparklineContainer.js
import { max } from 'd3-array'
import lowerCase from 'lodash.lowercase'
import startCase from 'lodash.startcase'
import PropTypes from 'prop-types'
import React from 'react'
import { connect } from 'react-redux'
import ErrorCard from '../components/ErrorCard'
import Loading from '../components/Loading'
import Sparkline from '../components/Sparkline'
import { oriToState } from '../util/agencies'
import lookupUsa, { nationalKey } from '../util/usa'
const SparklineContainer = ({ pageType, since, summaries, until, usState }) => {
const { data, error, loading } = summaries
const normalizedCrime = pageType === 'rape' ? 'rape-legacy' : pageType
if (error) return <ErrorCard error={error} />
const filterYears = d => d.year >= since && d.year <= until
const computeRate = d => ({
rate: d[normalizedCrime].count * 10000 / d.population,
year: d.year,
})
const sparklines = [
{
data: data[usState] || [],
place: lookupUsa(usState).display,
url: `/explorer/state/${usState}/${pageType}`,
},
{
data: data[nationalKey] || [],
place: 'United States',
url: `/explorer/${pageType}`,
},
]
const yMax = max(
sparklines.map(s => s.data).reduce((a, n) => [...a, ...n]),
d => d.rate,
)
return (
<div className="mb4">
<h3 className="mt0 mb2 fs-18">
State and national {lowerCase(pageType)} rates
</h3>
<div className="clearfix mxn1">
{sparklines.map((s, i) =>
<div className="sm-col sm-col-6 mb1 px1" key={i}>
<div className="p2 bg-blue-lighter flex items-center">
<div className="flex-none">
<h4 className="m0 sans-serif fs-14">
{s.place}
</h4>
<p className="mb2 mw8 fs-14">
{startCase(pageType)},{' '}
<span className="nowrap">
{since}-{until}
</span>
</p>
<a
className="block btn btn-sm btn-primary fs-12 regular center"
href={s.url}
>
Explore {s.place === 'United States'
? 'national'
: 'state'}{' '}
data
</a>
</div>
<div className="pl1 sm-pl2 flex-auto center">
{loading
? <Loading slim />
: <Sparkline
data={s.data.filter(filterYears).map(computeRate)}
yMax={yMax}
/>}
</div>
</div>
</div>,
)}
</div>
<p className="mt1 mb0 fs-12 serif italic">
Rates are only available for state and national-level data.
</p>
</div>
)
}
SparklineContainer.propTypes = {
pageType: PropTypes.string.isRequired,
since: PropTypes.number.isRequired,
summaries: PropTypes.shape({
data: PropTypes.object,
loading: PropTypes.boolean,
}).isRequired,
until: PropTypes.number.isRequired,
usState: PropTypes.string.isRequired,
}
const mapStateToProps = ({ filters, summaries }) => ({
...filters,
usState: oriToState(filters.place),
summaries,
crime: filters.pageType,
})
export default connect(mapStateToProps)(SparklineContainer)