diff --git a/api/src/log/log.controller.ts b/api/src/log/log.controller.ts index 4ce4d36..6ba1c78 100644 --- a/api/src/log/log.controller.ts +++ b/api/src/log/log.controller.ts @@ -105,7 +105,7 @@ export class LogController { } } - // @UseGuards(AuthGuard) + @UseGuards(AuthGuard) @Post(':partitionKey/:rowKey/track') @UseInterceptors(FileInterceptor('file')) async createTrack(@Param('rowKey') rowKey: string, @UploadedFile() file: Express.Multer.File) { diff --git a/app/src/components/logTracks/LogTracks.tsx b/app/src/components/logTracks/LogTracks.tsx index dc2a566..fbe73c9 100644 --- a/app/src/components/logTracks/LogTracks.tsx +++ b/app/src/components/logTracks/LogTracks.tsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect, useReducer, useState } from "react"; import { Button, Drawer, Grid, Icon, IconButton, IconName, TextField, theme, Typography, useMediaQuery } from "@noahspan/noahspan-components"; import { useHttpClient } from "../../hooks/httpClient/UseHttpClient"; import { AxiosInstance, AxiosResponse } from "axios"; @@ -7,10 +7,11 @@ import { LogTracksProps } from "./LogTracksProps.interface"; import { FormMode } from "../../enums/formMode"; import { useIsAuthenticated } from "@azure/msal-react"; import { ILogbookEntry } from "../logbook/ILogbookEntry"; +import ConfirmationDialog from "../confirmationDialog/ConfirmationDialog"; +import { initialState, reducer } from "./reducer"; const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTracksProps) => { - const [tracks, setTracks] = useState([]); - const [isLoading, setIsLoading] = useState(false); + const [state, dispatch] = useReducer(reducer, initialState) const httpClient: AxiosInstance = useHttpClient(); const { getAccessToken } = useAccessToken(); const isAuthenticated = useIsAuthenticated(); @@ -37,7 +38,7 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack const handleFileUpload = async (event: React.ChangeEvent) => { try { - setIsLoading(true); + dispatch({ type: 'SET_IS_LOADING', payload: true}) const file = event.target.files![0] const formData = new FormData(); @@ -62,11 +63,11 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack const updatedLog = await getLog(); - setTracks(JSON.parse(updatedLog.tracks!)) + dispatch({ type: 'SET_TRACKS', payload: JSON.parse(updatedLog.tracks!) }) } catch (error) { console.log(error) } finally { - setIsLoading(false); + dispatch({ type: 'SET_IS_LOADING', payload: false }); } } @@ -74,32 +75,41 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack onOpenClose(FormMode.CANCEL) } - const onDelete = async (fileName: string, index: number) => { + const onDeleteTrack = async (fileName: string, index: number) => { + dispatch({ type: 'SET_ON_DELETE_TRACK', payload: { isConfirmDialogOpen: true, selectedTrack: { fileName: fileName, index: index }}}) + } + + const onConfirmDialogConfirm = async () => { try { const config = await getConfig(); - await httpClient.delete(`api/logs/log/${selectedRowKey}/track?fileName=${fileName}`, config); + await httpClient.delete(`api/logs/log/${selectedRowKey}/track?fileName=${state.selectedTrack!.fileName}`, config); const log = await getLog(); const tracks: string[] = JSON.parse(log.tracks!); - tracks.splice(index, 1); + tracks.splice(state.selectedTrack!.index, 1); log.tracks = JSON.stringify(tracks); await httpClient.put(`api/logs/log/${selectedRowKey}`, log, config); const updatedLog = await getLog(); - setTracks(JSON.parse(updatedLog.tracks!)) + dispatch({ type: 'SET_TRACKS', payload: JSON.parse(updatedLog.tracks!) }) + dispatch({ type: 'SET_IS_CONFIRM_DIALOG_OPEN', payload: false }) } catch (error) { console.log(error); } } + const onConfirmDialogCancel = async () => { + dispatch({ type: 'SET_IS_CONFIRM_DIALOG_OPEN', payload: false }) + } + useEffect(() => { const updateTracks = async () => { const log = await getLog(); - setTracks(JSON.parse(log.tracks!)); + dispatch({ type: 'SET_TRACKS', payload: JSON.parse(log.tracks!) }); } updateTracks(); @@ -125,7 +135,7 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack - {tracks.length > 0 && tracks.map((track, index) => { + {state.tracks.length > 0 && state.tracks.map((track, index) => { const trackSplit = track.split('/') const filename = trackSplit[trackSplit.length - 1]; @@ -135,7 +145,7 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack - onDelete(filename, index)}> + onDeleteTrack(filename, index)}> ) @@ -153,16 +163,26 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack {mode.toString() !== FormMode.VIEW && ( )} + {state.isConfirmDialogOpen && ( + + )} ) } diff --git a/app/src/components/logTracks/LogTracksState.interface.ts b/app/src/components/logTracks/LogTracksState.interface.ts new file mode 100644 index 0000000..6c2984c --- /dev/null +++ b/app/src/components/logTracks/LogTracksState.interface.ts @@ -0,0 +1,10 @@ +export interface LogTracksState { + isConfirmDialogOpen: boolean; + isConfirmDialogLoading: boolean; + isLoading: boolean; + selectedTrack: { + fileName: string, + index: number + } | undefined; + tracks: string[]; +} \ No newline at end of file diff --git a/app/src/components/logTracks/reducer.ts b/app/src/components/logTracks/reducer.ts new file mode 100644 index 0000000..ca9d6f5 --- /dev/null +++ b/app/src/components/logTracks/reducer.ts @@ -0,0 +1,55 @@ +import { LogTracksState } from "./LogTracksState.interface"; + +type Action = + | { type: 'SET_IS_CONFIRM_DIALOG_OPEN'; payload: boolean } + | { type: 'SET_IS_CONFORM_DIALOG_LOADING'; payload: boolean } + | { type: 'SET_IS_LOADING'; payload: boolean } + | { type: 'SET_ON_DELETE_TRACK'; payload: { isConfirmDialogOpen: boolean, selectedTrack: { fileName: string, index: number } }} + | { type: 'SET_TRACKS'; payload: string[] }; + +export const initialState: LogTracksState = { + isConfirmDialogOpen: false, + isConfirmDialogLoading: false, + isLoading: false, + selectedTrack: undefined, + tracks: [] +} + +export const reducer = (state: LogTracksState, action: Action): LogTracksState => { + switch (action.type) { + case 'SET_IS_CONFIRM_DIALOG_OPEN': { + return { + ...state, + isConfirmDialogOpen: action.payload + } + } + case 'SET_IS_CONFORM_DIALOG_LOADING': { + return { + ...state, + isConfirmDialogLoading: action.payload + } + } + case 'SET_IS_LOADING': { + return { + ...state, + isLoading: action.payload + } + } + case 'SET_ON_DELETE_TRACK': { + return { + ...state, + isConfirmDialogOpen: action.payload.isConfirmDialogOpen, + selectedTrack: action.payload.selectedTrack + } + } + case 'SET_TRACKS': { + return { + ...state, + tracks: action.payload + } + } + default: { + return state + } + } +} diff --git a/app/src/components/pilotForm/PilotForm.tsx b/app/src/components/pilotForm/PilotForm.tsx index 6580c34..736b98f 100644 --- a/app/src/components/pilotForm/PilotForm.tsx +++ b/app/src/components/pilotForm/PilotForm.tsx @@ -197,7 +197,7 @@ const PilotForm: React.FC = ({ }} > -
+ {`${mode.toString().toLowerCase().charAt(0).toUpperCase() + mode.toString().slice(1).toLowerCase()} Pilot`}