Skip to content
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

ability to fetch number of processed applications #1591

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions backend/root/utils/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,7 @@
samfundet__interview_list = 'samfundet:interview-list'
samfundet__interview_detail = 'samfundet:interview-detail'
samfundet__api_root = 'samfundet:api-root'
samfundet__api_root = 'samfundet:api-root'
samfundet__schema = 'samfundet:schema'
samfundet__swagger_ui = 'samfundet:swagger_ui'
samfundet__redoc = 'samfundet:redoc'
Expand Down Expand Up @@ -607,5 +608,6 @@
samfundet__recruitment_availability = 'samfundet:recruitment_availability'
samfundet__feedback = 'samfundet:feedback'
samfundet__purchase_feedback = 'samfundet:purchase_feedback'
samfundet__gang_application_stats = 'samfundet:gang-application-stats'
static__path = ''
media__path = ''
1 change: 1 addition & 0 deletions backend/samfundet/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,5 @@
path('recruitment/<int:id>/availability/', views.RecruitmentAvailabilityView.as_view(), name='recruitment_availability'),
path('feedback/', views.UserFeedbackView.as_view(), name='feedback'),
path('purchase-feedback/', views.PurchaseFeedbackView.as_view(), name='purchase_feedback'),
path('recruitment/<int:recruitment_id>/gang/<int:gang_id>/stats/', views.GangApplicationCountView.as_view(), name='gang-application-stats'),
]
19 changes: 19 additions & 0 deletions backend/samfundet/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
Recruitment,
InterviewRoom,
OccupiedTimeslot,
RecruitmentGangStat,
RecruitmentPosition,
RecruitmentStatistics,
RecruitmentApplication,
Expand Down Expand Up @@ -1342,3 +1343,21 @@ def post(self, request: Request) -> Response:
form=purchase_model,
)
return Response(status=status.HTTP_201_CREATED, data={'message': 'Feedback submitted successfully!'})


class GangApplicationCountView(APIView):
permission_classes = [IsAuthenticated]

def get(self, request: Request, recruitment_id: int, gang_id: int) -> Response:
# Get total applications from RecruitmentGangStat
gang_stat = get_object_or_404(RecruitmentGangStat, gang_id=gang_id, recruitment_stats__recruitment_id=recruitment_id)

