Skip to content

Commit 76e75e5

Browse files
utsukta1barshathakuri
authored andcommitted
Add source information field in ops update and final Report in dref event detail form
1 parent 5f6f941 commit 76e75e5

File tree

6 files changed

+200
-31
lines changed

6 files changed

+200
-31
lines changed

src/views/DrefFinalReportForm/EventDetail/i18n.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
"finalReportPeopleTargeted": "Number of people targeted",
2525
"drefFormPeopleTargetedDescription": "Include all those whose the National Society is aiming or planning to assist",
2626
"drefFormPeopleTargeted": "Number of people targeted",
27-
"drefFormPeopleInNeedDescriptionSlowSudden": "People in Need (PIN) are those members whose physical security, basic rights, dignity, living conditions or livelihoods are threatened or have been disrupted, and whose current level of access to basic services, goods and social protection is inadequate to re-establish normal living conditions without additional assistance."
27+
"drefFormPeopleInNeedDescriptionSlowSudden": "People in Need (PIN) are those members whose physical security, basic rights, dignity, living conditions or livelihoods are threatened or have been disrupted, and whose current level of access to basic services, goods and social protection is inadequate to re-establish normal living conditions without additional assistance.",
28+
"drefFormSourceInformationAddButton": "Add New Source Information",
29+
"drefFormSourceInformationTitle": "Source Information",
30+
"drefFormSourceInformationDescription": "Add the links and the name of the sources, the name will be shown in the export, as an hyperlink."
2831
}
2932
}

src/views/DrefFinalReportForm/EventDetail/index.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import { useCallback } from 'react';
2+
import { randomString } from '@togglecorp/fujs';
13
import {
24
type Error,
35
type EntriesAsList,
46
getErrorObject,
7+
useFormArray,
58
} from '@togglecorp/toggle-form';
69
import { WikiHelpSectionLineIcon } from '@ifrc-go/icons';
710

@@ -14,6 +17,9 @@ import Link from '#components/Link';
1417
import useTranslation from '#hooks/useTranslation';
1518
import MultiImageWithCaptionInput from '#components/domain/MultiImageWithCaptionInput';
1619

