Skip to content

Commit 5c9a36b

Browse files
committed
feat(eap): clean-up simplied form schema
1 parent a6a2481 commit 5c9a36b

File tree

17 files changed

+162
-188
lines changed

17 files changed

+162
-188
lines changed

app/src/components/domain/Admin2Input/i18n.json

Whitespace-only changes.

app/src/components/domain/OperationActivityInput/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { stringValueSelector } from '@ifrc-go/ui/utils';
1313
import {
1414
type ArrayError,
1515
getErrorObject,
16+
getErrorString,
1617
type SetValueArg,
1718
useFormObject,
1819
} from '@togglecorp/toggle-form';
@@ -125,6 +126,7 @@ function OperationActivityInput(props: Props) {
125126
label={strings.operationPriorityActionLabel}
126127
name="activity"
127128
value={value.activity}
129+
error={error?.activity}
128130
onChange={onFieldChange}
129131
disabled={disabled}
130132
withAsterisk
@@ -154,6 +156,7 @@ function OperationActivityInput(props: Props) {
154156
disabled={disabled}
155157
renderer={TimeSpanCheck}
156158
withoutOpticalSpacingCorrection
159+
error={getErrorString(error?.time_value)}
157160
/>
158161
)}
159162
</ListView>

app/src/components/printable/PrintableContainer/index.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,18 @@ function PrintableContainer(props: Props) {
2929
<>
3030
{breakBefore && <div className={styles.pageBreak} />}
3131
{heading && (
32-
<Heading level={headingLevel}>
32+
<Heading
33+
level={headingLevel}
34+
className={styles.heading}
35+
>
3336
{heading}
3437
</Heading>
3538
)}
3639
{children}
37-
<div style={{ marginBlockEnd: spacing }} />
40+
<div
41+
className={styles.blockSpacing}
42+
style={{ marginBlockEnd: spacing }}
43+
/>
3844
{breakAfter && <div className={styles.pageBreak} />}
3945
</>
4046
);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
11
.page-break {
22
break-before: page;
3+
4+
@media screen {
5+
margin: var(--go-ui-spacing-lg) 0;
6+
border: var(--go-ui-width-separator-thin) dashed var(--go-ui-color-separator);
7+
}
8+
}
9+
10+
.heading:has(+ :empty) {
11+
display: none;
12+
}
13+
14+
.block-spacing:has(+ :empty) {
15+
display: none;
316
}

app/src/components/printable/PrintableDataDisplay/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ interface NodeProps {
5555
value?: React.ReactNode;
5656
}
5757