return Response(
{
'total_applications': gang_stat.application_count,
'total_applicants': gang_stat.applicant_count,
'average_priority': gang_stat.average_priority,
'total_accepted': gang_stat.total_accepted,
'total_rejected': gang_stat.total_rejected,
}
)
4 changes: 2 additions & 2 deletions frontend/src/Components/RejectionMail/RejectionMail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { t } from 'i18next';
import { useState } from 'react';
import { useParams } from 'react-router-dom';
import { toast } from 'react-toastify';
import { postRejectionMail } from '~/api';
//import { postRejectionMail } from '~/api';
Mathias-a marked this conversation as resolved.
Show resolved Hide resolved
import { KEY } from '~/i18n/constants';
import { Button } from '../Button';
import { InputField } from '../InputField';
Expand All @@ -15,7 +15,7 @@ export function RejectionMail() {

function handleSubmit() {
if (recruitmentId) {
postRejectionMail(recruitmentId, { subject, text });
//postRejectionMail(recruitmentId, { subject, text });
toast.success(t(KEY.common_save_successful));
} else {
toast.error(t(KEY.common_something_went_wrong));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { useParams } from 'react-router-dom';
import { toast } from 'react-toastify';
import { RecruitmentWithoutInterviewTable } from '~/Components';
import { Text } from '~/Components/Text/Text';
import { getApplicantsWithoutInterviews, getGang, getRecruitment } from '~/api';
import type { GangDto, RecruitmentDto, RecruitmentUserDto } from '~/dto';
import { getApplicantsWithoutInterviews, getGang, getRecruitment, getRecruitmentGangStats } from '~/api';
import type { GangDto, RecruitmentDto, RecruitmentGangStatDto, RecruitmentUserDto } from '~/dto';
import { useCustomNavigate, useTitle } from '~/hooks';
import { STATUS } from '~/http_status_codes';
import { KEY } from '~/i18n/constants';
Expand All @@ -18,7 +18,9 @@ export function RecruitmentUsersWithoutInterviewGangPage() {
const { recruitmentId, gangId } = useParams();
const [users, setUsers] = useState<RecruitmentUserDto[]>([]);
const [recruitment, setRecruitment] = useState<RecruitmentDto>();
const [withoutInterviewCount, setWithoutInterviewCount] = useState<number>();
const [gang, setGang] = useState<GangDto>();
const [recruitmentGangStat, setRecruitmentGangStat] = useState<RecruitmentGangStatDto>();
const [showSpinner, setShowSpinner] = useState<boolean>(true);
const { t } = useTranslation();
const navigate = useCustomNavigate();
Expand All @@ -29,6 +31,7 @@ export function RecruitmentUsersWithoutInterviewGangPage() {
getApplicantsWithoutInterviews(recruitmentId, gangId)
.then((response) => {
setUsers(response.data);
setWithoutInterviewCount(response.data.length);
setShowSpinner(false);
})
.catch((error) => {
Expand Down Expand Up @@ -62,16 +65,26 @@ export function RecruitmentUsersWithoutInterviewGangPage() {
setRecruitment(resp.data);
})
.catch((data) => {
// TODO add error pop up message?
if (data.request.status === STATUS.HTTP_404_NOT_FOUND) {
toast.error(t(KEY.common_something_went_wrong));
console.error(data);
navigate({ url: ROUTES.frontend.not_found, replace: true });
}
toast.error(t(KEY.common_something_went_wrong));
console.error(data);
});
}
}, [recruitmentId]);

useEffect(() => {
if (!recruitmentId || !gangId) return;
getRecruitmentGangStats(recruitmentId, gangId)
.then((response) => {
setRecruitmentGangStat(response.data);
})
.catch((error) => {
console.error(error);
});
}, [recruitmentId, gangId]);
Mathias-a marked this conversation as resolved.
Show resolved Hide resolved

const title = t(KEY.recruitment_applicants_without_interview);
useTitle(title);
const header = (
Expand All @@ -88,6 +101,18 @@ export function RecruitmentUsersWithoutInterviewGangPage() {
);
return (
<AdminPageLayout title={title} backendUrl={ROUTES.backend.samfundet__user} header={header} loading={showSpinner}>
{recruitmentGangStat && (
<Text size="l">
{[
withoutInterviewCount,
t(KEY.common_out_of),
`${t(KEY.common_total).toLowerCase()} ${recruitmentGangStat.total_applicants}`,
Mathias-a marked this conversation as resolved.
Show resolved Hide resolved
t(KEY.recruitment_applications),
t(KEY.common_have),
t(KEY.recruitment_interview),
].join(' ')}
</Text>
)}
<RecruitmentWithoutInterviewTable applicants={users} />
</AdminPageLayout>
);
Expand Down
18 changes: 10 additions & 8 deletions frontend/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import type {
InterviewDto,
InterviewRoomDto,
KeyValueDto,
MailDto,
MenuDto,
MenuItemDto,
OccupiedTimeslotDto,
Expand All @@ -29,6 +28,7 @@ import type {
RecruitmentAvailabilityDto,
RecruitmentDto,
RecruitmentGangDto,
RecruitmentGangStatDto,
RecruitmentPositionDto,
RecruitmentPositionPostDto,
RecruitmentPositionPutDto,
Expand Down Expand Up @@ -1088,16 +1088,18 @@ export async function postFeedback(feedbackData: FeedbackDto): Promise<AxiosResp
return response;
}

export async function postRejectionMail(recruitmentId: string, rejectionMail: MailDto): Promise<AxiosResponse> {
export async function getRecruitmentGangStats(
recruitmentId: string,
gangId: string,
): Promise<AxiosResponse<RecruitmentGangStatDto>> {
const url =
BACKEND_DOMAIN +
reverse({
pattern: ROUTES.backend.samfundet__rejected_applicants,
queryParams: {
recruitment: recruitmentId,
pattern: ROUTES.backend.samfundet__gang_application_stats,
urlParams: {
recruitmentId: recruitmentId,
gangId: gangId,
},
});
const response = await axios.post(url, rejectionMail, { withCredentials: true });

return response;
return await axios.get(url, { withCredentials: true });
}
5 changes: 2 additions & 3 deletions frontend/src/dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -556,9 +556,8 @@ export type RecruitmentCampusStatDto = {
};

export type RecruitmentGangStatDto = {
gang: string;
application_count: number;
applicant_count: number;
total_applications: number;
total_applicants: number;
average_priority: number;
total_accepted: number;
total_rejected: number;
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/i18n/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export const KEY = {
common_email: 'common_email',
common_email_subject: 'common_email_subject',
common_total: 'common_total',
common_out_of: 'common_out_of',
common_roles: 'common_roles',
common_role: 'common_role',
common_guests: 'common_guests',
Expand Down Expand Up @@ -169,6 +170,7 @@ export const KEY = {
common_something_went_wrong: 'common_something_went_wrong',
common_click_here: 'common_click_here',
common_have: 'common_have',
recruitment_interview: 'recruitment_interview',
common_been: 'common_been',
common_processed: 'common_processed',
common_rejected: 'common_rejected',
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/i18n/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ export const nb = prepareTranslations({
[KEY.common_something_went_wrong]: 'Noe gikk galt',
[KEY.common_click_here]: 'klikk her',
[KEY.common_total]: 'Totalt',
[KEY.common_out_of]: 'av',
[KEY.common_count]: 'Antall',
[KEY.common_guests]: 'Gjester',
[KEY.common_occasion]: 'Annledning',
Expand Down Expand Up @@ -261,6 +262,7 @@ export const nb = prepareTranslations({
[KEY.recruitment_all_applications]: 'Alle søknader',
[KEY.recruitment_not_applied]: 'Du har ikke sendt søknader til noen stillinger ennå',
[KEY.recruitment_will_be_anonymized]: 'All info relatert til dine søknader vil bli slettet 3 uker etter opptaket',
[KEY.recruitment_interview]: 'intervju',
[KEY.recruitment_interviews]: 'Intervjuer',
[KEY.recruitment_interviewer]: 'Intervjuer',
[KEY.recruitment_interviewers]: 'Intervjuere',
Expand Down Expand Up @@ -636,6 +638,7 @@ export const en = prepareTranslations({
[KEY.common_click_here]: 'click here',
[KEY.common_total]: 'In total',
[KEY.common_count]: 'Number of',
[KEY.common_out_of]: 'out of',
[KEY.common_guests]: 'Guests',
[KEY.common_occasion]: 'Occasion',
[KEY.common_have]: 'have',
Expand Down Expand Up @@ -746,6 +749,7 @@ export const en = prepareTranslations({
[KEY.recruitment_not_applied]: 'You have not applied to any positions yet',
[KEY.recruitment_will_be_anonymized]:
'All info related to the applications will be anonymized three weeks after the recruitment is over',
[KEY.recruitment_interview]: 'interview',
[KEY.recruitment_interviews]: 'Interviews',
[KEY.recruitment_interviewer]: 'Interviewer',
[KEY.recruitment_interviewers]: 'Interviewers',
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/routes/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ export const ROUTES_BACKEND = {
samfundet__recruitment_availability: '/recruitment/:id/availability/',
samfundet__feedback: '/feedback/',
samfundet__purchase_feedback: '/purchase-feedback/',
samfundet__gang_application_stats: '/recruitment/:recruitmentId/gang/:gangId/stats/',
static__path: '/static/:path',
media__path: '/media/:path',
} as const;
} as const;
Loading