diff --git a/src/components/metadataFormControls/CategoryComboSelect/CategoryComboSelect.tsx b/src/components/metadataFormControls/CategoryComboSelect/CategoryComboSelect.tsx index 45d6b5b1..4207a08d 100644 --- a/src/components/metadataFormControls/CategoryComboSelect/CategoryComboSelect.tsx +++ b/src/components/metadataFormControls/CategoryComboSelect/CategoryComboSelect.tsx @@ -1,52 +1,43 @@ -import React, { useCallback } from 'react' -import { DEFAULT_CATEGORY_COMBO } from '../../../lib' -import { PlainResourceQuery } from '../../../types' -import { CategoryCombo } from '../../../types/generated' -import { DisplayableModel } from '../../../types/models' -import { - ModelSingleSelect, - ModelSingleSelectProps, -} from '../ModelSingleSelect/ModelSingleSelect' +import i18n from '@dhis2/d2-i18n' +import React, { forwardRef } from 'react' +import { ModelSingleSelectLegacy } from '../ModelSingleSelect' +import type { ModelSingleSelectLegacyProps } from '../ModelSingleSelect' +import { useInitialOptionQuery } from './useInitialOptionQuery' +import { useOptionsQuery } from './useOptionsQuery' -export const categoryCombosSelectQuery = { - resource: 'categoryCombos', - params: { - filter: 'isDefault:eq:false', - fields: ['id', 'displayName'], - }, -} as const satisfies PlainResourceQuery - -type CategoryComboSelectProps = Omit< - ModelSingleSelectProps, - 'query' -> & { - query?: PlainResourceQuery -} - -export const CategoryComboSelect = < - TCategoryCombo extends Partial & DisplayableModel = Pick< - CategoryCombo, - 'id' | 'displayName' - > ->({ - query, - ...modelSingleSelectProps -}: CategoryComboSelectProps) => { - const resolvedQuery = query ?? categoryCombosSelectQuery - // add defaultCatcombo (None) to the list of categoryCombos - const transform = useCallback( - (value: TCategoryCombo[]) => [ - DEFAULT_CATEGORY_COMBO as TCategoryCombo, - ...value, - ], - [] - ) +type CategoryComboSelectProps = Omit< + ModelSingleSelectLegacyProps, + 'useInitialOptionQuery' | 'useOptionsQuery' +> +export const CategoryComboSelect = forwardRef(function CategoryComboSelect( + { + onChange, + invalid, + disabled, + placeholder = i18n.t('Category combo'), + required, + selected, + showAllOption, + onBlur, + onFocus, + }: CategoryComboSelectProps, + ref +) { return ( - - query={resolvedQuery} - transform={transform} - {...modelSingleSelectProps} + ) -} +}) diff --git a/src/pages/dataElements/fields/CategoryComboField.tsx b/src/pages/dataElements/fields/CategoryComboField.tsx index 29332125..aa785bb8 100644 --- a/src/pages/dataElements/fields/CategoryComboField.tsx +++ b/src/pages/dataElements/fields/CategoryComboField.tsx @@ -1,30 +1,18 @@ import i18n from '@dhis2/d2-i18n' import { Field } from '@dhis2/ui' -import React, { useEffect } from 'react' -import { useField, useForm } from 'react-final-form' +import React, { useEffect, useRef } from 'react' +import { useField, useForm, useFormState } from 'react-final-form' import { useHref } from 'react-router' import { CategoryComboSelect, EditableFieldWrapper } from '../../../components' -import { - ModelSingleSelectFieldProps -} from '../../../components/metadataFormControls/ModelSingleSelect/ModelSingleSelectField' -import { useRefreshModelSingleSelect } from '../../../components/metadataFormControls/ModelSingleSelect/useRefreshSingleSelect' -import { DEFAULT_CATEGORY_COMBO } from '../../../lib' -import { PlainResourceQuery } from '../../../types' +import { useDefaultCategoryComboQuery } from '../../../lib' import classes from './CategoryComboField.module.css' -import { DisplayableModel } from '../../../types/models' -const query = { - resource: 'categoryCombos', - params: { - filter: ['isDefault:eq:false'], - fields: ['id', 'displayName'], - }, -} as const satisfies PlainResourceQuery +const required = (value: { id: string }) => { + if (!value.id) { + return i18n.t('Required') + } +} -// stable reference for transform function -const withDefaultCategoryCombo: ModelSingleSelectFieldProps['transform'] = ( - value -) => [DEFAULT_CATEGORY_COMBO, ...value] /* * @TODO: Verify that the api ignores the category combo when it's disabled. * If it does not, file a jira issue and "escalate" this so it will be @@ -35,32 +23,41 @@ const withDefaultCategoryCombo: ModelSingleSelectFieldProps['transform'] = ( * domainType is Tracker */ export function CategoryComboField() { - const refresh = useRefreshModelSingleSelect(query) + const defaultCategoryComboQuery = useDefaultCategoryComboQuery() const { change } = useForm() - const { - input: { value: domainTypeValue }, - } = useField('domainType') - const { input, meta } = useField('categoryCombo', { validateFields: [] }) - const domainTypeIsTracker = domainTypeValue === 'TRACKER' + const { values } = useFormState({ subscription: { values: true } }) + const domainTypeIsTracker = values.domainType === 'TRACKER' const disabled = domainTypeIsTracker + const validate = disabled ? undefined : required const newCategoryComboLink = useHref('/categoryCombos/new') + const { input, meta } = useField('categoryCombo', { + validateFields: [], + validate, + format: (categoryCombo) => categoryCombo.id, + parse: (id) => ({ id }), + }) + const categoryComboHandle = useRef({ + refetch: () => { + throw new Error('Not initialized') + }, + }) useEffect(() => { - if (domainTypeIsTracker) { - change('categoryCombo', DEFAULT_CATEGORY_COMBO) + if (defaultCategoryComboQuery.data?.id && domainTypeIsTracker) { + change('categoryCombo.id', defaultCategoryComboQuery.data.id) } - }, [change, domainTypeIsTracker]) + }, [change, defaultCategoryComboQuery.data?.id, domainTypeIsTracker]) return ( refresh()} + onRefresh={() => categoryComboHandle.current.refetch()} onAddNew={() => window.open(newCategoryComboLink, '_blank')} >
{ + invalid={meta.touched && !!meta.error} + ref={categoryComboHandle} + selected={input.value} + onChange={({ selected }) => { input.onChange(selected) input.onBlur() }} onBlur={input.onBlur} onFocus={input.onFocus} - query={{ - resource: 'categoryCombos', - params: { - filter: [ - 'isDefault:eq:false', - 'dataDimensionType:eq:DISAGGREGATION', - ], - }, - }} />