58-
export type Props = BaseProps & (
58+
type Props = BaseProps & (
5959
NodeProps | TextProps | DateProps | NumberProps | BooleanProps
6060
);
6161

app/src/utils/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,6 @@ export const EAP_TYPE_FULL = 10;
209209

210210
// FIXME these need to satisfy some enum
211211
export const TIMEFRAME_YEAR = 10;
212-
export const TIMEFRAME_MONTHS = 20;
212+
// export const TIMEFRAME_MONTHS = 20;
213213
// export const TIMEFRAME_DAYS = 30;
214214
// export const TIMEFRAME_HOURS = 40;

app/src/views/SimplifiedEapExport/index.tsx

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,13 @@ export function Component() {
8181
);
8282

8383
const {
84-
cover_image_details,
84+
disaster_type_details,
85+
country_details,
86+
} = eapRegistrationResponse ?? {};
87+
88+
const {
89+
cover_image_file,
90+
admin2_details,
8591

8692
total_budget,
8793
readiness_budget,
@@ -113,6 +119,12 @@ export function Component() {
113119
national_society_contact_phone_number,
114120
} = simplifiedEapResponse ?? {};
115121

122+
const eapTitle = [
123+
country_details?.name,
124+
admin2_details?.map(({ name }) => name).join(', '),
125+
disaster_type_details?.name,
126+
].filter(isTruthyString).join(' | ');
127+
116128
return (
117129
<PrintablePage
118130
heading={(
@@ -122,14 +134,14 @@ export function Component() {
122134
Early Action Protocol
123135
</>
124136
)}
125-
description="Nepal, Western Terai | Flood"
137+
description={eapTitle ?? '--'}
126138
>
127-
{isDefined(cover_image_details?.file) && (
139+
{isDefined(cover_image_file?.file) && (
128140
<PrintableContainer>
129141
<Image
130-
src={cover_image_details.file}
142+
src={cover_image_file.file}
131143
alt=""
132-
caption={cover_image_details.caption}
144+
caption={cover_image_file.caption}
133145
/>
134146
</PrintableContainer>
135147
)}
@@ -531,7 +543,7 @@ export function Component() {
531543
national_society_contact_title,
532544
national_society_contact_email,
533545
national_society_contact_phone_number,
534-
].join(', ')}
546+
].filter(isTruthyString).join(', ')}
535547
variant="block"
536548
strongLabel
537549
/>

app/src/views/SimplifiedEapForm/EnablingApproaches/ApproachesInput/index.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
} from '@ifrc-go/ui';
1313
import { useTranslation } from '@ifrc-go/ui/hooks';
1414
import {
15-
isDefined,
1615
isNotDefined,
1716
randomString,
1817
} from '@togglecorp/fujs';
@@ -37,7 +36,7 @@ type PrepositioningFormFields = NonNullable<EnableApproachesFormFields['preposit
3736
type ReadinessFormFields = NonNullable<EnableApproachesFormFields['readiness_activities']>[number];
3837

3938
const defaultApproachValue: EnableApproachesFormFields = {
40-
client_id: '-1',
39+
approach: 10,
4140
};
4241

4342
interface Props {
@@ -47,7 +46,7 @@ interface Props {
4746
onRemove: (index: number) => void;
4847
index: number;
4948
disabled?: boolean;
50-
titleMap: Record<string, string> | undefined;
49+
approachTitle?: React.ReactNode;
5150
}
5251

5352
function OperationsBySectorInput(props: Props) {
@@ -58,18 +57,14 @@ function OperationsBySectorInput(props: Props) {
5857
index,
5958
onRemove,
6059
disabled,
61-
titleMap,
60+
approachTitle,
6261
} = props;
6362

6463
const strings = useTranslation(i18n);
6564
const onFieldChange = useFormObject(index, onChange, defaultApproachValue);
6665

67-
const approachLabel = isDefined(value.title)
68-
? titleMap?.[value.title]
69-
: undefined;
70-
71-
const error = (value && value.client_id && errorFromProps)
72-
? getErrorObject(errorFromProps?.[value.client_id])
66+
const error = (value && value.approach && errorFromProps)
67+
? getErrorObject(errorFromProps?.[value.approach])
7368
: undefined;
7469

7570
const {
@@ -144,7 +139,7 @@ function OperationsBySectorInput(props: Props) {
144139

145140
return (
146141
<ExpandableContainer
147-
heading={approachLabel ?? '--'}
142+
heading={approachTitle ?? '--'}
148143
headerActions={(
149144
<Button
150145
name={index}

app/src/views/SimplifiedEapForm/EnablingApproaches/index.tsx

Lines changed: 37 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ import {
1010
} from '@ifrc-go/ui';
1111
import { useTranslation } from '@ifrc-go/ui/hooks';
1212
import { stringValueSelector } from '@ifrc-go/ui/utils';
13-
import {
14-
listToMap,
15-
randomString,
16-
} from '@togglecorp/fujs';
13+
import { listToMap } from '@togglecorp/fujs';
1714
import {
1815
type EntriesAsList,
1916
type Error,
@@ -22,16 +19,16 @@ import {
2219
} from '@togglecorp/toggle-form';
2320

2421
import NonFieldError from '#components/NonFieldError';
22+
import { type components } from '#generated/types';
2523
import useGlobalEnums from '#hooks/domain/useGlobalEnums';
26-
import { type GoApiResponse } from '#utils/restRequest';
2724

2825
import { type PartialSimplifiedEapType } from '../schema';
2926
import ApproachesInput from './ApproachesInput';
3027

3128
import i18n from './i18n.json';
3229

33-
type GlobalEnumsResponse = GoApiResponse<'/api/v2/global-enums/'>;
34-
type EnablingApproachesOption = NonNullable<GlobalEnumsResponse['eap_approach']>[number];
30+
type EapApproach = components['schemas']['EapApproachEnumKey'];
31+
type EapApproachOption = components['schemas']['EapApproachEnum'];
3532

3633
type EnablingApproachesFormFields = NonNullable<PartialSimplifiedEapType['enable_approaches']>[number];
3734

@@ -42,7 +39,7 @@ interface Props {
4239
setFieldValue: (...entries: EntriesAsList<PartialSimplifiedEapType>) => void;
4340
}
4441

45-
function approachesKeySelector(option: EnablingApproachesOption) {
42+
function approachesKeySelector(option: EapApproachOption) {
4643
return option.key;
4744
}
4845
function EnablingApproaches(props: Props) {
@@ -56,13 +53,15 @@ function EnablingApproaches(props: Props) {
5653
const error = getErrorObject(formError);
5754
const strings = useTranslation(i18n);
5855

59-
const {
60-
eap_approach: approachesOptions,
61-
} = useGlobalEnums();
56+
const { eap_approach: eapApproachOptions } = useGlobalEnums();
6257

63-
const selectedApproach = (value.enable_approaches ?? [])
64-
.map((op) => op.title)
65-
.filter((key): key is EnablingApproachesOption['key'] => key !== undefined);
58+
const eapApproachLabelMapping = useMemo(() => (
59+
listToMap(
60+
eapApproachOptions,
61+
({ key }) => key,
62+
({ value: label }) => label,
63+
)
64+
), [eapApproachOptions]);
6665

6766
const {
6867
setValue: onApproachChange,
@@ -72,58 +71,28 @@ function EnablingApproaches(props: Props) {
7271
setFieldValue,
7372
);
7473

75-
const handleApproachSelect = useCallback((selectedKeys: EnablingApproachesOption['key'][]) => {
76-
const previousKeys = (value.enable_approaches ?? [])
77-
.map((op) => op.title)
78-
.filter((key): key is EnablingApproachesOption['key'] => key !== undefined);
79-
80-
const addedKeys = selectedKeys.filter((key) => !previousKeys.includes(key));
81-
const removedKeys = previousKeys.filter((key) => !selectedKeys.includes(key));
82-
83-
if (addedKeys.length > 0) {
84-
const newOperations = addedKeys.map((key) => ({
85-
client_id: randomString(),
86-
title: key,
87-
}));
88-
89-
setFieldValue(
90-
(oldValue: EnablingApproachesFormFields[] = []) => {
91-
const safeOldValue = oldValue.map((op) => ({
92-
...op,
93-
title: op.title,
94-
}));
95-
return [...safeOldValue, ...newOperations];
96-
},
97-
'enable_approaches',
74+
const handleApproachChecklistChange = useCallback((approaches: EapApproach[] | undefined) => {
75+
setFieldValue((previousValue: EnablingApproachesFormFields[] | undefined) => {
76+
const previousValueMapping = listToMap(
77+
previousValue,
78+
({ approach }) => approach,
9879
);
99-
}
100-
101-
if (removedKeys.length > 0) {
102-
removedKeys.forEach((key) => {
103-
const index = value.enable_approaches?.findIndex(
104-
(op) => op.title === key,
105-
);
106-
if (index !== undefined && index >= 0) {
107-
onApproachRemove(index);
80+
81+
return approaches?.map((approach) => {
82+
const prevapproachValue = previousValueMapping?.[approach];
83+
84+
if (prevapproachValue) {
85+
return prevapproachValue;
10886
}
87+
88+
return {
89+
approach,
90+
} satisfies EnablingApproachesFormFields;
10991
});
110-
}
111-
}, [
112-
value.enable_approaches,
113-
setFieldValue,
114-
onApproachRemove,
115-
]);
116-
117-
const approachTitleMap = useMemo(
118-
() => (
119-
listToMap(
120-
approachesOptions,
121-
(approach) => approach.key,
122-
(approach) => approach.value,
123-
)
124-
),
125-
[approachesOptions],
126-
);
92+
}, 'enable_approaches');
93+
}, [setFieldValue]);
94+
95+
const selectedApproaches = value?.enable_approaches?.map(({ approach }) => approach);
12796

12897
return (
12998
<Container heading={strings.enablingApproachesTitle}>
@@ -138,9 +107,9 @@ function EnablingApproaches(props: Props) {
138107
<NonFieldError error={getErrorObject(error?.enable_approaches)} />
139108
<Checklist
140109
name={undefined}
141-
options={approachesOptions}
142-
onChange={handleApproachSelect}
143-
value={selectedApproach}
110+
options={eapApproachOptions}
111+
onChange={handleApproachChecklistChange}
112+
value={selectedApproaches}
144113
disabled={disabled}
145114
keySelector={approachesKeySelector}
146115
labelSelector={stringValueSelector}
@@ -150,14 +119,14 @@ function EnablingApproaches(props: Props) {
150119
</InputSection>
151120
{value?.enable_approaches?.map((approach, index) => (
152121
<ApproachesInput
153-
key={approach.client_id}
122+
approachTitle={eapApproachLabelMapping?.[approach.approach]}
123+
key={approach.approach}
154124
index={index}
155125
value={approach}
156126
onChange={onApproachChange}
157127
onRemove={onApproachRemove}
158128
error={getErrorObject(error?.enable_approaches)}
159129
disabled={disabled}
160-
titleMap={approachTitleMap}
161130
/>
162131
))}
163132
</ListView>

0 commit comments

Comments
 (0)