Skip to content

Commit

Permalink
ET-848: Add local storage persistence for select and ICD options (#183)
Browse files Browse the repository at this point in the history
* feat(select, icd-classification): Add local storage persistence for select and ICD options

- Enhance Select component to handle search value when options are selected
- Implement local storage caching for ICD classification options and search value
- Improve user experience by preserving search context across page reloads

* feat(icd-classification): Add question-specific local storage for ICD options

- Modify useICDClassificationList hook to support question-specific local storage
- Update Question component to pass question ID to the hook
- Ensure ICD classification options and search values are stored uniquely per question

* fix(select): Prevent unnecessary dropdown opening after exact label search

- Add condition to close dropdown when search value matches selected option's label
- Improve search behavior for select component when allowSearchAfterSelect is true
  • Loading branch information
mohsinht authored Jan 29, 2025
1 parent ef571e6 commit fb9a618
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 5 deletions.
27 changes: 25 additions & 2 deletions src/atoms/select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import React, {
import classes from './select.module.scss'
import { QuestionLabel } from '../questionLabel'
import { type Option } from './types'
import { isNil, noop } from 'lodash'
import { isEmpty, isNil, noop } from 'lodash'
import { FixedSizeList as List } from 'react-window'

export interface SelectProps
Expand Down Expand Up @@ -147,9 +147,10 @@ export const Select = ({
return value as Array<Option>
}
if (type === 'single') {
return [
const matchingOption = [
options.find((option) => value === option.value) ?? undefined,
].filter((option) => option !== undefined) as Array<Option>
return matchingOption
}
return []
}
Expand Down Expand Up @@ -205,6 +206,15 @@ export const Select = ({
}, [isOpen, handleClickOutside])

useEffect(() => {
if (
!isNil(onSearch) &&
allowSearchAfterSelect &&
searchValue === selected[0]?.label
) {
// no need to open the dropdown in this case as search exactly matches the label of the first selected option
setIsOpen(false)
return
}
if (!isNil(onSearch) && options.length > 0) {
setIsOpen(true)
setFilteredOptions(options)
Expand All @@ -214,6 +224,16 @@ export const Select = ({
}
}, [options])

useEffect(() => {
/*
* When the form is refreshed, we want to set the searchValue to the label of the first selected option
* This is to ensure that the searchValue is set to the label of the first selected option
*/
if (allowSearchAfterSelect && selected.length > 0 && isEmpty(searchValue)) {
setSearchValue(selected[0]?.label ?? '')
}
}, [selected, allowSearchAfterSelect, searchValue])

useEffect(() => {
if (isOpen) {
const container = document.getElementById(
Expand Down Expand Up @@ -301,6 +321,9 @@ export const Select = ({
const getDisplayValue = (): string => {
if (filtering) {
if (allowSearchAfterSelect) {
if (isEmpty(searchValue) && selected.length > 0) {
return selected[0]?.label ?? ''
}
return searchValue ?? ''
} else if (selected.length === 0) {
return searchValue ?? ''
Expand Down
12 changes: 10 additions & 2 deletions src/hooks/useIcdClassificationList/useIcdClassficationList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import { debounce } from 'lodash'

const ICD_10_CLASSIFICATION_ENDPOINT = `https://clinicaltables.nlm.nih.gov/api/icd10cm/v3/search`

export const useICDClassificationList = () => {
const [options, setOptions] = useState<Array<Option>>([])
export const useICDClassificationList = (questionId: string) => {
const [options, setOptions] = useState<Array<Option>>(() => {
const savedOptions = localStorage.getItem(`icdOptions-${questionId}`)
return savedOptions ? JSON.parse(savedOptions) : []
})
const [loading, setLoading] = useState<boolean>(false)
const [error, setError] = useState<string | null>(null)
const [searchValue, setSearchValue] = useState('')
Expand Down Expand Up @@ -35,6 +38,10 @@ export const useICDClassificationList = () => {
)

setOptions(icdOptions)
localStorage.setItem(
`icdOptions-${questionId}`,
JSON.stringify(icdOptions)
)
} catch (err) {
setError('Failed to fetch ICD-10 codes')
} finally {
Expand Down Expand Up @@ -62,6 +69,7 @@ export const useICDClassificationList = () => {

const onIcdClassificationSearchChange = (val: string) => {
setSearchValue(val)
localStorage.setItem(`icdSearchValue-${questionId}`, val)
}

return { options, loading, error, onIcdClassificationSearchChange }
Expand Down
2 changes: 1 addition & 1 deletion src/molecules/question/Question.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const QuestionData = ({
options: icdClassificationOptions,
loading: optionsLoading,
onIcdClassificationSearchChange,
} = useICDClassificationList()
} = useICDClassificationList(question.id)

switch (question.userQuestionType) {
case UserQuestionType.YesNo:
Expand Down

0 comments on commit fb9a618

Please sign in to comment.