Skip to content

Commit

Permalink
feat(con): unsubscribe from marketing emails on CON (#995)
Browse files Browse the repository at this point in the history
* Add a isSubscribedToCONMarketingEmails field to the con-profile

* Add the isSubscribedToCONMarketingEmails checkbox to the My profile page

* Update FAQ

* Add Subscribed_to_CON_Marketing_Emails__c check for two marketing reminders
  • Loading branch information
katamatata authored Nov 19, 2024
1 parent 0745af5 commit 15ae39f
Show file tree
Hide file tree
Showing 15 changed files with 102 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ export class PatchConProfileInput extends PartialType(
'categories',
'optOutOfMenteesFromOtherRediLocation',
'menteeCountCapacity',
'isSubscribedToCONMarketingEmails',
] as const)
) {}
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export class ReminderEmailsService {
Profile_First_Approved_At__c: {
$eq: jsforce.SfDate.toDateLiteral(approvedDate),
},
Subscribed_to_CON_Marketing_Emails__c: true,
})

const approvedMenteeIds = menteesApproved45DaysAgo.map(
Expand Down Expand Up @@ -187,6 +188,7 @@ export class ReminderEmailsService {
'Contact__r.Id': {
$in: [...menteeIds, ...mentorIds],
},
Subscribed_to_CON_Marketing_Emails__c: true,
})
}

Expand Down Expand Up @@ -233,7 +235,7 @@ export class ReminderEmailsService {
const mentorshipMatchesWithSessionsCount = {} as Record<
string,
{
mentorshipMatchId: string,
mentorshipMatchId: string
menteeId: string
mentorId: string
mentoringSessionsCount: number
Expand Down Expand Up @@ -650,7 +652,10 @@ export class ReminderEmailsService {
)
.replace(/{{{Recipient.FirstName}}}/g, mentorFirstName)
.replace(/\${matchMadeActiveOn}/g, matchMadeActiveOn)
.replace(/\${logMentoringSessionUrl}/g, `https://connect.redi-school.org/app/mentorships/${mentorshipMatchId}`)
.replace(
/\${logMentoringSessionUrl}/g,
`https://connect.redi-school.org/app/mentorships/${mentorshipMatchId}`
)

const menteeParams = {
Destination: {
Expand Down
8 changes: 8 additions & 0 deletions apps/redi-connect/src/assets/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@
{
"question": "Is the mentorship service at ReDI School free of charge?",
"answer": "Yes, mentorship at ReDI School is completely free of charge! Our mentors are wonderful volunteers who generously dedicate their time and passion to support our learners on their journey. Their commitment helps make the mentoring experience impactful and accessible for everyone. <b>Important:</b> If at any point a mentor suggests or refers you to a paid service where they are a direct beneficiary, please report this to us immediately at <a href=‘mailto:career@redi-school.org’>career@redi-school.org</a> <b>(for ReDI Schools in Germany)</b> and at <a href=‘mailto:career.sweden@redi-school.org’>career.sweden@redi-school.org</a> <b>(for ReDI School in Sweden)</b>. We want to ensure that all mentorship remains free and aligned with ReDI's values of volunteer-driven support."
},
{
"question": "Will ReDI School check in with me to see how my long-term mentorship is going?",
"answer": "Yes! If your mentorship has continued for over three months, we'll reach out to hear about your experience, including any highlights, milestones, or challenges. Your feedback is optional but invaluable, as it helps us improve the mentorship program to keep it meaningful for everyone involved. You can also unsubscribe from these check-in emails by unchecking a box in your Profile Settings."
}
]
},
Expand Down Expand Up @@ -151,6 +155,10 @@
{
"question": "How can I update or improve my profile?",
"answer": "To update or improve your profile, go to ReDI Connect and work on <a href='https://connect.redi-school.org/app/me'>'My Profile'</a>. Ensure your information is accurate and as complete as possible. The more details you provide, the easier it will be for a mentor to assess how they can assist you. Including a photo can also help build trust and connection. If you have a portfolio, consider adding a link to your GitHub or other portfolio sites to showcase your work."
},
{
"question": "Will ReDI School remind me to apply for a mentor if I remain unmatched?",
"answer": "Absolutely! If you're still unmatched 45 days after your profile is approved, we'll send you a reminder email explaining the benefits of having a mentor and the next steps to take. You can unsubscribe from these reminder emails anytime by unchecking a box in your Profile Settings."
}
]
},
Expand Down
4 changes: 4 additions & 0 deletions apps/redi-connect/src/pages/app/me/Me.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@
position: relative;
bottom: 2px;
}

