Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Proposed Action for Dref Application Form #1632

Merged
merged 3 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"namespace": "drefAppicationForm",

Check warning on line 2 in app/src/views/DrefApplicationForm/Operation/ProposedActionsInput/i18n.json

View workflow job for this annotation

GitHub Actions / Spell Check with Typos

"Appication" should be "Application".
"strings": {
"drefFormProposedActionActivityLabel": "Activity",
"drefFormProposedActionBudgetLabel": "Budget(CHF)",
"drefFormRemoveActivity": "Remove Activity"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { DeleteBinLineIcon } from '@ifrc-go/icons';
import {
IconButton,
NumberInput,
SelectInput,
} from '@ifrc-go/ui';
import { useTranslation } from '@ifrc-go/ui/hooks';
import {
type ArrayError,
getErrorObject,
type SetValueArg,
useFormObject,
} from '@togglecorp/toggle-form';

import { type GoApiResponse } from '#utils/restRequest';

import { type PartialDref } from '../../schema';

import i18n from './i18n.json';
import styles from './styles.module.css';

type ProposedActionsFormFields = NonNullable<PartialDref['proposed_action']>[number];
type ActivityOptions = NonNullable<GoApiResponse<'/api/v2/primarysector'>>[number];

function activityLabelSelector(option: ActivityOptions) {
return option.label;
}

function activityKeySelector(option: ActivityOptions) {
return option.key;
}

const defaultProposedActionsValue: ProposedActionsFormFields = {
client_id: '-1',
};

interface Props {
value: ProposedActionsFormFields;
error: ArrayError<ProposedActionsFormFields> | undefined;
onChange: (
value: SetValueArg<ProposedActionsFormFields>,
index: number,
) => void;
onRemove: (index: number) => void;
index: number;
disabled?: boolean;
activityOptions?: ActivityOptions[];
}
function ProposedActionsInput(props: Props) {
const {
error: errorFromProps,
onChange,
value,
onRemove,
index,
activityOptions,
disabled,
} = props;

const strings = useTranslation(i18n);

const onProposedActionChange = useFormObject(index, onChange, defaultProposedActionsValue);

const error = (value && value.client_id && errorFromProps)
? getErrorObject(errorFromProps?.[value.client_id])
: undefined;

return (
<div className={styles.actionInputContainer}>
<div
className={styles.activities}
samshara marked this conversation as resolved.
Show resolved Hide resolved
>
<SelectInput
required
label={strings.drefFormProposedActionActivityLabel}
name="activity"
readOnly
value={value.activity}
options={activityOptions}
onChange={onProposedActionChange}
error={error?.activity}
keySelector={activityKeySelector}
labelSelector={activityLabelSelector}
/>
</div>
<NumberInput
required
name="budget"
value={value.budget}
label={strings.drefFormProposedActionBudgetLabel}
onChange={onProposedActionChange}
disabled={disabled}
error={error?.budget}
/>
<IconButton
name={index}
onClick={onRemove}
title={strings.drefFormRemoveActivity}
ariaLabel={strings.drefFormRemoveActivity}
round={false}
variant="tertiary"
disabled={disabled}
>
<DeleteBinLineIcon />
</IconButton>
</div>
);
}

export default ProposedActionsInput;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.action-input-container {
display: flex;
gap: var(--go-ui-spacing-md);

.activities {
flex-grow: 1;
}
}
12 changes: 11 additions & 1 deletion app/src/views/DrefApplicationForm/Operation/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"drefFormPeopleAssistedThroughOperationDescription": "Explain the logic behind our targets. Which groups are we targeting and why are we targeting these particular groups? Explain how you will target vulnerable groups (e.g., Migrants, refugees, etc.)",
"drefFormPeopleTargetedWithEarlyActions": "Numbers of persons targeted with early actions (if any)",
"drefFormPlannedIntervention": "Planned Intervention",
"drefFormProposedActions": "Proposed Actions",
"drefFormRequestAmount": "Requested Amount in CHF",
"drefFormPmer": "How will this operation be monitored?",
"drefFormPmerDescription": "Will there be IFRC monitoring visits? How will it be deployed?",
Expand Down Expand Up @@ -56,6 +57,15 @@
"drefFormTotalTargeted": "Total targeted population is different from that in Operation Overview",
"drefFormTotalTargetedPopulation": "Total targeted population is not equal to sum of other population fields",
"drefFormUploadTargetingSupportingDocument": "Upload any additional support document (Optional)",
"drefFormUploadTargetingDocumentButtonLabel": "Upload document"
"drefFormUploadTargetingDocumentButtonLabel": "Upload document",
"drefFormProposedActionSelectBudgetNote": "If Surge Personnel are deployed, costs include CHF 10,000 for deployment and CHF 5,800 in indirect costs. Without deployment, only CHF 5,000 in indirect costs apply.",
"drefFormProposedActionSelectActivitiesLabel": "Select the activity",
"drefFormProposedActionEarlyActionsLabel": "Early Actions",
"drefFormProposedActionEarlyResponseLabel": "Early Response",
"drefFormProposedActionAddActivityLabel": "Add Activity",
"drefFormProposedActionSubTotal": "Sub-total",
"drefFormProposedActionSurgeDeployment": "Surge Deployment",
"drefFormProposedActionIndirectCost": "Indirect cost",
"drefFormProposedActionTotal": "Total"
}
}
Loading
Loading