Skip to content

Commit

Permalink
[#767] isPartnershipMentor & Work Place on Sign Up page (#773)
Browse files Browse the repository at this point in the history
* add isPartnershipMentor checkbox and workplace textfield

* update con-profile mapper and recordprops

* add codegen output

* add mentor_isPartnershipMentor initialValue

* Conditionally render the company name input field, add validation

* Add isPartnershipMentor checkbox to the occupation section in the profile

* fix partnership mentor for both read and write

* Add isPartnershipMentor to ReadOccupation, update validation for the work place field

* Resolve conflicts

* fix partnership_mentor info not being passed on signup

* Update signup-complete page for partnership mentors

* Add signup complete email for partnership mentors

---------

Co-authored-by: Kate <kateryna@redi-school.org>
Co-authored-by: Eric Bolikowski <eric@binarylights.com>
  • Loading branch information
3 people authored Sep 26, 2023
1 parent c328378 commit 7925371
Show file tree
Hide file tree
Showing 27 changed files with 178 additions and 36 deletions.
2 changes: 2 additions & 0 deletions apps/api/common/models/red-user.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,8 @@ function generateJwtToken(redUser) {
operationType: redUser.operationType,
productSignupSource: redUser.productSignupSource,
tpSignupType: redUser.tpSignupType,
mentor_isPartnershipMentor: redUser.mentor_isPartnershipMentor,
mentor_workPlace: redUser.mentor_workPlace,
},
process.env.NX_JWT_SECRET,
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<mjml>
<mj-include path="./head.mjml" />
<mj-body mj-class="body">
<mj-wrapper background-color="#F0F0F0">
<mj-section />
<mj-section css-class="section">
<mj-column>
<mj-text mj-class="headline">Sign-up complete!</mj-text>
<mj-divider mj-class="divider-top" css-class="divider" />

<mj-text mj-class="text" padding="0 0 20px 0"
>Hi ${firstName},</mj-text
>
<mj-text mj-class="text paragraph"
>Great news - you're officially signed up!</mj-text
>
<mj-text mj-class="text paragraph"
>Please take a moment to <a
href="https://connect.redi-school.org/"
class="text-link"
>log into your account</a> and <strong>fill out your profile information</strong>. This step is super important because it helps students get to know you better and understand how you can support them.</mj-text
>
<mj-text mj-class="text paragraph"
>You will receive an application from your assigned student before the mentorship kick off event, make sure you <strong>accept the application</strong> to continue your sessions online.</mj-text
>

<mj-text mj-class="text">All the best,</mj-text>
<mj-text mj-class="text">Your ReDI Career Support Team</mj-text>
</mj-column>
</mj-section>
<mj-include path="./footer.career.support.team.mjml" />
<mj-section />
</mj-wrapper>
</mj-body>
</mjml>
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export class ConProfilesSalesforceEventHandlerService {
this.emailService.sendMentorSignupCompleteEmail({
recipient: conProfile.props.email,
firstName: conProfile.props.firstName,
isPartnershipMentor: conProfile.props.mentor_isPartnershipMentor,
})
break
}
Expand Down
4 changes: 3 additions & 1 deletion apps/nestjs-api/src/con-profiles/con-profiles.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Injectable, NotFoundException } from '@nestjs/common'
import {
ConnectProfileStatus,
ConProfileEntity,
ConProfileMapper,
ConnectProfileStatus,
UserType,
} from '@talent-connect/common-types'
import { deleteUndefinedProperties } from '@talent-connect/shared-utils'
Expand Down Expand Up @@ -30,6 +30,8 @@ export class ConProfilesService {
rediLocation: input.rediLocation,
userType: input.userType,
menteeCountCapacity: input.userType === UserType.MENTOR ? 1 : 0,
mentor_isPartnershipMentor: input.mentor_isPartnershipMentor,
mentor_workPlace: input.mentor_workPlace,
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ export class ConProfileSignUpInput extends PickType(_ConProfileEntityProps, [
'email',
'userType',
'rediLocation',
'mentor_workPlace',
'mentor_isPartnershipMentor',
] as const) {}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export class PatchConProfileInput extends PartialType(
PickType(_ConProfileEntityProps, [
'mentor_occupation',
'mentor_workPlace',
'mentor_isPartnershipMentor',
'expectations',
'mentee_occupationCategoryId',
'mentee_occupationJob_placeOfEmployment',
Expand Down
9 changes: 7 additions & 2 deletions apps/nestjs-api/src/email/lib/email/email.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,8 +347,13 @@ export const sendMenteeSignupCompleteEmail = ({
})
}

export const sendMentorSignupCompleteEmail = ({ recipient, firstName }) => {
const html = convertTemplateToHtml(null, 'signup-complete-mentor').replace(
export const sendMentorSignupCompleteEmail = ({ recipient, firstName, isPartnershipMentor }) => {
const templateFile =
isPartnershipMentor === true
? 'signup-complete-mentor-partnership'
: 'signup-complete-mentor'

const html = convertTemplateToHtml(null, templateFile).replace(
/\${firstName}/g,
firstName
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export class SfApiConProfilesService {
loopbackUserId: string
userType: UserType
menteeCountCapacity: number
mentor_isPartnershipMentor?: boolean
mentor_workPlace?: string
}) {
const recordTypeId = await this.repository.findRecordIdOfObject(
ConProfileRecord.metadata.SALESFORCE_OBJECT_NAME,
Expand All @@ -46,6 +48,8 @@ export class SfApiConProfilesService {
ReDI_Location__c: data.rediLocation,
RecordTypeId: recordTypeId,
total_mentee_capacity__c: data.menteeCountCapacity,
Partnership_Mentor__c: data.mentor_isPartnershipMentor,
Work_Place__c: data.mentor_workPlace,
}
)

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

export type ReadOccupationProfilePropFragment = { __typename?: 'ConProfile', userType: Types.UserType, mentor_occupation?: string | null, mentor_workPlace?: string | null, mentee_occupationCategoryId?: Types.OccupationCategory | null, mentee_occupationJob_placeOfEmployment?: string | null, mentee_occupationJob_position?: string | null, mentee_occupationStudent_studyPlace?: string | null, mentee_occupationStudent_studyName?: string | null, mentee_occupationLookingForJob_what?: string | null, mentee_occupationOther_description?: string | null };
export type ReadOccupationProfilePropFragment = { __typename?: 'ConProfile', userType: Types.UserType, mentor_occupation?: string | null, mentor_workPlace?: string | null, mentor_isPartnershipMentor?: boolean | null, mentee_occupationCategoryId?: Types.OccupationCategory | null, mentee_occupationJob_placeOfEmployment?: string | null, mentee_occupationJob_position?: string | null, mentee_occupationStudent_studyPlace?: string | null, mentee_occupationStudent_studyName?: string | null, mentee_occupationLookingForJob_what?: string | null, mentee_occupationOther_description?: string | null };

export const ReadOccupationProfilePropFragmentDoc = `
fragment ReadOccupationProfileProp on ConProfile {
userType
mentor_occupation
mentor_workPlace
mentor_isPartnershipMentor
mentee_occupationCategoryId
mentee_occupationJob_placeOfEmployment
mentee_occupationJob_position
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ fragment ReadOccupationProfileProp on ConProfile {
userType
mentor_occupation
mentor_workPlace
mentor_isPartnershipMentor
mentee_occupationCategoryId
mentee_occupationJob_placeOfEmployment
mentee_occupationJob_position
Expand Down
4 changes: 4 additions & 0 deletions apps/redi-connect/src/components/molecules/ReadOccupation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const ReadOccupation = ({ profile, shortInfo }: Props) => {
userType,
mentor_occupation,
mentor_workPlace,
mentor_isPartnershipMentor,
mentee_occupationCategoryId,
mentee_occupationJob_placeOfEmployment,
mentee_occupationJob_position,
Expand Down Expand Up @@ -51,6 +52,9 @@ const ReadOccupation = ({ profile, shortInfo }: Props) => {
<>
<p>{mentor_occupation}</p>
<p>{mentor_workPlace}</p>
{mentor_isPartnershipMentor && (
<p>My employer is in a mentorship partnership with ReDI School</p>
)}
</>
)}
{isMentee && (
Expand Down
20 changes: 17 additions & 3 deletions apps/redi-connect/src/components/organisms/EditableOccupation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
UserType,
} from '@talent-connect/data-access'
import {
Checkbox,
Editable,
FormInput,
FormSelect,
Expand All @@ -25,6 +26,7 @@ export interface OccupationFormValues {
userType: UserType
mentor_occupation: string
mentor_workPlace: string
mentor_isPartnershipMentor?: boolean
mentee_occupationCategoryId: string
mentee_occupationJob_placeOfEmployment: string
mentee_occupationJob_position: string
Expand All @@ -43,9 +45,12 @@ const validationSchema = Yup.object({
}),
mentor_workPlace: Yup.string()
.nullable()
.when('userType', {
is: 'MENTOR',
then: (schema) => schema.max(255).label('Work place'),
.when(['userType', 'mentor_isPartnershipMentor'], {
is: (userType, mentor_isPartnershipMentor) =>
userType === 'MENTOR' && mentor_isPartnershipMentor,
then: (schema) =>
schema.required('Please enter the company name').max(255),
otherwise: (schema) => schema.max(255),
}),
mentee_occupationCategoryId: Yup.string()
.nullable()
Expand Down Expand Up @@ -112,6 +117,7 @@ function EditableOccupation() {
const userType = profile?.userType
const mentor_occupation = profile?.mentor_occupation
const mentor_workPlace = profile?.mentor_workPlace
const mentor_isPartnershipMentor = profile?.mentor_isPartnershipMentor
const mentee_occupationCategoryId = profile?.mentee_occupationCategoryId
const mentee_occupationJob_placeOfEmployment =
profile?.mentee_occupationJob_placeOfEmployment
Expand Down Expand Up @@ -142,6 +148,7 @@ function EditableOccupation() {
userType,
mentor_occupation,
mentor_workPlace,
mentor_isPartnershipMentor,
mentee_occupationCategoryId,
mentee_occupationJob_placeOfEmployment,
mentee_occupationJob_position,
Expand Down Expand Up @@ -184,6 +191,13 @@ function EditableOccupation() {
placeholder="Company"
{...formik}
/>
<Checkbox.Form
name="mentor_isPartnershipMentor"
checked={formik.values.mentor_isPartnershipMentor}
{...formik}
>
My employer is in a mentorship partnership with ReDI School
</Checkbox.Form>
</>
)}

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_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 } };


export const ProfilePageQueryDocument = `
Expand Down
15 changes: 11 additions & 4 deletions apps/redi-connect/src/pages/front/login/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -170,14 +170,21 @@ export default function Login() {
// in localStorage contains the data from RedUser which contains the data from the CON
// sign-up page. We now want to use this to create a CON profile for them.
const accessToken = getAccessTokenFromLocalStorage()
const { email, userType, rediLocation } = decodeJwt(
accessToken.jwtToken
) as { [key: string]: string }
const {
email,
userType,
rediLocation,
mentor_isPartnershipMentor,
mentor_workPlace,
} = decodeJwt(accessToken.jwtToken)

await conProfileSignUpMutation.mutateAsync({
input: {
email: email,
email,
userType: userType as UserType,
rediLocation: rediLocation as RediLocation,
mentor_isPartnershipMentor: mentor_isPartnershipMentor as boolean,
mentor_workPlace,
},
})
return history.push(`/front/signup-complete/${userType.toLowerCase()}`)
Expand Down
54 changes: 41 additions & 13 deletions apps/redi-connect/src/pages/front/signup/SignUp.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
import { useState } from 'react'
import { Link, useParams } from 'react-router-dom'
import AccountOperation from '../../../components/templates/AccountOperation'

import * as Yup from 'yup'

import { RediLocation, UserType } from '@talent-connect/data-access'
import {
Button,
Checkbox,
FormInput,
Heading,
} from '@talent-connect/shared-atomic-design-components'
import { toPascalCaseAndTrim } from '@talent-connect/shared-utils'
import { FormikHelpers as FormikActions, FormikValues, useFormik } from 'formik'

import Teaser from '../../../components/molecules/Teaser'

import { useState } from 'react'
import { Columns, Content, Form, Notification } from 'react-bulma-components'

import { RediLocation, UserType } from '@talent-connect/data-access'
import { toPascalCaseAndTrim } from '@talent-connect/shared-utils'
import { Link, useParams } from 'react-router-dom'
import * as Yup from 'yup'
import Teaser from '../../../components/molecules/Teaser'
import AccountOperation from '../../../components/templates/AccountOperation'
import { signUpLoopback } from '../../../services/api/api'
import { history } from '../../../services/history/history'
import { envRediLocation } from '../../../utils/env-redi-location'
Expand Down Expand Up @@ -46,6 +41,11 @@ export const validationSchema = Yup.object({
.oneOf([Yup.ref('password')], 'Passwords do not match'),
agreesWithCodeOfConduct: Yup.boolean().required().oneOf([true]),
gaveGdprConsent: Yup.boolean().required().oneOf([true]),
mentor_isPartnershipMentor: Yup.boolean(),
mentor_workPlace: Yup.string().when('mentor_isPartnershipMentor', {
is: true,
then: (schema) => schema.required('Please enter the company name').max(255),
}),
})

export interface SignUpFormValues {
Expand All @@ -57,6 +57,8 @@ export interface SignUpFormValues {
firstName: string
lastName: string
agreesWithCodeOfConduct: boolean
mentor_isPartnershipMentor?: boolean
mentor_workPlace?: string
}

export default function SignUp() {
Expand All @@ -71,6 +73,7 @@ export default function SignUp() {
firstName: '',
lastName: '',
agreesWithCodeOfConduct: false,
mentor_isPartnershipMentor: false,
}

const [loopbackSubmitError, setLoopbackSubmitError] = useState<string | null>(
Expand All @@ -88,6 +91,12 @@ export default function SignUp() {
userType: type.toUpperCase() as UserType,
rediLocation: envRediLocation() as RediLocation,
productSignupSource: 'CON',
...(type === 'mentor'
? {
mentor_isPartnershipMentor: values.mentor_isPartnershipMentor,
mentor_workPlace: values.mentor_workPlace,
}
: {}),
})
actions.setSubmitting(false)
history.push(`/front/signup-email-verification`)
Expand All @@ -112,6 +121,8 @@ export default function SignUp() {
onSubmit: submitForm,
})

const isPartnershipMentor = formik.values.mentor_isPartnershipMentor === true

return (
<AccountOperation>
<Columns vCentered>
Expand Down Expand Up @@ -171,10 +182,27 @@ export default function SignUp() {
{...formik}
/>

{type === 'mentor' && (
<Checkbox.Form
name="mentor_isPartnershipMentor"
checked={formik.values.mentor_isPartnershipMentor}
className="submit-spacer"
{...formik}
>
My employer is in a mentorship partnership with ReDI School
</Checkbox.Form>
)}
{type === 'mentor' && isPartnershipMentor && (
<FormInput
name="mentor_workPlace"
placeholder="Which company are you working for?"
{...formik}
/>
)}

<Checkbox.Form
name="agreesWithCodeOfConduct"
checked={formik.values.agreesWithCodeOfConduct}
className="submit-spacer"
{...formik}
>
I agree to the{' '}
Expand Down
Loading

0 comments on commit 7925371

Please sign in to comment.