diff --git a/src/views/Home/AlertsMap/index.tsx b/src/views/Home/AlertsMap/index.tsx index bab79f74..24bdabbe 100644 --- a/src/views/Home/AlertsMap/index.tsx +++ b/src/views/Home/AlertsMap/index.tsx @@ -188,13 +188,14 @@ export function Component() { ); const defaultSubscription = useMemo(() => ({ - id: '', - title: '', - urgency: selectedUrgencyTypes, - severity: selectedSeverityTypes, - certainty: selectedCertaintyTypes, - country: activeCountryId, - admin1: activeAdmin1Id, + name: '', + alertFilters: { + urgency: selectedUrgencyTypes, + severity: selectedSeverityTypes, + certainty: selectedCertaintyTypes, + country: activeCountryId ?? '', + admin1s: activeAdmin1Id ? [activeAdmin1Id] : [], + }, }), [ selectedUrgencyTypes, selectedSeverityTypes, diff --git a/src/views/Home/AlertsTable/index.tsx b/src/views/Home/AlertsTable/index.tsx index db1311c9..6b0ae9f2 100644 --- a/src/views/Home/AlertsTable/index.tsx +++ b/src/views/Home/AlertsTable/index.tsx @@ -288,13 +288,14 @@ export function Component() { ); const defaultSubscription = useMemo(() => ({ - id: '', - title: '', - urgency: selectedUrgencyTypes, - severity: selectedSeverityTypes, - certainty: selectedCertaintyTypes, - country: activeCountryId, - admin1: activeAdmin1Id, + name: '', + alertFilters: { + urgency: selectedUrgencyTypes, + severity: selectedSeverityTypes, + certainty: selectedCertaintyTypes, + country: activeCountryId ?? '', + admin1s: activeAdmin1Id ? [activeAdmin1Id] : [], + }, }), [ selectedUrgencyTypes, selectedSeverityTypes, diff --git a/src/views/NewSubscriptionModal/i18n.json b/src/views/NewSubscriptionModal/i18n.json index b687099f..baf9706a 100644 --- a/src/views/NewSubscriptionModal/i18n.json +++ b/src/views/NewSubscriptionModal/i18n.json @@ -8,6 +8,8 @@ "filterUrgencyPlaceholder": "All Urgency Types", "filterSeverityPlaceholder": "All Severity Types", "filterCertaintyPlaceholder": "All Certainty Types", + "filterCategoryPlaceholder": "All Category Types", + "filterCategoryLabel": "Category", "filterCountriesLabel": "Country", "filterAdmin1Label": "Admin1", "filterUrgencyLabel": "Urgency Level", @@ -16,6 +18,8 @@ "filterRegionsLabel": "Regions", "filterRegionsPlaceholder": "All Regions", "newSubscriptionHeading": "New Subscription", - "newSubscriptionTitle": "Title" + "newSubscriptionTitle": "Title", + "newSubscriptionCreatedSucessfully": "Subscription created successfully.", + "newSubscriptionFailed": "Failed to create subscription" } } \ No newline at end of file diff --git a/src/views/NewSubscriptionModal/index.tsx b/src/views/NewSubscriptionModal/index.tsx index 1c361c91..1e538b4e 100644 --- a/src/views/NewSubscriptionModal/index.tsx +++ b/src/views/NewSubscriptionModal/index.tsx @@ -4,6 +4,7 @@ import { } from 'react'; import { gql, + useMutation, useQuery, } from '@apollo/client'; import { @@ -18,35 +19,39 @@ import { import { useTranslation } from '@ifrc-go/ui/hooks'; import { isNotDefined } from '@togglecorp/fujs'; import { + createSubmitHandler, getErrorObject, + getErrorString, type ObjectSchema, type PartialForm, requiredCondition, requiredStringCondition, useForm, + useFormObject, } from '@togglecorp/toggle-form'; import { - AlertEnumsAndAllCountryListQuery, - AlertEnumsAndAllCountryListQueryVariables, + AlertEnumsAndAllCountriesQuery, + AlertEnumsAndAllCountriesQueryVariables, AlertEnumsQuery, + AppEnumCollection, + CreateUserAlertSubscriptionMutation, + CreateUserAlertSubscriptionMutationVariables, FilteredAdminListQuery, FilteredAdminListQueryVariables, + UserAlertSubscriptionInput, } from '#generated/types/graphql'; +import useAlert from '#hooks/useAlert'; import { stringIdSelector, stringNameSelector, } from '#utils/selectors'; -import { - FrequencyOption, - SubscriptionDetail, -} from '#views/MySubscription/common'; import i18n from './i18n.json'; import styles from './styles.module.css'; -const ALERT_ENUMS_AND_ALL_COUNTRY = gql` -query AlertEnumsAndAllCountryList { +const ALERT_ENUMS_AND_ALL_COUNTIES = gql` +query AlertEnumsAndAllCountries { enums { AlertInfoCertainty { key @@ -64,6 +69,10 @@ query AlertEnumsAndAllCountryList { key label } + UserAlertSubscriptionEmailFrequency { + key + label + } } public { id @@ -91,67 +100,94 @@ query FilteredAdminList($filters:Admin1Filter, $pagination: OffsetPaginationInpu } `; +const CREATE_USER_ALERT_SUBSCRIPTION = gql` +mutation CreateUserAlertSubscription( + $data: UserAlertSubscriptionInput!, +) { + private { + id + createUserAlertSubcription(data: $data){ + errors + ok + result { + id + name + alertFilters + emailFrequency + notifyByEmail + emailFrequencyDisplay + } + } + } +} +`; + type AdminOption = NonNullable['admin1s']>['items']>[number]; type Urgency = NonNullable[number]; type Severity = NonNullable[number]; type Certainty = NonNullable[number]; +type Category = NonNullable[number]; -interface AlertFilters { - key: string; - label: string; -} +type EmailFrequency = NonNullable[number]; const adminKeySelector = (admin1: AdminOption) => admin1.id; const urgencyKeySelector = (urgency: Urgency) => urgency.key; +const urgencyLabelSelector = (urgency: Urgency) => urgency.label; + const severityKeySelector = (severity: Severity) => severity.key; +const severityLabelSelector = (severity: Severity) => severity.label; + const certaintyKeySelector = (certainty: Certainty) => certainty.key; -const labelSelector = (alert: AlertFilters) => alert.label; +const certaintyLabelSelector = (certainty: Certainty) => certainty.label; -const frequencyKeySelector = (frequency: FrequencyOption) => frequency.key; -const frequencyLabelSelector = (frequency: FrequencyOption) => frequency.label; +const frequencyKeySelector = (frequency: EmailFrequency) => frequency.key; +const frequencyLabelSelector = (frequency: EmailFrequency) => frequency.label; -const frequencyOption: FrequencyOption[] = [ - { label: 'Daily', key: 'daily' }, - { label: 'Weekly', key: 'weekly' }, -]; +const categoryKeySelector = (category: Category) => category.key; +const categoryLabelSelector = (category: Category) => category.label; -type PartialFormFields = PartialForm; +type PartialFormFields = PartialForm; + +type AlertFilterType = ObjectSchema; +type AlertFilterTypeFields = ReturnType type FormSchema = ObjectSchema; type FormSchemaFields = ReturnType const formSchema: FormSchema = { fields: (): FormSchemaFields => ({ - title: { + name: { required: true, requiredValidation: requiredStringCondition, }, - urgency: { - required: true, - requiredValidation: requiredCondition, - }, - severity: { - required: true, - requiredValidation: requiredCondition, - }, - certainty: { - required: true, - requiredValidation: requiredCondition, - }, - country: { - required: true, - requiredValidation: requiredCondition, - }, - admin1: { - required: true, - requiredValidation: requiredCondition, + alertFilters: { + fields: (): AlertFilterTypeFields => ({ + admin1s: { + required: true, + }, + urgency: { + required: true, + }, + certainty: { + required: true, + }, + category: { + required: true, + }, + severity: { + required: true, + }, + country: { + required: true, + }, + }), }, - sendEmail: { + notifyByEmail: { required: true, requiredValidation: requiredCondition, }, - frequency: { + emailFrequency: { required: true, requiredValidation: requiredCondition, }, @@ -159,8 +195,8 @@ const formSchema: FormSchema = { }; interface Props { - subscription?: SubscriptionDetail; - onCloseModal?: () => void; + subscription?: UserAlertSubscriptionInput; + onCloseModal: () => void; } function NewSubscriptionModal(props: Props) { @@ -172,14 +208,17 @@ function NewSubscriptionModal(props: Props) { const strings = useTranslation(i18n); const defaultFormValue = useMemo(() => ({ - title: subscription?.title, - urgency: subscription?.urgency, - severity: subscription?.severity, - certainty: subscription?.certainty, - sendEmail: subscription?.sendEmail, - frequency: subscription?.frequency, - country: subscription?.country, - admin1: subscription?.admin1, + name: subscription?.name, + notifyByEmail: subscription?.notifyByEmail, + emailFrequency: subscription?.emailFrequency, + alertFilters: { + urgency: subscription?.alertFilters?.urgency, + severity: subscription?.alertFilters?.severity, + certainty: subscription?.alertFilters?.certainty, + category: subscription?.alertFilters?.category, + country: subscription?.alertFilters?.country, + admin1s: subscription?.alertFilters?.admin1s, + }, }), [ subscription, ]); @@ -188,21 +227,67 @@ function NewSubscriptionModal(props: Props) { value, setFieldValue, error: formError, - // setError, - // validate, + setError, + validate, } = useForm(formSchema, { value: defaultFormValue }); const fieldError = getErrorObject(formError); + const filterError = getErrorObject(fieldError?.alertFilters); + + const alert = useAlert(); + + const setAlertFilterValue = useFormObject<'alertFilters', NonNullable>( + 'alertFilters' as const, + setFieldValue, + {}, + ); + + const [ + createAlertSubscription, + { loading: loadingSubscription }, + ] = useMutation< + CreateUserAlertSubscriptionMutation, + CreateUserAlertSubscriptionMutationVariables + >( + CREATE_USER_ALERT_SUBSCRIPTION, + { + onCompleted: (res) => { + const response = res.private.createUserAlertSubcription; + if (!response) { + return; + } + if (response.ok) { + alert.show( + strings.newSubscriptionCreatedSucessfully, + { variant: 'success' }, + ); + onCloseModal(); + } else { + alert.show( + strings.newSubscriptionFailed, + { variant: 'danger' }, + ); + } + }, + onError: () => { + alert.show( + strings.newSubscriptionFailed, + { variant: 'danger' }, + ); + }, + }, + ); + const { data: alertEnumsResponse, - } = useQuery( - ALERT_ENUMS_AND_ALL_COUNTRY, + } = useQuery( + ALERT_ENUMS_AND_ALL_COUNTIES, ); const adminQueryVariables = useMemo( () => { - if (isNotDefined(value.country)) { + if (isNotDefined(value.alertFilters?.country)) { return { filters: undefined, // FIXME: Implement search select input @@ -215,7 +300,7 @@ function NewSubscriptionModal(props: Props) { return { filters: { - country: { pk: value.country }, + country: { pk: value.alertFilters.country }, }, // FIXME: Implement search select input pagination: { @@ -224,20 +309,36 @@ function NewSubscriptionModal(props: Props) { }, }; }, - [value.country], + [value.alertFilters?.country], ); const { data: adminResponse, } = useQuery( ADMIN_LIST, - { variables: adminQueryVariables, skip: isNotDefined(value.country) }, + { variables: adminQueryVariables, skip: isNotDefined(value.alertFilters?.country) }, ); const subscriptionCreate = useCallback(() => { - // eslint-disable-next-line no-console - console.info('create'); - }, []); + const handler = createSubmitHandler( + validate, + setError, + (val) => { + createAlertSubscription({ + variables: { + data: val as UserAlertSubscriptionInput, + }, + }); + }, + ); + handler(); + }, [ + setError, + createAlertSubscription, + validate, + ]); + + const handleFormSubmit = createSubmitHandler(validate, setError, subscriptionCreate); return ( {strings.createNewSubscription} @@ -258,10 +359,10 @@ function NewSubscriptionModal(props: Props) { onClose={onCloseModal} > @@ -272,9 +373,11 @@ function NewSubscriptionModal(props: Props) { name="urgency" options={alertEnumsResponse?.enums.AlertInfoUrgency} keySelector={urgencyKeySelector} - labelSelector={labelSelector} - value={value.urgency} - onChange={setFieldValue} + labelSelector={urgencyLabelSelector} + value={value.alertFilters?.urgency} + onChange={setAlertFilterValue} + error={filterError?.urgency} + withAsterisk /> + - );