Skip to content

Commit

Permalink
fix: use partialLoadedDisplayAbleModel type
Browse files Browse the repository at this point in the history
  • Loading branch information
Birkbjo committed Dec 11, 2024
1 parent 43f3e19 commit 865cae3
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import i18n from '@dhis2/d2-i18n'
import React, { useCallback, useMemo } from 'react'
import { DisplayableModel } from '../../../types/models'
import { DisplayableModel, PartialLoadedDisplayableModel } from '../../../types/models'
import {
SearchableSingleSelect,
SearchableSingleSelectPropTypes,
} from '../../SearchableSingleSelect'


const toDisplayOption = (model: DisplayableModel) => ({
const toDisplayOption = (model: PartialLoadedDisplayableModel) => ({
value: model.id,
label: model.displayName || i18n.t('Loading...'),
})
Expand All @@ -19,14 +19,14 @@ type OwnProps<TModel> = {
noValueOption?: { value: string; label: string } | boolean
}

export type BaseModelSingleSelectProps<TModel extends DisplayableModel = DisplayableModel> = Omit<
export type BaseModelSingleSelectProps<TModel extends PartialLoadedDisplayableModel = PartialLoadedDisplayableModel> = Omit<
SearchableSingleSelectPropTypes,
keyof OwnProps<TModel> | 'options' | 'selected'
> &
OwnProps<TModel>

/* Simple wrapper component handle generic models with SingleSelect-component. */
export const BaseModelSingleSelect = <TModel extends DisplayableModel>({
export const BaseModelSingleSelect = <TModel extends PartialLoadedDisplayableModel>({
available,
selected,
onChange,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React, { useMemo, useState } from 'react'
import { useInfiniteQuery } from 'react-query'
import React, { useEffect, useMemo, useState } from 'react'
import { useInfiniteQuery, useQuery } from 'react-query'
import { useDebouncedCallback } from 'use-debounce'
import { useBoundResourceQueryFn } from '../../../lib/query/useBoundQueryFn'
import { PlainResourceQuery } from '../../../types'
import { PagedResponse } from '../../../types/generated'
import { DisplayableModel } from '../../../types/models'
import {
PartialLoadedDisplayableModel
} from '../../../types/models'
import {
BaseModelSingleSelect,
BaseModelSingleSelectProps,
Expand All @@ -20,7 +22,9 @@ const defaultQuery = {
},
} satisfies Omit<PlainResourceQuery, 'resource'>

export type ModelSingleSelectProps<TModel extends DisplayableModel = DisplayableModel> = Omit<
export type ModelSingleSelectProps<
TModel extends PartialLoadedDisplayableModel = PartialLoadedDisplayableModel
> = Omit<
BaseModelSingleSelectProps<TModel>,
| 'available'
| 'onFilterChange'
Expand All @@ -35,14 +39,17 @@ export type ModelSingleSelectProps<TModel extends DisplayableModel = Displayable
transform?: (value: TModel[]) => TModel[]
}

export const ModelSingleSelect = <TModel extends DisplayableModel>({
export const ModelSingleSelect = <
TModel extends PartialLoadedDisplayableModel
>({
selected,
query,
transform,
...baseModelSingleSelectProps
}: ModelSingleSelectProps<TModel>) => {
const queryFn = useBoundResourceQueryFn()
const [searchTerm, setSearchTerm] = useState('')
const onChange = baseModelSingleSelectProps.onChange

const searchFilter = `identifiable:token:${searchTerm}`
const filter: string[] = searchTerm ? [searchFilter] : []
Expand All @@ -68,6 +75,23 @@ export const ModelSingleSelect = <TModel extends DisplayableModel>({
firstPage.pager.prevPage ? firstPage.pager.page - 1 : undefined,
})

const shouldFetchSelected = selected && selected.displayName === undefined
// if we just have the ID - fetch the displayName
const selectedQuery = useQuery({
queryKey: [
{
resource: query.resource,
id: selected?.id,
params: {
fields: queryObject.params.fields,
order: queryObject.params.order,
},
},
],
queryFn: queryFn<TModel>,
enabled: shouldFetchSelected,
})

const allDataMap = useMemo(() => {
const flatData =
queryResult.data?.pages.flatMap((page) => page[modelName]) ?? []
Expand All @@ -78,6 +102,15 @@ export const ModelSingleSelect = <TModel extends DisplayableModel>({
return transform ? transform(allDataMap) : allDataMap
}, [allDataMap, transform])

useEffect(() => {
if (!selectedQuery.data || selected?.displayName !== undefined) {
return
}
// if we had to fetch the selected model, call the onChange
// to update store with the full model
onChange?.(selectedQuery.data)
}, [selectedQuery.data, selected, onChange])

const handleFilterChange = useDebouncedCallback(({ value }) => {
if (value != undefined) {
setSearchTerm(value)
Expand Down
5 changes: 5 additions & 0 deletions src/types/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ export type DisplayableModel = {
id: string
displayName: string
}

export type PartialLoadedDisplayableModel = {
id: string
displayName?: string
}

0 comments on commit 865cae3

Please sign in to comment.