Skip to content

Commit d2be962

Browse files
committed
feat: improve CategorySelector and LinkToExisting components
1 parent 58cdcfc commit d2be962

File tree

4 files changed

+60
-53
lines changed

4 files changed

+60
-53
lines changed

i18n/en.pot

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ msgstr ""
55
"Content-Type: text/plain; charset=utf-8\n"
66
"Content-Transfer-Encoding: 8bit\n"
77
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
8-
"POT-Creation-Date: 2025-12-19T18:08:41.230Z\n"
9-
"PO-Revision-Date: 2025-12-19T18:08:41.230Z\n"
8+
"POT-Creation-Date: 2025-12-19T20:04:49.883Z\n"
9+
"PO-Revision-Date: 2025-12-19T20:04:49.883Z\n"
1010

1111
msgid "Choose one or more dates..."
1212
msgstr "Choose one or more dates..."
@@ -1499,8 +1499,8 @@ msgstr "{{trackedEntityTypeName}} profile"
14991499
msgid "Choose a {{linkableStageLabel}} event"
15001500
msgstr "Choose a {{linkableStageLabel}} event"
15011501

1502-
msgid "Choose a {{linkableStageLabel}}"
1503-
msgstr "Choose a {{linkableStageLabel}}"
1502+
msgid "Select an event"
1503+
msgstr "Select an event"
15041504

15051505
msgid "{{ linkableStageLabel }} can only have one event"
15061506
msgstr "{{ linkableStageLabel }} can only have one event"

src/core_modules/capture-core/components/Pagination/rowsPerPage.css

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
padding-left: 7px!important;
1111
}
1212

13-
14-
1513
#rows-per-page-selector .Select-arrow-zone {
1614
font-size: initial;
1715
width: 15px;

src/core_modules/capture-core/components/WidgetEventSchedule/CategoryOptions/CategorySelector.component.tsx

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,13 @@ type Props = {
1414
// eslint-disable-next-line react/no-unused-prop-types
1515
category: { id: string; displayName: string};
1616
selectedOrgUnitId: string | null;
17-
onChange: (option: SelectOption) => void;
17+
onChange: (option: SelectOption | null) => void;
1818
initialValue?: SelectOption | null;
1919
}
2020

2121
type State = {
2222
options: Array<SelectOption> | null;
2323
prevOrgUnitId: string | null;
24-
open: boolean;
2524
selectedOption?: SelectOption | null;
2625
};
2726

@@ -61,6 +60,7 @@ export class CategorySelector extends React.Component<Props, State> {
6160
return {
6261
prevOrgUnitId: props.selectedOrgUnitId,
6362
options: null,
63+
selectedOption: null,
6464
};
6565
}
6666
return null;
@@ -73,15 +73,14 @@ export class CategorySelector extends React.Component<Props, State> {
7373
this.state = {
7474
options: null,
7575
prevOrgUnitId: null,
76-
open: false,
7776
selectedOption: props.initialValue,
7877
};
79-
this.loadCagoryOptions(this.props);
78+
this.loadCategoryOptions(this.props);
8079
}
8180

8281
componentDidUpdate(prevProps: Props) {
8382
if (!this.state.options && prevProps.selectedOrgUnitId !== this.props.selectedOrgUnitId) {
84-
this.loadCagoryOptions(this.props);
83+
this.loadCategoryOptions(this.props);
8584
}
8685
}
8786

@@ -90,7 +89,7 @@ export class CategorySelector extends React.Component<Props, State> {
9089
this.cancelablePromise = null;
9190
}
9291

