Skip to content

Commit

Permalink
feat: implement project type header in phase tab
Browse files Browse the repository at this point in the history
  • Loading branch information
stdavis committed Jun 15, 2022
1 parent 9e26709 commit 999fd2e
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 7 deletions.
77 changes: 74 additions & 3 deletions src/components/AdvancedControls.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,44 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import PropTypes from 'prop-types';
import React from 'react';
import { Button, Col, Collapse, Container, Row } from 'reactstrap';
import config from '../services/config';
import Checkbox from './Checkbox';

export default function AdvancedControls({ projectTypes, labelColors, dispatch, selectedProjectTypes, disabled }) {
const numPossibleProjectTypes = {
road: Object.keys(config.projectTypes.road).length,
transit: Object.keys(config.projectTypes.transit).length,
activeTransportation: Object.keys(config.projectTypes.activeTransportation).length,
};

export default function AdvancedControls({
projectTypes,
labelColors,
dispatch,
selectedProjectTypes,
disabled,
showProjectTypeHeaders = false,
}) {
const [isOpen, setIsOpen] = React.useState(true);
const toggle = () => setIsOpen((current) => !current);

const getHeaderChecked = (mode) => {
const selectedTypesForMode = selectedProjectTypes[mode];

if (selectedTypesForMode.length === numPossibleProjectTypes[mode]) {
return true;
} else if (selectedTypesForMode.length === 0) {
return false;
}

return null;
};

const onHeaderClick = (mode) => {
const checked = getHeaderChecked(mode);

dispatch({ type: 'projectTypeHeader', payload: !checked, meta: mode });
};

return (
<>
<div className="d-flex justify-content-center">
Expand All @@ -19,8 +51,18 @@ export default function AdvancedControls({ projectTypes, labelColors, dispatch,
<Collapse isOpen={isOpen}>
<Container fluid className="p-0">
<div>Filter By Project Type:</div>
<Row>
<Row className="mb-2">
<Col>
{showProjectTypeHeaders ? (
<Checkbox
uniqueId="road-header"
label="Road"
disabled={disabled}
checked={getHeaderChecked('road')}
color={labelColors?.road}
onChange={() => onHeaderClick('road')}
/>
) : null}
{Object.keys(projectTypes.road).map((name) => (
<Checkbox
key={name}
Expand All @@ -30,10 +72,21 @@ export default function AdvancedControls({ projectTypes, labelColors, dispatch,
color={labelColors?.road}
onChange={() => dispatch({ type: 'projectType', payload: name, meta: 'road' })}
disabled={disabled}
indent={showProjectTypeHeaders}
/>
))}
</Col>
<Col>
{showProjectTypeHeaders ? (
<Checkbox
uniqueId="transit-header"
label="Transit"
disabled={disabled}
checked={getHeaderChecked('transit')}
color={labelColors?.transit}
onChange={() => onHeaderClick('transit')}
/>
) : null}
{Object.keys(projectTypes.transit).map((name) => (
<Checkbox
key={name}
Expand All @@ -43,11 +96,26 @@ export default function AdvancedControls({ projectTypes, labelColors, dispatch,
color={labelColors?.transit}
onChange={() => dispatch({ type: 'projectType', payload: name, meta: 'transit' })}
disabled={disabled}
indent={showProjectTypeHeaders}
/>
))}
</Col>
</Row>
<Row className="mt-2">
{showProjectTypeHeaders ? (
<Row>
<Col>
<Checkbox
uniqueId="activateTransportation-header"
label="Active Transportation"
disabled={disabled}
checked={getHeaderChecked('activeTransportation')}
color={labelColors?.activeTransportation}
onChange={() => onHeaderClick('activeTransportation')}
/>
</Col>
</Row>
) : null}
<Row>
<Col>
{Object.keys(projectTypes.activeTransportation)
.slice(0, Object.keys(projectTypes.activeTransportation).length / 2)
Expand All @@ -60,6 +128,7 @@ export default function AdvancedControls({ projectTypes, labelColors, dispatch,
color={labelColors?.activeTransportation}
onChange={() => dispatch({ type: 'projectType', payload: name, meta: 'activeTransportation' })}
disabled={disabled}
indent={showProjectTypeHeaders}
/>
))}
</Col>
Expand All @@ -75,6 +144,7 @@ export default function AdvancedControls({ projectTypes, labelColors, dispatch,
color={labelColors?.activeTransportation}
onChange={() => dispatch({ type: 'projectType', payload: name, meta: 'activeTransportation' })}
disabled={disabled}
indent={showProjectTypeHeaders}
/>
))}
</Col>
Expand All @@ -91,4 +161,5 @@ AdvancedControls.propTypes = {
selectedProjectTypes: PropTypes.object.isRequired,
dispatch: PropTypes.func.isRequired,
disabled: PropTypes.bool.isRequired,
showProjectTypeHeaders: PropTypes.bool,
};
24 changes: 20 additions & 4 deletions src/components/Checkbox.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
import clsx from 'clsx';
import PropTypes from 'prop-types';
import { FormGroup, Input, Label } from 'reactstrap';

export default function Checkbox({ label, checked, color, onChange, uniqueId, disabled }) {
export default function Checkbox({ label, checked, color, onChange, uniqueId, disabled, indent = false }) {
const setIndeterminate = (ref) => {
if (ref) {
console.log('checked', checked);
ref.indeterminate = checked === null;
}
};

return (
<FormGroup check inline>
<Input id={uniqueId ?? label} type="checkbox" checked={checked} onChange={onChange} disabled={disabled} />{' '}
<FormGroup check inline className={clsx(indent && 'ms-3')}>
<Input
innerRef={setIndeterminate}
id={uniqueId ?? label}
type="checkbox"
checked={!!checked}
onChange={onChange}
disabled={disabled}
/>{' '}
<Label check for={uniqueId ?? label} style={{ marginBottom: 0, color }}>
{` ${label}`}
</Label>
Expand All @@ -14,9 +29,10 @@ export default function Checkbox({ label, checked, color, onChange, uniqueId, di

Checkbox.propTypes = {
label: PropTypes.string.isRequired,
checked: PropTypes.bool.isRequired,
checked: PropTypes.bool,
color: PropTypes.string,
onChange: PropTypes.func.isRequired,
uniqueId: PropTypes.string,
disabled: PropTypes.bool.isRequired,
indent: PropTypes.bool,
};
13 changes: 13 additions & 0 deletions src/components/Filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,18 @@ function reducer(draft, action) {

break;

case 'projectTypeHeader':
if (action.payload) {
// toggle all sub project types on
draft.projectTypes[action.meta] = Object.keys(config.projectTypes[action.meta]);
} else {
draft.projectTypes[action.meta] = [];
}

updateLayerDefinitions();

break;

default:
throw new Error(`Unhandled action type: ${action.type}`);
}
Expand Down Expand Up @@ -257,6 +269,7 @@ export default function Filter({ mapView }) {
state={state}
dispatch={dispatch}
disabled={!layers}
showProjectTypeHeaders={true}
/>
</TabPane>
</TabContent>
Expand Down

0 comments on commit 999fd2e

Please sign in to comment.