From 0732f3890dce1af938a834ccda678909c6b584da Mon Sep 17 00:00:00 2001 From: Kevin Foong Date: Tue, 15 Oct 2024 18:27:52 +0800 Subject: [PATCH] feat: port approval status to mrf completion email --- .../multirespondent-submission.service.ts | 11 ++- src/app/services/mail/mail.service.ts | 9 +- .../templates/MrfApprovalOutcomeEmail.tsx | 90 ------------------- .../templates/MrfWorkflowCompletionEmail.tsx | 22 ++++- src/app/views/templates/styles.ts | 16 +++- 5 files changed, 44 insertions(+), 104 deletions(-) delete mode 100644 src/app/views/templates/MrfApprovalOutcomeEmail.tsx diff --git a/src/app/modules/submission/multirespondent-submission/multirespondent-submission.service.ts b/src/app/modules/submission/multirespondent-submission/multirespondent-submission.service.ts index a172cb2c11..37ff4909a6 100644 --- a/src/app/modules/submission/multirespondent-submission/multirespondent-submission.service.ts +++ b/src/app/modules/submission/multirespondent-submission/multirespondent-submission.service.ts @@ -240,6 +240,11 @@ const sendMrfOutcomeEmails = ({ return okAsync(true) } + const formQuestionAnswers = getQuestionTitleAnswerString({ + formFields: form.form_fields, + responses, + }) + if (isApproval) { return MailService.sendMrfApprovalEmail({ emails: destinationEmails, @@ -247,6 +252,7 @@ const sendMrfOutcomeEmails = ({ formTitle: form.title, responseId: submissionId, isRejected, + formQuestionAnswers, }).orElse((error) => { logger.error({ message: 'Failed to send approval email', @@ -265,10 +271,7 @@ const sendMrfOutcomeEmails = ({ formId: form._id, formTitle: form.title, responseId: submissionId, - formQuestionAnswers: getQuestionTitleAnswerString({ - formFields: form.form_fields, - responses, - }), + formQuestionAnswers, }).orElse((error) => { logger.error({ message: 'Failed to send workflow completion email', diff --git a/src/app/services/mail/mail.service.ts b/src/app/services/mail/mail.service.ts index d44f7ec4fa..96c2bd7a87 100644 --- a/src/app/services/mail/mail.service.ts +++ b/src/app/services/mail/mail.service.ts @@ -33,11 +33,9 @@ import { getAdminEmails, } from '../../modules/form/form.utils' import { formatAsPercentage } from '../../utils/formatters' -import MrfApprovalOutcomeEmail, { - WorkflowOutcome, -} from '../../views/templates/MrfApprovalOutcomeEmail' import MrfWorkflowCompletionEmail, { QuestionAnswer, + WorkflowOutcome, } from '../../views/templates/MrfWorkflowCompletionEmail' import MrfWorkflowEmail, { WorkflowEmailData, @@ -1138,12 +1136,14 @@ export class MailService { formTitle, responseId, isRejected, + formQuestionAnswers, }: { emails: string[] formId: string formTitle: string responseId: string isRejected: boolean + formQuestionAnswers: QuestionAnswer[] }) => { const outcome = isRejected ? WorkflowOutcome.NOT_APPROVED @@ -1152,9 +1152,10 @@ export class MailService { formTitle, responseId: responseId.toString(), outcome, + formQuestionAnswers, } - const html = render(MrfApprovalOutcomeEmail(htmlData)) + const html = render(MrfWorkflowCompletionEmail(htmlData)) const mail: MailOptions = { to: emails, diff --git a/src/app/views/templates/MrfApprovalOutcomeEmail.tsx b/src/app/views/templates/MrfApprovalOutcomeEmail.tsx deleted file mode 100644 index 5ec35f4a43..0000000000 --- a/src/app/views/templates/MrfApprovalOutcomeEmail.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { - Body, - Column, - Container, - Head, - Heading, - Hr, - Html, - Img, - Row, - Text, -} from '@react-email/components' -import { FORMSG_LOGO_URL } from '../../constants/formsg-logo' - -import { - headingStyle, - innerContainerStyle, - outerContainerStyle, - textStyle, -} from './styles' - -export enum WorkflowOutcome { - APPROVED = 'Approved', - NOT_APPROVED = 'Not approved' -} - -export type WorkflowOutcomeEmailData = { - formTitle: string - responseId: string - outcome: WorkflowOutcome -} - -export const MrfApprovalOutcomeEmail = ({ - // Defaults are provided only for testing purposes in react-email-preview. - outcome = WorkflowOutcome.APPROVED, - formTitle = 'Test form title', - responseId = '64303c45828035f732088a41' -}: WorkflowOutcomeEmailData): JSX.Element => { - return ( - - - - - - - FormSG - - - - - - The outcome for {formTitle}. - - - - - - Outcome - - - {outcome} - - - - - Response ID - - - {responseId} - - - - -
-
-
- - - - For more details, please contact the respondent(s) or form administrator. - - - -
- - - ) -} - -export default MrfApprovalOutcomeEmail diff --git a/src/app/views/templates/MrfWorkflowCompletionEmail.tsx b/src/app/views/templates/MrfWorkflowCompletionEmail.tsx index 928f3cba48..4488ab32fc 100644 --- a/src/app/views/templates/MrfWorkflowCompletionEmail.tsx +++ b/src/app/views/templates/MrfWorkflowCompletionEmail.tsx @@ -16,10 +16,16 @@ import { containerStyle, headingTextStyle, mainStyle, + outcomeTextStyle, sectionStyle, titleTextStyle, } from './styles' +export enum WorkflowOutcome { + APPROVED = 'Approved', + NOT_APPROVED = 'Not approved' +} + export type QuestionAnswer = { question: string, answer: string @@ -29,13 +35,15 @@ export type WorkflowEmailData = { formTitle: string responseId: string formQuestionAnswers: QuestionAnswer[] + outcome?: WorkflowOutcome | undefined } export const MrfWorkflowCompletionEmail = ({ // Defaults are provided only for testing purposes in react-email-preview. formTitle = 'Test form title', responseId = '64303c45828035f732088a41', - formQuestionAnswers = [] + formQuestionAnswers = [], + outcome }: WorkflowEmailData): JSX.Element => { return ( @@ -45,8 +53,18 @@ export const MrfWorkflowCompletionEmail = ({
FormSG - {formTitle} has been completed by all respondents. + { + outcome + ? `The outcome for ${formTitle}` + : `${formTitle} has been completed by all respondents.` + } + { + outcome ? <> + Outcome + {outcome} + : null + }
Responses for {formTitle} diff --git a/src/app/views/templates/styles.ts b/src/app/views/templates/styles.ts index 3b76032f3d..38b571af88 100644 --- a/src/app/views/templates/styles.ts +++ b/src/app/views/templates/styles.ts @@ -60,8 +60,6 @@ export const linkStyle: NonNullable = { const textStyles = { 'body-1': { fontStyle: 'normal', - fontFamily: - "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif", fontWeight: 400, fontSize: '1rem', lineHeight: '1.5rem', @@ -70,13 +68,18 @@ const textStyles = { }, h4: { fontWeight: 500, - fontFamily: - "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif", fontSize: '1.125rem', lineHeight: '1.5rem', letterSpacing: '-0.014em', fontFeatureSettings: "'tnum' on, 'lnum' on, 'cv05' on", }, + h5: { + fontWeight: 600, + fontSize: '1.25rem', + lineHeight: '1.75rem', + letterSpacing: '-0.014em', + fontFeatureSettings: "'tnum' on, 'lnum' on, 'cv05' on", + }, } export const mainStyle = { @@ -104,6 +107,11 @@ export const headingTextStyle: NonNullable = { fontSize: '1.5rem', } +export const outcomeTextStyle: NonNullable = { + ...textStyles['h5'], + color: '#000000', +} + export const titleTextStyle: NonNullable = { ...textStyles['body-1'], color: '#000000',