Skip to content

project: DREF Imminent Changes #1674

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

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions .changeset/modern-hats-fry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"go-web-app": minor
---

Imminent DREF Application Form Updates in [#1455](https://github.com/IFRCGo/go-web-app/issues/1455)
5 changes: 5 additions & 0 deletions .changeset/short-otters-boil.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ifrc-go/ui": patch
---

Add `addNumDaysToDate` and `ceilToEndOfMonth` date helper functions
16 changes: 16 additions & 0 deletions app/src/assets/icons/early_actions.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions app/src/assets/icons/early_response.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions app/src/components/Navbar/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"userMenuSurge":"The section displays the summary of deployments within current and ongoing emergencies. Login to see available details",
"userMenuSurgeGlobalOverview":"Surge Global Overview",
"userMenuOperationalToolbox":"Operational Toolbox",
"userMenuCatalogueSurgeServices":"Catalogue of Surge services",
"userMenuCatalogueSurgeServices":"Catalogue of Surge Services",
"userMenuLearnLabel":"Learn",
"userMenuTools":"Tools",
"userMenuResources":"Resources",
Expand All @@ -63,8 +63,8 @@
"userMenuOperationalLearningDescription":"Operational learning in emergencies is the lesson learned from managing and dealing with crises, refining protocols for resource allocation, decision-making, communication strategies, and others.",
"userMenuOperationalToolboxItem":"Operational Toolbox",
"userMenuOperationalToolboxItemDescription":"This operational toolbox is a central repository with key operational document helpful for your mission like templates, checklists, guidance and examples.",
"userMenuCatalogueSurgeServicesItem": "Catalogue of Surge services",
"userMenuCatalogueSurgeServicesItemDescription":"Catalogue of Surge services contains all relevant content and materials related to Surge.",
"userMenuCatalogueSurgeServicesItem": "Catalogue of Surge Services",
"userMenuCatalogueSurgeServicesItemDescription":"Catalogue of Surge Services contains all relevant content and materials related to Surge.",
"userMenuPERCatalogueItem":"PER Catalogue of Resources",
"userMenuPERCatalogueItemDescription":"PER Catalogue of Resources contains resource relevant to strengthening resource and capacity.",
"userMenuGoResourcesItem":"GO Resources",
Expand Down
1 change: 1 addition & 0 deletions app/src/components/PerExportModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ function PerExportModal(props: Props) {
export_id: Number(perId),
export_type: 'per' as const,
per_country: Number(countryId),
is_pga: false,
}),
[perId, countryId],
);
Expand Down
2 changes: 1 addition & 1 deletion app/src/components/SelectOutput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { TextOutput } from '@ifrc-go/ui';
import { isDefined } from '@togglecorp/fujs';

