Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
"strings": {
"addSubscriptionHeading": "New subscription",
"editSubscriptionHeading": "Edit subscription",
"earthquakeLabel": "Earthquake",
"cycloneLabel": "Cyclone",
"floodLabel": "Flood",
"updateButtonLabel": "Save",
"cancelButtonLabel": "Cancel",
"subscriptionTitleLabel": "Enter subscription title",
Expand All @@ -21,6 +24,6 @@
"countryLabelSingular": "country",
"countryLabelPlural": "countries",
"unlimitedOptionValue": "No limit",
"detailFetchFailureMessage": "Failed to fetch subscription details"

Check warning on line 27 in app/src/views/AccountNotifications/EmailPreferences/SubscriptionModal/i18n.json

View workflow job for this annotation

GitHub Actions / Lint JS

Unused key 'detailFetchFailureMessage' found

Check warning on line 27 in app/src/views/AccountNotifications/EmailPreferences/SubscriptionModal/i18n.json

View workflow job for this annotation

GitHub Actions / Build GO Web App

Unused key 'detailFetchFailureMessage' found
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import {
import NonFieldError from '#components/NonFieldError';
import { type components } from '#generated/types';
import useCountry from '#hooks/domain/useCountry';
import useDisasterTypes, { type DisasterType } from '#hooks/domain/useDisasterType';
import { type DisasterType } from '#hooks/domain/useDisasterType';
import useGlobalEnums from '#hooks/domain/useGlobalEnums';
import useAlert from '#hooks/useAlert';
import {
Expand All @@ -62,7 +62,7 @@ function alertPerDayKeySelector(option: AlertPerDayEnums) {
return option.key;
}

const disasterTypeLabelSelector = (disasterType: DisasterType) => disasterType.name ?? '?';
const disasterTypeLabelSelector = (disasterType: Pick<DisasterType, 'id' | 'name'>) => disasterType.name ?? '?';

interface Props {
onClose: () => void;
Expand All @@ -85,7 +85,21 @@ function SubscriptionModal(props: Props) {
const strings = useTranslation(i18n);
const alert = useAlert();

const disasterTypeOptions = useDisasterTypes();
// NOTE: Email alerts only supports 3 disasters at the moment
const disasterTypeOptions = [
{
id: 2,
name: strings.earthquakeLabel,
},
{
id: 4,
name: strings.cycloneLabel,
},
{
id: 12,
name: strings.floodLabel,
},
];

const defaultFormValue: PartialFormFields = useMemo(() => ({
user: userId,
Expand Down Expand Up @@ -289,7 +303,9 @@ function SubscriptionModal(props: Props) {
region,
];
}

if (regionIndex === -1) {
return selectedRegions;
}
if (isSelected) {
return selectedRegions;
}
Expand All @@ -304,7 +320,7 @@ function SubscriptionModal(props: Props) {
setFieldValue(
(selectedCountries: number[] | undefined = []) => {
const countryIndex = selectedCountries.findIndex(
(selectedRegion) => selectedRegion === country,
(selectedCountry) => selectedCountry === country,
);

if (countryIndex === -1 && isSelected) {
Expand All @@ -325,8 +341,8 @@ function SubscriptionModal(props: Props) {

if (isSelected) {
const countryDetails = countryDetailsById[country];
if (isDefined(countryDetails)) {
updateRegionSelection(false, countryDetails.id);
if (isDefined(countryDetails?.region)) {
updateRegionSelection(false, countryDetails?.region);
}
}
}, [setFieldValue, countryDetailsById, updateRegionSelection]);
Expand Down Expand Up @@ -420,10 +436,10 @@ function SubscriptionModal(props: Props) {
{regionOptions?.map((region) => {
const regionCountries = regionGroupedCountries[region.key];
const selectedCountries = regionCountries?.filter(
(country) => selectedCountriesIdMap?.[country.id],
(country) => !!selectedCountriesIdMap?.[country.id],
);
const hasSelectedCountries = isDefined(selectedCountries)
&& selectedCountries?.length !== 0;
&& selectedCountries?.length > 0;

return (
<ExpandableContainer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"namespace": "emailPreferences",
"strings": {
"heading": "Email Alert Subscriptions",
"description": "Alerts are powered by Montandon data from GDACS and USGS. You'll receive email alerts with key impact figures and similar past events in the area.",
"emptyMessage": "No subscriptions",
"alertFrequencies": "Alert limit (per day)",
"unlimitedOption": "No limit",
Expand All @@ -10,6 +11,12 @@
"disasters": "Disasters",
"addSubscriptionLabel": "New Alert Subscription",
"editSubscriptionLabel": "Edit",
"editSubscriptionTitle": "Edit Alert Subscription"
"editSubscriptionTitle": "Edit Alert Subscription",
"deleteSubscriptionLabel": "Delete",
"deleteSubscriptionTitle": "Delete Alert Subscription",
"deleteSubscriptionConfirmationHeading": "Delete Alert Subscription",
"deleteSubscriptionConfirmationMessage": "Are you sure you want to delete your subscription?",
"subscriptionDeletedSuccessMessage": "Your subscription has been deleted.",
"subscriptionDeletedFailureMessage": "Subscription could not be deleted."
}
}
74 changes: 63 additions & 11 deletions app/src/views/AccountNotifications/EmailPreferences/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import {
} from 'react';
import {
AddLineIcon,
DeleteBinTwoLineIcon,
PencilLineIcon,
} from '@ifrc-go/icons';
import {
Button,
ConfirmButton,
Container,
ListView,
TextOutput,
Expand All @@ -22,7 +24,11 @@ import {
} from '@togglecorp/fujs';

import useUserMe from '#hooks/domain/useUserMe';
import { useRequest } from '#utils/restRequest';
import useAlert from '#hooks/useAlert';
import {
useLazyRequest,
useRequest,
} from '#utils/restRequest';

import SubscriptionModal from './SubscriptionModal';

Expand All @@ -31,6 +37,7 @@ import i18n from './i18n.json';
function EmailPreferences() {
const user = useUserMe();
const strings = useTranslation(i18n);
const alert = useAlert();

const {
response: subscriptionListResponse,
Expand All @@ -41,6 +48,29 @@ function EmailPreferences() {
method: 'GET',
});

const {
pending: subscriptionDeletePending,
trigger: deleteSubscription,
} = useLazyRequest({
method: 'DELETE',
url: '/api/v2/alert-subscription/{id}/',
pathVariables: ({ id }) => ({ id }),
onSuccess: () => {
refetchSubscriptionList();
alert.show(
strings.subscriptionDeletedSuccessMessage,
{ variant: 'success' },
);
},
onFailure: () => {
alert.show(
strings.subscriptionDeletedFailureMessage,
{ variant: 'danger' },
);
},

});

const subscriptionList = subscriptionListResponse?.results;

const [subscriptionModalVisible, {
Expand All @@ -61,6 +91,10 @@ function EmailPreferences() {
setActiveSubscriptionId(subId);
}, [setActiveSubscriptionId, showSubscriptionModal]);

const handleSubscriptionDelete = useCallback((subId: number) => {
deleteSubscription({ id: subId });
}, [deleteSubscription]);

const handleSubscriptionAddClick = useCallback(() => {
showSubscriptionModal();
setActiveSubscriptionId(undefined);
Expand All @@ -70,6 +104,7 @@ function EmailPreferences() {
<>
<Container
heading={strings.heading}
headerDescription={strings.description}
pending={subscriptionListPending}
empty={isNotDefined(subscriptionList) || subscriptionList?.length === 0}
emptyMessage={strings.emptyMessage}
Expand All @@ -96,16 +131,33 @@ function EmailPreferences() {
withDarkBackground
withPadding
headerActions={(
<Button
name={item.id}
onClick={handleSubscriptionEditClick}
title={strings.editSubscriptionTitle}
before={<PencilLineIcon />}
styleVariant="action"
colorVariant="primary"
>
{strings.editSubscriptionLabel}
</Button>
<>
<Button
name={item.id}
onClick={handleSubscriptionEditClick}
title={strings.editSubscriptionTitle}
before={<PencilLineIcon />}
styleVariant="action"
colorVariant="primary"
>
{strings.editSubscriptionLabel}
</Button>
<ConfirmButton
name={item.id}
styleVariant="action"
colorVariant="primary"
title={strings.deleteSubscriptionTitle}
onConfirm={handleSubscriptionDelete}
// eslint-disable-next-line max-len
confirmHeading={strings.deleteSubscriptionConfirmationHeading}
// eslint-disable-next-line max-len
confirmMessage={strings.deleteSubscriptionConfirmationMessage}
before={<DeleteBinTwoLineIcon />}
disabled={subscriptionDeletePending}
>
{strings.deleteSubscriptionLabel}
</ConfirmButton>
</>
)}
headingLevel={5}
withHeaderBorder
Expand Down
Loading