Skip to content

Commit

Permalink
Merge pull request #67 from ls1intum/66-accept-button
Browse files Browse the repository at this point in the history
66 accept button
  • Loading branch information
airelawaleria authored Jul 15, 2023
2 parents f037d84 + 57d5656 commit 4deb00f
Show file tree
Hide file tree
Showing 7 changed files with 272 additions and 0 deletions.
48 changes: 48 additions & 0 deletions client/src/forms/ApplicationAssessmentForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ import {
sendCoachApplicationRejection,
sendTutorApplicationRejection,
} from '../redux/applicationsSlice/thunks/sendApplicationRejection'
import {
sendCoachApplicationAcceptance,
sendTutorApplicationAcceptance,
} from '../redux/applicationsSlice/thunks/sendApplicationAcceptance'

interface ConfirmationModalProps {
title: string
Expand Down Expand Up @@ -89,6 +93,10 @@ export const ApplicationAssessmentForm = ({
applicationRejectionEmailSendConfirmationModalOpened,
setApplicationRejectionSendConfirmationModalOpened,
] = useState(false)
const [
applicationAcceptanceEmailSendConfirmationModalOpened,
setApplicationAcceptanceSendConfirmationModalOpened,
] = useState(false)
const assessmentForm = useForm<ApplicationAssessment>({
initialValues: {
instructorComments: assessment?.instructorComments ?? [],
Expand All @@ -100,6 +108,7 @@ export const ApplicationAssessmentForm = ({
accepted: assessment?.accepted ?? false,
assessed: assessment?.assessed ?? false,
interviewInviteSent: assessment?.interviewInviteSent ?? false,
acceptanceSent: assessment?.acceptanceSent ?? false,
rejectionSent: assessment?.rejectionSent ?? false,
},
})
Expand Down Expand Up @@ -138,6 +147,22 @@ export const ApplicationAssessmentForm = ({
setInterviewInvitationSendConfirmationModalOpened(false)
}}
/>
<ConfirmationModal
title='Confirm Application Acceptance'
text='Are You sure You would like to accept this application?'
opened={applicationAcceptanceEmailSendConfirmationModalOpened}
onClose={() => {
setApplicationAcceptanceSendConfirmationModalOpened(false)
}}
onConfirm={() => {
if (applicationType === 'coach') {
void dispatch(sendCoachApplicationAcceptance(applicationId))
} else if (applicationType === 'tutor') {
void dispatch(sendTutorApplicationAcceptance(applicationId))
}
setApplicationAcceptanceSendConfirmationModalOpened(false)
}}
/>
<ConfirmationModal
title='Confirm Application Rejection'
text='Are You sure You would like to reject this application?'
Expand Down Expand Up @@ -240,6 +265,29 @@ export const ApplicationAssessmentForm = ({
</Button>
</div>
</Tooltip>
<Tooltip
label={
assessment?.acceptanceSent
? 'The application acceptance email has already been sent successfully.'
: 'An application acceptance email will be sent out to the student.'
}
color='blue'
withArrow
multiline
>
<div>
<Button
variant='outline'
color='green'
disabled={assessment?.acceptanceSent}
onClick={() => {
setApplicationAcceptanceSendConfirmationModalOpened(true)
}}
>
Accept Application
</Button>
</div>
</Tooltip>
<Tooltip
label={
assessment?.interviewInviteSent
Expand Down
39 changes: 39 additions & 0 deletions client/src/redux/applicationsSlice/applicationsSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ import {
sendCoachApplicationRejection,
sendTutorApplicationRejection,
} from './thunks/sendApplicationRejection'
import {
sendCoachApplicationAcceptance,
sendTutorApplicationAcceptance,
} from './thunks/sendApplicationAcceptance'

enum LanguageProficiency {
A1A2 = 'A1/A2',
Expand Down Expand Up @@ -99,6 +103,7 @@ interface ApplicationAssessment {
assessed: boolean
accepted: boolean
interviewInviteSent: boolean
acceptanceSent: boolean
rejectionSent: boolean
}

Expand Down Expand Up @@ -288,6 +293,23 @@ export const applicationsState = createSlice({
state.status = 'idle'
})

builder.addCase(sendCoachApplicationAcceptance.pending, (state) => {
state.status = 'loading'
state.error = null
})

builder.addCase(sendCoachApplicationAcceptance.fulfilled, (state, { payload }) => {
state.coachApplications = state.coachApplications.map((coachApplication) =>
coachApplication.id === payload.id ? payload : coachApplication,
)
state.status = 'idle'
})

builder.addCase(sendCoachApplicationAcceptance.rejected, (state, { payload }) => {
if (payload) state.error = 'error'
state.status = 'idle'
})

builder.addCase(sendCoachApplicationRejection.pending, (state) => {
state.status = 'loading'
state.error = null
Expand Down Expand Up @@ -322,6 +344,23 @@ export const applicationsState = createSlice({
state.status = 'idle'
})

builder.addCase(sendTutorApplicationAcceptance.pending, (state) => {
state.status = 'loading'
state.error = null
})

builder.addCase(sendTutorApplicationAcceptance.fulfilled, (state, { payload }) => {
state.tutorApplications = state.tutorApplications.map((tutorApplication) =>
tutorApplication.id === payload.id ? payload : tutorApplication,
)
state.status = 'idle'
})

builder.addCase(sendTutorApplicationAcceptance.rejected, (state, { payload }) => {
if (payload) state.error = 'error'
state.status = 'idle'
})

builder.addCase(sendTutorApplicationRejection.pending, (state) => {
state.status = 'loading'
state.error = null
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import axios from 'axios'
import { createAsyncThunk } from '@reduxjs/toolkit'
import { serverBaseUrl } from '../../../service/configService'
import { notifications } from '@mantine/notifications'

export const sendCoachApplicationAcceptance = createAsyncThunk(
'applications/sendCoachApplicationAcceptance',

async (applicationId: string, { rejectWithValue }) => {
try {
return (
await axios.post(
`${serverBaseUrl}/api/applications/coach/${applicationId}/acceptance`,
{},
{
headers: {
Authorization: `Bearer ${localStorage.getItem('jwt_token') ?? ''}`,
},
},
)
).data
} catch (err) {
notifications.show({
color: 'red',
autoClose: 5000,
title: 'Error',
message: `Failed to send an application acceptance.`,
})

rejectWithValue(err)
}
},
)

export const sendTutorApplicationAcceptance = createAsyncThunk(
'applications/sendTutorApplicationAcceptance',

async (applicationId: string, { rejectWithValue }) => {
try {
return (
await axios.post(
`${serverBaseUrl}/api/applications/tutor/${applicationId}/acceptance`,
{},
{
headers: {
Authorization: `Bearer ${localStorage.getItem('jwt_token') ?? ''}`,
},
},
)
).data
} catch (err) {
notifications.show({
color: 'red',
autoClose: 5000,
title: 'Error',
message: `Failed to send an application acceptance.`,
})

rejectWithValue(err)
}
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,18 @@ public ResponseEntity<Application> sendTutorInterviewInvitation(@PathVariable UU
return ResponseEntity.ok(applicationService.sendTutorInterviewInvite(applicationId));
}

@PostMapping("/coach/{applicationId}/acceptance")
@PreAuthorize("hasRole('ipraktikum-pm')")
public ResponseEntity<Application> sendCoachApplicationAcceptance(@PathVariable UUID applicationId) {
return ResponseEntity.ok(applicationService.sendCoachApplicationAcceptance(applicationId));
}

@PostMapping("/tutor/{applicationId}/acceptance")
@PreAuthorize("hasRole('ipraktikum-pm')")
public ResponseEntity<Application> sendTutorApplicationAcceptance(@PathVariable UUID applicationId) {
return ResponseEntity.ok(applicationService.sendTutorApplicationAcceptance(applicationId));
}

@PostMapping("/coach/{applicationId}/rejection")
@PreAuthorize("hasRole('ipraktikum-pm')")
public ResponseEntity<Application> sendCoachApplicationRejection(@PathVariable UUID applicationId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class ApplicationAssessment {
private Integer assessmentScore;

private Boolean interviewInviteSent;
private Boolean acceptanceSent;

private Boolean rejectionSent;

Expand Down
28 changes: 28 additions & 0 deletions server/src/main/java/prompt/ls1/service/ApplicationService.java
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,34 @@ public TutorApplication sendTutorApplicationRejection(final UUID applicationId)
return tutorApplicationRepository.save(tutorApplication);
}

public CoachApplication sendCoachApplicationAcceptance(final UUID applicationId) {
final CoachApplication coachApplication = findCoachApplicationById(applicationId);

try {
mailingService.sendCoachApplicationAcceptanceEmail(coachApplication.getStudent(), coachApplication.getCourseIteration());
} catch (MessagingException e) {
log.error(String.format("Failed to send a coach application acceptance email. Error message: %s. Stacktrace: %s",
e.getMessage(), Arrays.toString(e.getStackTrace())));
}

coachApplication.getAssessment().setAcceptanceSent(true);
return coachApplicationRepository.save(coachApplication);
}

public TutorApplication sendTutorApplicationAcceptance(final UUID applicationId) {
final TutorApplication tutorApplication = findTutorApplicationById(applicationId);

try {
mailingService.sendTutorApplicationAcceptanceEmail(tutorApplication.getStudent(), tutorApplication.getCourseIteration());
} catch (MessagingException e) {
log.error(String.format("Failed to send a tutor application acceptance email. Error message: %s. Stacktrace: %s",
e.getMessage(), Arrays.toString(e.getStackTrace())));
}

tutorApplication.getAssessment().setAcceptanceSent(true);
return tutorApplicationRepository.save(tutorApplication);
}

public DeveloperApplication updateDeveloperApplicationAssessment(final UUID developerApplicationId, JsonPatch patchDeveloperApplicationAssessment)
throws JsonPatchException, JsonProcessingException {
final DeveloperApplication application = findDeveloperApplicationById(developerApplicationId);
Expand Down
82 changes: 82 additions & 0 deletions server/src/main/java/prompt/ls1/service/MailingService.java
Original file line number Diff line number Diff line change
Expand Up @@ -398,4 +398,86 @@ public void sendTutorApplicationRejectionEmail(final Student student,

javaMailSender.send(message);
}

public void sendCoachApplicationAcceptanceEmail(final Student student,
final CourseIteration courseIteration) throws MessagingException {
MimeMessage message = javaMailSender.createMimeMessage();

message.setFrom(sender);
message.setRecipients(MimeMessage.RecipientType.TO, student.getEmail());
message.addRecipients(MimeMessage.RecipientType.TO, sender);
message.setSubject(String.format("Agile Project Management %s Application Acceptance", courseIteration.getSemesterName()));

String htmlContent = String.format("""
<table align="left" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td><strong>iPraktikum&nbsp;%s APM&nbsp;Accept</strong></td>
</tr>
<tr>
<td>&nbsp;</td>
</tr>
<tr>
<td>
<p>Dear %s,</p>
<p>
Congratulations, you have been&nbsp;accepted&nbsp;as a Coach in the&nbsp;iPraktikum!&nbsp;</p>
<p>In order to complete your registration,&nbsp; please log in at&nbsp;<a href="https://lists.ase.in.tum.de/links/DnJKYSWUiH/XpGznUsipz/hOMCKCIxFy/zkcCoueKil" target="_blank">https://matching.in.tum.de</a>&nbsp;and prioritize the &quot;Praktikum&nbsp;- Agile Project Management (IN0012, IN2106, IN2175, IN4087)&quot; - NOT the&nbsp;iPraktikum&nbsp;itself!! It is very important that you give this course the highest priority and that it is the only lab course you prioritize - this means no other courses should be on the list at all.</p>
<p>Best Regards,<br />
Agile Project Management Program Management</p>
</td>
</tr>
</tbody>
</table>
""",
courseIteration.getSemesterName(),
student.getFirstName());
message.setContent(htmlContent, "text/html; charset=utf-8");

javaMailSender.send(message);
}

public void sendTutorApplicationAcceptanceEmail(final Student student,
final CourseIteration courseIteration) throws MessagingException {
MimeMessage message = javaMailSender.createMimeMessage();

message.setFrom(sender);
message.setRecipients(MimeMessage.RecipientType.TO, student.getEmail());
message.addRecipients(MimeMessage.RecipientType.TO, sender);
message.setSubject(String.format("Teaching iOS %s Application Acceptance", courseIteration.getSemesterName()));

String htmlContent = String.format("""
<table align="left" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td><strong>Teaching iOD&nbsp;%s &nbsp;Accept</strong></td>
</tr>
<tr>
<td>&nbsp;</td>
</tr>
<tr>
<td>
<p>Dear %s,</p>
<p>
Congratulations, you have been&nbsp;accepted&nbsp;as a Tutor for the Teaching iOS Course!&nbsp;</p>
<p>In order to complete your registration,&nbsp; please log in at&nbsp;<a href="https://lists.ase.in.tum.de/links/DnJKYSWUiH/XpGznUsipz/hOMCKCIxFy/zkcCoueKil" target="_blank">https://matching.in.tum.de</a>&nbsp;and prioritize the &quot;Seminar - Teaching iOS (IN0014, IN2107, IN4741)&quot;! It is very important that you give this course the highest priority and that it is the only lab course you prioritize - this means no other courses should be on the list at all.</p>
<p>Best Regards,<br />
Teaching iOS Program Management</p>
</td>
</tr>
</tbody>
</table>
""",
courseIteration.getSemesterName(),
student.getFirstName());
message.setContent(htmlContent, "text/html; charset=utf-8");

javaMailSender.send(message);
}
}

0 comments on commit 4deb00f

Please sign in to comment.