interface Props<VALUE, OPTION> {
className: string;
className?: string;
value: VALUE | undefined;
options: OPTION[] | undefined;
keySelector: (datum: OPTION) => VALUE;
Expand Down
5 changes: 4 additions & 1 deletion app/src/components/domain/DrefExportModal/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
"drefExportFailed": "Export failed",
"drefExportSuccessfully": "Export completed successfully",
"drefClickDownloadLink": "Click on the download link below!",
"drefDownloadPDF": "Download PDF"
"drefDownloadPDF": "Download PDF",
"drefDownloadPDFWithPGA": "Download PDF with PGA",
"drefDownloadPDFwithoutPGA": "Download PDF without PGA",
"drefFailureToExportMessage":"Failed to export PDF."
}
}
147 changes: 140 additions & 7 deletions app/src/components/domain/DrefExportModal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import {
useCallback,
useMemo,
useState,
} from 'react';
import {
Button,
Checkbox,
Message,
Modal,
} from '@ifrc-go/ui';
Expand All @@ -14,9 +17,18 @@ import {

import Link from '#components/Link';
import { type components } from '#generated/types';
import { useRequest } from '#utils/restRequest';
import useAlert from '#hooks/useAlert';
import {
DREF_TYPE_IMMINENT,
type TypeOfDrefEnum,
} from '#utils/constants';
import {
useLazyRequest,
useRequest,
} from '#utils/restRequest';

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

type ExportTypeEnum = components<'read'>['schemas']['ExportTypeEnum'];
type ExportStatusEnum = components<'read'>['schemas']['ExportStatusEnum'];
Expand All @@ -29,18 +41,48 @@ interface Props {
id: number;
onCancel: () => void;
applicationType: 'DREF' | 'OPS_UPDATE' | 'FINAL_REPORT';
drefType?: TypeOfDrefEnum | null;
}

function DrefExportModal(props: Props) {
const {
id,
onCancel,
applicationType,
drefType,
} = props;

const strings = useTranslation(i18n);
const alert = useAlert();

const [exportId, setExportId] = useState<number | undefined>();
const [isPga, setIsPga] = useState<boolean>(false);
const [isPgaCheckboxVisible, setIsPgaCheckboxVisible] = useState(true);

const drefExportTriggerBody = useMemo(
() => {
let type: ExportTypeEnum;
if (applicationType === 'OPS_UPDATE') {
type = 'dref-operational-updates';
} else if (applicationType === 'FINAL_REPORT') {
type = 'dref-final-reports';
} else {
type = 'dref-applications';
}
return {
export_id: id,
export_type: type,
is_pga: isPga,
selector: '#pdf-preview-ready',
per_country: undefined,
};
},
[
id,
isPga,
applicationType,
],
);

const exportTriggerBody = useMemo(
() => {
Expand All @@ -56,18 +98,45 @@ function DrefExportModal(props: Props) {
return {
export_id: id,
export_type: type,
is_pga: isPga,
selector: '#pdf-preview-ready',
per_country: undefined, // FIXME: typing is altered by the useRequest function
};
},
[id, applicationType],
[
id,
isPga,
applicationType,
],
);

const {
pending: pendingDrefImminentExportTrigger,
error: drefImminentExportError,
trigger: drefImminentExportTrigger,
} = useLazyRequest({
method: 'POST',
useCurrentLanguageForMutation: true,
url: '/api/v2/pdf-export/',
body: drefExportTriggerBody,
onSuccess: (response) => {
if (isDefined(response.id)) {
setExportId(response.id);
}
},
onFailure: () => {
alert.show(
strings.drefFailureToExportMessage,
{ variant: 'danger' },
);
},
});

const {
pending: pendingExportTrigger,
error: exportTriggerError,
} = useRequest({
skip: isDefined(exportId) || isNotDefined(id),
skip: isDefined(exportId) || isNotDefined(id) || drefType === DREF_TYPE_IMMINENT,
method: 'POST',
useCurrentLanguageForMutation: true,
url: '/api/v2/pdf-export/',
Expand All @@ -77,6 +146,12 @@ function DrefExportModal(props: Props) {
setExportId(response.id);
}
},
onFailure: () => {
alert.show(
strings.drefFailureToExportMessage,
{ variant: 'danger' },
);
},
});

const {
Expand All @@ -97,18 +172,40 @@ function DrefExportModal(props: Props) {
},
});

const handleDrefImminent = useCallback(() => {
setIsPgaCheckboxVisible(false);
drefImminentExportTrigger(drefExportTriggerBody);
}, [
drefExportTriggerBody,
drefImminentExportTrigger,
]);

return (
<Modal
heading={strings.drefExportTitle}
onClose={onCancel}
>
{pendingExportTrigger && (
{drefType === DREF_TYPE_IMMINENT
&& isPgaCheckboxVisible
&& !(pendingExportTrigger
|| pendingExportStatus
|| exportStatusResponse?.status === EXPORT_STATUS_PENDING)
&& (
<Checkbox
name={undefined}
value={isPga}
onChange={setIsPga}
label={strings.drefDownloadPDFWithPGA}
/>
)}
{pendingExportTrigger && pendingDrefImminentExportTrigger && (
<Message
pending
title={strings.drefPreparingExport}
/>
)}
{(pendingExportStatus || exportStatusResponse?.status === EXPORT_STATUS_PENDING) && (
{(pendingExportStatus
|| exportStatusResponse?.status === EXPORT_STATUS_PENDING) && (
<Message
pending
title={strings.drefWaitingExport}
Expand All @@ -117,16 +214,52 @@ function DrefExportModal(props: Props) {
{(exportStatusResponse?.status === EXPORT_STATUS_ERRORED
|| isDefined(exportTriggerError)
|| isDefined(exportStatusError)
|| isDefined(drefImminentExportError)
) && (
<Message
title={strings.drefExportFailed}
description={exportTriggerError?.value.messageForNotification
?? exportStatusError?.value.messageForNotification}
?? exportStatusError?.value.messageForNotification
?? drefImminentExportError?.value.messageForNotification}
/>
)}
{!(pendingExportTrigger
|| pendingExportStatus
|| exportStatusResponse?.status === EXPORT_STATUS_PENDING)
&& drefType === DREF_TYPE_IMMINENT
&& !drefImminentExportError && (
exportStatusResponse?.pdf_file ? (
<Message
title={strings.drefExportSuccessfully}
description={strings.drefClickDownloadLink}
actions={(
<Link
variant="secondary"
href={exportStatusResponse?.pdf_file}
external
>
{strings.drefDownloadPDF}
</Link>
)}
/>
) : (!exportStatusResponse && (
<div className={styles.downloadButton}>
<Button
variant="secondary"
name={undefined}
onClick={handleDrefImminent}
>
{isPga
? strings.drefDownloadPDFWithPGA
: strings.drefDownloadPDFwithoutPGA}
</Button>
</div>
))
)}
{isDefined(exportStatusResponse)
&& exportStatusResponse.status === EXPORT_STATUS_COMPLETED
&& isDefined(exportStatusResponse.pdf_file) && (
&& isDefined(exportStatusResponse.pdf_file)
&& drefType !== DREF_TYPE_IMMINENT && (
<Message
title={strings.drefExportSuccessfully}
description={strings.drefClickDownloadLink}
Expand Down
6 changes: 6 additions & 0 deletions app/src/components/domain/DrefExportModal/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.download-button {
display: flex;
align-items: center;
flex-direction: column;
padding: var(--go-ui-spacing-md);
}
3 changes: 2 additions & 1 deletion app/src/components/domain/RiskSeasonalMap/i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"riskCategoryVeryHigh": "Very High",
"riskSeasonalMapHeading": "Risk Map",
"riskSeasonalCountriesByRiskHeading": "Countries by Risk",
"riskPopupLabel": "Risk"
"riskPopupLabel": "Risk",
"riskDataNotAvailable": "Data not available for selected filters"
}
}
3 changes: 1 addition & 2 deletions app/src/components/domain/RiskSeasonalMap/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -980,8 +980,7 @@ function RiskSeasonalMap(props: Props) {
{dataPending && <BlockLoading />}
{!dataPending && (isNotDefined(filteredData) || filteredData?.length === 0) && (
<Message
// FIXME: add translations
title="Data not available for selected filters"
title={strings.riskDataNotAvailable}
/>
)}
{/* FIXME: use List */}
Expand Down
6 changes: 5 additions & 1 deletion app/src/contexts/domain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import { createContext } from 'react';

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

export type CacheKey = 'country' | 'global-enums' | 'disaster-type' | 'user-me' | 'region' | 'secondary-sector' | 'per-components';
export type CacheKey = 'country' | 'global-enums' | 'disaster-type' | 'user-me' | 'region' | 'secondary-sector' | 'per-components' | 'primary-sector';

export type GlobalEnums = Partial<GoApiResponse<'/api/v2/global-enums/'>>;
export type Countries = GoApiResponse<'/api/v2/country/'>;
export type DisasterTypes = GoApiResponse<'/api/v2/disaster_type/'>;
type UserMe = GoApiResponse<'/api/v2/user/me/'>;
export type Regions = GoApiResponse<'/api/v2/region/'>;
export type SecondarySectors = GoApiResponse<'/api/v2/secondarysector'>;
export type PrimarySectors = GoApiResponse<'/api/v2/primarysector'>;
export type PerComponents = GoApiResponse<'/api/v2/per-formcomponent/'>;

export interface Domain {
Expand All @@ -34,6 +35,9 @@ export interface Domain {
secondarySectors?: SecondarySectors;
secondarySectorsPending?: boolean;

primarySectors?: PrimarySectors;
primarySectorsPending?: boolean;

perComponents?: PerComponents;
perComponentsPending?: boolean;
}
Expand Down
Loading
Loading