Compare commits
10 Commits
feature/73
...
feature/81
| Author | SHA1 | Date | |
|---|---|---|---|
| c12b4a02e1 | |||
| f92a858281 | |||
| c5f9dcce73 | |||
| cc8e2f55fe | |||
| b6be7a9d2c | |||
| 729ab636be | |||
| a185abf6d8 | |||
| 9f13cc20a5 | |||
| 3ab9024152 | |||
| f15008a8db |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "api",
|
||||
"version": "1.3.0",
|
||||
"version": "1.3.1",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "app",
|
||||
"private": true,
|
||||
"version": "1.3.0",
|
||||
"version": "1.3.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -13,7 +13,7 @@
|
||||
"dependencies": {
|
||||
"@azure/msal-browser": "^4.0.1",
|
||||
"@azure/msal-react": "^3.0.1",
|
||||
"@noahspan/noahspan-components": "1.6.0",
|
||||
"@noahspan/noahspan-components": "^1.9.1",
|
||||
"axios": "^1.7.2",
|
||||
"dotenv": "^16.4.7",
|
||||
"leaflet": "^1.9.4",
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Box, Container } from "@noahspan/noahspan-components";
|
||||
import { Box, Container, Grid, Spinner } from "@noahspan/noahspan-components";
|
||||
import LogbookCard from "../logbookCard/LogbookCard";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useLogs } from "../../hooks/logs/UseLogs";
|
||||
import { ILogbookEntry } from "../logbook/ILogbookEntry";
|
||||
|
||||
const Flights = () => {
|
||||
const [flights, setFlights] = useState<ILogbookEntry[]>([])
|
||||
const { logs } = useLogs();
|
||||
const [flights, setFlights] = useState<ILogbookEntry[]>([]);
|
||||
const { logs, isLoading } = useLogs();
|
||||
|
||||
useEffect(() => {
|
||||
const flights: ILogbookEntry[] | undefined = logs?.filter((log: ILogbookEntry) => {
|
||||
@@ -23,7 +23,23 @@ const Flights = () => {
|
||||
return (
|
||||
<Container>
|
||||
<Box sx={{ margin: '20px' }}>
|
||||
<LogbookCard logs={flights} mode='flights' />
|
||||
<Grid container spacing={2}>
|
||||
{isLoading &&
|
||||
<>
|
||||
<Grid display="flex" justifyContent="center" size={12}>
|
||||
<Spinner />
|
||||
</Grid>
|
||||
<Grid display="flex" justifyContent="center" size={12}>
|
||||
Loading...
|
||||
</Grid>
|
||||
</>
|
||||
}
|
||||
{!isLoading &&
|
||||
<Grid size={12}>
|
||||
<LogbookCard logs={flights} mode='flights' />
|
||||
</Grid>
|
||||
}
|
||||
</Grid>
|
||||
</Box>
|
||||
</Container>
|
||||
)
|
||||
|
||||
@@ -4,8 +4,6 @@ import { useHttpClient } from '../../hooks/httpClient/UseHttpClient';
|
||||
import { AxiosInstance, AxiosResponse } from 'axios';
|
||||
import { useAccessToken } from '../../hooks/accessToken/UseAcessToken';
|
||||
import { useIsAuthenticated } from '@azure/msal-react';
|
||||
import { Swiper, SwiperSlide } from 'swiper/react';
|
||||
import { Pagination } from 'swiper/modules';
|
||||
import { MapContainer, TileLayer } from 'react-leaflet';
|
||||
import ReactLeafletKml from 'react-leaflet-kml';
|
||||
import 'swiper/css';
|
||||
@@ -46,35 +44,20 @@ const LogTrackMaps = ({ rowKey, trackUrls }: LogTrackMapsProps) => {
|
||||
}, [trackUrls])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Swiper
|
||||
spaceBetween={30}
|
||||
pagination={{
|
||||
clickable: true,
|
||||
}}
|
||||
modules={[Pagination]}
|
||||
className="mySwiper"
|
||||
>
|
||||
{tracks.length > 0 && tracks.map((track) => {
|
||||
return (
|
||||
<SwiperSlide>
|
||||
<MapContainer
|
||||
center={[45.14489, -93.21019]}
|
||||
scrollWheelZoom={false}
|
||||
style={{ height: '500px', width: '100%' }}
|
||||
zoom={8}
|
||||
>
|
||||
<TileLayer
|
||||
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
/>
|
||||
<ReactLeafletKml kml={track} />
|
||||
</MapContainer>
|
||||
</SwiperSlide>
|
||||
)
|
||||
})}
|
||||
</Swiper>
|
||||
</>
|
||||
<MapContainer
|
||||
center={[45.14489, -93.21019]}
|
||||
scrollWheelZoom={false}
|
||||
style={{ height: '500px', width: '100%' }}
|
||||
zoom={8}
|
||||
>
|
||||
<TileLayer
|
||||
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||
/>
|
||||
{tracks.length > 0 && tracks.map((track) => (
|
||||
<ReactLeafletKml kml={track} />
|
||||
))}
|
||||
</MapContainer>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack
|
||||
const uploadResponse: AxiosResponse = await httpClient.post(`api/logs/log/${selectedRowKey}/track`, formData, formDataConfig);
|
||||
const uploadUrl = uploadResponse.data.url;
|
||||
const log = await getLog();
|
||||
const tracks: string[] = JSON.parse(log.tracks!);
|
||||
const tracks: string[] = log.tracks ? JSON.parse(log.tracks!) : [];
|
||||
|
||||
tracks.push(uploadUrl)
|
||||
log.tracks = JSON.stringify(tracks);
|
||||
@@ -171,7 +171,7 @@ const LogTracks = ({ isDrawerOpen, mode, onOpenClose, selectedRowKey }: LogTrack
|
||||
onClick={onCancel}
|
||||
size="small"
|
||||
>
|
||||
{mode.toString() !== FormMode.VIEW ? 'Cancel' : 'Close'}
|
||||
Close
|
||||
</Button>
|
||||
{mode.toString() !== FormMode.VIEW && (
|
||||
<Button
|
||||
|
||||
@@ -1,15 +1,26 @@
|
||||
import {
|
||||
CellContext,
|
||||
ColumnDef,
|
||||
Icon,
|
||||
IconButton,
|
||||
IconName
|
||||
HeaderContext,
|
||||
} from '@noahspan/noahspan-components';
|
||||
import { ILogbookEntry } from './ILogbookEntry';
|
||||
|
||||
const columnTotal = (info: HeaderContext<ILogbookEntry, unknown>): number => {
|
||||
const values: number[] = info.table.getFilteredRowModel().rows.map((row: any) => Number(row.getValue(info.column.id))).filter((value: any) => !Number.isNaN(value));
|
||||
let total: number = 0;
|
||||
|
||||
if (values.length > 0) {
|
||||
total = values.reduce((accumulator, currentValue) => accumulator + currentValue, total)
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
const pilotName: ColumnDef<ILogbookEntry> = {
|
||||
id: 'pilotName',
|
||||
accessorKey: 'pilotName',
|
||||
header: 'Pilot'
|
||||
header: 'Pilot',
|
||||
footer: 'PAGE TOTALS'
|
||||
}
|
||||
const date: ColumnDef<ILogbookEntry> = {
|
||||
id: 'date',
|
||||
@@ -48,8 +59,9 @@ const durationOfFlight: ColumnDef<ILogbookEntry> = {
|
||||
align: 'right',
|
||||
headerAlign: 'right'
|
||||
},
|
||||
cell: (info: any) =>
|
||||
info.getValue() ? parseFloat(info.getValue()).toFixed(1) : ''
|
||||
cell: (info: CellContext<ILogbookEntry, unknown>) =>
|
||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : '',
|
||||
footer: (info: HeaderContext<ILogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : ''
|
||||
}
|
||||
const notes: ColumnDef<ILogbookEntry> = {
|
||||
id: 'notes',
|
||||
@@ -85,8 +97,9 @@ export const authColumns: ColumnDef<ILogbookEntry>[] = [
|
||||
align: 'right',
|
||||
headerAlign: 'right'
|
||||
},
|
||||
cell: (info: any) =>
|
||||
info.getValue() ? parseFloat(info.getValue()).toFixed(1) : ''
|
||||
cell: (info: CellContext<ILogbookEntry, unknown>) =>
|
||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : '',
|
||||
footer: (info: HeaderContext<ILogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : ''
|
||||
},
|
||||
{
|
||||
id: 'landings',
|
||||
@@ -99,6 +112,7 @@ export const authColumns: ColumnDef<ILogbookEntry>[] = [
|
||||
id: 'landingsDay',
|
||||
accessorKey: 'landingsDay',
|
||||
header: 'Day',
|
||||
footer: (info: HeaderContext<ILogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info) : '',
|
||||
meta: {
|
||||
align: 'right',
|
||||
headerAlign: 'right'
|
||||
@@ -108,6 +122,7 @@ export const authColumns: ColumnDef<ILogbookEntry>[] = [
|
||||
id: 'landingsNight',
|
||||
accessorKey: 'landingsNight',
|
||||
header: 'Night',
|
||||
footer: (info: HeaderContext<ILogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info) : '',
|
||||
meta: {
|
||||
align: 'right',
|
||||
headerAlign: 'right'
|
||||
@@ -126,28 +141,31 @@ export const authColumns: ColumnDef<ILogbookEntry>[] = [
|
||||
id: 'instrumentActual',
|
||||
accessorKey: 'instrumentActual',
|
||||
header: 'Actual',
|
||||
footer: (info: HeaderContext<ILogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
||||
meta: {
|
||||
align: 'right',
|
||||
headerAlign: 'right'
|
||||
},
|
||||
cell: (info: any) =>
|
||||
info.getValue() ? parseFloat(info.getValue()).toFixed(1) : ''
|
||||
cell: (info: CellContext<ILogbookEntry, unknown>) =>
|
||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : '',
|
||||
},
|
||||
{
|
||||
id: 'instrumentSimulated',
|
||||
accessorKey: 'instrumentSimulated',
|
||||
header: 'Simulated',
|
||||
footer: (info: HeaderContext<ILogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
||||
meta: {
|
||||
align: 'right',
|
||||
headerAlign: 'right'
|
||||
},
|
||||
cell: (info: any) =>
|
||||
info.getValue() ? parseFloat(info.getValue()).toFixed(1) : ''
|
||||
cell: (info: CellContext<ILogbookEntry, unknown>) =>
|
||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : ''
|
||||
},
|
||||
{
|
||||
id: 'instrumentApproaches',
|
||||
accessorKey: 'instrumentApproaches',
|
||||
header: 'Approaches',
|
||||
footer: (info: HeaderContext<ILogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
||||
meta: {
|
||||
align: 'right',
|
||||
headerAlign: 'right'
|
||||
@@ -157,6 +175,7 @@ export const authColumns: ColumnDef<ILogbookEntry>[] = [
|
||||
id: 'instrumentHolds',
|
||||
accessorKey: 'instrumentHolds',
|
||||
header: 'Holds',
|
||||
footer: (info: HeaderContext<ILogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
||||
meta: {
|
||||
align: 'right',
|
||||
headerAlign: 'right'
|
||||
@@ -166,6 +185,7 @@ export const authColumns: ColumnDef<ILogbookEntry>[] = [
|
||||
id: 'instrumentNavTrack',
|
||||
accessorKey: 'instrumentNavTrack',
|
||||
header: 'Nav/Track',
|
||||
footer: (info: HeaderContext<ILogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
||||
meta: {
|
||||
align: 'right',
|
||||
headerAlign: 'right'
|
||||
@@ -184,67 +204,73 @@ export const authColumns: ColumnDef<ILogbookEntry>[] = [
|
||||
id: 'groundTrainingReceived',
|
||||
accessorKey: 'groundTrainingReceived',
|
||||
header: 'Ground Training Received',
|
||||
footer: (info: HeaderContext<ILogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
||||
meta: {
|
||||
align: 'right',
|
||||
headerAlign: 'right'
|
||||
},
|
||||
cell: (info: any) =>
|
||||
info.getValue() ? parseFloat(info.getValue()).toFixed(1) : ''
|
||||
cell: (info: CellContext<ILogbookEntry, unknown>) =>
|
||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : ''
|
||||
},
|
||||
{
|
||||
id: 'flightTrainingReceived',
|
||||
accessorKey: 'flightTrainingReceived',
|
||||
header: 'Flight Training Received',
|
||||
footer: (info: HeaderContext<ILogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
||||
meta: {
|
||||
align: 'right',
|
||||
headerAlign: 'right'
|
||||
},
|
||||
cell: (info: any) =>
|
||||
info.getValue() ? parseFloat(info.getValue()).toFixed(1) : ''
|
||||
cell: (info: CellContext<ILogbookEntry, unknown>) =>
|
||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : ''
|
||||
},
|
||||
{
|
||||
id: 'crossCountry',
|
||||
accessorKey: 'crossCountry',
|
||||
header: 'Cross Country',
|
||||
footer: (info: HeaderContext<ILogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
||||
meta: {
|
||||
align: 'right',
|
||||
headerAlign: 'right'
|
||||
},
|
||||
cell: (info: any) =>
|
||||
info.getValue() ? parseFloat(info.getValue()).toFixed(1) : ''
|
||||
cell: (info: CellContext<ILogbookEntry, unknown>) =>
|
||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : ''
|
||||
},
|
||||
{
|
||||
id: 'night',
|
||||
accessorKey: 'night',
|
||||
header: 'Night',
|
||||
footer: (info: HeaderContext<ILogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
||||
meta: {
|
||||
align: 'right',
|
||||
headerAlign: 'right'
|
||||
},
|
||||
cell: (info: any) =>
|
||||
info.getValue() ? parseFloat(info.getValue()).toFixed(1) : ''
|
||||
cell: (info: CellContext<ILogbookEntry, unknown>) =>
|
||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : ''
|
||||
},
|
||||
{
|
||||
id: 'solo',
|
||||
accessorKey: 'solo',
|
||||
header: 'Solo',
|
||||
footer: (info: HeaderContext<ILogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
||||
meta: {
|
||||
align: 'right',
|
||||
headerAlign: 'right'
|
||||
},
|
||||
cell: (info: any) =>
|
||||
info.getValue() ? parseFloat(info.getValue()).toFixed(1) : ''
|
||||
cell: (info: CellContext<ILogbookEntry, unknown>) =>
|
||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : ''
|
||||
},
|
||||
{
|
||||
id: 'pilotInCommand',
|
||||
accessorKey: 'pilotInCommand',
|
||||
header: 'Pilot In Command',
|
||||
footer: (info: HeaderContext<ILogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
||||
meta: {
|
||||
align: 'right',
|
||||
headerAlign: 'right'
|
||||
},
|
||||
cell: (info: any) =>
|
||||
info.getValue() ? parseFloat(info.getValue()).toFixed(1) : ''
|
||||
cell: (info: CellContext<ILogbookEntry, unknown>) =>
|
||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : ''
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -7,6 +7,7 @@ import { ILogbookEntry } from "../../components/logbook/ILogbookEntry";
|
||||
|
||||
export const useLogs = () => {
|
||||
const [logs, setLogs] = useState<ILogbookEntry[]>();
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const httpClient: AxiosInstance = useHttpClient();
|
||||
const { getAccessToken } = useAccessToken();
|
||||
const isAuthenticated = useIsAuthenticated();
|
||||
@@ -14,6 +15,8 @@ export const useLogs = () => {
|
||||
useEffect(() => {
|
||||
const getLogs = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
|
||||
const config = isAuthenticated
|
||||
? { headers: { Authorization: await getAccessToken() } }
|
||||
: {};
|
||||
@@ -28,6 +31,8 @@ export const useLogs = () => {
|
||||
setLogs(logs)
|
||||
} catch (error) {
|
||||
return error;
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +40,7 @@ export const useLogs = () => {
|
||||
}, [])
|
||||
|
||||
return {
|
||||
logs
|
||||
logs,
|
||||
isLoading
|
||||
}
|
||||
}
|
||||
916
pnpm-lock.yaml
generated
916
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user