diff --git a/publisher/src/components/Forms/BinaryRadioButton.tsx b/publisher/src/components/Forms/BinaryRadioButton.tsx index 95519810d..7afd8145c 100644 --- a/publisher/src/components/Forms/BinaryRadioButton.tsx +++ b/publisher/src/components/Forms/BinaryRadioButton.tsx @@ -20,7 +20,7 @@ import { typography, } from "@justice-counts/common/components/GlobalStyles"; import React, { InputHTMLAttributes } from "react"; -import styled from "styled-components/macro"; +import styled, { css } from "styled-components/macro"; export const BinaryRadioGroupContainer = styled.div` display: flex; @@ -43,7 +43,7 @@ export const BinaryRadioGroupQuestion = styled.div` color: ${palette.solid.darkgrey}; `; -export const RadioButtonWrapper = styled.div` +export const RadioButtonWrapper = styled.div<{ lastOptionBlue?: boolean }>` display: flex; flex: 1 1 0; margin: 15px 0 0 0; @@ -51,6 +51,22 @@ export const RadioButtonWrapper = styled.div` &:first-child { margin: 15px 10px 0 0; } + + ${({ lastOptionBlue }) => + lastOptionBlue && + css` + margin: 0; + + &:first-child { + margin: 0px 10px 0 0; + } + + &:first-child input:checked + label { + background-color: ${palette.highlight.grey9}; + border-color: unset; + color: ${palette.solid.white}; + } + `} `; export const RadioButtonElement = styled.input<{ @@ -83,6 +99,7 @@ export const RadioButtonElement = styled.input<{ export const RadioButtonLabel = styled.label<{ disabled?: boolean; + buttonSize?: string; }>` ${typography.sizeCSS.medium} width: 100%; @@ -100,6 +117,16 @@ export const RadioButtonLabel = styled.label<{ background-color: ${({ disabled }) => disabled ? "none" : palette.highlight.grey2}; } + + ${({ buttonSize }) => + buttonSize === "small" && + css` + ${typography.sizeCSS.normal} + width: unset; + height: unset; + min-width: 60px; + padding: 9px 16px; + `} `; export const BinaryRadioGroupClearButton = styled.div<{ @@ -119,6 +146,8 @@ interface RadioButtonProps extends InputHTMLAttributes { label: string; context?: string; metricKey?: string; + buttonSize?: string; + lastOptionBlue?: boolean; } /** Single radio button in the style of a regular button */ @@ -127,16 +156,22 @@ export const BinaryRadioButton: React.FC = ({ context, metricKey, disabled, + buttonSize, + lastOptionBlue, ...props }): JSX.Element => { return ( - + - + {label} diff --git a/publisher/src/components/MetricConfiguration/RaceEthnicitiesForm.tsx b/publisher/src/components/MetricConfiguration/RaceEthnicitiesForm.tsx index d906e34b0..91096230d 100644 --- a/publisher/src/components/MetricConfiguration/RaceEthnicitiesForm.tsx +++ b/publisher/src/components/MetricConfiguration/RaceEthnicitiesForm.tsx @@ -15,8 +15,9 @@ // along with this program. If not, see . // ============================================================================= +import { debounce } from "lodash"; import { observer } from "mobx-react-lite"; -import React from "react"; +import React, { useRef } from "react"; import { useStore } from "../../stores"; import { BinaryRadioButton } from "../Forms"; @@ -31,7 +32,6 @@ import { RaceEthnicitiesTitle, raceEthnicityGridStates, RaceSelection, - RaceSelectionButton, RadioButtonGroupWrapper, SpecifyEthnicityWrapper, Subheader, @@ -79,6 +79,8 @@ export const RaceEthnicitiesForm = observer(() => { const currentState = determineCurrentState(); + const debouncedSave = useRef(debounce(saveMetricSettings, 1000)).current; + return ( @@ -112,7 +114,7 @@ export const RaceEthnicitiesForm = observer(() => { "CAN_SPECIFY_ETHNICITY", raceEthnicityGridStates ); - saveMetricSettings(updatedDimensions); + debouncedSave(updatedDimensions); }} /> { "NO_ETHNICITY_HISPANIC_AS_RACE", raceEthnicityGridStates ); - saveMetricSettings(updatedDimensions); + debouncedSave(updatedDimensions); }} /> @@ -148,32 +150,44 @@ export const RaceEthnicitiesForm = observer(() => { Hispanic/Latino - { - const updatedDimensions = - updateAllRaceEthnicitiesToDefaultState( - "NO_ETHNICITY_HISPANIC_NOT_SPECIFIED", - raceEthnicityGridStates - ); - saveMetricSettings(updatedDimensions); - }} - > - No - - { - const updatedDimensions = - updateAllRaceEthnicitiesToDefaultState( - "NO_ETHNICITY_HISPANIC_AS_RACE", - raceEthnicityGridStates - ); - saveMetricSettings(updatedDimensions); - }} - > - Yes - + + { + const updatedDimensions = + updateAllRaceEthnicitiesToDefaultState( + "NO_ETHNICITY_HISPANIC_NOT_SPECIFIED", + raceEthnicityGridStates + ); + debouncedSave(updatedDimensions); + }} + /> + { + const updatedDimensions = + updateAllRaceEthnicitiesToDefaultState( + "NO_ETHNICITY_HISPANIC_AS_RACE", + raceEthnicityGridStates + ); + debouncedSave(updatedDimensions); + }} + /> + )} @@ -188,62 +202,62 @@ export const RaceEthnicitiesForm = observer(() => { {race} - { - let switchedGridStateUpdatedDimensions; - /** - * When Unknown Race is disabled in NO_ETHNICITY_HISPANIC_AS_RACE state, we automatically switch - * to the NO_ETHNICITY_HISPANIC_NOT_SPECIFIED state because the Unknown Race (Hispanic/Latino Ethnicity) - * dimension is the only dimension an agency can specify their numbers for Hispanic/Latino as a Race (while - * in the NO_ETHNICITY_HISPANIC_AS_RACE state). - */ - if ( - race === "Unknown" && - currentState === "NO_ETHNICITY_HISPANIC_AS_RACE" - ) { - switchedGridStateUpdatedDimensions = + + { + /** + * When Unknown Race is disabled in NO_ETHNICITY_HISPANIC_AS_RACE state, we automatically switch + * to the NO_ETHNICITY_HISPANIC_NOT_SPECIFIED state because the Unknown Race (Hispanic/Latino Ethnicity) + * dimension is the only dimension an agency can specify their numbers for Hispanic/Latino as a Race (while + * in the NO_ETHNICITY_HISPANIC_AS_RACE state). + */ + if ( + race === "Unknown" && + currentState === "NO_ETHNICITY_HISPANIC_AS_RACE" + ) { updateAllRaceEthnicitiesToDefaultState( "NO_ETHNICITY_HISPANIC_NOT_SPECIFIED", raceEthnicityGridStates ); - } - - const updatedDimensions = updateRaceDimensions( - race, - false, - currentState, - raceEthnicityGridStates - ); - - if (switchedGridStateUpdatedDimensions) { - /** Add the updated dimension from disabling the Unknown race to the switchedGridStateUpdatedDimensions */ - switchedGridStateUpdatedDimensions.disaggregations[0].dimensions.push( - ...updatedDimensions.disaggregations[0].dimensions + } + + const updatedDimensions = updateRaceDimensions( + race, + false, + currentState, + raceEthnicityGridStates ); - return saveMetricSettings( - switchedGridStateUpdatedDimensions + debouncedSave(updatedDimensions); + }} + /> + { + const updatedDimensions = updateRaceDimensions( + race, + true, + currentState, + raceEthnicityGridStates ); - } - saveMetricSettings(updatedDimensions); - }} - > - No - - { - const updatedDimensions = updateRaceDimensions( - race, - true, - currentState, - raceEthnicityGridStates - ); - saveMetricSettings(updatedDimensions); - }} - > - Yes - + debouncedSave(updatedDimensions); + }} + /> + ); diff --git a/publisher/src/stores/MetricConfigStore.tsx b/publisher/src/stores/MetricConfigStore.tsx index 9c9be7422..d32cd8bf8 100644 --- a/publisher/src/stores/MetricConfigStore.tsx +++ b/publisher/src/stores/MetricConfigStore.tsx @@ -701,7 +701,6 @@ class MetricConfigStore { ...acc[dimension.race], [dimension.ethnicity]: dimension, }; - return acc; }, {} as { @@ -729,7 +728,6 @@ class MetricConfigStore { state === "NO_ETHNICITY_HISPANIC_AS_RACE" && unknownRaceDisabled ? "NO_ETHNICITY_HISPANIC_NOT_SPECIFIED" : state; - const updatedDimensions = [] as UpdatedDimension[]; /** * When Unknown Race dimensions are disabled AND user is switching to NO_ETHNICITY_HISPANIC_AS_RACE state, @@ -738,18 +736,6 @@ class MetricConfigStore { if (unknownRaceDisabled && state === "NO_ETHNICITY_HISPANIC_AS_RACE") { this.ethnicitiesByRace.Unknown.Hispanic.enabled = true; this.ethnicitiesByRace.Unknown["Not Hispanic"].enabled = true; - updatedDimensions.push( - ...[ - { - ...this.ethnicitiesByRace.Unknown.Hispanic, - enabled: true, - }, - { - ...this.ethnicitiesByRace.Unknown["Not Hispanic"], - enabled: true, - }, - ] - ); sanitizedState = state; } @@ -781,21 +767,22 @@ class MetricConfigStore { this.ethnicitiesByRace[race][ethnicity].key, gridStates[sanitizedState][race][ethnicity] ); - - updatedDimensions.push({ - ...this.ethnicitiesByRace[race][ethnicity], - enabled: gridStates[sanitizedState][race][ethnicity], - }); }); }); - /** Return array of dimensions that were updated */ + const raceEthnicitiesDimensions = + this.dimensions[systemMetricKey][RACE_ETHNICITY_DISAGGREGATION_KEY]; + const dimensions = + raceEthnicitiesDimensions && + (Object.values(raceEthnicitiesDimensions) as UpdatedDimension[]); + + /** Return an object w/ all dimensions in the desired backend data structure for saving purposes */ return { key: this.activeMetricKey as string, disaggregations: [ { key: RACE_ETHNICITY_DISAGGREGATION_KEY, - dimensions: updatedDimensions, + dimensions, }, ], }; @@ -807,8 +794,6 @@ class MetricConfigStore { state: StateKeys, gridStates: RaceEthnicitiesGridStates ): UpdatedDisaggregation => { - const updatedDimensions = [] as UpdatedDimension[]; - ethnicities.forEach((ethnicity) => { /** No update if intended update matches the current state (e.g. enabling an already enabled dimension) */ if (this.ethnicitiesByRace[race][ethnicity].enabled === enabled) return; @@ -827,17 +812,25 @@ class MetricConfigStore { this.ethnicitiesByRace[race][ethnicity].key, enabled ); - - updatedDimensions.push(this.ethnicitiesByRace[race][ethnicity]); }); - /** Return array of dimensions that were updated */ + const systemMetricKey = MetricConfigStore.getSystemMetricKey( + this.activeSystem as string, + this.activeMetricKey as string + ); + const raceEthnicitiesDimensions = + this.dimensions[systemMetricKey][RACE_ETHNICITY_DISAGGREGATION_KEY]; + const dimensions = + raceEthnicitiesDimensions && + (Object.values(raceEthnicitiesDimensions) as UpdatedDimension[]); + + /** Return an object w/ all dimensions in the desired backend data structure for saving purposes */ return { key: this.activeMetricKey as string, disaggregations: [ { key: RACE_ETHNICITY_DISAGGREGATION_KEY, - dimensions: updatedDimensions, + dimensions, }, ], };