Skip to content

Commit

Permalink
feat(Boolean Stat Chart): add boolean stat, move Stat component out o…
Browse files Browse the repository at this point in the history
…f directory
  • Loading branch information
b5 committed Nov 15, 2019
1 parent 5b864e7 commit cb3d5a7
Show file tree
Hide file tree
Showing 5 changed files with 243 additions and 42 deletions.
116 changes: 92 additions & 24 deletions app/components/stats/Stat.tsx → app/components/StatsChart.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import { ResponsiveBar } from '@nivo/bar'
import { ResponsivePie } from '@nivo/pie'
import * as React from 'react'

const primaryStatColor = '#0061A6'

interface StatProps {
interface StatsChartProps {
height: number
data: Record<string, any>
}

const Stat: React.FunctionComponent<StatProps> = (props: StatProps) => {
const StatsChart: React.FunctionComponent<StatsChartProps> = (props: StatsChartProps) => {
const { data, height = 250 } = props
switch (data.type) {
case 'string':
return <StringStat data={data} height={height} />
case 'numeric':
return <NumericStat data={data} height={height} />
case 'boolean':
return <BooleanStat data={data} height={height} />
default:
return (
<div>
Expand All @@ -26,9 +29,28 @@ const Stat: React.FunctionComponent<StatProps> = (props: StatProps) => {
}
}

export default Stat
export default StatsChart

const NumericStat: React.FunctionComponent<StatProps> = (props: StatProps) => {
interface StatValuesProps {
stats: Array<[string, any]>
}

const StatValues: React.FunctionComponent<StatValuesProps> = ({ stats }) => {
return (
<div className='stats-values'>
{stats.map((stat, i) => {
return (
<div key={i} className="stats-value" style={{ marginLeft: 15 }}>
<h4>{stat[1]}</h4>
<label className="label">{stat[0]}</label>
</div>
)
})}
</div>
)
}

const NumericStat: React.FunctionComponent<StatsChartProps> = (props: StatsChartProps) => {
const { data, height } = props
let histogram

Expand Down Expand Up @@ -91,26 +113,7 @@ const NumericStat: React.FunctionComponent<StatProps> = (props: StatProps) => {
)
}

interface StatValuesProps {
stats: Array<[string, any]>
}

const StatValues: React.FunctionComponent<StatValuesProps> = ({ stats }) => {
return (
<div className='stats-values'>
{stats.map((stat, i) => {
return (
<div key={i} className="stats-value" style={{ marginLeft: 15 }}>
<h4>{stat[1]}</h4>
<label className="label">{stat[0]}</label>
</div>
)
})}
</div>
)
}

const StringStat: React.FunctionComponent<StatProps> = (props: StatProps) => {
const StringStat: React.FunctionComponent<StatsChartProps> = (props: StatsChartProps) => {
const { data, height } = props
let frequencies

Expand Down Expand Up @@ -176,3 +179,68 @@ const StringStat: React.FunctionComponent<StatProps> = (props: StatProps) => {
</div>
)
}

const BooleanStat: React.FunctionComponent<StatsChartProps> = (props: StatsChartProps) => {
const { data, height } = props
let frequencies = [
{
id: 'false',
label: 'false',
value: data.falseCount,
color: '#EE325C'
},
{
id: 'true',
label: 'true',
value: data.trueCount,
color: primaryStatColor
}]

const other = data.count - data.trueCount - data.falseCount
if (other !== 0) {
frequencies.push({
id: 'other',
label: 'other',
value: other,
color: '#F4A935'
})
}

return (
<div>
{frequencies && <div style={{ height: height }}>
<div style={{ paddingLeft: 35 }}>
<b>frequencies</b>
</div>
<ResponsivePie
data={frequencies}
margin={{ top: 40, right: 80, bottom: 80, left: 80 }}
innerRadius={0.5}
padAngle={0.7}
colors={(d) => d.color }
cornerRadius={3}
borderWidth={1}
borderColor={{ from: 'color', modifiers: [ [ 'darker', 0.2 ] ] }}
radialLabelsSkipAngle={10}
radialLabelsTextXOffset={6}
radialLabelsTextColor="#333333"
radialLabelsLinkOffset={0}
radialLabelsLinkDiagonalLength={16}
radialLabelsLinkHorizontalLength={0}
radialLabelsLinkStrokeWidth={1}
radialLabelsLinkColor={{ from: 'color' }}
slicesLabelsSkipAngle={10}
slicesLabelsTextColor="#333333"
animate={true}
motionStiffness={90}
motionDamping={15}
/>
</div>}
<StatValues stats={[
['count', data.count.toLocaleString()],
['true', data.trueCount.toLocaleString()],
['false', data.falseCount.toLocaleString()]
]} />
</div>
)
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@
"@fortawesome/free-solid-svg-icons": "5.11.2",
"@fortawesome/react-fontawesome": "0.1.7",
"@nivo/bar": "^0.59.2",
"@nivo/pie": "^0.59.1",
"@storybook/cli": "^5.2.6",
"@storybook/react": "^5.2.6",
"@types/webpack-env": "1.14.1",
Expand Down
57 changes: 39 additions & 18 deletions stories/0-Stats.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,38 @@
import React from 'react'
import Stat from '../app/components/stats/Stat.tsx'
import StatsChart from '../app/components/StatsChart.tsx'
import fjcReport from './data/stats_nyc_report_family_justice_center_stats.json'
import allTypes from './data/stats_all_types.json'

export default {
title: 'Stats',
title: 'Stats|Charts',
parameters: {
notes: `feeding different data to the stats component.
stats data from the [nyc fjc report](https://data.cityofnewyork.us/Social-Services/Annual-Report-on-Family-Justice-Center-Client-Sati/g62n-cz6a)`
}
}

export const overview = () => {
return (
<div style={{ display: 'flex', flexWrap: 'wrap' }}>
{allTypes.map((d, i) => {
return (
<div key={i} style={{ margin: 15, minWidth: 300 }}>
<p>{d.type}</p>
<hr />
<StatsChart data={d} />
</div>
)
})}
</div>
)
}

overview.story = {
name: 'All Stats',
parameters: { note: 'idealized overview of each stat' }
}

const wrap = (component) => {
return (
<div style={{ maxWidth: 300, margin: '0 auto' }}>
Expand All @@ -19,29 +41,28 @@ const wrap = (component) => {
)
}

export const zero = () => wrap(<Stat data={fjcReport[0]} />)
export const languages = () => wrap(<StatsChart data={fjcReport[3]} />)

zero.story = {
name: 'Many Long String',
languages.story = {
name: 'String: Languages'
}

export const one = () => wrap(<Stat data={fjcReport[1]} />)
export const manyLongStrings = () => wrap(<StatsChart data={fjcReport[0]} />)

one.story = {
name: 'Empty String'
manyLongStrings.story = {
name: 'String: Many Long',
}

export const two = () => wrap(<Stat data={fjcReport[2]} />)
export const empty = () => wrap(<StatsChart data={fjcReport[1]} />)

two.story = {
name: 'Yes/No/Blank String'
empty.story = {
name: 'String: Empty'
}

export const yesNoBlank = () => wrap(<StatsChart data={fjcReport[2]} />)

export const three = () => wrap(<Stat data={fjcReport[3]} />)

three.story = {
name: 'Languages String'
yesNoBlank.story = {
name: 'String: Yes/No/Blank'
}

const charityFdnGrant2016AmountStat = {
Expand Down Expand Up @@ -80,9 +101,9 @@ const charityFdnGrant2016AmountStat = {
"type": "numeric"
}

export const four = () => wrap(<Stat data={charityFdnGrant2016AmountStat} />)
export const lopsided = () => wrap(<StatsChart data={charityFdnGrant2016AmountStat} />)

four.story = {
name: 'Lopsided Numeric',
lopsided.story = {
name: 'Numeric: Lopsided',
parameters: { notes: 'bonkers histogram from charitable foundation donations in 2016'}
}
97 changes: 97 additions & 0 deletions stories/data/stats_all_types.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
[
{
"count": 5,
"falseCount": 3,
"key": "bool",
"trueCount": 2,
"type": "boolean"
},
{
"count": 5,
"histogram": {
"bins": [
1.1,
1.6400000000000001,
2.18,
2.72,
3.2600000000000002,
3.8000000000000003,
4.34,
4.880000000000001,
5.42,
5.960000000000001,
6.5
],
"frequencies": [
2,
0,
0,
0,
1,
0,
1,
0,
1,
0
]
},
"key": "float",
"max": 5.5,
"mean": 3.08,
"median": 3.3,
"min": 1.1,
"type": "numeric"
},
{
"count": 5,
"histogram": {
"bins": [
1,
1.5,
2,
2.5,
3,
3.5,
4,
4.5,
5,
5.5,
6
],
"frequencies": [
2,
0,
0,
0,
1,
0,
1,
0,
1,
0
]
},
"key": "int",
"max": 5,
"mean": 2.8,
"median": 3,
"min": 1,
"type": "numeric"
},
{
"count": 5,
"key": "nil",
"type": "null"
},
{
"count": 5,
"frequencies": {
"aaa": 2
},
"key": "string",
"maxLength": 5,
"minLength": 1,
"type": "string",
"unique": 3
}
]
14 changes: 14 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1681,6 +1681,20 @@
lodash "^4.17.11"
recompose "^0.30.0"

"@nivo/pie@^0.59.1":
version "0.59.1"
resolved "https://registry.yarnpkg.com/@nivo/pie/-/pie-0.59.1.tgz#08be965f877cabb96c14bb2eefbe6022d856877e"
integrity sha512-odQPqQ3CmAbqS9Te3N7VsbKKBByjxDPe3SqTCUPysqGC5f+/DrynKwDxRSqOSL0HG7s0mq+vvA5kaW5EIeIEPg==
dependencies:
"@nivo/colors" "0.59.0"
"@nivo/core" "0.59.1"
"@nivo/legends" "0.59.1"
"@nivo/tooltip" "0.59.1"
d3-shape "^1.3.5"
lodash "^4.17.11"
react-motion "^0.5.2"
recompose "^0.30.0"

"@nivo/tooltip@0.59.1":
version "0.59.1"
resolved "https://registry.yarnpkg.com/@nivo/tooltip/-/tooltip-0.59.1.tgz#82e981d6af397b1f18a8a2906c8fd60da0234881"
Expand Down

0 comments on commit cb3d5a7

Please sign in to comment.