.tooltip-text {
font-family: Avenir LT Std;
}
65 changes: 64 additions & 1 deletion apps/redi-connect/src/pages/app/me/Me.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// import { usePatchMyProfileMutation } from '@talent-connect/data-access'
import { Tooltip } from '@mui/material'
import {
Button,
Checkbox,
Heading,
Icon,
} from '@talent-connect/shared-atomic-design-components'
Expand Down Expand Up @@ -30,6 +31,7 @@ import {
UserType,
useConProfileSubmitForReviewMutation,
useLoadMyProfileQuery,
usePatchMyProfileMutation,
} from '@talent-connect/data-access'
import { REDI_LOCATION_NAMES } from '@talent-connect/shared-config'
import { useLoading } from '../../../hooks/WithLoading'
Expand All @@ -41,6 +43,7 @@ import OnboardingSteps from './OnboardingSteps'
function Me() {
const queryClient = useQueryClient()
const submitProfileForReviewMutation = useConProfileSubmitForReviewMutation()
const patchMyProfileMutation = usePatchMyProfileMutation()
const { Loading, isLoading } = useLoading()
const history = useHistory()

Expand Down Expand Up @@ -85,6 +88,23 @@ function Me() {
rediLocation,
} = conProfile

const loopbackUserId = getAccessTokenFromLocalStorage().userId

const onSubscribeToMarketingEmailsChange = async () => {
const mutationResult = await patchMyProfileMutation.mutateAsync({
input: {
isSubscribedToCONMarketingEmails:
!conProfile?.isSubscribedToCONMarketingEmails,
},
})
queryClient.setQueryData(
useLoadMyProfileQuery.getKey({
loopbackUserId,
}),
{ conProfile: mutationResult.patchConProfile }
)
}

const isMentee = userType === UserType.Mentee
const isMentor = userType === UserType.Mentor
const isCorporateMentor = isMentor && mentor_isPartnershipMentor
Expand Down Expand Up @@ -222,6 +242,49 @@ function Me() {
</Element>
)}

{isMentee && (
<Element className="block-separator">
<Checkbox
checked={conProfile?.isSubscribedToCONMarketingEmails}
customOnChange={onSubscribeToMarketingEmailsChange}
>
<Tooltip
title={
<span className="tooltip-text">
By selecting this option, you'll receive notifications about
new mentors (if unmatched) and a check-in email for
mentorships lasting over 3 months.
</span>
}
placement="top-start"
>
<span>Receive mentee updates</span>
</Tooltip>
</Checkbox>
</Element>
)}

{isMentor && (
<Element className="block-separator">
<Checkbox
checked={conProfile?.isSubscribedToCONMarketingEmails}
customOnChange={onSubscribeToMarketingEmailsChange}
>
<Tooltip
title={
<span className="tooltip-text">
By selecting this option, you'll receive a check-in email for
mentorships lasting over 3 months.
</span>
}
placement="top-start"
>
<span>Receive mentor updates</span>
</Tooltip>
</Checkbox>
</Element>
)}

