Feature/6 pilots delete (#42)

* adding pilot delete

* adding pilot delete

* adding pilot delete
This commit was merged in pull request #42.
This commit is contained in:
2025-02-19 00:16:05 +00:00
committed by GitHub
parent b9629ee4e9
commit c19b8aa855
24 changed files with 220 additions and 450 deletions

View File

@@ -1,5 +1,7 @@
import { Alert } from "../../interfaces/Alert.interface";
export interface ILogFormState {
error: string | undefined;
alert: Alert | undefined;
isDisabled: boolean;
isLoading: boolean;
pilotOptions: { label: string; value: string }[];

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useReducer, useState } from 'react';
import React, { useEffect, useReducer } from 'react';
import {
Accordion,
AccordionDetails,
@@ -19,7 +19,7 @@ import {
import { useForm, Controller, FormProvider } from 'react-hook-form';
import { ILogFormProps } from './ILogFormProps';
import { initialState, reducer } from './reducer';
import axios, { AxiosError, AxiosInstance, AxiosResponse } from 'axios';
import { AxiosError, AxiosInstance, AxiosResponse } from 'axios';
import { useHttpClient } from '../../hooks/httpClient/UseHttpClient';
import { useAccessToken } from '../../hooks/accessToken/UseAcessToken';
import { useIsAuthenticated } from '@azure/msal-react';
@@ -97,7 +97,7 @@ const LogForm: React.FC<ILogFormProps> = ({
} catch (error) {
const axiosError = error as AxiosError;
dispatch({ type: 'SET_ERROR', payload: axiosError.message });
dispatch({ type: 'SET_ALERT', payload: { severity: 'error', message: axiosError.message }});
} finally {
dispatch({ type: 'SET_IS_LOADING', payload: false });
}
@@ -127,7 +127,7 @@ const LogForm: React.FC<ILogFormProps> = ({
} catch (error) {
const axiosError = error as AxiosError;
dispatch({ type: 'SET_ERROR', payload: axiosError.message });
dispatch({ type: 'SET_ALERT', payload: { severity: 'error', message: axiosError.message }});
} finally {
dispatch({ type: 'SET_IS_LOADING', payload: false });
}
@@ -173,16 +173,16 @@ const LogForm: React.FC<ILogFormProps> = ({
<XmarkIcon />
</IconButton>
</Grid>
{state.error && (
{state.alert && (
<Grid display="flex" justifyContent="center" size={12}>
<Alert
onClose={() =>
dispatch({ type: 'SET_ERROR', payload: undefined })
dispatch({ type: 'SET_ALERT', payload: undefined })
}
severity="error"
severity={state.alert.severity}
sx={{ width: '100%' }}
>
{state.error}
{state.alert.message}
</Alert>
</Grid>
)}

View File

@@ -1,14 +1,15 @@
import { Alert } from '../../interfaces/Alert.interface';
import { ILogFormState } from './ILogFormState';
type Action =
| { type: 'SET_ERROR'; payload: string | undefined }
| { type: 'SET_ALERT'; payload: Alert | undefined }
| { type: 'SET_IS_DISABLED'; payload: boolean }
| { type: 'SET_IS_LOADING'; payload: boolean }
| { type: 'SET_PILOT_OPTIONS'; payload: { label: string; value: string }[] }
| { type: 'SET_SELECTED_ENTRY_PILOT_NAME'; payload: string };
export const initialState: ILogFormState = {
error: undefined,
alert: undefined,
isDisabled: false,
isLoading: true,
pilotOptions: [],
@@ -20,10 +21,10 @@ export const reducer = (
action: Action
): ILogFormState => {
switch (action.type) {
case 'SET_ERROR': {
case 'SET_ALERT': {
return {
...state,
error: action.payload
alert: action.payload
};
}
case 'SET_IS_DISABLED': {

View File

@@ -1,10 +1,11 @@
import { FormMode } from '../../enums/formMode';
import { Alert } from '../../interfaces/Alert.interface';
import { ILogbookEntry } from './ILogbookEntry';
export interface ILogbookState {
alert: Alert | undefined;
entries: ILogbookEntry[];
formMode: FormMode;
error: string | undefined;
isConfirmDialogLoading: boolean;
isConfirmDialogOpen: boolean;
isFormOpen: boolean;

View File

@@ -31,19 +31,23 @@ const Logbook: React.FC<unknown> = () => {
try {
dispatch({ type: 'SET_IS_LOADING', payload: true });
const token = await getAccessToken();
const config = isAuthenticated
? { headers: { Authorization: `${token}` } }
: {};
const response: AxiosResponse = await httpClient.get(`api/logs`, config);
const response: AxiosResponse = await httpClient.get(`api/logs`);
console.log(response)
dispatch({ type: 'SET_ENTRIES', payload: response.data });
if (response.data.length > 0) {
dispatch({ type: 'SET_ENTRIES', payload: response.data });
if (state.alert) {
dispatch({ type: 'SET_ALERT', payload: undefined})
}
} else {
dispatch({ type: 'SET_ALERT', payload: { severity: 'info', message: 'No logbook entries found.'}})
}
} catch (error) {
const axiosError = error as AxiosError;
dispatch({
type: 'SET_ERROR',
payload: `Loading of logbook entries failed with the following message: ${axiosError.message}`
type: 'SET_ALERT',
payload: { severity: 'error', message: `Loading of logbook entries failed with the following message: ${axiosError.message}`}
});
} finally {
dispatch({ type: 'SET_IS_LOADING', payload: false });
@@ -106,8 +110,8 @@ const Logbook: React.FC<unknown> = () => {
const axiosError = error as AxiosError;
dispatch({
type: 'SET_ERROR',
payload: `Loading of logbook entries failed with the following message: ${axiosError.message}`
type: 'SET_ALERT',
payload: { severity: 'error', message: `Loading of logbook entries failed with the following message: ${axiosError.message}`}
});
} finally {
dispatch({ type: 'SET_IS_CONFIRMATION_DIALOG_LOADING', payload: false });
@@ -363,10 +367,10 @@ const Logbook: React.FC<unknown> = () => {
];
useEffect(() => {
if (isAuthenticated && !state.isFormOpen) {
if (!state.isFormOpen) {
getLogbookEntries();
}
}, [isAuthenticated, state.isFormOpen]);
}, [state.isFormOpen]);
return (
<Box sx={{ margin: '20px' }}>
@@ -386,16 +390,16 @@ const Logbook: React.FC<unknown> = () => {
</Button>
}
</Grid>
{!state.isLoading && state.error && (
{!state.isLoading && state.alert && (
<Grid display="flex" justifyContent="center" size={12}>
<Alert
onClose={() =>
dispatch({ type: 'SET_ERROR', payload: undefined })
dispatch({ type: 'SET_ALERT', payload: undefined })
}
severity="error"
severity={state.alert.severity}
sx={{ width: '100%' }}
>
{state.error}
{state.alert.message}
</Alert>
</Grid>
)}
@@ -406,7 +410,7 @@ const Logbook: React.FC<unknown> = () => {
)}
</Grid>
)}
{state.isLoading && !state.error && (
{state.isLoading && !state.alert && (
<>
<Grid display="flex" justifyContent="center" size={12}>
<Spinner />

View File

@@ -1,4 +1,5 @@
import { FormMode } from '../../enums/formMode';
import { Alert } from '../../interfaces/Alert.interface';
import { ILogbookEntry } from './ILogbookEntry';
import { ILogbookState } from './ILogbookState';
@@ -11,7 +12,7 @@ type Action =
};
}
| { type: 'SET_ENTRIES'; payload: ILogbookEntry[] }
| { type: 'SET_ERROR'; payload: string | undefined }
| { type: 'SET_ALERT'; payload: Alert | undefined }
| { type: 'SET_FORM_MODE'; payload: FormMode }
| { type: 'SET_IS_CONFIRMATION_DIALOG_LOADING'; payload: boolean }
| { type: 'SET_IS_LOADING'; payload: boolean }
@@ -25,8 +26,8 @@ type Action =
};
export const initialState: ILogbookState = {
alert: undefined,
entries: [],
error: undefined,
formMode: FormMode.CANCEL,
isConfirmDialogLoading: false,
isConfirmDialogOpen: false,
@@ -53,10 +54,10 @@ export const reducer = (
entries: action.payload
};
}
case 'SET_ERROR': {
case 'SET_ALERT': {
return {
...state,
error: action.payload
alert: action.payload
};
}
case 'SET_FORM_MODE': {

View File

@@ -66,7 +66,7 @@ const PilotForm: React.FC<IPilotFormProps> = ({
const searchString: string = value;
const accessToken: string = await getAccessToken();
const response: AxiosResponse = await httpClient.get(
`api/personSearch?search=${searchString}`,
`api/user/search?search=${searchString}`,
{
headers: {
Authorization: accessToken

View File

@@ -1,6 +1,7 @@
import { useEffect, useReducer, useState } from 'react';
import PilotForm from '../pilotForm/PilotForm';
import {
Alert,
Box,
Button,
ColumnDef,
@@ -34,7 +35,7 @@ const Pilots: React.FC<unknown> = () => {
const isAuthenticated = useIsAuthenticated();
const { getAccessToken } = useAccessToken();
const getPilots = async (): Promise<Pilot[]> => {
const getPilots = async () => {
try {
const config = isAuthenticated
? { headers: { Authorization: await getAccessToken() } }
@@ -43,11 +44,25 @@ const Pilots: React.FC<unknown> = () => {
`api/pilots`,
config
);
const pilots: Pilot[] = response.data;
console.log(response.data)
if (response.data.length > 0) {
dispatch({ type: 'SET_PILOTS', payload: response.data });
return pilots;
if (state.alert) {
dispatch({ type: 'SET_ALERT', payload: undefined })
}
} else {
dispatch({ type: 'SET_ALERT', payload: { severity: 'info', message: 'No pilots found.' }})
}
} catch (error) {
throw new Error('broken');
const axiosError = error as AxiosError;
dispatch({
type: 'SET_ALERT',
payload: { severity: 'error', message: `Loading of pilots failed with the following message: ${axiosError.message}`}
})
} finally {
dispatch({ type: 'SET_IS_LOADING', payload: false })
}
};
@@ -107,8 +122,8 @@ const Pilots: React.FC<unknown> = () => {
const axiosError = error as AxiosError;
dispatch({
type: 'SET_ERROR',
payload: `Loading of logbook entries failed with the following message: ${axiosError.message}`
type: 'SET_ALERT',
payload: { severity: 'error', message: `Loading of logbook entries failed with the following message: ${axiosError.message}`}
});
} finally {
dispatch({ type: 'SET_IS_CONFIRMATION_DIALOG_LOADING', payload: false });
@@ -140,18 +155,8 @@ const Pilots: React.FC<unknown> = () => {
];
useEffect(() => {
const loadPilots = async () => {
try {
const pilots = await getPilots();
dispatch({ type: 'SET_PILOTS', payload: pilots })
} catch (error) {
console.log(error);
}
};
if (isAuthenticated && !state.isFormOpen) {
loadPilots();
getPilots();
}
}, [isAuthenticated, state.isFormOpen]);
@@ -173,6 +178,19 @@ const Pilots: React.FC<unknown> = () => {
</Button>
}
</Grid>
{!state.isLoading && state.alert && (
<Grid display="flex" justifyContent="center" size={12}>
<Alert
onClose={() =>
dispatch({ type: 'SET_ALERT', payload: undefined })
}
severity={state.alert.severity}
sx={{ width: '100%' }}
>
{state.alert.message}
</Alert>
</Grid>
)}
<Grid size={12}>
{state.pilots.length > 0 && <Table columns={columns} data={state.pilots} />}
</Grid>

View File

@@ -1,13 +1,14 @@
import { FormMode } from "../../enums/formMode";
import { Alert } from "../../interfaces/Alert.interface";
import { Pilot } from "./Pilot.interface";
export interface PilotsState {
pilots: Pilot[];
error: string | undefined;
alert: Alert | undefined;
isConfirmDialogLoading: boolean;
isConfirmDialogOpen: boolean;
isFormOpen: boolean;
isLoading: boolean;
formMode: FormMode;
pilots: Pilot[];
selectedPilotId: string | undefined;
}

View File

@@ -1,4 +1,5 @@
import { FormMode } from "../../enums/formMode";
import { Alert } from "../../interfaces/Alert.interface";
import { Pilot } from "./Pilot.interface";
import { PilotsState } from './PilotsState.interface'
@@ -11,7 +12,7 @@ type Action =
}
}
| { type: 'SET_PILOTS'; payload: Pilot[] }
| { type: 'SET_ERROR'; payload: string | undefined }
| { type: 'SET_ALERT'; payload: Alert | undefined }
| { type: 'SET_FORM_MODE'; payload: FormMode }
| { type: 'SET_IS_CONFIRMATION_DIALOG_LOADING'; payload: boolean }
| { type: 'SET_IS_LOADING'; payload: boolean }
@@ -25,13 +26,13 @@ type Action =
}
export const initialState: PilotsState = {
pilots: [],
error: undefined,
alert: undefined,
formMode: FormMode.CANCEL,
isConfirmDialogLoading: false,
isConfirmDialogOpen: false,
isFormOpen: false,
isLoading: false,
pilots: [],
selectedPilotId: undefined
}
@@ -53,10 +54,10 @@ export const reducer = (
pilots: action.payload
}
}
case 'SET_ERROR': {
case 'SET_ALERT': {
return {
...state,
error: action.payload
alert: action.payload
}
}
case 'SET_FORM_MODE': {

View File

@@ -53,7 +53,7 @@ const SiteNav: React.FC<unknown> = () => {
};
const getUserProfile = async (accessToken: string): Promise<User> => {
try {
const response: AxiosResponse = await httpClient.get(`api/userProfile`, {
const response: AxiosResponse = await httpClient.get(`api/user/profile`, {
headers: {
Authorization: accessToken
}
@@ -67,7 +67,7 @@ const SiteNav: React.FC<unknown> = () => {
};
const getUserPhoto = async (accessToken: string): Promise<string> => {
try {
const response: AxiosResponse = await httpClient.get(`api/userPhoto`, {
const response: AxiosResponse = await httpClient.get(`api/user/photo`, {
headers: {
Authorization: accessToken
},
@@ -98,45 +98,6 @@ const SiteNav: React.FC<unknown> = () => {
);
};
// useEffect(() => {
// const callback = instance.addEventCallback(
// async (message: EventMessage) => {
// if (message.eventType === EventType.LOGIN_SUCCESS) {
// try {
// setLoading(true);
// const eventPayload: EventPayloadExtended =
// message.payload as EventPayloadExtended;
// const userProfile: User = await getUserProfile(
// eventPayload.accessToken
// );
// const userPhoto = await getUserPhoto(eventPayload.accessToken);
// appContext.dispatch({
// type: 'SET_USER_PROFILE',
// payload: userProfile
// });
// } catch (error) {
// console.log(error);
// } finally {
// setLoading(false);
// }
// }
// }
// );
// instance.handleRedirectPromise().then((response) => {
// console.log(response)
// })
// return () => {
// if (callback) {
// instance.removeEventCallback(callback);
// appContext.dispatch({ type: 'SET_USER_PROFILE', payload: {} });
// }
// };
// }, []);
useEffect(() => {
const setUserProfile = async () => {
try {

View File

@@ -0,0 +1,4 @@
export interface Alert {
severity: 'success' | 'error' | 'info' | 'warning';
message: string;
}