Skip to content

Commit

Permalink
added functionality for sending reminder emails
Browse files Browse the repository at this point in the history
  • Loading branch information
pavliuc75 committed Oct 29, 2024
1 parent 905d82a commit fd53163
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 25 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"@babel/plugin-transform-react-jsx-self": "^7.24.7",
"@babel/plugin-transform-react-jsx-source": "^7.24.7",
"@carp-dk/authentication-react": "^1.0.1",
"@carp-dk/client": "1.2.0",
"@carp-dk/client": "1.4.0",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@js-joda/core": "^5.6.2",
Expand Down
76 changes: 53 additions & 23 deletions src/components/SendReminderModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@ import {
VerticalInputContainer,
} from "./styles";
import * as yup from "yup";
import {GenericEmailRequest} from "../../../../carp-client-ts/src/models/Email";
import {usePostEmailSendGeneric} from "@Utils/queries/participants";

type Props = {
open: boolean,
onClose: () => void,
to: string,
initials: string
researcherEmail: string,
researcherName: string,
studyName: string
};

const ccLabelStyling = {
Expand All @@ -33,8 +38,8 @@ const ccHorizontalInputContainerStyling = {

const subjectHorizontalInputContainerStyling = ccHorizontalInputContainerStyling;

const SendReminderModal = ({open, onClose, to, initials}: Props) => {
// const sendEmail = useSendEmail();
const SendReminderModal = ({open, onClose, to, initials, researcherEmail, researcherName, studyName}: Props) => {
const postEmailSendGeneric = usePostEmailSendGeneric();

const validationSchema = yup.object({
message: yup.string().required("Message (email content) is required"),
Expand All @@ -50,35 +55,59 @@ const SendReminderModal = ({open, onClose, to, initials}: Props) => {

const reminderFormik = useFormik({
initialValues: {
cc: "",
message: `Dear Jakob Bardram,
cc: researcherEmail,
message: `Dear ${initials},
You have recently been invited to participate in the "${studyName}" study.
I am writing to remind you about the importance of uploading data to the Clinical Study, which is investigating the efficacy and safety in patients with cardiovascular disease. Your participation in this study contributes to our efforts in understanding and improving the treatment of cardiovascular disease.
However, it appears that you have not yet joined the study on your phone. Your participation in this study is important to us and we would really appreciate your contribution.
Kindly click on the link below to be redirected to the study:
[Digital Tech Summit]
If you have any questions or encounter any difficulties while uploading the data, please do not hesitate to reach out to us for assistance.
[Researcher's Name][Researcher's Title/Position][Research Institution/Organization]
___________________________________________________
Study invitation
If you haven't yet registered as a user or want to reset the password, please do it on this link - https://carp.computerome.dk/
You are cordially invited to participate in the Clinical Study, investigating the efficacy and safety in patients with cardiovascular disease. Your participation in this study is important and will help us to better understand the potential benefits in treating cardiovascular disease.
`,
subject: "Reminder to participate in the XXX Study",
If you have any questions, don't hesitate to contact me at this email address.
Kind regards,
${researcherName}
Kære ${initials},
Du er fornylig blevet inviteret til at deltage i "${studyName}" studiet.
Vi kan dog se, at du ikke har startet studiet på din telefon og vi vil meget gerne have at du kommer i gang. Studiet er vigtigt for os og det er vigtigt at du også deltager.
Hvis du endnu ikke er oprettet som bruger, eller hvis du har glemt din password, kan du gøre det her - https://carp.computerome.dk/
Hvis du har spørgsmål, så er du velkommen til at skrive til mig på denne mail adresse.
Med venlig hilsen
${researcherName}`,
subject: studyName,
},
onSubmit: (values) => {
console.log("test")
// TODO: Send email
// eslint-disable-next-line no-console
// TODO: Delete this after implementing the send email functionality
// onClose();
let genericEmailRequest: GenericEmailRequest = {
recipient: to,
subject: values.subject,
message: convertTextareaInputToHtml(values.message),
cc: values.cc.split(/[\s,]+/).filter(Boolean),
}
postEmailSendGeneric.mutate(genericEmailRequest)
},
validationSchema
});

function convertTextareaInputToHtml(str: string): string {
const urlRegex = /(https?:\/\/[^\s]+)/g;
const urlsWrappedIntoAnchorTags = str.replace(urlRegex, url => `<a href="${url}">${url}</a>`);
let withAddedBr = urlsWrappedIntoAnchorTags.replace(/\n/g, "<br>");
let wrappedInPre = `<pre style="white-space: pre-wrap;">${withAddedBr}</pre>`;

return wrappedInPre;
}

useEffect(() => {
return () => {
reminderFormik.resetForm();
Expand All @@ -90,7 +119,7 @@ const SendReminderModal = ({open, onClose, to, initials}: Props) => {
onClose();
},
[
/* sendEmail.isSuccess */
postEmailSendGeneric.isSuccess
],
);

Expand Down Expand Up @@ -148,7 +177,7 @@ const SendReminderModal = ({open, onClose, to, initials}: Props) => {
name="message"
fullWidth
multiline
rows={5}
rows={9}
helperText={reminderFormik.errors.message}
error={!!reminderFormik.errors.message}
value={reminderFormik.values.message}
Expand All @@ -161,6 +190,7 @@ const SendReminderModal = ({open, onClose, to, initials}: Props) => {
Cancel
</CancelButton>
<DoneButton
disabled={postEmailSendGeneric.isPending}
variant="contained"
sx={{elevation: 0}}
onClick={() => {
Expand Down
29 changes: 28 additions & 1 deletion src/pages/Participant/BasicInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import {
StyledCard,
StyledDivider,
} from "./styles";
import {getUser} from "@carp-dk/authentication-react";
import {useStudyDetails} from "@Utils/queries/studies";

const BasicInfo = () => {
const [open, setOpen] = useState(false);
Expand All @@ -30,7 +32,15 @@ const BasicInfo = () => {
isLoading: participantDataLoading,
error: participantError,
} = useParticipantGroupsAccountsAndStatus(studyId);

const {
data: studyDetailsData,
isLoading: studyDetailsLoading,
error: studyDetailsError,
} = useStudyDetails(studyId);

const [participant, setParticipant] = useState<ParticipantData | null>(null);
const [studyDetails, setStudyDetails] = useState<any>(null);

useEffect(() => {
if (!participantDataLoading && participantData && participantData.groups) {
Expand All @@ -42,6 +52,12 @@ const BasicInfo = () => {
}
}, [participantData, participantDataLoading, participantId, deploymentId]);

useEffect(() => {
if (!studyDetailsLoading && studyDetailsData) {
setStudyDetails(studyDetailsData);
}
}, [studyDetailsData, studyDetailsLoading, studyId]);

const initials = useMemo(() => {
if (participant && (participant.firstName || participant.lastName)) {
return participant.firstName[0] + participant.lastName[0];
Expand All @@ -63,7 +79,7 @@ const BasicInfo = () => {
);
}, [participant]);

if (participantDataLoading || !participant) return <LoadingSkeleton />;
if (participantDataLoading || !participant || studyDetailsLoading || !studyDetails) return <LoadingSkeleton />;

if (participantError)
return (
Expand All @@ -73,6 +89,14 @@ const BasicInfo = () => {
/>
);

if (studyDetailsError)
return (
<CarpErrorCardComponent
message="An error occurred while loading study details"
error={studyDetailsError}
/>
);

return (
<StyledCard elevation={2}>
<Left>
Expand All @@ -96,6 +120,9 @@ const BasicInfo = () => {
open={open}
to={participant.email}
initials={initials}
researcherEmail={getUser()?.profile?.email || ''}
researcherName={getUser()?.profile?.name || ''}
studyName={studyDetails?.name || ''}
/>
</StyledCard>
);
Expand Down
20 changes: 20 additions & 0 deletions src/utils/queries/participants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import dk = carpStudiesCore.dk;
import NamespacedId = dk.cachet.carp.common.application.NamespacedId;

import Participant = dk.cachet.carp.studies.application.users.Participant;
import {GenericEmailRequest} from "@carp-dk/client/models/Email";

type ParticipantGroupStatus =
dk.cachet.carp.studies.application.users.ParticipantGroupStatus;
Expand Down Expand Up @@ -101,6 +102,25 @@ export const useInviteParticipants = (studyId: string) => {
});
};

export const usePostEmailSendGeneric = () => {
const { setSnackbarSuccess, setSnackbarError } = useSnackbar();

return useMutation({
mutationFn: async (genericEmailRequest: GenericEmailRequest) => {
return carpApi.postEmailSendGeneric(
genericEmailRequest,
getConfig(),
);
},
onSuccess: () => {
setSnackbarSuccess("Email has been sent!");
},
onError: (error: CarpServiceError) => {
setSnackbarError(error.httpResponseMessage);
},
})
}

export const useAddParticipantByEmail = (studyId: string) => {
const { setSnackbarSuccess, setSnackbarError } = useSnackbar();
const queryClient = useQueryClient();
Expand Down

0 comments on commit fd53163

Please sign in to comment.