{isDraftingProfile && (
<Element className="block-separator" textAlignment="right">
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export type ProfilePageQueryQueryVariables = Types.Exact<{
}>;


export type ProfilePageQueryQuery = { __typename?: 'Query', conProfile: { __typename?: 'ConProfile', userId: string, age?: number | null, birthDate?: any | null, categories: Array<Types.MentoringTopic>, createdAt: any, doesNotHaveAvailableMentorshipSlot: boolean, email: string, expectations?: string | null, firstName: string, fullName: string, gender?: Types.Gender | null, githubProfileUrl?: string | null, id: string, languages?: Array<Types.Language> | null, lastName: string, linkedInProfileUrl?: string | null, loopbackUserId: string, menteeCountCapacity?: number | null, mentee_highestEducationLevel?: Types.EducationLevel | null, mentee_occupationCategoryId?: Types.OccupationCategory | null, mentee_occupationJob_placeOfEmployment?: string | null, mentee_occupationJob_position?: string | null, mentee_occupationLookingForJob_what?: string | null, mentee_occupationOther_description?: string | null, mentee_occupationStudent_studyName?: string | null, mentee_occupationStudent_studyPlace?: string | null, mentor_isPartnershipMentor?: boolean | null, mentor_occupation?: string | null, mentor_workPlace?: string | null, optOutOfMenteesFromOtherRediLocation: boolean, personalDescription?: string | null, profileAvatarImageS3Key?: string | null, profileStatus: Types.ConnectProfileStatus, rediLocation: Types.RediLocation, slackUsername?: string | null, telephoneNumber?: string | null, updatedAt: any, userActivatedAt?: any | null, userType: Types.UserType } };
export type ProfilePageQueryQuery = { __typename?: 'Query', conProfile: { __typename?: 'ConProfile', userId: string, age?: number | null, birthDate?: any | null, categories: Array<Types.MentoringTopic>, createdAt: any, doesNotHaveAvailableMentorshipSlot: boolean, email: string, expectations?: string | null, firstName: string, fullName: string, gender?: Types.Gender | null, githubProfileUrl?: string | null, id: string, languages?: Array<Types.Language> | null, lastName: string, linkedInProfileUrl?: string | null, loopbackUserId: string, menteeCountCapacity?: number | null, mentee_highestEducationLevel?: Types.EducationLevel | null, mentee_occupationCategoryId?: Types.OccupationCategory | null, mentee_occupationJob_placeOfEmployment?: string | null, mentee_occupationJob_position?: string | null, mentee_occupationLookingForJob_what?: string | null, mentee_occupationOther_description?: string | null, mentee_occupationStudent_studyName?: string | null, mentee_occupationStudent_studyPlace?: string | null, mentor_isPartnershipMentor?: boolean | null, mentor_occupation?: string | null, mentor_workPlace?: string | null, optOutOfMenteesFromOtherRediLocation: boolean, personalDescription?: string | null, profileAvatarImageS3Key?: string | null, profileStatus: Types.ConnectProfileStatus, rediLocation: Types.RediLocation, slackUsername?: string | null, telephoneNumber?: string | null, updatedAt: any, userActivatedAt?: any | null, userType: Types.UserType, isSubscribedToCONMarketingEmails: boolean } };


export const ProfilePageQueryDocument = `
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export class ConProfileEntityProps implements EntityProps {
menteeCountCapacity?: number
// userActivated?: boolean //! REINSTATE, COMPLEX CASE
userActivatedAt?: Date
isSubscribedToCONMarketingEmails: boolean

// The next ones are computed fields in Salesforce
age?: number
Expand Down
4 changes: 4 additions & 0 deletions libs/common-types/src/lib/con-profile/con-profile.mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ export class ConProfileMapper
props.createdAt = raw.props.CreatedDate
props.updatedAt = raw.props.LastModifiedDate
props.userActivatedAt = raw.props.Profile_First_Approved_At__c
props.isSubscribedToCONMarketingEmails =
raw.props.Subscribed_to_CON_Marketing_Emails__c

props.categories =
(raw.props.Mentoring_Topics__c?.split(';') as MentoringTopic[]) ?? []
Expand Down Expand Up @@ -128,6 +130,8 @@ export class ConProfileMapper
props.Main_Occupation_Other__c = srcProps.mentee_occupationOther_description
props.Education__c = srcProps.mentee_highestEducationLevel
props.Avatar_Image_URL__c = srcProps.profileAvatarImageS3Key
props.Subscribed_to_CON_Marketing_Emails__c =
srcProps.isSubscribedToCONMarketingEmails

props.Languages__c = srcProps.languages?.join(';')
props.Personal_Description__c = srcProps.personalDescription
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export class ConProfileRecord extends Record<ConProfileRecordProps> {
'Work_Place__c',
'total_mentee_capacity__c',
'Partnership_Mentor__c',
'Subscribed_to_CON_Marketing_Emails__c',

'Active_Mentorship_Matches_Mentee__c',
'Active_Mentorship_Matches_Mentor__c',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export class ConProfileRecordProps implements RecordProps {
Work_Place__c?: string
total_mentee_capacity__c?: number
Partnership_Mentor__c?: boolean
Subscribed_to_CON_Marketing_Emails__c: boolean

Active_Mentorship_Matches_Mentee__c: number
Active_Mentorship_Matches_Mentor__c: number
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// THIS FILE IS GENERATED, DO NOT EDIT!
import * as Types from '@talent-connect/data-access';

export type AllConProfileFieldsFragment = { __typename?: 'ConProfile', userId: string, age?: number | null, birthDate?: any | null, categories: Array<Types.MentoringTopic>, createdAt: any, doesNotHaveAvailableMentorshipSlot: boolean, email: string, expectations?: string | null, firstName: string, fullName: string, gender?: Types.Gender | null, githubProfileUrl?: string | null, id: string, languages?: Array<Types.Language> | null, lastName: string, linkedInProfileUrl?: string | null, loopbackUserId: string, menteeCountCapacity?: number | null, mentee_highestEducationLevel?: Types.EducationLevel | null, mentee_occupationCategoryId?: Types.OccupationCategory | null, mentee_occupationJob_placeOfEmployment?: string | null, mentee_occupationJob_position?: string | null, mentee_occupationLookingForJob_what?: string | null, mentee_occupationOther_description?: string | null, mentee_occupationStudent_studyName?: string | null, mentee_occupationStudent_studyPlace?: string | null, mentor_isPartnershipMentor?: boolean | null, mentor_occupation?: string | null, mentor_workPlace?: string | null, optOutOfMenteesFromOtherRediLocation: boolean, personalDescription?: string | null, profileAvatarImageS3Key?: string | null, profileStatus: Types.ConnectProfileStatus, rediLocation: Types.RediLocation, slackUsername?: string | null, telephoneNumber?: string | null, updatedAt: any, userActivatedAt?: any | null, userType: Types.UserType };
export type AllConProfileFieldsFragment = { __typename?: 'ConProfile', userId: string, age?: number | null, birthDate?: any | null, categories: Array<Types.MentoringTopic>, createdAt: any, doesNotHaveAvailableMentorshipSlot: boolean, email: string, expectations?: string | null, firstName: string, fullName: string, gender?: Types.Gender | null, githubProfileUrl?: string | null, id: string, languages?: Array<Types.Language> | null, lastName: string, linkedInProfileUrl?: string | null, loopbackUserId: string, menteeCountCapacity?: number | null, mentee_highestEducationLevel?: Types.EducationLevel | null, mentee_occupationCategoryId?: Types.OccupationCategory | null, mentee_occupationJob_placeOfEmployment?: string | null, mentee_occupationJob_position?: string | null, mentee_occupationLookingForJob_what?: string | null, mentee_occupationOther_description?: string | null, mentee_occupationStudent_studyName?: string | null, mentee_occupationStudent_studyPlace?: string | null, mentor_isPartnershipMentor?: boolean | null, mentor_occupation?: string | null, mentor_workPlace?: string | null, optOutOfMenteesFromOtherRediLocation: boolean, personalDescription?: string | null, profileAvatarImageS3Key?: string | null, profileStatus: Types.ConnectProfileStatus, rediLocation: Types.RediLocation, slackUsername?: string | null, telephoneNumber?: string | null, updatedAt: any, userActivatedAt?: any | null, userType: Types.UserType, isSubscribedToCONMarketingEmails: boolean };

export const AllConProfileFieldsFragmentDoc = `
fragment AllConProfileFields on ConProfile {
Expand Down Expand Up @@ -44,5 +44,6 @@ export const AllConProfileFieldsFragmentDoc = `
updatedAt
userActivatedAt
userType
isSubscribedToCONMarketingEmails
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ fragment AllConProfileFields on ConProfile {
updatedAt
userActivatedAt
userType
isSubscribedToCONMarketingEmails
}
Loading

0 comments on commit 15ae39f

Please sign in to comment.