-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
1610 implement put for interview notes #1651
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -933,6 +933,20 @@ def list(self, request: Request) -> Response: | |
return Response(serializer.data) | ||
|
||
|
||
class RecruitmentApplicationInterviewNotesView(APIView): | ||
permission_classes = [IsAuthenticated] | ||
serializer_class = InterviewSerializer | ||
|
||
def put(self, request: Request, interview_id: str) -> Response: | ||
interview = get_object_or_404(Interview, pk=interview_id) | ||
update_serializer = self.serializer_class(interview, data=request.data, partial=True) | ||
if update_serializer.is_valid() and 'notes' in update_serializer.validated_data: | ||
interview.notes = update_serializer.validated_data['notes'] | ||
interview.save() | ||
return Response(status=status.HTTP_200_OK) | ||
return Response(update_serializer.errors, status=status.HTTP_400_BAD_REQUEST) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did not include any data in the successful response as the user already has the live changes. |
||
|
||
|
||
class RecruitmentApplicationWithdrawApplicantView(APIView): | ||
permission_classes = [IsAuthenticated] | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,7 @@ export function RecruitmentApplicantAdminPage() { | |
const applicant = data?.data.user; | ||
const otherRecruitmentApplications = data?.data.other_applications; | ||
const interviewNotes = recruitmentApplication?.interview?.notes; | ||
const interviewId = recruitmentApplication?.interview?.id; | ||
|
||
const adminWithdraw = useMutation({ | ||
mutationFn: (id: string) => { | ||
|
@@ -84,6 +85,11 @@ export function RecruitmentApplicantAdminPage() { | |
</Text> | ||
<Text>{recruitmentApplication?.application_text}</Text> | ||
</div> | ||
{interviewId && ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If interviewId excist then show this div |
||
<div className={classNames(styles.infoContainer)}> | ||
<RecruitmentInterviewNotesForm initialData={initialData} interviewId={interviewId} /> | ||
</div> | ||
)} | ||
<div className={styles.withdrawContainer}> | ||
{recruitmentApplication?.withdrawn ? ( | ||
<Text as="i" size="l" className={styles.withdrawnText}> | ||
|
@@ -102,10 +108,6 @@ export function RecruitmentApplicantAdminPage() { | |
</Button> | ||
)} | ||
</div> | ||
<div className={classNames(styles.infoContainer)}> | ||
<RecruitmentInterviewNotesForm initialData={initialData} /> | ||
</div> | ||
|
||
<div className={classNames(styles.infoContainer)}> | ||
<Text size="l" as="strong" className={styles.textBottom}> | ||
{t(KEY.recruitment_all_applications)} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,54 @@ | ||
import { zodResolver } from '@hookform/resolvers/zod'; | ||
import { useMutation } from '@tanstack/react-query'; | ||
import { useState } from 'react'; | ||
import { useForm } from 'react-hook-form'; | ||
import { useTranslation } from 'react-i18next'; | ||
import { toast } from 'react-toastify'; | ||
import { z } from 'zod'; | ||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, Textarea } from '~/Components'; | ||
import { putRecrutmentInterviewNotes } from '~/api'; | ||
import { KEY } from '~/i18n/constants'; | ||
|
||
const recruitmentNotesSchema = z.object({ | ||
notes: z.string(), | ||
interviewId: z.number(), | ||
}); | ||
|
||
type RecruitmentInterviewNotesFormType = z.infer<typeof recruitmentNotesSchema>; | ||
|
||
interface RecruitmentInterviewNotesFormProps { | ||
initialData: Partial<RecruitmentInterviewNotesFormType>; | ||
interviewId?: number; | ||
} | ||
|
||
export function RecruitmentInterviewNotesForm({ initialData }: RecruitmentInterviewNotesFormProps) { | ||
export function RecruitmentInterviewNotesForm({ initialData, interviewId }: RecruitmentInterviewNotesFormProps) { | ||
const { t } = useTranslation(); | ||
|
||
const [currentNotes, setCurrentNotes] = useState(initialData.notes || ''); | ||
const form = useForm<RecruitmentInterviewNotesFormType>({ | ||
resolver: zodResolver(recruitmentNotesSchema), | ||
defaultValues: initialData, | ||
defaultValues: { | ||
notes: initialData.notes || '', | ||
interviewId: interviewId || 0, | ||
}, | ||
}); | ||
|
||
const handleUpdateNotes = useMutation({ | ||
mutationFn: ({ notes, interviewId }: { notes: string; interviewId: number }) => | ||
putRecrutmentInterviewNotes(notes, interviewId), | ||
onSuccess: () => { | ||
toast.success(t(KEY.common_update_successful)); | ||
}, | ||
onError: (error) => { | ||
toast.error(t(KEY.common_something_went_wrong)); | ||
}, | ||
}); | ||
|
||
function handleUpdateNotes(value: string) { | ||
// TODO: Update notes using a put request | ||
console.log(value); | ||
} | ||
const handleNotesChange = (newNotes: string) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Helper method to check if any changes was made. If no changes was made, but onBlur was triggered, we don't need to send a put request |
||
if (newNotes !== currentNotes && interviewId) { | ||
setCurrentNotes(newNotes); | ||
handleUpdateNotes.mutate({ notes: newNotes, interviewId }); | ||
} | ||
}; | ||
|
||
return ( | ||
<Form {...form}> | ||
|
@@ -43,7 +65,7 @@ export function RecruitmentInterviewNotesForm({ initialData }: RecruitmentInterv | |
{...field} | ||
onBlur={(newNotes) => { | ||
field.onBlur(); // Call the default onBlur handler from react-hook-form | ||
handleUpdateNotes(newNotes.target.value); // Call your custom function on blur | ||
handleNotesChange(newNotes.target.value); // Call your custom function on blur | ||
}} | ||
/> | ||
</FormControl> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We needed to add the interview object to the serializer. Could potentially limit this to only id and notes.