From e39e7907272d9b42b242006e6af32ddabfe588bc Mon Sep 17 00:00:00 2001 From: hei98 <144371674+hei98@users.noreply.github.com> Date: Wed, 21 Feb 2024 16:54:27 +0100 Subject: [PATCH] 704 possibility to access interview notes from overview page3 (#986) * Edit interview notes * Add putRecruitmentAdmissionInterview to edit interview in backend * Add help functions and util functions * Make putRecruitmentAdmissionInterview allow numbers * Edit comment on util func filterRecruitmentAdmission --------- Co-authored-by: Robin <16273164+robines@users.noreply.github.com> --- backend/samfundet/serializers.py | 1 + .../InterviewNotesAdminPage.tsx | 59 +++++++++++++++---- .../InterviewNotesAdminPage/utils.ts | 20 +++++++ frontend/src/api.ts | 15 +++++ frontend/src/i18n/constants.ts | 1 + frontend/src/i18n/translations.ts | 2 + frontend/src/routes/frontend.ts | 2 +- 7 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 frontend/src/PagesAdmin/InterviewNotesAdminPage/utils.ts diff --git a/backend/samfundet/serializers.py b/backend/samfundet/serializers.py index 33d35edc8..c394a9ccf 100644 --- a/backend/samfundet/serializers.py +++ b/backend/samfundet/serializers.py @@ -698,6 +698,7 @@ def update(self, instance: RecruitmentAdmission, validated_data: dict) -> Recrui interview_instance = instance.interview interview_instance.interview_location = interview_data.get('interview_location', interview_instance.interview_location) interview_instance.interview_time = interview_data.get('interview_time', interview_instance.interview_time) + interview_instance.notes = interview_data.get('notes', interview_instance.notes) interview_instance.save() # Update other fields of RecruitmentAdmission instance diff --git a/frontend/src/PagesAdmin/InterviewNotesAdminPage/InterviewNotesAdminPage.tsx b/frontend/src/PagesAdmin/InterviewNotesAdminPage/InterviewNotesAdminPage.tsx index 6b8ed1344..9619475ed 100644 --- a/frontend/src/PagesAdmin/InterviewNotesAdminPage/InterviewNotesAdminPage.tsx +++ b/frontend/src/PagesAdmin/InterviewNotesAdminPage/InterviewNotesAdminPage.tsx @@ -1,35 +1,72 @@ -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import { useParams } from 'react-router-dom'; +import { toast } from 'react-toastify'; import { Button } from '~/Components'; import { TextAreaField } from '~/Components/TextAreaField/TextAreaField'; +import { getRecruitmentAdmissionsForGang, putRecruitmentAdmissionInterview } from '~/api'; +import { InterviewDto, RecruitmentAdmissionDto } from '~/dto'; import { KEY } from '~/i18n/constants'; import { AdminPageLayout } from '../AdminPageLayout/AdminPageLayout'; import styles from './InterviewNotesAdminPage.module.scss'; +import { filterRecruitmentAdmission, getNameUser } from './utils'; export function InterviewNotesPage() { - //TODO: interview notes from backend + const recruitmentId = useParams().recruitmentId; + const gangId = useParams().gangId; + const positionId = useParams().positionId; + const interviewId = useParams().interviewId; const [editingMode, setEditingMode] = useState(false); - const [text, setText] = useState('Notater fra intervjuet her...'); //TODO: place the text from the backend here. - const posId = 1; //TODO: get the posId from the backend. + const [recruitmentAdmission, setRecruitmentAdmission] = useState([]); + const [interview, setInterview] = useState(null); + const [disabled, setdisabled] = useState(true); + const [nameUser, setNameUser] = useState(''); const { t } = useTranslation(); - function handleEditSave() { - if (editingMode) { - //TODO: save the text in the textbox and send it to the backend + useEffect(() => { + if (positionId && recruitmentId && gangId && interviewId) { + getRecruitmentAdmissionsForGang(gangId, recruitmentId).then((response) => { + const admission = filterRecruitmentAdmission(response.data, positionId, interviewId); + if (admission.length !== 0) { + setdisabled(false); + setRecruitmentAdmission(admission); + setInterview(admission[0].interview); + setNameUser(getNameUser(admission[0])); + } + }); + } + }, [recruitmentId, positionId, gangId, interviewId]); + + async function handleEditSave() { + if (editingMode && interview) { + try { + await putRecruitmentAdmissionInterview(interview.id, interview); + toast.success(t(KEY.common_save_successful)); + } catch (error) { + toast.error(t(KEY.common_something_went_wrong)); + } } setEditingMode(!editingMode); } - //TODO: make handleSave function to save the text in the textbox and send it to the backend + function handleUpdateNotes(value: string) { + const updatedNotes = value; + const updatedInterview: InterviewDto = { ...recruitmentAdmission[0].interview, notes: updatedNotes }; + setInterview(updatedInterview); + } return (
- -
diff --git a/frontend/src/PagesAdmin/InterviewNotesAdminPage/utils.ts b/frontend/src/PagesAdmin/InterviewNotesAdminPage/utils.ts new file mode 100644 index 000000000..0b53301dc --- /dev/null +++ b/frontend/src/PagesAdmin/InterviewNotesAdminPage/utils.ts @@ -0,0 +1,20 @@ +import { RecruitmentAdmissionDto } from '~/dto'; + +/** Filtrer recruitmentadmission based on positionId, InterviewId and interview time */ +export function filterRecruitmentAdmission( + recruitmentAdmissions: RecruitmentAdmissionDto[], + positionId: string, + interviewId: string, +): RecruitmentAdmissionDto[] { + return recruitmentAdmissions.filter( + (admission) => + admission.recruitment_position && + admission.recruitment_position.toString() === positionId && + admission.interview.id.toString() === interviewId && + admission.interview.interview_time !== null, + ); +} + +export function getNameUser(admission: RecruitmentAdmissionDto): string { + return admission.user.first_name ? admission.user.first_name + ' ' + admission.user.last_name : ''; +} diff --git a/frontend/src/api.ts b/frontend/src/api.ts index 1b8e3ea90..dd05de8a4 100644 --- a/frontend/src/api.ts +++ b/frontend/src/api.ts @@ -11,6 +11,7 @@ import { ImageDto, ImagePostDto, InformationPageDto, + InterviewDto, KeyValueDto, MenuDto, MenuItemDto, @@ -713,3 +714,17 @@ export async function putRecruitmentAdmission( return response; } + +export async function putRecruitmentAdmissionInterview( + interviewId: string | number, + interview: Partial, +): Promise { + const url = + BACKEND_DOMAIN + + reverse({ + pattern: ROUTES.backend.samfundet__interview_detail, + urlParams: { pk: interviewId.toString() }, + }); + const response = await axios.put(url, interview, { withCredentials: true }); + return response; +} diff --git a/frontend/src/i18n/constants.ts b/frontend/src/i18n/constants.ts index 0da06c03d..ffcbfedff 100644 --- a/frontend/src/i18n/constants.ts +++ b/frontend/src/i18n/constants.ts @@ -114,6 +114,7 @@ export const KEY = { common_long_description: 'common_long_description', common_short_description: 'common_short_description', common_back_to_samfundet: 'common_back_to_samfundet', + common_save_successful: 'common_save_successful', common_delete_successful: 'common_delete_successful', common_update_successful: 'common_update_successful', common_creation_successful: 'common_creation_successful', diff --git a/frontend/src/i18n/translations.ts b/frontend/src/i18n/translations.ts index b3070c7af..b30607d87 100644 --- a/frontend/src/i18n/translations.ts +++ b/frontend/src/i18n/translations.ts @@ -100,6 +100,7 @@ export const nb: Record = { [KEY.common_long_description]: 'Lang beskrivelse', [KEY.common_short_description]: 'Kort beskrivelse', [KEY.common_back_to_samfundet]: 'Tilbake til samfundet.no', + [KEY.common_save_successful]: 'Lagring var vellykket', [KEY.common_delete_successful]: 'Slettingen var vellykket', [KEY.common_update_successful]: 'Oppdateringen var vellykket', [KEY.common_see_in_django_admin]: 'Se i django admin-panel', @@ -380,6 +381,7 @@ export const en: Record = { [KEY.common_long_description]: 'Long description', [KEY.common_short_description]: 'Short description', [KEY.common_back_to_samfundet]: 'Back to samfundet.no', + [KEY.common_save_successful]: 'Saving was successful', [KEY.common_delete_successful]: 'Deletion was successful', [KEY.common_update_successful]: 'The update was successful', [KEY.common_see_in_django_admin]: 'See in django admin-panel', diff --git a/frontend/src/routes/frontend.ts b/frontend/src/routes/frontend.ts index fd1eb1066..7ccab33bc 100644 --- a/frontend/src/routes/frontend.ts +++ b/frontend/src/routes/frontend.ts @@ -70,7 +70,7 @@ export const ROUTES_FRONTEND = { admin_recruitment_gang_position_applicants_overview: '/control-panel/recruitment/:recruitmentId/gang/:gangId/position/:positionId', admin_recruitment_gang_position_applicants_interview_notes: - '/control-panel/recruitment/:recruitmentId/gang/:gangId/position/:positionId/notesId', //fix when backend is done + '/control-panel/recruitment/:recruitmentId/gang/:gangId/position/:positionId/interview-notes/:interviewId', admin_sulten_menu: '/control-panel/lyche/menu', // ==================== // // Development //