From cb402fa57e6e954f025af4f981a0cb67275ace7b Mon Sep 17 00:00:00 2001 From: Alexander Petkov Date: Mon, 17 Jun 2024 17:00:21 +0300 Subject: [PATCH 1/5] feat(admin): Add marketing sections Will be used to send and manage marketing emails --- public/locales/bg/marketing.json | 5 ++ public/locales/en/marketing.json | 5 ++ src/common/routes.ts | 4 ++ .../admin/marketing/MarketingPage.tsx | 58 +++++++++++++++++++ .../marketing/navigation/marketingCards.ts | 16 +++++ .../common/navigation/adminMenu.tsx | 6 ++ src/pages/admin/marketing/index.tsx | 6 ++ .../marketing/newsletter-consent/index.tsx | 6 ++ 8 files changed, 106 insertions(+) create mode 100644 public/locales/bg/marketing.json create mode 100644 public/locales/en/marketing.json create mode 100644 src/components/admin/marketing/MarketingPage.tsx create mode 100644 src/components/admin/marketing/navigation/marketingCards.ts create mode 100644 src/pages/admin/marketing/index.tsx create mode 100644 src/pages/admin/marketing/newsletter-consent/index.tsx diff --git a/public/locales/bg/marketing.json b/public/locales/bg/marketing.json new file mode 100644 index 000000000..74906a2d5 --- /dev/null +++ b/public/locales/bg/marketing.json @@ -0,0 +1,5 @@ +{ + "admin": { + "marketing": "Маркетинг" + } +} diff --git a/public/locales/en/marketing.json b/public/locales/en/marketing.json new file mode 100644 index 000000000..f1627b4b8 --- /dev/null +++ b/public/locales/en/marketing.json @@ -0,0 +1,5 @@ +{ + "admin": { + "marketing": "Marketing" + } +} diff --git a/src/common/routes.ts b/src/common/routes.ts index 60a0d6560..c12f3e0ad 100644 --- a/src/common/routes.ts +++ b/src/common/routes.ts @@ -248,6 +248,10 @@ export const routes = { company: { create: '/admin/companies/create', }, + marketing: { + index: '/admin/marketing/', + newsLetterConsent: '/admin/marketing/newsletter-consent', + }, }, dev: { openData: '/open-data', diff --git a/src/components/admin/marketing/MarketingPage.tsx b/src/components/admin/marketing/MarketingPage.tsx new file mode 100644 index 000000000..0eb3b45a8 --- /dev/null +++ b/src/components/admin/marketing/MarketingPage.tsx @@ -0,0 +1,58 @@ +import { Box, Card, CardContent, Container, Grid, Typography } from '@mui/material' +import AdminContainer from 'components/common/navigation/AdminContainer' +import AdminLayout from 'components/common/navigation/AdminLayout' +import React from 'react' +import { useTranslation } from 'next-i18next' +import { adminCards } from 'components/common/navigation/adminMenu' +import Link from 'next/link' +import { marketingCards } from './navigation/marketingCards' + +const colors = ['#0179a8', '#346cb0', '#5f4b8b', '#b76ba3', '#a7c796', '#00a28a', '#3686a0'] +export default function MarketingPage() { + const { t } = useTranslation('marketing') + return ( + + + + + {marketingCards.map(({ label, href, icon: Icon }, index) => ( + + + + + + + + + {label} + + + + + + ))} + + + + + ) +} diff --git a/src/components/admin/marketing/navigation/marketingCards.ts b/src/components/admin/marketing/navigation/marketingCards.ts new file mode 100644 index 000000000..513c6a720 --- /dev/null +++ b/src/components/admin/marketing/navigation/marketingCards.ts @@ -0,0 +1,16 @@ +import { routes } from 'common/routes' +import ThumbUpAltIcon from '@mui/icons-material/ThumbUpAlt' +import SendIcon from '@mui/icons-material/Send' + +export const marketingCards = [ + { + label: 'Изпращане на емайл за съгласие', + icon: ThumbUpAltIcon, + href: routes.admin.marketing.newsLetterConsent, + }, + { + label: 'Изпращане на маркетинг емайл', + icon: SendIcon, + href: routes.admin.marketing.newsLetterConsent, + }, +] diff --git a/src/components/common/navigation/adminMenu.tsx b/src/components/common/navigation/adminMenu.tsx index e9217bc1c..cb13f0f32 100644 --- a/src/components/common/navigation/adminMenu.tsx +++ b/src/components/common/navigation/adminMenu.tsx @@ -14,6 +14,7 @@ import { DisplaySettings, RequestQuote, ArticleOutlined, + BroadcastOnPersonal, } from '@mui/icons-material' import VolunteerActivismOutlinedIcon from '@mui/icons-material/VolunteerActivismOutlined' import LocationCityRoundedIcon from '@mui/icons-material/LocationCityRounded' @@ -105,4 +106,9 @@ export const adminCards = [ icon: HandshakeIcon, href: routes.admin.affiliates, }, + { + label: 'Маркетинг', + icon: BroadcastOnPersonal, + href: routes.admin.marketing.index, + }, ] diff --git a/src/pages/admin/marketing/index.tsx b/src/pages/admin/marketing/index.tsx new file mode 100644 index 000000000..6453df300 --- /dev/null +++ b/src/pages/admin/marketing/index.tsx @@ -0,0 +1,6 @@ +import MarketingPage from 'components/admin/marketing/MarketingPage' +import { securedAdminProps } from 'middleware/auth/securedProps' + +export const getServerSideProps = securedAdminProps(['common', 'auth', 'validation', 'marketing']) + +export default MarketingPage diff --git a/src/pages/admin/marketing/newsletter-consent/index.tsx b/src/pages/admin/marketing/newsletter-consent/index.tsx new file mode 100644 index 000000000..6453df300 --- /dev/null +++ b/src/pages/admin/marketing/newsletter-consent/index.tsx @@ -0,0 +1,6 @@ +import MarketingPage from 'components/admin/marketing/MarketingPage' +import { securedAdminProps } from 'middleware/auth/securedProps' + +export const getServerSideProps = securedAdminProps(['common', 'auth', 'validation', 'marketing']) + +export default MarketingPage From d78fe1c7e7d0a7b436fd5dc5a14ee3438347f438 Mon Sep 17 00:00:00 2001 From: Alexander Petkov Date: Tue, 18 Jun 2024 17:11:54 +0300 Subject: [PATCH 2/5] feat: Add Form to send newsletter consent email --- public/locales/bg/marketing.json | 7 +- public/locales/en/marketing.json | 7 +- .../EmailConsent/SendEmailConsentPage.tsx | 19 ++++ .../admin/marketing/EmailConsent/SendForm.tsx | 98 +++++++++++++++++++ src/gql/marketing.ts | 8 ++ .../marketing/newsletter-consent/index.tsx | 4 +- src/service/apiEndpoints.ts | 1 + src/service/marketing.ts | 18 ++++ 8 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 src/components/admin/marketing/EmailConsent/SendEmailConsentPage.tsx create mode 100644 src/components/admin/marketing/EmailConsent/SendForm.tsx create mode 100644 src/gql/marketing.ts create mode 100644 src/service/marketing.ts diff --git a/public/locales/bg/marketing.json b/public/locales/bg/marketing.json index 74906a2d5..a1d91ae86 100644 --- a/public/locales/bg/marketing.json +++ b/public/locales/bg/marketing.json @@ -1,5 +1,10 @@ { "admin": { - "marketing": "Маркетинг" + "marketing": "Маркетинг", + "sendConsentEmail": "Изпращане на емайл за съгласие", + "common": { + "templateId": "Идентификатор на Sendgrid шаблон", + "listId": "Идентифицатор на Sendgrid списък с контакти" + } } } diff --git a/public/locales/en/marketing.json b/public/locales/en/marketing.json index f1627b4b8..35a56c394 100644 --- a/public/locales/en/marketing.json +++ b/public/locales/en/marketing.json @@ -1,5 +1,10 @@ { "admin": { - "marketing": "Marketing" + "marketing": "Marketing", + "sendConsentEmail": "Send newsletter consent email", + "common": { + "templateId": "ID of Sendgrid template", + "listId": "ID of Sendgrid contact list" + } } } diff --git a/src/components/admin/marketing/EmailConsent/SendEmailConsentPage.tsx b/src/components/admin/marketing/EmailConsent/SendEmailConsentPage.tsx new file mode 100644 index 000000000..bd895281a --- /dev/null +++ b/src/components/admin/marketing/EmailConsent/SendEmailConsentPage.tsx @@ -0,0 +1,19 @@ +import AdminContainer from 'components/common/navigation/AdminContainer' +import AdminLayout from 'components/common/navigation/AdminLayout' +import React from 'react' +import SendForm from './SendForm' +import { useTranslation } from 'next-i18next' +import { Container } from '@mui/material' + +export default function SendEmailConsentPage() { + const { t } = useTranslation('marketing') + return ( + + + + + + + + ) +} diff --git a/src/components/admin/marketing/EmailConsent/SendForm.tsx b/src/components/admin/marketing/EmailConsent/SendForm.tsx new file mode 100644 index 000000000..4a0483610 --- /dev/null +++ b/src/components/admin/marketing/EmailConsent/SendForm.tsx @@ -0,0 +1,98 @@ +import { Box, Button, Grid, Typography } from '@mui/material' +import { useMutation } from '@tanstack/react-query' +import { AxiosError, AxiosResponse } from 'axios' +import { routes } from 'common/routes' +import FormDatePicker from 'components/common/form/FormDatePicker' +import FormTextField from 'components/common/form/FormTextField' +import GenericForm from 'components/common/form/GenericForm' +import SubmitButton from 'components/common/form/SubmitButton' +import { SendNewsLetterConsent } from 'gql/marketing' +import { useTranslation } from 'next-i18next' +import Link from 'next/link' +import { useRouter } from 'next/router' +import { ApiErrors } from 'service/apiErrors' +import { useSendConsentEmail } from 'service/marketing' +import { AlertStore } from 'stores/AlertStore' +import * as yup from 'yup' + +export default function EditForm() { + const router = useRouter() + const { t } = useTranslation('marketing') + + const initialValues: SendNewsLetterConsent = { + templateId: '', + listId: '', + dateThreshold: undefined, + } + + const validationSchema: yup.SchemaOf = yup.object().defined().shape({ + templateId: yup.string().required(), + listId: yup.string().required(), + dateThreshold: yup.string().optional(), + }) + + const mutationFn = useSendConsentEmail() + + const handleError = (e: AxiosError) => { + AlertStore.show(t(e.message), 'error') + } + + const mutation = useMutation, AxiosError, SendNewsLetterConsent>({ + mutationFn, + onError: (error) => handleError(error), + onSuccess: (data) => { + AlertStore.show(t(`Емайлът беше изпратен успешно на ${data.data} емайла.`), 'success') + router.push(routes.admin.marketing.index) + }, + }) + + async function onSubmit(values: SendNewsLetterConsent) { + const data: SendNewsLetterConsent = { + templateId: values.templateId, + listId: values.listId, + dateThreshold: values.dateThreshold, + } + mutation.mutate(data) + } + + return ( + + + + {t('admin.sendConsentEmail')} + + + + + + + + + + + + + Премахване от списък на потребители регистрирани след: + + + + + + + + + + + + + ) +} diff --git a/src/gql/marketing.ts b/src/gql/marketing.ts new file mode 100644 index 000000000..2869b241f --- /dev/null +++ b/src/gql/marketing.ts @@ -0,0 +1,8 @@ +export type SendMarketingEmail = { + templateId: string + listId: string +} + +export type SendNewsLetterConsent = SendMarketingEmail & { + dateThreshold?: string +} diff --git a/src/pages/admin/marketing/newsletter-consent/index.tsx b/src/pages/admin/marketing/newsletter-consent/index.tsx index 6453df300..efcbe5b35 100644 --- a/src/pages/admin/marketing/newsletter-consent/index.tsx +++ b/src/pages/admin/marketing/newsletter-consent/index.tsx @@ -1,6 +1,6 @@ -import MarketingPage from 'components/admin/marketing/MarketingPage' +import SendEmailConsentPage from 'components/admin/marketing/EmailConsent/SendEmailConsentPage' import { securedAdminProps } from 'middleware/auth/securedProps' export const getServerSideProps = securedAdminProps(['common', 'auth', 'validation', 'marketing']) -export default MarketingPage +export default SendEmailConsentPage diff --git a/src/service/apiEndpoints.ts b/src/service/apiEndpoints.ts index b4fad72e2..629235b41 100644 --- a/src/service/apiEndpoints.ts +++ b/src/service/apiEndpoints.ts @@ -65,6 +65,7 @@ export const endpoints = { notifications: { sendConfirmationEmail: { url: '/notifications/send-confirm-email', method: 'POST' }, subscribePublicEmail: { url: '/notifications/public/subscribe', method: 'POST' }, + sendNewsLetterConsentEmail: { url: '/notifications/send-newsletter-consent' }, unsubscribePublicEmail: { url: '/notifications/public/unsubscribe', method: 'POST' }, subscribeEmail: { url: '/notifications/subscribe', method: 'POST' }, unsubscribeEmail: { url: '/notifications/unsubscribe', method: 'POST' }, diff --git a/src/service/marketing.ts b/src/service/marketing.ts new file mode 100644 index 000000000..00de79dcc --- /dev/null +++ b/src/service/marketing.ts @@ -0,0 +1,18 @@ +import { SendNewsLetterConsent } from 'gql/marketing' +import { SendConfirmationEmailInput } from 'gql/notification' +import { useSession } from 'next-auth/react' +import { authConfig } from './restRequests' +import { endpoints } from './apiEndpoints' +import { apiClient } from './apiClient' +import { AxiosResponse } from 'axios' + +export function useSendConsentEmail() { + const { data: session } = useSession() + return async (data: SendNewsLetterConsent) => { + return await apiClient.post>( + endpoints.notifications.sendNewsLetterConsentEmail.url, + data, + authConfig(session?.accessToken), + ) + } +} From db1b07c2e5ec818996d319dabc960fa22f1c4937 Mon Sep 17 00:00:00 2001 From: Alexander Petkov Date: Tue, 18 Jun 2024 18:14:14 +0300 Subject: [PATCH 3/5] ui: Form improvements --- src/components/admin/cities/CreateForm.tsx | 6 ++++-- .../admin/marketing/EmailConsent/SendForm.tsx | 18 +++++++++++++----- .../admin/marketing/MarketingPage.tsx | 9 +++++---- .../marketing/navigation/marketingCards.ts | 2 ++ src/service/apiErrors.ts | 2 +- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/components/admin/cities/CreateForm.tsx b/src/components/admin/cities/CreateForm.tsx index 9d46544ec..4866935e8 100644 --- a/src/components/admin/cities/CreateForm.tsx +++ b/src/components/admin/cities/CreateForm.tsx @@ -9,7 +9,7 @@ import { Box, Button, Grid, Typography } from '@mui/material' import { CityFormData, CityInput, CityResponse } from 'gql/cities' import { routes } from 'common/routes' -import { ApiErrors, handleUniqueViolation } from 'service/apiErrors' +import { ApiErrors, Message, handleUniqueViolation } from 'service/apiErrors' import { useCreateCity } from 'service/city' import { AlertStore } from 'stores/AlertStore' import GenericForm from 'components/common/form/GenericForm' @@ -42,7 +42,9 @@ export default function EditForm() { const error = e.response if (error?.status === 409) { - const message = error.data.message.map((el) => handleUniqueViolation(el.constraints, t)) + const message = (error.data.message as Message[]).map((el) => + handleUniqueViolation(el.constraints, t), + ) return AlertStore.show(message.join('/n'), 'error') } diff --git a/src/components/admin/marketing/EmailConsent/SendForm.tsx b/src/components/admin/marketing/EmailConsent/SendForm.tsx index 4a0483610..aaf46fdc8 100644 --- a/src/components/admin/marketing/EmailConsent/SendForm.tsx +++ b/src/components/admin/marketing/EmailConsent/SendForm.tsx @@ -6,6 +6,7 @@ import FormDatePicker from 'components/common/form/FormDatePicker' import FormTextField from 'components/common/form/FormTextField' import GenericForm from 'components/common/form/GenericForm' import SubmitButton from 'components/common/form/SubmitButton' +import { FormikHelpers } from 'formik' import { SendNewsLetterConsent } from 'gql/marketing' import { useTranslation } from 'next-i18next' import Link from 'next/link' @@ -22,7 +23,7 @@ export default function EditForm() { const initialValues: SendNewsLetterConsent = { templateId: '', listId: '', - dateThreshold: undefined, + dateThreshold: new Date().toISOString(), } const validationSchema: yup.SchemaOf = yup.object().defined().shape({ @@ -34,7 +35,8 @@ export default function EditForm() { const mutationFn = useSendConsentEmail() const handleError = (e: AxiosError) => { - AlertStore.show(t(e.message), 'error') + const error = e.response + AlertStore.show(t(error?.data.message as string), 'error') } const mutation = useMutation, AxiosError, SendNewsLetterConsent>({ @@ -42,17 +44,23 @@ export default function EditForm() { onError: (error) => handleError(error), onSuccess: (data) => { AlertStore.show(t(`Емайлът беше изпратен успешно на ${data.data} емайла.`), 'success') - router.push(routes.admin.marketing.index) }, }) - async function onSubmit(values: SendNewsLetterConsent) { + async function onSubmit( + values: SendNewsLetterConsent, + formikHelpers: FormikHelpers, + ) { const data: SendNewsLetterConsent = { templateId: values.templateId, listId: values.listId, dateThreshold: values.dateThreshold, } - mutation.mutate(data) + await mutation.mutateAsync(data) + if (mutation.isSuccess && !mutation.isLoading) { + console.log(mutation.isSuccess) + formikHelpers.resetForm({ values: initialValues }) + } } return ( diff --git a/src/components/admin/marketing/MarketingPage.tsx b/src/components/admin/marketing/MarketingPage.tsx index 0eb3b45a8..1989cac53 100644 --- a/src/components/admin/marketing/MarketingPage.tsx +++ b/src/components/admin/marketing/MarketingPage.tsx @@ -1,4 +1,4 @@ -import { Box, Card, CardContent, Container, Grid, Typography } from '@mui/material' +import { Box, Button, Card, CardContent, Container, Grid, Typography } from '@mui/material' import AdminContainer from 'components/common/navigation/AdminContainer' import AdminLayout from 'components/common/navigation/AdminLayout' import React from 'react' @@ -15,9 +15,10 @@ export default function MarketingPage() { - {marketingCards.map(({ label, href, icon: Icon }, index) => ( + {marketingCards.map(({ label, href, icon: Icon, disabled }, index) => ( - - + ))} diff --git a/src/components/admin/marketing/navigation/marketingCards.ts b/src/components/admin/marketing/navigation/marketingCards.ts index 513c6a720..321c9d95d 100644 --- a/src/components/admin/marketing/navigation/marketingCards.ts +++ b/src/components/admin/marketing/navigation/marketingCards.ts @@ -7,10 +7,12 @@ export const marketingCards = [ label: 'Изпращане на емайл за съгласие', icon: ThumbUpAltIcon, href: routes.admin.marketing.newsLetterConsent, + disabled: false, }, { label: 'Изпращане на маркетинг емайл', icon: SendIcon, href: routes.admin.marketing.newsLetterConsent, + disabled: true, }, ] diff --git a/src/service/apiErrors.ts b/src/service/apiErrors.ts index d0f3f76d8..cef085333 100644 --- a/src/service/apiErrors.ts +++ b/src/service/apiErrors.ts @@ -6,7 +6,7 @@ export { isAxiosError } export interface ApiErrors { statusCode: number - message: Message[] + message: Message[] | string error: string } From ef43c2b4aa9a5a1b1ae7b63062047e51b613d1c1 Mon Sep 17 00:00:00 2001 From: Alexander Petkov Date: Wed, 19 Jun 2024 13:11:54 +0300 Subject: [PATCH 4/5] fix: Build issues --- ...{SendForm.tsx => SendEmailConsentForm.tsx} | 33 +++++++++++-------- .../EmailConsent/SendEmailConsentPage.tsx | 4 +-- .../admin/marketing/MarketingPage.tsx | 3 +- src/gql/marketing.ts | 4 +++ src/service/apiErrors.ts | 2 +- src/service/marketing.ts | 6 ++-- 6 files changed, 29 insertions(+), 23 deletions(-) rename src/components/admin/marketing/EmailConsent/{SendForm.tsx => SendEmailConsentForm.tsx} (79%) diff --git a/src/components/admin/marketing/EmailConsent/SendForm.tsx b/src/components/admin/marketing/EmailConsent/SendEmailConsentForm.tsx similarity index 79% rename from src/components/admin/marketing/EmailConsent/SendForm.tsx rename to src/components/admin/marketing/EmailConsent/SendEmailConsentForm.tsx index aaf46fdc8..83c2c4ff1 100644 --- a/src/components/admin/marketing/EmailConsent/SendForm.tsx +++ b/src/components/admin/marketing/EmailConsent/SendEmailConsentForm.tsx @@ -1,4 +1,4 @@ -import { Box, Button, Grid, Typography } from '@mui/material' +import { Button, Grid, Typography } from '@mui/material' import { useMutation } from '@tanstack/react-query' import { AxiosError, AxiosResponse } from 'axios' import { routes } from 'common/routes' @@ -7,17 +7,15 @@ import FormTextField from 'components/common/form/FormTextField' import GenericForm from 'components/common/form/GenericForm' import SubmitButton from 'components/common/form/SubmitButton' import { FormikHelpers } from 'formik' -import { SendNewsLetterConsent } from 'gql/marketing' +import { NewsLetterConsentResponse, SendNewsLetterConsent } from 'gql/marketing' import { useTranslation } from 'next-i18next' import Link from 'next/link' -import { useRouter } from 'next/router' -import { ApiErrors } from 'service/apiErrors' +import { ApiError } from 'service/apiErrors' import { useSendConsentEmail } from 'service/marketing' import { AlertStore } from 'stores/AlertStore' import * as yup from 'yup' -export default function EditForm() { - const router = useRouter() +export default function SendConsentEmailForm() { const { t } = useTranslation('marketing') const initialValues: SendNewsLetterConsent = { @@ -34,16 +32,24 @@ export default function EditForm() { const mutationFn = useSendConsentEmail() - const handleError = (e: AxiosError) => { - const error = e.response - AlertStore.show(t(error?.data.message as string), 'error') + const handleError = (e: AxiosError) => { + const error = e.response as AxiosResponse + AlertStore.show(error.data.message, 'error') } - const mutation = useMutation, AxiosError, SendNewsLetterConsent>({ + const mutation = useMutation< + AxiosResponse, + AxiosError, + SendNewsLetterConsent + >({ mutationFn, onError: (error) => handleError(error), onSuccess: (data) => { - AlertStore.show(t(`Емайлът беше изпратен успешно на ${data.data} емайла.`), 'success') + const response = data.data + AlertStore.show( + t(`Съобщението беше изпратен успешно на ${response.contactCount} емайла.`), + 'success', + ) }, }) @@ -58,7 +64,6 @@ export default function EditForm() { } await mutation.mutateAsync(data) if (mutation.isSuccess && !mutation.isLoading) { - console.log(mutation.isSuccess) formikHelpers.resetForm({ values: initialValues }) } } @@ -88,13 +93,13 @@ export default function EditForm() { direction={'row'} justifyContent={'space-between'} alignItems={'center'}> - + Премахване от списък на потребители регистрирани след: - + diff --git a/src/components/admin/marketing/EmailConsent/SendEmailConsentPage.tsx b/src/components/admin/marketing/EmailConsent/SendEmailConsentPage.tsx index bd895281a..db670ca40 100644 --- a/src/components/admin/marketing/EmailConsent/SendEmailConsentPage.tsx +++ b/src/components/admin/marketing/EmailConsent/SendEmailConsentPage.tsx @@ -1,7 +1,7 @@ import AdminContainer from 'components/common/navigation/AdminContainer' import AdminLayout from 'components/common/navigation/AdminLayout' import React from 'react' -import SendForm from './SendForm' +import SendEmailConsentForm from './SendEmailConsentForm' import { useTranslation } from 'next-i18next' import { Container } from '@mui/material' @@ -11,7 +11,7 @@ export default function SendEmailConsentPage() { - + diff --git a/src/components/admin/marketing/MarketingPage.tsx b/src/components/admin/marketing/MarketingPage.tsx index 1989cac53..394f9587d 100644 --- a/src/components/admin/marketing/MarketingPage.tsx +++ b/src/components/admin/marketing/MarketingPage.tsx @@ -1,9 +1,8 @@ -import { Box, Button, Card, CardContent, Container, Grid, Typography } from '@mui/material' +import { Box, Button, CardContent, Container, Grid, Typography } from '@mui/material' import AdminContainer from 'components/common/navigation/AdminContainer' import AdminLayout from 'components/common/navigation/AdminLayout' import React from 'react' import { useTranslation } from 'next-i18next' -import { adminCards } from 'components/common/navigation/adminMenu' import Link from 'next/link' import { marketingCards } from './navigation/marketingCards' diff --git a/src/gql/marketing.ts b/src/gql/marketing.ts index 2869b241f..7547091c8 100644 --- a/src/gql/marketing.ts +++ b/src/gql/marketing.ts @@ -6,3 +6,7 @@ export type SendMarketingEmail = { export type SendNewsLetterConsent = SendMarketingEmail & { dateThreshold?: string } + +export type NewsLetterConsentResponse = { + contactCount: number +} diff --git a/src/service/apiErrors.ts b/src/service/apiErrors.ts index cef085333..d0f3f76d8 100644 --- a/src/service/apiErrors.ts +++ b/src/service/apiErrors.ts @@ -6,7 +6,7 @@ export { isAxiosError } export interface ApiErrors { statusCode: number - message: Message[] | string + message: Message[] error: string } diff --git a/src/service/marketing.ts b/src/service/marketing.ts index 00de79dcc..91e3bc211 100644 --- a/src/service/marketing.ts +++ b/src/service/marketing.ts @@ -1,15 +1,13 @@ -import { SendNewsLetterConsent } from 'gql/marketing' -import { SendConfirmationEmailInput } from 'gql/notification' +import { NewsLetterConsentResponse, SendNewsLetterConsent } from 'gql/marketing' import { useSession } from 'next-auth/react' import { authConfig } from './restRequests' import { endpoints } from './apiEndpoints' import { apiClient } from './apiClient' -import { AxiosResponse } from 'axios' export function useSendConsentEmail() { const { data: session } = useSession() return async (data: SendNewsLetterConsent) => { - return await apiClient.post>( + return await apiClient.post( endpoints.notifications.sendNewsLetterConsentEmail.url, data, authConfig(session?.accessToken), From 515efe102ac9a3d6fe30ef916d028da9bc73a027 Mon Sep 17 00:00:00 2001 From: Alexander Petkov Date: Wed, 19 Jun 2024 13:36:24 +0300 Subject: [PATCH 5/5] feat: Add email subject to form Will be used if subject is set dynamically to sendgrid --- public/locales/bg/marketing.json | 3 ++- public/locales/en/marketing.json | 3 ++- .../admin/marketing/EmailConsent/SendEmailConsentForm.tsx | 6 ++++++ src/gql/marketing.ts | 1 + 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/public/locales/bg/marketing.json b/public/locales/bg/marketing.json index a1d91ae86..54cfa08cd 100644 --- a/public/locales/bg/marketing.json +++ b/public/locales/bg/marketing.json @@ -4,7 +4,8 @@ "sendConsentEmail": "Изпращане на емайл за съгласие", "common": { "templateId": "Идентификатор на Sendgrid шаблон", - "listId": "Идентифицатор на Sendgrid списък с контакти" + "listId": "Идентифицатор на Sendgrid списък с контакти", + "subject": "Тема на емайл" } } } diff --git a/public/locales/en/marketing.json b/public/locales/en/marketing.json index 35a56c394..43bc2206b 100644 --- a/public/locales/en/marketing.json +++ b/public/locales/en/marketing.json @@ -4,7 +4,8 @@ "sendConsentEmail": "Send newsletter consent email", "common": { "templateId": "ID of Sendgrid template", - "listId": "ID of Sendgrid contact list" + "listId": "ID of Sendgrid contact list", + "subject": "Email subject" } } } diff --git a/src/components/admin/marketing/EmailConsent/SendEmailConsentForm.tsx b/src/components/admin/marketing/EmailConsent/SendEmailConsentForm.tsx index 83c2c4ff1..0e8b5fa53 100644 --- a/src/components/admin/marketing/EmailConsent/SendEmailConsentForm.tsx +++ b/src/components/admin/marketing/EmailConsent/SendEmailConsentForm.tsx @@ -21,12 +21,14 @@ export default function SendConsentEmailForm() { const initialValues: SendNewsLetterConsent = { templateId: '', listId: '', + subject: '', dateThreshold: new Date().toISOString(), } const validationSchema: yup.SchemaOf = yup.object().defined().shape({ templateId: yup.string().required(), listId: yup.string().required(), + subject: yup.string().required(), dateThreshold: yup.string().optional(), }) @@ -60,6 +62,7 @@ export default function SendConsentEmailForm() { const data: SendNewsLetterConsent = { templateId: values.templateId, listId: values.listId, + subject: values.subject, dateThreshold: values.dateThreshold, } await mutation.mutateAsync(data) @@ -86,6 +89,9 @@ export default function SendConsentEmailForm() { + + +