20+
import SourceInformationInput from '#views/DrefApplicationForm/EventDetail/SourceInformationInput';
21+
import NonFieldError from '#components/NonFieldError';
22+
import Button from '#components/Button';
1723
import {
1824
TYPE_IMMINENT,
1925
TYPE_ASSESSMENT,
@@ -25,6 +31,7 @@ import i18n from './i18n.json';
2531
import styles from './styles.module.css';
2632

2733
type Value = PartialFinalReport;
34+
type SourceInformationFormFields = NonNullable<PartialFinalReport['source_information']>[number];
2835
interface Props {
2936
value: Value;
3037
setFieldValue: (...entries: EntriesAsList<Value>) => void;
@@ -53,6 +60,27 @@ function EventDetail(props: Props) {
5360

5461
const error = getErrorObject(formError);
5562

63+
const {
64+
setValue: onSourceInformationChange,
65+
removeValue: onSourceInformationRemove,
66+
} = useFormArray<'source_information', SourceInformationFormFields>(
67+
'source_information',
68+
setFieldValue,
69+
);
70+
71+
const handleSourceInformationAdd = useCallback(() => {
72+
const newSourceInformationItem: SourceInformationFormFields = {
73+
client_id: randomString(),
74+
};
75+
76+
setFieldValue(
77+
(oldValue: SourceInformationFormFields[] | undefined) => (
78+
[...(oldValue ?? []), newSourceInformationItem]
79+
),
80+
'source_information' as const,
81+
);
82+
}, [setFieldValue]);
83+
5684
return (
5785
<div className={styles.eventDetail}>
5886
<Container
@@ -246,6 +274,32 @@ function EventDetail(props: Props) {
246274
/>
247275
</InputSection>
248276
)}
277+
<InputSection
278+
title={strings.drefFormSourceInformationTitle}
279+
description={strings.drefFormSourceInformationDescription}
280+
>
281+
<NonFieldError error={getErrorObject(error?.source_information)} />
282+
{value.source_information?.map((source, index) => (
283+
<SourceInformationInput
284+
key={source.client_id}
285+
index={index}
286+
value={source}
287+
onChange={onSourceInformationChange}
288+
onRemove={onSourceInformationRemove}
289+
error={getErrorObject(error?.source_information)}
290+
disabled={disabled}
291+
/>
292+
))}
293+
<Button
294+
className={styles.actions}
295+
name={undefined}
296+
onClick={handleSourceInformationAdd}
297+
variant="secondary"
298+
disabled={disabled}
299+
>
300+
{strings.drefFormSourceInformationAddButton}
301+
</Button>
302+
</InputSection>
249303
</Container>
250304
</div>
251305
);

src/views/DrefFinalReportForm/schema.ts

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
nullValue,
1111
lessThanOrEqualToCondition,
1212
emailCondition,
13+
urlCondition,
1314
} from '@togglecorp/toggle-form';
1415
import { isDefined } from '@togglecorp/fujs';
1516
import { type DeepReplace } from '#utils/common';
@@ -52,11 +53,13 @@ type InterventionResponse = NonNullable<FinalReportRequestBody['planned_interven
5253
type IndicatorResponse = NonNullable<InterventionResponse['indicators']>[number];
5354
type RiskSecurityResponse = NonNullable<FinalReportRequestBody['risk_security']>[number];
5455
type ImagesFileResponse = NonNullable<FinalReportRequestBody['images_file']>[number];
56+
type SourceInformationResponse = NonNullable<FinalReportRequestBody['source_information']>[number];
5557

5658
type NeedIdentifiedFormFields = NeedIdentifiedResponse & { client_id: string };
5759
type NsActionFormFields = NsActionResponse & { client_id: string; }
5860
type InterventionFormFields = InterventionResponse & { client_id: string };
5961
type IndicatorFormFields = IndicatorResponse & { client_id: string };
62+
type SourceInformationFormFields = SourceInformationResponse & { client_id: string };
6063

6164
type RiskSecurityFormFields = RiskSecurityResponse & { client_id: string; };
6265
type ImagesFileFormFields = ImagesFileResponse & { client_id: string };
@@ -76,30 +79,34 @@ type FinalReportFormFields = (
7679
DeepReplace<
7780
DeepReplace<
7881
DeepReplace<
79-
FinalReportRequestBody,
80-
NeedIdentifiedResponse,
81-
NeedIdentifiedFormFields
82+
DeepReplace<
83+
FinalReportRequestBody,
84+
NeedIdentifiedResponse,
85+
NeedIdentifiedFormFields
86+
>,
87+
NsActionResponse,
88+
NsActionFormFields
8289
>,
83-
NsActionResponse,
84-
NsActionFormFields
90+
InterventionResponse,
91+
InterventionFormFields
8592
>,
86-
InterventionResponse,
87-
InterventionFormFields
93+
IndicatorResponse,
94+
IndicatorFormFields
8895
>,
8996
IndicatorResponse,
9097
IndicatorFormFields
9198
>,
92-
IndicatorResponse,
93-
IndicatorFormFields
99+
RiskSecurityResponse,
100+
RiskSecurityFormFields
94101
>,
95-
RiskSecurityResponse,
96-
RiskSecurityFormFields
102+
ImagesFileResponse,
103+
ImagesFileFormFields
97104
>,
98-
ImagesFileResponse,
99-
ImagesFileFormFields
105+
EventMapFileResponse,
106+
EventMapFileFormField
100107
>,
101-
EventMapFileResponse,
102-
EventMapFileFormField
108+
SourceInformationResponse,
109+
SourceInformationFormFields
103110
>
104111
);
105112

@@ -116,6 +123,7 @@ type CoverImageFileFields = ReturnType<ObjectSchema<PartialFinalReport['cover_im
116123
type ImageFileFields = ReturnType<ObjectSchema<NonNullable<PartialFinalReport['images_file']>[number], PartialFinalReport>['fields']>;
117124
type NeedsIdentifiedFields = ReturnType<ObjectSchema<NonNullable<PartialFinalReport['needs_identified']>[number], PartialFinalReport>['fields']>;
118125
type RiskSecurityFields = ReturnType<ObjectSchema<NonNullable<PartialFinalReport['risk_security']>[number], PartialFinalReport>['fields']>;
126+
type SourceInformationFields = ReturnType<ObjectSchema<NonNullable<PartialFinalReport['source_information']>[number], PartialFinalReport>['fields']>;
119127
type PlannedInterventionFields = ReturnType<ObjectSchema<NonNullable<PartialFinalReport['planned_interventions']>[number], PartialFinalReport>['fields']>;
120128
type IndicatorFields = ReturnType<ObjectSchema<NonNullable<NonNullable<PartialFinalReport['planned_interventions']>[number]['indicators']>[number], PartialFinalReport>['fields']>;
121129

@@ -335,6 +343,7 @@ const schema: FinalReportFormSchema = {
335343
const eventDetailDrefTypeRelatedFields = [
336344
'event_text',
337345
'event_date',
346+
'source_information',
338347
] as const;
339348
type EventDetailDrefTypeRelatedFields = Pick<
340349
FinalReportFormSchemaFields,
@@ -349,6 +358,22 @@ const schema: FinalReportFormSchema = {
349358
const conditionalFields: EventDetailDrefTypeRelatedFields = {
350359
event_text: { forceValue: nullValue },
351360
event_date: { forceValue: nullValue },
361+
source_information: {
362+
keySelector: (source) => source.client_id,
363+
member: () => ({
364+
fields: (): SourceInformationFields => ({
365+
client_id: {},
366+
source_name: {
367+
required: true,
368+
requiredValidation: requiredStringCondition,
369+
},
370+
source_link: {
371+
required: true,
372+
validations: [urlCondition],
373+
},
374+
}),
375+
}),
376+
},
352377
};
353378

354379
if (val?.type_of_dref === TYPE_IMMINENT) {

src/views/DrefOperationalUpdateForm/EventDetail/i18n.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
"drefFormImminentDisaster": "Provide any updates in the situation since the field report and explain what is expected to happen.",
1919
"drefFormScopeAndScaleDescription": "Describe the extent this hazard will produce negative impacts on lives, livelihoods, well-being and infrastructure. Explain which people are most likely to experience the impacts of this hazard? Where do they live, and why are they vulnerable? Please explain which groups (e.g elderly, children, people with disabilities, IDPs, Refugees, etc.) are most likely to be affected? Provide historic information on how communities have been affected by the magnitude of this hazard in the past?",
2020
"drefFormScopeAndScaleEvent": "Scope and scale of the event",
21+
"drefFormSourceInformationTitle": "Source Information",
22+
"drefFormSourceInformationDescription": "Add the links and the name of the sources, the name will be shown in the export, as an hyperlink.",
23+
"drefFormSourceInformationAddButton": "Add New Source Information",
24+
"drefFormSelectImages": "Select images",
2125
"drefFormSlowEventDate": "Date when the trigger was met",
2226
"drefFormTargetCommunities": "Explain why your National Society is acting now and what criteria is used to launch this operation.",
2327
"drefFormTargetCommunitiesDescription": "If the operation uses triggers related to different phases (such as readiness activities and early actions) add your triggers and data sources",

src/views/DrefOperationalUpdateForm/EventDetail/index.tsx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import { useCallback } from 'react';
2+
import { randomString } from '@togglecorp/fujs';
13
import {
24
type Error,
35
type EntriesAsList,
46
getErrorObject,
7+
useFormArray,
58
} from '@togglecorp/toggle-form';
69
import { WikiHelpSectionLineIcon } from '@ifrc-go/icons';
710

@@ -15,6 +18,9 @@ import Link from '#components/Link';
1518
import useTranslation from '#hooks/useTranslation';
1619
import MultiImageWithCaptionInput from '#components/domain/MultiImageWithCaptionInput';
1720

21+
import NonFieldError from '#components/NonFieldError';
22+
import Button from '#components/Button';
23+
import SourceInformationInput from '#views/DrefApplicationForm/EventDetail/SourceInformationInput';
1824
import {
1925
TYPE_IMMINENT,
2026
TYPE_ASSESSMENT,
@@ -27,6 +33,8 @@ import i18n from './i18n.json';
2733
import styles from './styles.module.css';
2834

2935
type Value = PartialOpsUpdate;
36+
type SourceInformationFormFields = NonNullable<PartialOpsUpdate['source_information']>[number];
37+
3038
interface Props {
3139
value: Value;
3240
setFieldValue: (...entries: EntriesAsList<Value>) => void;
@@ -55,6 +63,27 @@ function EventDetail(props: Props) {
5563

5664
const error = getErrorObject(formError);
5765

66+
const {
67+
setValue: onSourceInformationChange,
68+
removeValue: onSourceInformationRemove,
69+
} = useFormArray<'source_information', SourceInformationFormFields>(
70+
'source_information',
71+
setFieldValue,
72+
);
73+
74+
const handleSourceInformationAdd = useCallback(() => {
75+
const newSourceInformationItem: SourceInformationFormFields = {
76+
client_id: randomString(),
77+
};
78+
79+
setFieldValue(
80+
(oldValue: SourceInformationFormFields[] | undefined) => (
81+
[...(oldValue ?? []), newSourceInformationItem]
82+
),
83+
'source_information' as const,
84+
);
85+
}, [setFieldValue]);
86+
5887
return (
5988
<div className={styles.eventDetail}>
6089
{value.type_of_dref !== TYPE_LOAN && (
@@ -357,6 +386,34 @@ function EventDetail(props: Props) {
357386
/>
358387
</InputSection>
359388
)}
389+
{value.type_of_dref !== TYPE_LOAN && (
390+
<InputSection
391+
title={strings.drefFormSourceInformationTitle}
392+
description={strings.drefFormSourceInformationDescription}
393+
>
394+
<NonFieldError error={getErrorObject(error?.source_information)} />
395+
{value.source_information?.map((source, index) => (
396+
<SourceInformationInput
397+
key={source.client_id}
398+
index={index}
399+
value={source}
400+
onChange={onSourceInformationChange}
401+
onRemove={onSourceInformationRemove}
402+
error={getErrorObject(error?.source_information)}
403+
disabled={disabled}
404+
/>
405+
))}
406+
<Button
407+
className={styles.actions}
408+
name={undefined}
409+
onClick={handleSourceInformationAdd}
410+
variant="secondary"
411+
disabled={disabled}
412+
>
413+
{strings.drefFormSourceInformationAddButton}
414+
</Button>
415+
</InputSection>
416+
)}
360417
</Container>
361418
</div>
362419
);

0 commit comments

Comments
 (0)