diff --git a/backend/src/controllers/user/UserEndorsementAdminController.ts b/backend/src/controllers/user/UserEndorsementAdminController.ts index fa16863..faabdfd 100644 --- a/backend/src/controllers/user/UserEndorsementAdminController.ts +++ b/backend/src/controllers/user/UserEndorsementAdminController.ts @@ -4,7 +4,7 @@ import _UserAdminValidator from "./_UserAdmin.validator"; import { EndorsementGroupsBelongsToUsers } from "../../models/through/EndorsementGroupsBelongsToUsers"; import { HttpStatusCode } from "axios"; import { EndorsementGroup } from "../../models/EndorsementGroup"; -import { createEndorsement } from "../../libraries/vateud/VateudCoreLibrary"; +import { createEndorsement, removeEndorsement } from "../../libraries/vateud/VateudCoreLibrary"; async function addEndorsement(request: Request, response: Response, next: NextFunction) { try { @@ -50,6 +50,48 @@ async function addEndorsement(request: Request, response: Response, next: NextFu } } +async function deleteEndorsement(request: Request, response: Response, next: NextFunction) { + try { + const requestingUser: User = response.locals.user; + const body = request.body as { user_endorsement_id: string }; + _UserAdminValidator.validateCreateRequest(body); + + + const userEndorsement = await EndorsementGroupsBelongsToUsers.findOne({where: { + id: Number(body.user_endorsement_id), + },}) + + + const user = await User.findOne({ + where: { + id: userEndorsement?.user_id ?? -1, + }, + include: [User.associations.endorsement_groups], + }); + + + const endorsementGroup = await EndorsementGroup.findOne({where: { + id: userEndorsement?.endorsement_group_id ?? -1, + },}) + + + + const success = await removeEndorsement(userEndorsement, endorsementGroup); + + if(success){ + throw new Error("Could not delete endorsement in VATEUD CORE."); + } + + await userEndorsement?.destroy(); + + + response.status(HttpStatusCode.Ok).send(user?.endorsement_groups ?? []); + } catch (e) { + next(e); + } +} + export default { addEndorsement, + deleteEndorsement, }; diff --git a/backend/src/libraries/vateud/VateudCoreLibrary.ts b/backend/src/libraries/vateud/VateudCoreLibrary.ts index 8e24e0b..bcec29c 100644 --- a/backend/src/libraries/vateud/VateudCoreLibrary.ts +++ b/backend/src/libraries/vateud/VateudCoreLibrary.ts @@ -132,8 +132,6 @@ export async function removeSolo(userSolo: UserSolo) { /** * Creates a Tier 1 or 2 endorsement. * On success, it updates the corresponding endorsement with the returned VATEUD ID - * On failure, it schedules a job which repeats the same request n times until it succeeds - * - If it fails more than n times, then it really isn't our problem anymore tbh... */ export async function createEndorsement(userEndorsement: EndorsementGroupsBelongsToUsers, endorsementGroup: EndorsementGroup | null) { if (!endorsementGroup) return false; @@ -169,3 +167,32 @@ export async function createEndorsement(userEndorsement: EndorsementGroupsBelong return true; } + +/** + * Removes a Tier 1 or 2 endorsement. + * On success, it updates the corresponding endorsement + */ +export async function removeEndorsement(userEndorsement: EndorsementGroupsBelongsToUsers|null, endorsementGroup: EndorsementGroup | null) { + if(!endorsementGroup || !userEndorsement) return false; + if(!userEndorsement.vateud_id) return true; + + const res = await _send({ + endpoint: `facility/endorsements/tier-${endorsementGroup.tier}/${userEndorsement.vateud_id}`, + method: "delete", + }); + + if (!res) return false; + + await EndorsementGroupsBelongsToUsers.update( + { + vateud_id: null, + }, + { + where: { + id: userEndorsement.id, + }, + } + ); + + return true; +} diff --git a/frontend/src/pages/administration/mentor/users/view/_modals/UVDeleteEndorsement.modal.tsx b/frontend/src/pages/administration/mentor/users/view/_modals/UVDeleteEndorsement.modal.tsx new file mode 100644 index 0000000..3cec2a5 --- /dev/null +++ b/frontend/src/pages/administration/mentor/users/view/_modals/UVDeleteEndorsement.modal.tsx @@ -0,0 +1,79 @@ +import { Modal } from "@/components/ui/Modal/Modal"; +import { UserModel, UserSoloModel } from "@/models/UserModel"; +import { Input } from "@/components/ui/Input/Input"; +import { getAtcRatingCombined } from "@/utils/helper/vatsim/AtcRatingHelper"; +import { Separator } from "@/components/ui/Separator/Separator"; +import { Select } from "@/components/ui/Select/Select"; +import dayjs from "dayjs"; +import React, { Dispatch, FormEvent, useState } from "react"; +import { Button } from "@/components/ui/Button/Button"; +import { TbPlaylistAdd, TbTrack, TbTrash } from "react-icons/tb"; +import { COLOR_OPTS } from "@/assets/theme.config"; +import FormHelper from "@/utils/helper/FormHelper"; +import { axiosInstance } from "@/utils/network/AxiosInstance"; +import ToastHelper from "@/utils/helper/ToastHelper"; +import { AxiosResponse } from "axios"; +import { EndorsementGroupModel } from "@/models/EndorsementGroupModel"; +import useApi from "@/utils/hooks/useApi"; +import { MapArray } from "@/components/conditionals/MapArray"; + +export function UVDeleteSoloModal({ show, onClose, user, setUser }: { show: boolean; onClose: () => any; user?: UserModel; setUser: Dispatch }) { + const [deletingSolo, setDeletingSolo] = useState(false); + + function deleteSolo(e: FormEvent) { + e.preventDefault(); + + if (user == null || user.user_solo == null) { + return; + } + setDeletingSolo(true); + + axiosInstance + .delete("/administration/solo", { + data: { + solo_id: user.user_solo.id, + trainee_id: user.id, + }, + }) + .then(res => { + const data: UserModel = res.data as UserModel; + + setUser({ + ...user, + user_solo: undefined, + endorsement_groups: data.endorsement_groups, + }); + ToastHelper.success("Freigabe erfolgreich gelöscht"); + onClose(); + }) + .catch(() => { + ToastHelper.error("Fehler beim Löschen der Freigabe"); + }) + .finally(() => setDeletingSolo(false)); + } + + return ( +
+ } color={COLOR_OPTS.DANGER} variant={"twoTone"}> + Löschen + + }> + + + +

+ Bist du sicher, dass du die Freigabe von{" "} + + {user?.first_name} {user?.last_name} + {" "} + löschen möchtest? Diese Aktion kann nicht rückgängig gemacht werden. +

+
+
+ ); +}