93-
loadCagoryOptions(props: Props) {
92+
loadCategoryOptions(props: Props) {
9493
const { category, selectedOrgUnitId } = props;
9594

9695
this.setState({
@@ -144,21 +143,31 @@ export class CategorySelector extends React.Component<Props, State> {
144143
this.cancelablePromise = currentRequestCancelablePromise;
145144
}
146145

147-
render() {
146+
onSelectCategory = (value: string | null) => {
148147
const { onChange } = this.props;
149148
const { options } = this.state;
150149

150+
if (value === null) {
151+
this.setState({ selectedOption: null });
152+
onChange(null);
153+
return;
154+
}
155+
156+
const option = options?.find(opt => opt.value === value);
157+
if (option) {
158+
this.setState({ selectedOption: option });
159+
onChange(option);
160+
}
161+
}
162+
163+
render() {
164+
const { options, selectedOption } = this.state;
165+
151166
return (
152167
options ? <NewSingleSelectField
153-
value={this.state.selectedOption?.value ?? null}
168+
value={selectedOption?.value ?? null}
154169
clearable
155-
onChange={(value: string | null) => {
156-
const selectedOption = value != null ? options.find(opt => opt.value === value) : null;
157-
this.setState({ selectedOption });
158-
// Match OptionsSelectVirtualized behavior: always call onChange, even when null
159-
// @ts-expect-error - onChange type doesn't accept null, but OptionsSelectVirtualized called it with null
160-
onChange(selectedOption);
161-
}}
170+
onChange={this.onSelectCategory}
162171
options={options}
163172
/> : null
164173
);

src/core_modules/capture-core/components/WidgetRelatedStages/LinkToExisting/LinkToExisting.component.tsx

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,16 @@ import React, { type ComponentType } from 'react';
22
import i18n from '@dhis2/d2-i18n';
33
import { spacers } from '@dhis2/ui';
44
import { withStyles, type WithStyles } from 'capture-core-utils/styles';
5-
import { NewSingleSelectField } from '../../FormFields/New';
5+
// @ts-expect-error - SimpleSingleSelectField exists but types may not be available
6+
import { SimpleSingleSelectField } from '@dhis2-ui/select';
67
import type { LinkToExistingProps } from './LinkToExisting.types';
78

8-
const styles: Readonly<any> = {
9-
searchRow: {
9+
const styles: Readonly<any> = ({ typography }: any) => ({
10+
selectField: {
11+
maxWidth: typography.pxToRem(300),
1012
padding: spacers.dp16,
11-
display: 'flex',
12-
alignItems: 'center',
13-
gap: spacers.dp16,
1413
},
15-
label: {
16-
width: '150px',
17-
fontSize: '14px',
18-
},
19-
singleSelectField: {
20-
flexGrow: 1,
21-
},
22-
};
14+
});
2315

2416
type Props = LinkToExistingProps & WithStyles<typeof styles>;
2517

@@ -38,7 +30,14 @@ export const LinkToExistingPlain = ({
3830
const onChange = (value: string | null) => {
3931
setRelatedStagesDataValues({
4032
...relatedStagesDataValues,
41-
linkedEventId: value || '',
33+
linkedEventId: value ?? '',
34+
});
35+
};
36+
37+
const handleClear = () => {
38+
setRelatedStagesDataValues({
39+
...relatedStagesDataValues,
40+
linkedEventId: '',
4241
});
4342
};
4443

@@ -47,24 +46,25 @@ export const LinkToExistingPlain = ({
4746
label: event.label,
4847
}));
4948

49+
const label = i18n.t('Choose a {{linkableStageLabel}} event', {
50+
linkableStageLabel,
51+
});
52+
53+
5054
return (
51-
<div className={classes.searchRow}>
52-
<p className={classes.label}>
53-
{i18n.t('Choose a {{linkableStageLabel}} event', {
54-
linkableStageLabel,
55-
})}
56-
</p>
57-
<div className={classes.singleSelectField}>
58-
<NewSingleSelectField
59-
value={relatedStagesDataValues.linkedEventId}
60-
onChange={onChange}
61-
placeholder={i18n.t('Choose a {{linkableStageLabel}}', {
62-
linkableStageLabel,
63-
})}
64-
dataTest="related-stages-existing-response-list"
65-
options={options}
66-
/>
67-
</div>
55+
<div className={classes.selectField}>
56+
57+
<SimpleSingleSelectField
58+
name="related-stages-existing-response-list"
59+
selected={relatedStagesDataValues.linkedEventId}
60+
onChange={onChange}
61+
onClear={handleClear}
62+
placeholder={i18n.t('Select an event')}
63+
label={label}
64+
options={options}
65+
clearable
66+
dataTest="related-stages-existing-response-list"
67+
/>
6868
</div>
6969
);
7070
};

0 commit comments

Comments
 (0)