From 712e0619bdc9bf0d3f6fc3f74a497f657cdaa8f1 Mon Sep 17 00:00:00 2001 From: John Lee <124739504+jlee-enquizit@users.noreply.github.com> Date: Fri, 6 Sep 2024 13:40:08 -0500 Subject: [PATCH] Data Elements Table rows (#1776) --- .../DataElementsConfiguration.tsx | 48 +++--- .../DataElementsTable.tsx | 158 ++++++++++++++++++ .../data-elements-table.module.scss | 29 ++++ .../src/apps/dedup-config/const/init.ts | 106 +++++++++--- .../context/DataElementsContext.tsx | 108 +++++++++--- .../src/design-system/checkbox/Checkbox.tsx | 2 +- 6 files changed, 392 insertions(+), 59 deletions(-) create mode 100644 apps/modernization-ui/src/apps/dedup-config/DataElementsConfiguration/DataElementsTable.tsx create mode 100644 apps/modernization-ui/src/apps/dedup-config/DataElementsConfiguration/data-elements-table.module.scss diff --git a/apps/modernization-ui/src/apps/dedup-config/DataElementsConfiguration/DataElementsConfiguration.tsx b/apps/modernization-ui/src/apps/dedup-config/DataElementsConfiguration/DataElementsConfiguration.tsx index 9224072ea3..76a03ee8a6 100644 --- a/apps/modernization-ui/src/apps/dedup-config/DataElementsConfiguration/DataElementsConfiguration.tsx +++ b/apps/modernization-ui/src/apps/dedup-config/DataElementsConfiguration/DataElementsConfiguration.tsx @@ -3,11 +3,17 @@ import { useDataElementsContext } from '../context/DataElementsContext'; import { useDedupeContext } from '../context/DedupeContext'; import styles from './data-elements-configuration.module.scss'; import { Input } from 'components/FormInputs/Input'; +import { DataElementsTable } from './DataElementsTable'; +import { useForm, FormProvider } from 'react-hook-form'; const DataElementsConfiguration = () => { const { dataElements } = useDataElementsContext(); const { setMode } = useDedupeContext(); - console.log(dataElements); + const form = useForm({ + mode: 'onBlur', + defaultValues: { dataElements } + }); + return (
@@ -17,27 +23,31 @@ const DataElementsConfiguration = () => {
-
-
-

Global settings

-
-
- -
-
-
-
+ +
-

Data elements

+

Global settings

+
+
+ +
+
+
+
+
+

Data elements

+
+
+ +
-
Table data
-
+

How to

diff --git a/apps/modernization-ui/src/apps/dedup-config/DataElementsConfiguration/DataElementsTable.tsx b/apps/modernization-ui/src/apps/dedup-config/DataElementsConfiguration/DataElementsTable.tsx new file mode 100644 index 0000000000..5135961e00 --- /dev/null +++ b/apps/modernization-ui/src/apps/dedup-config/DataElementsConfiguration/DataElementsTable.tsx @@ -0,0 +1,158 @@ +import React, { useEffect, useState } from 'react'; +import { useFormContext, Controller, useWatch } from 'react-hook-form'; +import { DataElement } from '../const/init'; +import { DataTable, Column } from 'design-system/table'; +import { Checkbox } from '@trussworks/react-uswds'; +import { Input } from 'components/FormInputs/Input'; +import { useDataElementsContext } from '../context/DataElementsContext'; + +const columns = ( + control: any, + handleRowCheckboxChange: (index: number, checked: boolean) => void, + checkedState: boolean[], + watchedDataElements: DataElement[] +): Column[] => [ + { + id: 'active', + name: 'Active', + render: (dataElement, index) => ( + ( + { + handleRowCheckboxChange(index, e.target.checked); + onChange(e.target.checked); + }} + /> + )} + /> + ) + }, + { + id: 'name', + name: 'Name', + render: (dataElement) => dataElement.name + }, + { + id: 'm', + name: 'M', + render: (dataElement, index) => ( + ( + + )} + /> + ) + }, + { + id: 'u', + name: 'U', + render: (dataElement, index) => ( + ( + + )} + /> + ) + }, + { + id: 'oddsRatio', + name: 'Odds ratio', + render: (dataElement, index) => { + const m = watchedDataElements[index]?.m; + const u = watchedDataElements[index]?.u; + const oddsRatio = m && u && u !== 0 ? (m / u).toFixed(2) : 'No Data'; + return oddsRatio; + } + }, + { + id: 'logOdds', + name: 'Log odds', + render: (dataElement, index) => { + const m = watchedDataElements[index]?.m; + const u = watchedDataElements[index]?.u; + const logOdds = m && u && u !== 0 && m !== 0 ? Math.log(m / u).toFixed(2) : 'No Data'; + return logOdds; + } + }, + { + id: 'threshold', + name: 'Threshold', + render: (dataElement, index) => ( + ( + + )} + /> + ) + } +]; + +const DataElementsTable = () => { + const { control, setValue } = useFormContext<{ dataElements: DataElement[] }>(); + const { dataElements } = useDataElementsContext(); + const [checkedState, setCheckedState] = useState([]); + + const watchedDataElements = useWatch({ + control, + name: 'dataElements', + defaultValue: dataElements + }); + + useEffect(() => { + setValue('dataElements', dataElements); + setCheckedState(dataElements.map((de) => de.active)); + }, [dataElements, setValue]); + + const handleRowCheckboxChange = (index: number, checked: boolean) => { + const updatedCheckedState = [...checkedState]; + updatedCheckedState[index] = checked; + setCheckedState(updatedCheckedState); + }; + + return ( + + id="dataElementsTable" + columns={columns(control, handleRowCheckboxChange, checkedState, watchedDataElements)} + data={dataElements} + /> + ); +}; + +export { DataElementsTable }; diff --git a/apps/modernization-ui/src/apps/dedup-config/DataElementsConfiguration/data-elements-table.module.scss b/apps/modernization-ui/src/apps/dedup-config/DataElementsConfiguration/data-elements-table.module.scss new file mode 100644 index 0000000000..560f9ade10 --- /dev/null +++ b/apps/modernization-ui/src/apps/dedup-config/DataElementsConfiguration/data-elements-table.module.scss @@ -0,0 +1,29 @@ +@use 'styles/colors'; + +.table { + width: 100%; + tbody tr:nth-child(odd) { + background-color: colors.$base-lightest; + } + th { + label::before { + margin-top: -0.5rem; + content: ''; + display: inline-block; + width: 1rem; + height: 1rem; + margin-right: 0.5rem; + } + } + td { + height: 3rem; + label::before { + margin-top: -0.75rem; + content: ''; + display: inline-block; + width: 1rem; + height: 1rem; + margin-right: 0.5rem; + } + } +} \ No newline at end of file diff --git a/apps/modernization-ui/src/apps/dedup-config/const/init.ts b/apps/modernization-ui/src/apps/dedup-config/const/init.ts index d16cb88f95..202ed63b7d 100644 --- a/apps/modernization-ui/src/apps/dedup-config/const/init.ts +++ b/apps/modernization-ui/src/apps/dedup-config/const/init.ts @@ -1,19 +1,87 @@ -export const DataElements = { - "lastName": "", - "secondLastName": "", - "firstName": "", - "middleName": "", - "secondMiddleName": "", - "suffix": "", - "currentSex": "", - "dateOfBirth": "", - "ssn": "", - "idType": "", - "idAssigningAuthority": "", - "idValue": "", - "streetAddress1": "", - "city": "", - "state": "", - "zipCode": "", - "telephone": "" - }; \ No newline at end of file +export type DataElement = { + name: string; + active: boolean; + m: number; + u: number; + threshold: number; +}; + +export const DataElements: DataElement[] = [ + { name: "lastName", active: true, m: 0.5, u: 0.5, threshold: 0.5 }, + { name: "secondLastName", active: true, m: 0.5, u: 0.5, threshold: 0.5 }, + { name: "firstName", active: true, m: 0.5, u: 0.5, threshold: 0.5 }, + { name: "middleName", active: true, m: 0.5, u: 0.5, threshold: 0.5 }, + { name: "secondMiddleName", active: true, m: 0.5, u: 0.5, threshold: 0.5 }, + { name: "suffix", active: true, m: 0.5, u: 0.5, threshold: 0.5 }, + { name: "currentSex", active: true, m: 0.5, u: 0.5, threshold: 0.5 }, + { + name: "dateOfBirth", + active: true, + m: 0.5, + u: 0.5, + threshold: 0.5, + }, + { + name: "ssn", + active: true, + m: 0.5, + u: 0.5, + threshold: 0.5, + }, + { + name: "idType", + active: true, + m: 0.5, + u: 0.25, + threshold: 0.5, + }, + { + name: "idAssigningAuthority", + active: true, + m: 0.5, + u: 0.25, + threshold: 0.5, + }, + { + name: "idValue", + active: true, + m: 0.5, + u: 0.25, + threshold: 0.5, + }, + { + name: "streetAddress1", + active: true, + m: 0.5, + u: 0.25, + threshold: 0.5, + }, + { + name: "city", + active: true, + m: 0.5, + u: 0.25, + threshold: 0.5, + }, + { + name: "state", + active: true, + m: 0.5, + u: 0.25, + threshold: 0.5, + }, + { + name: "zip", + active: true, + m: 0.5, + u: 0.25, + threshold: 0.5, + }, + { + name: "telephone", + active: true, + m: 0.5, + u: 0.1, + threshold: 0.5, + } +]; diff --git a/apps/modernization-ui/src/apps/dedup-config/context/DataElementsContext.tsx b/apps/modernization-ui/src/apps/dedup-config/context/DataElementsContext.tsx index 347cccf87d..c8635d679b 100644 --- a/apps/modernization-ui/src/apps/dedup-config/context/DataElementsContext.tsx +++ b/apps/modernization-ui/src/apps/dedup-config/context/DataElementsContext.tsx @@ -3,30 +3,98 @@ import React, { createContext, useContext, useState } from 'react'; const DataElementsContext = createContext(undefined); type DataElementsContextProps = { - dataElements: typeof DataElements | null; - setDataElements: (dataElements: typeof DataElements) => void; + dataElements: DataElement[]; + setDataElements: (dataElements: DataElement[]) => void; }; -const DataElements = { - lastName: '', - secondLastName: '', - firstName: '', - middleName: '', - secondMiddleName: '', - suffix: '', - currentSex: '', - dateOfBirth: '', - ssn: '', - idType: '', - idAssigningAuthority: '', - idValue: '', - streetAddress1: '', - city: '', - state: '', - zipCode: '', - telephone: '' +export type DataElement = { + name: string; + active: boolean; + m: number; + u: number; + threshold: number; }; +export const DataElements: DataElement[] = [ + { name: 'lastName', active: false, m: 0.5, u: 0.5, threshold: 0.5 }, + { name: 'secondLastName', active: true, m: 0.5, u: 0.5, threshold: 0.5 }, + { name: 'firstName', active: true, m: 0.5, u: 0.5, threshold: 0.5 }, + { name: 'middleName', active: true, m: 0.5, u: 0.5, threshold: 0.5 }, + { name: 'secondMiddleName', active: true, m: 0.5, u: 0.5, threshold: 0.5 }, + { name: 'suffix', active: true, m: 0.5, u: 0.5, threshold: 0.5 }, + { name: 'currentSex', active: true, m: 0.5, u: 0.5, threshold: 0.5 }, + { + name: 'dateOfBirth', + active: true, + m: 0.5, + u: 0.5, + threshold: 0.5 + }, + { + name: 'ssn', + active: true, + m: 0.5, + u: 0.5, + threshold: 0.5 + }, + { + name: 'idType', + active: true, + m: 0.5, + u: 0.25, + threshold: 0.5 + }, + { + name: 'idAssigningAuthority', + active: true, + m: 0.5, + u: 0.25, + threshold: 0.5 + }, + { + name: 'idValue', + active: true, + m: 0.5, + u: 0.25, + threshold: 0.5 + }, + { + name: 'streetAddress1', + active: true, + m: 0.5, + u: 0.25, + threshold: 0.5 + }, + { + name: 'city', + active: true, + m: 0.5, + u: 0.25, + threshold: 0.5 + }, + { + name: 'state', + active: true, + m: 0.5, + u: 0.25, + threshold: 0.5 + }, + { + name: 'zip', + active: true, + m: 0.5, + u: 0.25, + threshold: 0.5 + }, + { + name: 'telephone', + active: true, + m: 0.5, + u: 0.1, + threshold: 0.5 + } +]; + const DataElementsContextProvider: React.FC<{ children: React.ReactNode; }> = ({ children }) => { diff --git a/apps/modernization-ui/src/design-system/checkbox/Checkbox.tsx b/apps/modernization-ui/src/design-system/checkbox/Checkbox.tsx index 6e6278b801..9b0229b0be 100644 --- a/apps/modernization-ui/src/design-system/checkbox/Checkbox.tsx +++ b/apps/modernization-ui/src/design-system/checkbox/Checkbox.tsx @@ -2,7 +2,7 @@ import classNames from 'classnames'; import styles from './checkbox.module.scss'; type Props = Omit & { - label: string; + label?: string; selected?: boolean; onChange?: (checked: boolean) => void; };