Compare commits
18 Commits
104-switch
...
v2.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
| f246c1f0f6 | |||
| 36b4018858 | |||
| 6b0c292d34 | |||
| 51de91f8d4 | |||
| 41e9ae33dc | |||
| 870241b37f | |||
| a827b5a39f | |||
| 0663ac873e | |||
| 7cfe005154 | |||
| f421b8d231 | |||
| 5977659dd4 | |||
| 01c1e7015e | |||
| 10d160bbc2 | |||
| f321c2506a | |||
| 976574c6ac | |||
| f3c7fb8853 | |||
| cf8e50fb9c | |||
| fec99878de |
7
.github/workflows/build.yaml
vendored
7
.github/workflows/build.yaml
vendored
@@ -39,7 +39,14 @@ jobs:
|
|||||||
npm run build -w api
|
npm run build -w api
|
||||||
|
|
||||||
- name: Build Client
|
- name: Build Client
|
||||||
|
env:
|
||||||
|
VITE_API_URL: ${{ vars.VITE_API_URL }}
|
||||||
|
VITE_BASE_URL: ${{ vars.VITE_BASE_URL }}
|
||||||
|
VITE_CLIENT_ID: ${{ vars.VITE_CLIENT_ID }}
|
||||||
|
VITE_ISSUER_URI: ${{ vars.VITE_ISSUER_URI }}
|
||||||
|
VITE_TENANT_ID: ${{ vars.VITE_TENANT_ID }}
|
||||||
run: |
|
run: |
|
||||||
|
printenv
|
||||||
npm run build -w client
|
npm run build -w client
|
||||||
|
|
||||||
- name: Log into Docker Hub
|
- name: Log into Docker Hub
|
||||||
|
|||||||
2
.github/workflows/main.yaml
vendored
2
.github/workflows/main.yaml
vendored
@@ -9,7 +9,7 @@ jobs:
|
|||||||
uses: ./.github/workflows/changes.yaml
|
uses: ./.github/workflows/changes.yaml
|
||||||
|
|
||||||
build:
|
build:
|
||||||
if: ${{ needs.changes.outputs.app == 'true' || needs.changes.outputs.client == 'true' }}
|
if: ${{ needs.changes.outputs.api == 'true' || needs.changes.outputs.client == 'true' }}
|
||||||
name: build
|
name: build
|
||||||
needs:
|
needs:
|
||||||
- changes
|
- changes
|
||||||
|
|||||||
2
.github/workflows/tag.yaml
vendored
2
.github/workflows/tag.yaml
vendored
@@ -2,7 +2,7 @@ name: Tag
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- 'v[0-9]+.[0-9]+.[0-9]+'
|
- '**'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM --platform=linux/amd64 node:22-slim
|
FROM node:22
|
||||||
|
|
||||||
WORKDIR app
|
WORKDIR app
|
||||||
COPY ./api/dist ./api/dist
|
COPY ./api/dist ./api/dist
|
||||||
@@ -9,10 +9,8 @@ WORKDIR api
|
|||||||
RUN npm ci
|
RUN npm ci
|
||||||
|
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
COPY ./api/entrypoint.sh ./entrypoint.sh
|
|
||||||
RUN chmod +x entrypoint.sh
|
|
||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
ENTRYPOINT ["/entrypoint.sh"]
|
CMD ["node", "./app/api/dist/main.js"]
|
||||||
# ENTRYPOINT ["tail", "-f", "/dev/null"]
|
# ENTRYPOINT ["tail", "-f", "/dev/null"]
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
npx typeorm migration:run -d ./app/api/dist/database/data-source.js
|
|
||||||
node ./app/api/dist/main.js
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "api",
|
"name": "api",
|
||||||
"version": "2.0.0-alpha-3",
|
"version": "2.0.0-beta-1",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "",
|
"author": "",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ export const dataSourceOptions: DataSourceOptions = {
|
|||||||
database: configService.get<string>('DB_PATH'),
|
database: configService.get<string>('DB_PATH'),
|
||||||
entities: ['../**/*.entity.js'],
|
entities: ['../**/*.entity.js'],
|
||||||
migrations: ['./migrations/*.js'],
|
migrations: ['./migrations/*.js'],
|
||||||
synchronize: configService.get<boolean>('DB_SYNC')
|
synchronize: configService.get<boolean>('DB_SYNC'),
|
||||||
|
migrationsRun: true
|
||||||
}
|
}
|
||||||
|
|
||||||
const dataSource = new DataSource(dataSourceOptions);
|
const dataSource = new DataSource(dataSourceOptions);
|
||||||
|
|||||||
@@ -9,11 +9,7 @@ async function bootstrap() {
|
|||||||
const httpService = new HttpService();
|
const httpService = new HttpService();
|
||||||
const app = await NestFactory.create(AppModule);
|
const app = await NestFactory.create(AppModule);
|
||||||
|
|
||||||
app.enableCors({
|
app.enableCors();
|
||||||
origin: 'http://localhost:8080',
|
|
||||||
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
|
|
||||||
credentials: true,
|
|
||||||
});
|
|
||||||
app.setGlobalPrefix('api');
|
app.setGlobalPrefix('api');
|
||||||
app.useGlobalFilters(new HttpExceptionFilter());
|
app.useGlobalFilters(new HttpExceptionFilter());
|
||||||
app.use(
|
app.use(
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
BLAH BLAH
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "client",
|
"name": "client",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2.0.0-alpha-3",
|
"version": "2.0.0-beta-1",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -14,7 +14,6 @@
|
|||||||
"@fortawesome/fontawesome-svg-core": "^7.1.0",
|
"@fortawesome/fontawesome-svg-core": "^7.1.0",
|
||||||
"@fortawesome/free-solid-svg-icons": "^7.1.0",
|
"@fortawesome/free-solid-svg-icons": "^7.1.0",
|
||||||
"@fortawesome/react-fontawesome": "^3.1.0",
|
"@fortawesome/react-fontawesome": "^3.1.0",
|
||||||
"@noahspan/noahspan-components": "^2.0.0-alpha-14",
|
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"@tailwindcss/vite": "^4.1.13",
|
"@tailwindcss/vite": "^4.1.13",
|
||||||
"@tanstack/react-table": "^8.21.3",
|
"@tanstack/react-table": "^8.21.3",
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
import { useState } from 'react';
|
|
||||||
import { IActionMenuProps } from './IActionMenuProps';
|
|
||||||
import {
|
|
||||||
IconButton,
|
|
||||||
Icon,
|
|
||||||
IconName,
|
|
||||||
Dropdown
|
|
||||||
} from '@noahspan/noahspan-components';
|
|
||||||
import { FormMode } from '../../enums/formMode';
|
|
||||||
import { useAuth } from 'react-oidc-context';
|
|
||||||
|
|
||||||
const ActionMenu = ({ id, onDelete, onOpenCloseForm, onOpenCloseTracks }: IActionMenuProps) => {
|
|
||||||
// const [anchorElAction, setAnchorElAction] = useState<null | HTMLElement>(
|
|
||||||
// null
|
|
||||||
// );
|
|
||||||
// const auth = useAuth();
|
|
||||||
|
|
||||||
// const onOpenActionMenu = (event: React.MouseEvent<HTMLElement>) => {
|
|
||||||
// setAnchorElAction(event.currentTarget);
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const onCloseActionMenu = () => {
|
|
||||||
// setAnchorElAction(null);
|
|
||||||
// };
|
|
||||||
|
|
||||||
const options = [
|
|
||||||
'Item 1',
|
|
||||||
'Item 2'
|
|
||||||
]
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Dropdown
|
|
||||||
onOptionSelected={() => console.log('clicked!')}
|
|
||||||
options={options}
|
|
||||||
>
|
|
||||||
<IconButton>
|
|
||||||
<Icon className='text-2xl' iconName={IconName.ELLIPSIS_VERTICAL} />
|
|
||||||
</IconButton>
|
|
||||||
</Dropdown>
|
|
||||||
</>
|
|
||||||
// <div>
|
|
||||||
// <IconButton onClick={onOpenActionMenu}>
|
|
||||||
// <Icon iconName={IconName.ELLIPSIS_VERTICAL} size="sm" />
|
|
||||||
// </IconButton>
|
|
||||||
// <Menu
|
|
||||||
// anchorEl={anchorElAction}
|
|
||||||
// keepMounted
|
|
||||||
// open={Boolean(anchorElAction)}
|
|
||||||
// onClose={onCloseActionMenu}
|
|
||||||
// >
|
|
||||||
// {auth.isAuthenticated &&
|
|
||||||
// <>
|
|
||||||
// <MenuItem onClick={() => onOpenCloseForm(FormMode.EDIT, id)}>
|
|
||||||
// <ListItemIcon>
|
|
||||||
// <Icon iconName={IconName.PEN} size="lg" />
|
|
||||||
// </ListItemIcon>
|
|
||||||
// <ListItemText>Edit</ListItemText>
|
|
||||||
// </MenuItem>
|
|
||||||
// {onOpenCloseTracks &&
|
|
||||||
// <MenuItem onClick={() => onOpenCloseTracks!(FormMode.EDIT, id)}>
|
|
||||||
// <ListItemIcon>
|
|
||||||
// <Icon iconName={IconName.MAP_LOCATION_DOT} size="lg" />
|
|
||||||
// </ListItemIcon>
|
|
||||||
// <ListItemText>Tracks</ListItemText>
|
|
||||||
// </MenuItem>
|
|
||||||
// }
|
|
||||||
// </>
|
|
||||||
|
|
||||||
// }
|
|
||||||
// <MenuItem onClick={() => onOpenCloseForm(FormMode.VIEW, id)}>
|
|
||||||
// <ListItemIcon>
|
|
||||||
// <Icon iconName={IconName.EYE} size="lg" />
|
|
||||||
// </ListItemIcon>
|
|
||||||
// <ListItemText>View</ListItemText>
|
|
||||||
// </MenuItem>
|
|
||||||
// {auth.isAuthenticated &&
|
|
||||||
// <>
|
|
||||||
// <hr className="my-3" />
|
|
||||||
// <MenuItem onClick={() => onDelete(id)}>
|
|
||||||
// <ListItemIcon>
|
|
||||||
// <Icon iconName={IconName.TRASH} size="lg" />
|
|
||||||
// </ListItemIcon>
|
|
||||||
// <ListItemText>Delete</ListItemText>
|
|
||||||
// </MenuItem>
|
|
||||||
// </>
|
|
||||||
// }
|
|
||||||
// </Menu>
|
|
||||||
// </div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ActionMenu;
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
import { FormMode } from '../../enums/formMode';
|
|
||||||
|
|
||||||
export interface IActionMenuProps {
|
|
||||||
id: string;
|
|
||||||
onDelete: (entryId: string) => void;
|
|
||||||
onOpenCloseForm: (formMode: FormMode, id: string) => void;
|
|
||||||
onOpenCloseTracks?: (formMode: FormMode, id: string) => void;
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,3 @@
|
|||||||
// import {
|
|
||||||
// Button,
|
|
||||||
// Dialog,
|
|
||||||
// DialogActions,
|
|
||||||
// DialogContent,
|
|
||||||
// Icon,
|
|
||||||
// IconName,
|
|
||||||
// Loading
|
|
||||||
// } from '@noahspan/noahspan-components';
|
|
||||||
import { DialogConfirmationProps } from './ConfirmationDialogProps.interface';
|
import { DialogConfirmationProps } from './ConfirmationDialogProps.interface';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { faCircleCheck, faXmark } from '@fortawesome/free-solid-svg-icons';
|
import { faCircleCheck, faXmark } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|||||||
@@ -48,30 +48,18 @@ const Flights = () => {
|
|||||||
<LogbookCard logs={state.flights} mode='flights' />
|
<LogbookCard logs={state.flights} mode='flights' />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{/* {logsLoading && [...Array(6)].map((_element, index) => {
|
{logsLoading && [...Array(5)].map((_element, index) => {
|
||||||
return (
|
return (
|
||||||
<div className='mb-5'>
|
<div className='card bg-base-100 border border-base-300 p-2 mb-7'>
|
||||||
<Card
|
<div className='card-body' key={index}>
|
||||||
key={index}
|
<div className='skeleton h-10 w-[150px]' />
|
||||||
>
|
<div className='skeleton h-[350px]' />
|
||||||
<div className='p-5'>
|
<div className='skeleton h-[65px]' />
|
||||||
<div className='mb-2'><Skeleton height='h-[60px]' width='w-[200px]' /></div>
|
</div>
|
||||||
<div className='mb-2'><Skeleton height='h-[30px]' width='w-[200px]' /></div>
|
</div>
|
||||||
<div className='mb-2'><Skeleton height='h-[300px]' width='w-[300px]' /></div>
|
|
||||||
{[...Array(4)].map((_element, index) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className='mb-2'><Skeleton height='h-[20px]' width='w-[300px]' /></div>
|
|
||||||
<div className='mb-2'><Skeleton height='h-[20px]' width='w-[300px]' /></div>
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})} */}
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { useEffect, useReducer } from 'react';
|
import { useEffect, useReducer, useState } from 'react';
|
||||||
import { initialState, reducer } from './reducer';
|
import { initialState, reducer } from './reducer';
|
||||||
import { AxiosError, AxiosResponse } from 'axios';
|
import { AxiosError, AxiosResponse } from 'axios';
|
||||||
import { FormMode } from '../../enums/formMode';
|
import { FormMode } from '../../enums/formMode';
|
||||||
import { authColumns, unauthColumns } from './columns';
|
|
||||||
import ConfirmationDialog from '../confirmationDialog/ConfirmationDialog';
|
import ConfirmationDialog from '../confirmationDialog/ConfirmationDialog';
|
||||||
import { LogbookEntry } from './LogbookEntry.interface';
|
import { LogbookEntry } from './LogbookEntry.interface';
|
||||||
import LogbookCard from '../logbookCard/LogbookCard';
|
import LogbookCard from '../logbookCard/LogbookCard';
|
||||||
@@ -21,6 +20,7 @@ import Alert from '../alert/Alert';
|
|||||||
|
|
||||||
const Logbook: React.FC<unknown> = () => {
|
const Logbook: React.FC<unknown> = () => {
|
||||||
const [state, dispatch] = useReducer(reducer, initialState);
|
const [state, dispatch] = useReducer(reducer, initialState);
|
||||||
|
const [columnVisibility, setColumnVisibility] = useState({})
|
||||||
const logbookContext = useLogbookContext()
|
const logbookContext = useLogbookContext()
|
||||||
const { isUserLoggedIn } = useOidc();
|
const { isUserLoggedIn } = useOidc();
|
||||||
const { userRole } = useUserRole();
|
const { userRole } = useUserRole();
|
||||||
@@ -51,7 +51,7 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
accessorKey: 'date',
|
accessorKey: 'date',
|
||||||
header: 'Date',
|
header: 'Date',
|
||||||
cell: (info: CellContext<LogbookEntry, unknown>) => {
|
cell: (info: CellContext<LogbookEntry, unknown>) => {
|
||||||
const date = new Date(info.getValue() as string);
|
const date = new Date((info.getValue() as string).replace('Z', ''));
|
||||||
const formattedDate = `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`
|
const formattedDate = `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`
|
||||||
|
|
||||||
return formattedDate;
|
return formattedDate;
|
||||||
@@ -118,7 +118,7 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
return (
|
return (
|
||||||
<div className='dropdown dropdown-end'>
|
<div className='dropdown dropdown-end'>
|
||||||
<div tabIndex={0} role='button' className='btn btn-ghost'><FontAwesomeIcon icon={faEllipsisVertical} /></div>
|
<div tabIndex={0} role='button' className='btn btn-ghost'><FontAwesomeIcon icon={faEllipsisVertical} /></div>
|
||||||
<ul tabIndex={-1} className="dropdown-content menu bg-base-100 rounded-box z-1 w-52 p-2 shadow-sm border border-base-300">
|
<ul tabIndex={-1} className="dropdown-content menu bg-base-100 rounded-box w-52 p-2 shadow-sm border border-base-300 !z-[100]">
|
||||||
{isUserLoggedIn && userRole === UserRole.WRITE &&
|
{isUserLoggedIn && userRole === UserRole.WRITE &&
|
||||||
<li><a onClick={() => onOpenCloseDrawer(FormMode.EDIT, info.row.original.id)}><FontAwesomeIcon icon={faPen} />Edit</a></li>
|
<li><a onClick={() => onOpenCloseDrawer(FormMode.EDIT, info.row.original.id)}><FontAwesomeIcon icon={faPen} />Edit</a></li>
|
||||||
}
|
}
|
||||||
@@ -132,16 +132,7 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const unauthColumns: ColumnDef<LogbookEntry>[] = [
|
const columns: ColumnDef<LogbookEntry>[] = [
|
||||||
pilotName,
|
|
||||||
date,
|
|
||||||
aircraftMakeModel,
|
|
||||||
route,
|
|
||||||
durationOfFlight,
|
|
||||||
notes
|
|
||||||
]
|
|
||||||
|
|
||||||
const authColumns: ColumnDef<LogbookEntry>[] = [
|
|
||||||
pilotName,
|
pilotName,
|
||||||
date,
|
date,
|
||||||
aircraftMakeModel,
|
aircraftMakeModel,
|
||||||
@@ -345,18 +336,46 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
},
|
},
|
||||||
notes,
|
notes,
|
||||||
actions
|
actions
|
||||||
]
|
];
|
||||||
|
|
||||||
|
const table = useReactTable({
|
||||||
|
data: state.entries,
|
||||||
|
columns: columns,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
onColumnVisibilityChange: setColumnVisibility,
|
||||||
|
state: {
|
||||||
|
columnVisibility: columnVisibility
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const getLogbookEntries = async () => {
|
const getLogbookEntries = async () => {
|
||||||
try {
|
try {
|
||||||
dispatch({ type: 'SET_IS_LOADING', payload: true });
|
dispatch({ type: 'SET_IS_LOADING', payload: true });
|
||||||
|
|
||||||
const response: AxiosResponse = await httpClient.get(`api/logs`);
|
const response: AxiosResponse = await httpClient.get(`api/logs`);
|
||||||
const entries: LogbookEntry[] = response.data;
|
|
||||||
entries.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
|
|
||||||
|
|
||||||
if (response.data.length > 0) {
|
if (response.data.length > 0) {
|
||||||
dispatch({ type: 'SET_ENTRIES', payload: response.data });
|
const entries: LogbookEntry[] = response.data;
|
||||||
|
const entryColumns: string[] = Object.keys(entries[0]);
|
||||||
|
const columnVisibility: {[key: string]: boolean} = {}
|
||||||
|
|
||||||
|
for (const column of table.getAllLeafColumns()) {
|
||||||
|
const entryColumnExists = entryColumns.find((entryColumn) => entryColumn === column.id);
|
||||||
|
|
||||||
|
if (entryColumnExists) {
|
||||||
|
columnVisibility[column.id] = true
|
||||||
|
} else {
|
||||||
|
columnVisibility[column.id] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
columnVisibility['pilotName'] = true
|
||||||
|
columnVisibility['actions'] = true
|
||||||
|
|
||||||
|
entries.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
|
||||||
|
setColumnVisibility(columnVisibility)
|
||||||
|
dispatch({ type: 'SET_ENTRIES', payload: entries });
|
||||||
|
|
||||||
if (state.alert) {
|
if (state.alert) {
|
||||||
dispatch({ type: 'SET_ALERT', payload: undefined})
|
dispatch({ type: 'SET_ALERT', payload: undefined})
|
||||||
@@ -441,44 +460,6 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// let newColumns: ColumnDef<LogbookEntry>[];
|
|
||||||
|
|
||||||
// if (userRole === UserRole.WRITE) {
|
|
||||||
// newColumns = [...authColumns];
|
|
||||||
// } else {
|
|
||||||
// newColumns = [...unauthColumns];
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const actionsColumnExists = newColumns.find((column) => column.id === 'actions');
|
|
||||||
// const tracksColumnExists = newColumns.find((column) => column.id === 'actions');
|
|
||||||
|
|
||||||
// if (!actionsColumnExists) {
|
|
||||||
// newColumns.push(actionsColumn);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!tracksColumnExists) {
|
|
||||||
// const notesColumnIndex = newColumns.findIndex((column) => column.id === 'notes')
|
|
||||||
|
|
||||||
// newColumns.splice(notesColumnIndex, 0, tracksColumn)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// dispatch({ type: 'SET_COLUMNS', payload: newColumns })
|
|
||||||
// }, [isUserLoggedIn])
|
|
||||||
|
|
||||||
const table = useReactTable({
|
|
||||||
data: state.entries,
|
|
||||||
columns: authColumns,
|
|
||||||
getCoreRowModel: getCoreRowModel(),
|
|
||||||
getPaginationRowModel: getPaginationRowModel()
|
|
||||||
});
|
|
||||||
|
|
||||||
const textAlignment = {
|
|
||||||
center: 'text-center',
|
|
||||||
left: 'text-start',
|
|
||||||
right: 'text-end'
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!logbookContext.state.isDrawerOpen) {
|
if (!logbookContext.state.isDrawerOpen) {
|
||||||
getLogbookEntries();
|
getLogbookEntries();
|
||||||
@@ -493,14 +474,6 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className='col-span-2 justify-self-end self-center'>
|
<div className='col-span-2 justify-self-end self-center'>
|
||||||
{userRole === UserRole.WRITE &&
|
{userRole === UserRole.WRITE &&
|
||||||
// <Button
|
|
||||||
// color='primary'
|
|
||||||
// onPress={() => onOpenCloseDrawer(FormMode.ADD)}
|
|
||||||
// startContent={<FontAwesomeIcon icon={faAdd} />}
|
|
||||||
// data-testid="pilot-add-button"
|
|
||||||
// >
|
|
||||||
// Add Entry
|
|
||||||
// </Button>
|
|
||||||
<button className='btn btn-primary'
|
<button className='btn btn-primary'
|
||||||
onClick={() => onOpenCloseDrawer(FormMode.ADD)}
|
onClick={() => onOpenCloseDrawer(FormMode.ADD)}
|
||||||
>
|
>
|
||||||
@@ -522,9 +495,8 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
</Alert>
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{!state.isLoading && (
|
{!state.isLoading && state.entries.length > 0 && screenSize !== ScreenSize.SM && (
|
||||||
<div className='col-span-12 p-5 bg-base-100 border border-base-100 rounded-lg'>
|
<div className='col-span-12 p-5 bg-base-100 border border-base-100 rounded-lg'>
|
||||||
{state.entries.length > 0 && screenSize !== ScreenSize.SM && (
|
|
||||||
<div className='overflow-x-auto'>
|
<div className='overflow-x-auto'>
|
||||||
<table className='table min-w-full h-auto table-auto w-full'>
|
<table className='table min-w-full h-auto table-auto w-full'>
|
||||||
<thead className='bg-base-200'>
|
<thead className='bg-base-200'>
|
||||||
@@ -564,7 +536,7 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
{row.getVisibleCells().map((cell) => {
|
{row.getVisibleCells().map((cell) => {
|
||||||
return (
|
return (
|
||||||
<td
|
<td
|
||||||
className={`py-2 px-3 relative align-middle whitespace-normal text-small font-normal [&>*]:z-1 [&>*]:relative outline-solid outline-transparent data-[focus-visible=true]:z-10 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-focus data-[focus-visible=true]:outline-offset-2 before:pointer-events-none before:content-[''] before:absolute before:z-0 before:inset-0 before:opacity-0 data-[selected=true]:before:opacity-100 group-data-[disabled=true]/tr:text-foreground-300 group-data-[disabled=true]/tr:cursor-not-allowed before:bg-default/60 data-[selected=true]:text-default-foreground first:before:rounded-s-lg last:before:rounded-e-lg text-start`}
|
className={`py-2 px-3 relative align-middle whitespace-normal text-small font-normal [&>*]:relative outline-solid outline-transparent data-[focus-visible=true]:z-10 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-focus data-[focus-visible=true]:outline-offset-2 before:pointer-events-none before:content-[''] before:absolute before:z-0 before:inset-0 before:opacity-0 data-[selected=true]:before:opacity-100 group-data-[disabled=true]/tr:text-foreground-300 group-data-[disabled=true]/tr:cursor-not-allowed before:bg-default/60 data-[selected=true]:text-default-foreground first:before:rounded-s-lg last:before:rounded-e-lg text-start`}
|
||||||
key={cell.id}
|
key={cell.id}
|
||||||
>
|
>
|
||||||
<div className={`${cell.column.columnDef.meta?.align ? cell.column.columnDef.meta?.align : ''}`}>
|
<div className={`${cell.column.columnDef.meta?.align ? cell.column.columnDef.meta?.align : ''}`}>
|
||||||
@@ -589,7 +561,7 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
{footerGroup.headers.map((header) => {
|
{footerGroup.headers.map((header) => {
|
||||||
return (
|
return (
|
||||||
<td
|
<td
|
||||||
className='group/th px-3 h-10 align-middle bg-default-100 whitespace-nowrap text-foreground-500 text-tiny font-semibold first:rounded-s-lg last:rounded-e-lg data-[sortable=true]:cursor-pointer data-[hover=true]:text-foreground-400 outline-solid outline-transparent data-[focus-visible=true]:z-10 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-focus data-[focus-visible=true]:outline-offset-2 text-start'
|
className='roup/th px-3 h-10 align-middle bg-default-100 whitespace-nowrap text-foreground-500 text-tiny font-semibold first:rounded-s-lg last:rounded-e-lg data-[sortable=true]:cursor-pointer data-[hover=true]:text-foreground-400 outline-solid outline-transparent data-[focus-visible=true]:z-10 data-[focus-visible=true]:outline-2 data-[focus-visible=true]:outline-focus data-[focus-visible=true]:outline-offset-2 text-start'
|
||||||
key={header.id}
|
key={header.id}
|
||||||
>
|
>
|
||||||
<div className={`${header.column.columnDef.meta?.headerAlign ? header.column.columnDef.meta?.headerAlign : ''}`}>
|
<div className={`${header.column.columnDef.meta?.headerAlign ? header.column.columnDef.meta?.headerAlign : ''}`}>
|
||||||
@@ -611,22 +583,21 @@ const Logbook: React.FC<unknown> = () => {
|
|||||||
</thead>
|
</thead>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
{state.entries.length > 0 && screenSize === ScreenSize.SM &&
|
{state.entries.length > 0 && screenSize === ScreenSize.SM &&
|
||||||
<LogbookCard logs={state.entries} onDelete={onDeleteLog} mode='logbook' onOpenCloseForm={onOpenCloseDrawer} />
|
<LogbookCard logs={state.entries} onDelete={onDeleteLog} mode='logbook' onOpenCloseForm={onOpenCloseDrawer} />
|
||||||
}
|
}
|
||||||
|
{state.isLoading && !state.alert && (
|
||||||
|
<div className='col-span-12 p-5 bg-base-100 border border-base-100 rounded-lg'>
|
||||||
|
<div className='col-span-12 justify-self-center'>
|
||||||
|
<span className='loading loading-spinner loading-xl' />
|
||||||
</div>
|
</div>
|
||||||
)}
|
<div className='col-span-12 justify-self-center'>
|
||||||
{/* {state.isLoading && !state.alert && (
|
|
||||||
<>
|
|
||||||
<div>
|
|
||||||
<Loading size='xl' />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Loading...
|
Loading...
|
||||||
</div>
|
</div>
|
||||||
</>
|
</div>
|
||||||
)} */}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{logbookContext.state.isDrawerOpen && (
|
{logbookContext.state.isDrawerOpen && (
|
||||||
<LogbookDrawer
|
<LogbookDrawer
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ColumnDef } from '@noahspan/noahspan-components';
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
import { FormMode } from '../../enums/formMode';
|
import { FormMode } from '../../enums/formMode';
|
||||||
import { Alert } from '../../interfaces/Alert.interface';
|
import { Alert } from '../../interfaces/Alert.interface';
|
||||||
import { LogbookEntry } from './LogbookEntry.interface';
|
import { LogbookEntry } from './LogbookEntry.interface';
|
||||||
|
|||||||
@@ -1,291 +0,0 @@
|
|||||||
import {
|
|
||||||
CellContext,
|
|
||||||
ColumnDef,
|
|
||||||
HeaderContext,
|
|
||||||
} from '@noahspan/noahspan-components';
|
|
||||||
import { LogbookEntry } from './LogbookEntry.interface';
|
|
||||||
|
|
||||||
const columnTotal = (info: HeaderContext<LogbookEntry, unknown>): number => {
|
|
||||||
const blah = info.table
|
|
||||||
const values: number[] = info.table.getPaginationRowModel().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<LogbookEntry> = {
|
|
||||||
id: 'pilotName',
|
|
||||||
accessorKey: 'pilot',
|
|
||||||
header: 'Pilot',
|
|
||||||
footer: 'PAGE TOTALS',
|
|
||||||
cell: (info: CellContext<LogbookEntry, unknown>) => {
|
|
||||||
const pilot: any = info.getValue();
|
|
||||||
|
|
||||||
return pilot.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const date: ColumnDef<LogbookEntry> = {
|
|
||||||
id: 'date',
|
|
||||||
accessorKey: 'date',
|
|
||||||
header: 'Date',
|
|
||||||
cell: (info: CellContext<LogbookEntry, unknown>) => {
|
|
||||||
const date = new Date(info.getValue() as string);
|
|
||||||
const formattedDate = `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`
|
|
||||||
|
|
||||||
return formattedDate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const aircraftMakeModel: ColumnDef<LogbookEntry> = {
|
|
||||||
id: 'aircraftMakeModel',
|
|
||||||
accessorKey: 'aircraftMakeModel',
|
|
||||||
header: 'Aircraft Make & Model'
|
|
||||||
}
|
|
||||||
const route: ColumnDef<LogbookEntry> = {
|
|
||||||
id: 'route',
|
|
||||||
header: 'Route of Flight',
|
|
||||||
meta: {
|
|
||||||
headerAlign: 'text-center',
|
|
||||||
className: 'border-l border-base-400'
|
|
||||||
},
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
id: 'routeFrom',
|
|
||||||
accessorKey: 'routeFrom',
|
|
||||||
header: 'From'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'routeTo',
|
|
||||||
accessorKey: 'routeTo',
|
|
||||||
header: 'To'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
const durationOfFlight: ColumnDef<LogbookEntry> = {
|
|
||||||
id: 'durationOfFlight',
|
|
||||||
accessorKey: 'durationOfFlight',
|
|
||||||
header: 'Duration Of Flight',
|
|
||||||
meta: {
|
|
||||||
align: 'text-right',
|
|
||||||
headerAlign: 'text-right'
|
|
||||||
},
|
|
||||||
cell: (info: CellContext<LogbookEntry, unknown>) =>
|
|
||||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : '',
|
|
||||||
footer: (info: HeaderContext<LogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : ''
|
|
||||||
}
|
|
||||||
const notes: ColumnDef<LogbookEntry> = {
|
|
||||||
id: 'notes',
|
|
||||||
accessorKey: 'notes',
|
|
||||||
header: 'Notes'
|
|
||||||
}
|
|
||||||
|
|
||||||
export const unauthColumns: ColumnDef<LogbookEntry>[] = [
|
|
||||||
pilotName,
|
|
||||||
date,
|
|
||||||
aircraftMakeModel,
|
|
||||||
route,
|
|
||||||
durationOfFlight,
|
|
||||||
notes
|
|
||||||
]
|
|
||||||
|
|
||||||
export const authColumns: ColumnDef<LogbookEntry>[] = [
|
|
||||||
pilotName,
|
|
||||||
date,
|
|
||||||
aircraftMakeModel,
|
|
||||||
{
|
|
||||||
id: 'aircraftIdentity',
|
|
||||||
accessorKey: 'aircraftIdentity',
|
|
||||||
header: 'Aircraft Identity',
|
|
||||||
},
|
|
||||||
route,
|
|
||||||
durationOfFlight,
|
|
||||||
{
|
|
||||||
id: 'singleEngineLand',
|
|
||||||
accessorKey: 'singleEngineLand',
|
|
||||||
header: 'Single Engine Land',
|
|
||||||
meta: {
|
|
||||||
align: 'text-right',
|
|
||||||
headerAlign: 'text-right'
|
|
||||||
},
|
|
||||||
cell: (info: CellContext<LogbookEntry, unknown>) =>
|
|
||||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : '',
|
|
||||||
footer: (info: HeaderContext<LogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'landings',
|
|
||||||
header: 'Landings',
|
|
||||||
meta: {
|
|
||||||
headerAlign: 'text-center'
|
|
||||||
},
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
id: 'landingsDay',
|
|
||||||
accessorKey: 'landingsDay',
|
|
||||||
header: 'Day',
|
|
||||||
footer: (info: HeaderContext<LogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info) : '',
|
|
||||||
meta: {
|
|
||||||
align: 'text-right',
|
|
||||||
headerAlign: 'text-right'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'landingsNight',
|
|
||||||
accessorKey: 'landingsNight',
|
|
||||||
header: 'Night',
|
|
||||||
footer: (info: HeaderContext<LogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info) : '',
|
|
||||||
meta: {
|
|
||||||
align: 'text-right',
|
|
||||||
headerAlign: 'text-right'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'instrument',
|
|
||||||
header: 'Instrument',
|
|
||||||
meta: {
|
|
||||||
headerAlign: 'text-center'
|
|
||||||
},
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
id: 'instrumentActual',
|
|
||||||
accessorKey: 'instrumentActual',
|
|
||||||
header: 'Actual',
|
|
||||||
footer: (info: HeaderContext<LogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
|
||||||
meta: {
|
|
||||||
align: 'text-right',
|
|
||||||
headerAlign: 'text-right'
|
|
||||||
},
|
|
||||||
cell: (info: CellContext<LogbookEntry, unknown>) =>
|
|
||||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'instrumentSimulated',
|
|
||||||
accessorKey: 'instrumentSimulated',
|
|
||||||
header: 'Simulated',
|
|
||||||
footer: (info: HeaderContext<LogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
|
||||||
meta: {
|
|
||||||
align: 'text-right',
|
|
||||||
headerAlign: 'text-right'
|
|
||||||
},
|
|
||||||
cell: (info: CellContext<LogbookEntry, unknown>) =>
|
|
||||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'instrumentApproaches',
|
|
||||||
accessorKey: 'instrumentApproaches',
|
|
||||||
header: 'Approaches',
|
|
||||||
footer: (info: HeaderContext<LogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
|
||||||
meta: {
|
|
||||||
align: 'text-right',
|
|
||||||
headerAlign: 'text-right'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'instrumentHolds',
|
|
||||||
accessorKey: 'instrumentHolds',
|
|
||||||
header: 'Holds',
|
|
||||||
footer: (info: HeaderContext<LogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
|
||||||
meta: {
|
|
||||||
align: 'text-right',
|
|
||||||
headerAlign: 'text-right'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'instrumentNavTrack',
|
|
||||||
accessorKey: 'instrumentNavTrack',
|
|
||||||
header: 'Nav/Track',
|
|
||||||
footer: (info: HeaderContext<LogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
|
||||||
meta: {
|
|
||||||
align: 'text-right',
|
|
||||||
headerAlign: 'text-right'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'experienceTraining',
|
|
||||||
header: 'Type of pilot experience or training',
|
|
||||||
meta: {
|
|
||||||
headerAlign: 'text-center'
|
|
||||||
},
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
id: 'groundTrainingReceived',
|
|
||||||
accessorKey: 'groundTrainingReceived',
|
|
||||||
header: 'Ground Training Received',
|
|
||||||
footer: (info: HeaderContext<LogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
|
||||||
meta: {
|
|
||||||
align: 'text-right',
|
|
||||||
headerAlign: 'text-right'
|
|
||||||
},
|
|
||||||
cell: (info: CellContext<LogbookEntry, unknown>) =>
|
|
||||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'flightTrainingReceived',
|
|
||||||
accessorKey: 'flightTrainingReceived',
|
|
||||||
header: 'Flight Training Received',
|
|
||||||
footer: (info: HeaderContext<LogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
|
||||||
meta: {
|
|
||||||
align: 'text-right',
|
|
||||||
headerAlign: 'text-right'
|
|
||||||
},
|
|
||||||
cell: (info: CellContext<LogbookEntry, unknown>) =>
|
|
||||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'crossCountry',
|
|
||||||
accessorKey: 'crossCountry',
|
|
||||||
header: 'Cross Country',
|
|
||||||
footer: (info: HeaderContext<LogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
|
||||||
meta: {
|
|
||||||
align: 'text-right',
|
|
||||||
headerAlign: 'text-right'
|
|
||||||
},
|
|
||||||
cell: (info: CellContext<LogbookEntry, unknown>) =>
|
|
||||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'night',
|
|
||||||
accessorKey: 'night',
|
|
||||||
header: 'Night',
|
|
||||||
footer: (info: HeaderContext<LogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
|
||||||
meta: {
|
|
||||||
align: 'text-right',
|
|
||||||
headerAlign: 'text-right'
|
|
||||||
},
|
|
||||||
cell: (info: CellContext<LogbookEntry, unknown>) =>
|
|
||||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'solo',
|
|
||||||
accessorKey: 'solo',
|
|
||||||
header: 'Solo',
|
|
||||||
footer: (info: HeaderContext<LogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
|
||||||
meta: {
|
|
||||||
align: 'text-right',
|
|
||||||
headerAlign: 'text-right'
|
|
||||||
},
|
|
||||||
cell: (info: CellContext<LogbookEntry, unknown>) =>
|
|
||||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'pilotInCommand',
|
|
||||||
accessorKey: 'pilotInCommand',
|
|
||||||
header: 'Pilot In Command',
|
|
||||||
footer: (info: HeaderContext<LogbookEntry, unknown>) => columnTotal(info) > 0 ? columnTotal(info).toFixed(1) : '',
|
|
||||||
meta: {
|
|
||||||
align: 'text-right',
|
|
||||||
headerAlign: 'text-right'
|
|
||||||
},
|
|
||||||
cell: (info: CellContext<LogbookEntry, unknown>) =>
|
|
||||||
info.getValue() ? parseFloat(info.getValue() as string).toFixed(1) : ''
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
notes
|
|
||||||
]
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ColumnDef } from '@noahspan/noahspan-components';
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
import { FormMode } from '../../enums/formMode';
|
import { FormMode } from '../../enums/formMode';
|
||||||
import { Alert } from '../../interfaces/Alert.interface';
|
import { Alert } from '../../interfaces/Alert.interface';
|
||||||
import { LogbookEntry } from './LogbookEntry.interface';
|
import { LogbookEntry } from './LogbookEntry.interface';
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ const LogbookCard = ({ logs, mode, onDelete, onOpenCloseForm }: LogbookCardProps
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{logs.map((log) => {
|
{logs.map((log) => {
|
||||||
const date = new Date(log.date);
|
const date = new Date(log.date.replace('Z', ''));
|
||||||
const formattedDate: string = `${date.getMonth()}/${date.getDate()}/${date.getFullYear()}`;
|
const formattedDate: string = `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='card bg-base-100 border border-base-300 p-2'>
|
<div className='card bg-base-100 border border-base-300 p-2'>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { FormMode } from "../../enums/formMode";
|
|||||||
import httpClient from "../../httpClient/httpClient";
|
import httpClient from "../../httpClient/httpClient";
|
||||||
import { AxiosError } from "axios";
|
import { AxiosError } from "axios";
|
||||||
import { useLogbookContext } from "../../hooks/logbookContext/UseLogbookContext";
|
import { useLogbookContext } from "../../hooks/logbookContext/UseLogbookContext";
|
||||||
import { useState } from "react";
|
import { ChangeEventHandler, MouseEventHandler, useState } from "react";
|
||||||
|
|
||||||
const LogbookDrawer = ({ onOpenClose }: LogbookDrawerProps) => {
|
const LogbookDrawer = ({ onOpenClose }: LogbookDrawerProps) => {
|
||||||
const [activeTab, setActiveTab] = useState<string>('time');
|
const [activeTab, setActiveTab] = useState<string>('time');
|
||||||
@@ -73,16 +73,12 @@ const LogbookDrawer = ({ onOpenClose }: LogbookDrawerProps) => {
|
|||||||
setActiveTab(tab)
|
setActiveTab(tab)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onTabClicked = (event: any) => {
|
||||||
|
setActiveTab(event.target.ariaLabel)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='drawer drawer-end'
|
<div className='drawer drawer-end'>
|
||||||
// closeButton={
|
|
||||||
// <Button isIconOnly>
|
|
||||||
// <FontAwesomeIcon icon={faXmark} />
|
|
||||||
// </Button>
|
|
||||||
// }
|
|
||||||
// isOpen={logbookContext.state.isDrawerOpen}
|
|
||||||
// onClose={onCancel}
|
|
||||||
>
|
|
||||||
<input type='checkbox' className='drawer-toggle' onChange={() => {}} checked={logbookContext.state.isDrawerOpen} />
|
<input type='checkbox' className='drawer-toggle' onChange={() => {}} checked={logbookContext.state.isDrawerOpen} />
|
||||||
<div className="drawer-side">
|
<div className="drawer-side">
|
||||||
<label
|
<label
|
||||||
@@ -93,9 +89,18 @@ const LogbookDrawer = ({ onOpenClose }: LogbookDrawerProps) => {
|
|||||||
<div className='menu bg-base-100 text-base-content min-h-full p-4' style={{ width: '25%' }}>
|
<div className='menu bg-base-100 text-base-content min-h-full p-4' style={{ width: '25%' }}>
|
||||||
<FormProvider {...methods}>
|
<FormProvider {...methods}>
|
||||||
<form className='prose max-w-none' onSubmit={methods.handleSubmit(onSubmit)} style={{ paddingBottom: '50px' }}>
|
<form className='prose max-w-none' onSubmit={methods.handleSubmit(onSubmit)} style={{ paddingBottom: '50px' }}>
|
||||||
<h2>
|
<div className='grid grid-cols-12 mb-6'>
|
||||||
|
<div className="col-span-10">
|
||||||
|
<h2 className="mt-0 mb-0 self-center">
|
||||||
{`${logbookContext.state.formMode.toString().toLowerCase().charAt(0).toUpperCase() + logbookContext.state.formMode.toString().slice(1).toLowerCase()} Entry`}
|
{`${logbookContext.state.formMode.toString().toLowerCase().charAt(0).toUpperCase() + logbookContext.state.formMode.toString().slice(1).toLowerCase()} Entry`}
|
||||||
</h2>
|
</h2>
|
||||||
|
</div>
|
||||||
|
<div className="col-span-2 justify-self-end self-center">
|
||||||
|
<button className="btn btn-ghost" onClick={onCancel}>
|
||||||
|
<FontAwesomeIcon icon={faXmark} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{logbookContext.state.formAlert && (
|
{logbookContext.state.formAlert && (
|
||||||
<Alert
|
<Alert
|
||||||
className='mb-5'
|
className='mb-5'
|
||||||
@@ -109,7 +114,7 @@ const LogbookDrawer = ({ onOpenClose }: LogbookDrawerProps) => {
|
|||||||
)}
|
)}
|
||||||
<div className='tabs tabs-lift mb-5'>
|
<div className='tabs tabs-lift mb-5'>
|
||||||
<label className='tab'>
|
<label className='tab'>
|
||||||
<input type='radio' name='my_tabs' defaultChecked={true} />
|
<input aria-label='time' type='radio' name='logbook_drawer_tabs' onChange={onTabClicked} checked={activeTab === 'time' ? true : false} />
|
||||||
<FontAwesomeIcon className='mr-1'icon={faClock} />
|
<FontAwesomeIcon className='mr-1'icon={faClock} />
|
||||||
Time
|
Time
|
||||||
</label>
|
</label>
|
||||||
@@ -119,7 +124,7 @@ const LogbookDrawer = ({ onOpenClose }: LogbookDrawerProps) => {
|
|||||||
{logbookContext.state.formMode !== FormMode.ADD &&
|
{logbookContext.state.formMode !== FormMode.ADD &&
|
||||||
<>
|
<>
|
||||||
<label className='tab'>
|
<label className='tab'>
|
||||||
<input type='radio' name='my_tabs'/>
|
<input aria-label='tracks' type='radio' name='logbook_drawer_tabs' onChange={onTabClicked} checked={activeTab === 'tracks' ? true : false} />
|
||||||
<FontAwesomeIcon className='mr-1' icon={faMapLocationDot} />
|
<FontAwesomeIcon className='mr-1' icon={faMapLocationDot} />
|
||||||
Tracks
|
Tracks
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
import { Card, CardActions, CardBody, CardHeader} from "@noahspan/noahspan-components"
|
// import { Card, CardActions, CardBody, CardHeader} from "@noahspan/noahspan-components"
|
||||||
import { PilotCardProps } from "./PilotCardProps.interface"
|
// import { PilotCardProps } from "./PilotCardProps.interface"
|
||||||
import ActionMenu from "../actionMenu/ActionMenu"
|
// import ActionMenu from "../actionMenu/ActionMenu"
|
||||||
|
|
||||||
const PilotCard = ({ pilots, onDelete, onOpenCloseForm }: PilotCardProps) => {
|
// const PilotCard = ({ pilots, onDelete, onOpenCloseForm }: PilotCardProps) => {
|
||||||
return (
|
// return (
|
||||||
<div>
|
// <div>
|
||||||
{pilots.map((pilot) => {
|
// {pilots.map((pilot) => {
|
||||||
return (
|
// return (
|
||||||
<div>
|
// <div>
|
||||||
<Card key={pilot.id}>
|
// <Card key={pilot.id}>
|
||||||
<CardBody>
|
// <CardBody>
|
||||||
<CardHeader>{pilot.name}</CardHeader>
|
// <CardHeader>{pilot.name}</CardHeader>
|
||||||
<CardActions>
|
// <CardActions>
|
||||||
<ActionMenu id={pilot.id} onDelete={onDelete} onOpenCloseForm={onOpenCloseForm} />
|
// <ActionMenu id={pilot.id} onDelete={onDelete} onOpenCloseForm={onOpenCloseForm} />
|
||||||
</CardActions>
|
// </CardActions>
|
||||||
</CardBody>
|
// </CardBody>
|
||||||
</Card>
|
// </Card>
|
||||||
</div>
|
// </div>
|
||||||
)
|
// )
|
||||||
})}
|
// })}
|
||||||
</div>
|
// </div>
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
|
|
||||||
export default PilotCard;
|
// export default PilotCard;
|
||||||
@@ -4,9 +4,9 @@ import { IPilotFormProps } from './IPilotFormProps';
|
|||||||
import { AxiosError, AxiosResponse } from 'axios';
|
import { AxiosError, AxiosResponse } from 'axios';
|
||||||
import { FormMode } from '../../enums/formMode';
|
import { FormMode } from '../../enums/formMode';
|
||||||
import { Person } from '@microsoft/microsoft-graph-types';
|
import { Person } from '@microsoft/microsoft-graph-types';
|
||||||
import PilotFormCertificates from '../pilotFormCertificates/PilotFormCertificates';
|
// import PilotFormCertificates from '../pilotFormCertificates/PilotFormCertificates';
|
||||||
import PilotFormEndorsements from '../pilotFormEndorsements/PilotFormEndorsements';
|
// import PilotFormEndorsements from '../pilotFormEndorsements/PilotFormEndorsements';
|
||||||
import PilotFormMedical from '../pilotFormMedical/PilotFormMedical';
|
// import PilotFormMedical from '../pilotFormMedical/PilotFormMedical';
|
||||||
import { useOidc } from '../../auth/oidcConfig';
|
import { useOidc } from '../../auth/oidcConfig';
|
||||||
import httpClient from '../../httpClient/httpClient';
|
import httpClient from '../../httpClient/httpClient';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
@@ -104,18 +104,7 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
|||||||
}, [pilotId]);
|
}, [pilotId]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='drawer drawer-end'
|
<div className='drawer drawer-end'>
|
||||||
// closeButton={
|
|
||||||
// <Button isIconOnly>
|
|
||||||
// <FontAwesomeIcon icon={faXmark} />
|
|
||||||
// </Button>
|
|
||||||
// }
|
|
||||||
// isOpen={isDrawerOpen}
|
|
||||||
// placement='right'
|
|
||||||
// data-testid="pilot-drawer"
|
|
||||||
// onClose={onCancel}
|
|
||||||
// size='xl'
|
|
||||||
>
|
|
||||||
<input type='checkbox' className='drawer-toggle' onChange={() => {}} checked={isDrawerOpen} />
|
<input type='checkbox' className='drawer-toggle' onChange={() => {}} checked={isDrawerOpen} />
|
||||||
<div className='drawer-side'>
|
<div className='drawer-side'>
|
||||||
<label
|
<label
|
||||||
@@ -126,10 +115,17 @@ const PilotForm: React.FC<IPilotFormProps> = ({
|
|||||||
<div className='menu bg-base-100 text-base-content min-h-full p-4' style={{ width: '25%' }}>
|
<div className='menu bg-base-100 text-base-content min-h-full p-4' style={{ width: '25%' }}>
|
||||||
<FormProvider {...methods}>
|
<FormProvider {...methods}>
|
||||||
<form className='prose max-w-none' onSubmit={methods.handleSubmit(onSubmit)} style={{ paddingBottom: '50px' }}>
|
<form className='prose max-w-none' onSubmit={methods.handleSubmit(onSubmit)} style={{ paddingBottom: '50px' }}>
|
||||||
<h2>
|
<div className='grid grid-cols-12 gap-3'>
|
||||||
|
<div className="col-span-10">
|
||||||
|
<h2 className="mt-0 mb-0 self-center">
|
||||||
{`${mode.toString().toLowerCase().charAt(0).toUpperCase() + mode.toString().slice(1).toLowerCase()} Pilot`}
|
{`${mode.toString().toLowerCase().charAt(0).toUpperCase() + mode.toString().slice(1).toLowerCase()} Pilot`}
|
||||||
</h2>
|
</h2>
|
||||||
<div className='grid grid-cols-12 gap-3'>
|
</div>
|
||||||
|
<div className="col-span-2 justify-self-end self-center">
|
||||||
|
<button className="btn btn-ghost" onClick={onCancel}>
|
||||||
|
<FontAwesomeIcon icon={faXmark} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div className='col-span-3 self-center'>
|
<div className='col-span-3 self-center'>
|
||||||
<span>Name *</span>
|
<span>Name *</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,153 +1,153 @@
|
|||||||
import { PilotFormCertificatesProps } from './PilotFormCertificatesProps.interface';
|
// import { PilotFormCertificatesProps } from './PilotFormCertificatesProps.interface';
|
||||||
import {
|
// import {
|
||||||
Button,
|
// Button,
|
||||||
DatePicker,
|
// DatePicker,
|
||||||
Icon,
|
// Icon,
|
||||||
IconButton,
|
// IconButton,
|
||||||
IconName,
|
// IconName,
|
||||||
Input,
|
// Input,
|
||||||
Select
|
// Select
|
||||||
} from '@noahspan/noahspan-components';
|
// } from '@noahspan/noahspan-components';
|
||||||
import { Controller, useFieldArray, useFormContext } from 'react-hook-form';
|
// import { Controller, useFieldArray, useFormContext } from 'react-hook-form';
|
||||||
import { FormMode } from '../../enums/formMode';
|
// import { FormMode } from '../../enums/formMode';
|
||||||
|
|
||||||
const PilotFormCertificates = ({
|
// const PilotFormCertificates = ({
|
||||||
isDisabled,
|
// isDisabled,
|
||||||
mode
|
// mode
|
||||||
}: PilotFormCertificatesProps ) => {
|
// }: PilotFormCertificatesProps ) => {
|
||||||
const {
|
// const {
|
||||||
control,
|
// control,
|
||||||
formState: { errors },
|
// formState: { errors },
|
||||||
} = useFormContext();
|
// } = useFormContext();
|
||||||
|
|
||||||
const { fields, append, remove } = useFieldArray({
|
// const { fields, append, remove } = useFieldArray({
|
||||||
name: 'certificates',
|
// name: 'certificates',
|
||||||
control
|
// control
|
||||||
});
|
// });
|
||||||
|
|
||||||
return (
|
// return (
|
||||||
<div>
|
// <div>
|
||||||
{fields.length > 0 || mode !== FormMode.VIEW &&
|
// {fields.length > 0 || mode !== FormMode.VIEW &&
|
||||||
<div>
|
// <div>
|
||||||
<h5>Certificates</h5>
|
// <h5>Certificates</h5>
|
||||||
</div>
|
// </div>
|
||||||
}
|
// }
|
||||||
{fields.length > 0 && (
|
// {fields.length > 0 && (
|
||||||
<>
|
// <>
|
||||||
<div>
|
// <div>
|
||||||
<h6>Type</h6>
|
// <h6>Type</h6>
|
||||||
</div>
|
// </div>
|
||||||
<div>
|
// <div>
|
||||||
<h6>Number</h6>
|
// <h6>Number</h6>
|
||||||
</div>
|
// </div>
|
||||||
<div>
|
// <div>
|
||||||
<h6>Date of Issue</h6>
|
// <h6>Date of Issue</h6>
|
||||||
</div>
|
// </div>
|
||||||
<div>
|
// <div>
|
||||||
</div>
|
// </div>
|
||||||
{fields.map((field, index) => {
|
// {fields.map((field, index) => {
|
||||||
return (
|
// return (
|
||||||
<>
|
// <>
|
||||||
<div>
|
// <div>
|
||||||
<Controller
|
// <Controller
|
||||||
name={`certificates.${index}.type`}
|
// name={`certificates.${index}.type`}
|
||||||
control={control}
|
// control={control}
|
||||||
render={({ field: { onChange, value } }) => {
|
// render={({ field: { onChange, value } }) => {
|
||||||
return (
|
// return (
|
||||||
<Select
|
// <Select
|
||||||
disabled={isDisabled}
|
// disabled={isDisabled}
|
||||||
onChange={onChange}
|
// onChange={onChange}
|
||||||
options={
|
// options={
|
||||||
[
|
// [
|
||||||
{
|
// {
|
||||||
label: 'Student',
|
// label: 'Student',
|
||||||
value: 'student'
|
// value: 'student'
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: 'Private',
|
// label: 'Private',
|
||||||
value: 'private'
|
// value: 'private'
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: 'Instrument',
|
// label: 'Instrument',
|
||||||
value: 'instrument'
|
// value: 'instrument'
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: 'Recreational',
|
// label: 'Recreational',
|
||||||
value: 'recreational'
|
// value: 'recreational'
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: 'Sport',
|
// label: 'Sport',
|
||||||
value: 'sport'
|
// value: 'sport'
|
||||||
}
|
// }
|
||||||
]
|
// ]
|
||||||
}
|
// }
|
||||||
value={value}
|
// value={value}
|
||||||
/>
|
// />
|
||||||
);
|
// );
|
||||||
}}
|
// }}
|
||||||
/>
|
// />
|
||||||
</div>
|
// </div>
|
||||||
<div>
|
// <div>
|
||||||
<Controller
|
// <Controller
|
||||||
name={`certificates.${index}.number`}
|
// name={`certificates.${index}.number`}
|
||||||
control={control}
|
// control={control}
|
||||||
render={({ field: { onChange, value } }) => {
|
// render={({ field: { onChange, value } }) => {
|
||||||
return (
|
// return (
|
||||||
<Input
|
// <Input
|
||||||
disabled={isDisabled}
|
// disabled={isDisabled}
|
||||||
onChange={onChange}
|
// onChange={onChange}
|
||||||
value={value}
|
// value={value}
|
||||||
/>
|
// />
|
||||||
)
|
// )
|
||||||
}}
|
// }}
|
||||||
/>
|
// />
|
||||||
</div>
|
// </div>
|
||||||
<div>
|
// <div>
|
||||||
<Controller
|
// <Controller
|
||||||
name={`certificates.${index}.dateOfIssue`}
|
// name={`certificates.${index}.dateOfIssue`}
|
||||||
control={control}
|
// control={control}
|
||||||
render={({ field: { onChange, value } }) => {
|
// render={({ field: { onChange, value } }) => {
|
||||||
return (
|
// return (
|
||||||
<DatePicker
|
// <DatePicker
|
||||||
disabled={isDisabled}
|
// disabled={isDisabled}
|
||||||
onChange={onChange}
|
// onChange={onChange}
|
||||||
value={value}
|
// value={value}
|
||||||
/>
|
// />
|
||||||
);
|
// );
|
||||||
}}
|
// }}
|
||||||
/>
|
// />
|
||||||
</div>
|
// </div>
|
||||||
<div>
|
// <div>
|
||||||
<IconButton
|
// <IconButton
|
||||||
disabled={isDisabled}
|
// disabled={isDisabled}
|
||||||
onClick={() => remove(index)}
|
// onClick={() => remove(index)}
|
||||||
>
|
// >
|
||||||
<Icon iconName={IconName.TRASH} size='sm' />
|
// <Icon iconName={IconName.TRASH} size='sm' />
|
||||||
</IconButton>
|
// </IconButton>
|
||||||
</div>
|
// </div>
|
||||||
</>
|
// </>
|
||||||
);
|
// );
|
||||||
})}
|
// })}
|
||||||
</>
|
// </>
|
||||||
)}
|
// )}
|
||||||
{!isDisabled &&
|
// {!isDisabled &&
|
||||||
<div>
|
// <div>
|
||||||
<Button
|
// <Button
|
||||||
onClick={() => {
|
// onClick={() => {
|
||||||
append({
|
// append({
|
||||||
type: '',
|
// type: '',
|
||||||
number: '',
|
// number: '',
|
||||||
dateOfIssue: null
|
// dateOfIssue: null
|
||||||
});
|
// });
|
||||||
}}
|
// }}
|
||||||
startContent={<Icon iconName={IconName.PLUS} />}
|
// startContent={<Icon iconName={IconName.PLUS} />}
|
||||||
>
|
// >
|
||||||
Add Certificate
|
// Add Certificate
|
||||||
</Button>
|
// </Button>
|
||||||
</div>
|
// </div>
|
||||||
}
|
// }
|
||||||
</div>
|
// </div>
|
||||||
);
|
// );
|
||||||
};
|
// };
|
||||||
|
|
||||||
export default PilotFormCertificates;
|
// export default PilotFormCertificates;
|
||||||
|
|||||||
@@ -1,129 +1,129 @@
|
|||||||
import { PilotFormEndorsementsProps } from './PilotFormEndorsementsProps.interface';
|
// import { PilotFormEndorsementsProps } from './PilotFormEndorsementsProps.interface';
|
||||||
import {
|
// import {
|
||||||
Button,
|
// Button,
|
||||||
DatePicker,
|
// DatePicker,
|
||||||
Icon,
|
// Icon,
|
||||||
IconButton,
|
// IconButton,
|
||||||
IconName,
|
// IconName,
|
||||||
Select
|
// Select
|
||||||
} from '@noahspan/noahspan-components';
|
// } from '@noahspan/noahspan-components';
|
||||||
import { Controller, useFieldArray, useFormContext } from 'react-hook-form';
|
// import { Controller, useFieldArray, useFormContext } from 'react-hook-form';
|
||||||
import { FormMode } from '../../enums/formMode';
|
// import { FormMode } from '../../enums/formMode';
|
||||||
|
|
||||||
const PilotFormEndorsements = ({
|
// const PilotFormEndorsements = ({
|
||||||
mode,
|
// mode,
|
||||||
isDisabled
|
// isDisabled
|
||||||
}: PilotFormEndorsementsProps) => {
|
// }: PilotFormEndorsementsProps) => {
|
||||||
const {
|
// const {
|
||||||
control,
|
// control,
|
||||||
formState: { errors },
|
// formState: { errors },
|
||||||
setValue
|
// setValue
|
||||||
} = useFormContext();
|
// } = useFormContext();
|
||||||
|
|
||||||
const { fields, append, remove } = useFieldArray({
|
// const { fields, append, remove } = useFieldArray({
|
||||||
name: 'endorsements',
|
// name: 'endorsements',
|
||||||
control
|
// control
|
||||||
});
|
// });
|
||||||
|
|
||||||
return (
|
// return (
|
||||||
<div>
|
// <div>
|
||||||
{fields.length > 0 || mode !== FormMode.VIEW &&
|
// {fields.length > 0 || mode !== FormMode.VIEW &&
|
||||||
<div>
|
// <div>
|
||||||
<h5>Endorsements</h5>
|
// <h5>Endorsements</h5>
|
||||||
</div>
|
// </div>
|
||||||
}
|
// }
|
||||||
{fields.length > 0 && (
|
// {fields.length > 0 && (
|
||||||
<>
|
// <>
|
||||||
<div>
|
// <div>
|
||||||
<h6>Type</h6>
|
// <h6>Type</h6>
|
||||||
</div>
|
// </div>
|
||||||
<div>
|
// <div>
|
||||||
<h6>Date of Issue</h6>
|
// <h6>Date of Issue</h6>
|
||||||
</div>
|
// </div>
|
||||||
<div></div>
|
// <div></div>
|
||||||
{fields.map((field, index) => {
|
// {fields.map((field, index) => {
|
||||||
return (
|
// return (
|
||||||
<>
|
// <>
|
||||||
<div>
|
// <div>
|
||||||
<Controller
|
// <Controller
|
||||||
name={`endorsements.${index}.type`}
|
// name={`endorsements.${index}.type`}
|
||||||
control={control}
|
// control={control}
|
||||||
render={({ field: { onChange, value } }) => {
|
// render={({ field: { onChange, value } }) => {
|
||||||
return (
|
// return (
|
||||||
<Select
|
// <Select
|
||||||
disabled={isDisabled}
|
// disabled={isDisabled}
|
||||||
onChange={onChange}
|
// onChange={onChange}
|
||||||
options={
|
// options={
|
||||||
[
|
// [
|
||||||
{
|
// {
|
||||||
label: 'Complex',
|
// label: 'Complex',
|
||||||
value: 'complex'
|
// value: 'complex'
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: 'High Performance',
|
// label: 'High Performance',
|
||||||
value: 'highPerfomance'
|
// value: 'highPerfomance'
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: 'High Altitude',
|
// label: 'High Altitude',
|
||||||
value: 'highAltitude'
|
// value: 'highAltitude'
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: 'Tailwheel',
|
// label: 'Tailwheel',
|
||||||
value: 'tailwheel'
|
// value: 'tailwheel'
|
||||||
}
|
// }
|
||||||
]
|
// ]
|
||||||
}
|
// }
|
||||||
value={value ? value : ''}
|
// value={value ? value : ''}
|
||||||
/>
|
// />
|
||||||
);
|
// );
|
||||||
}}
|
// }}
|
||||||
/>
|
// />
|
||||||
</div>
|
// </div>
|
||||||
<div>
|
// <div>
|
||||||
<Controller
|
// <Controller
|
||||||
name={`endorsements.${index}.dateOfIssue`}
|
// name={`endorsements.${index}.dateOfIssue`}
|
||||||
control={control}
|
// control={control}
|
||||||
render={({ field: { onChange, value } }) => {
|
// render={({ field: { onChange, value } }) => {
|
||||||
return (
|
// return (
|
||||||
<DatePicker
|
// <DatePicker
|
||||||
disabled={isDisabled}
|
// disabled={isDisabled}
|
||||||
onChange={onChange}
|
// onChange={onChange}
|
||||||
value={value}
|
// value={value}
|
||||||
/>
|
// />
|
||||||
);
|
// );
|
||||||
}}
|
// }}
|
||||||
/>
|
// />
|
||||||
</div>
|
// </div>
|
||||||
<div>
|
// <div>
|
||||||
<IconButton
|
// <IconButton
|
||||||
disabled={isDisabled}
|
// disabled={isDisabled}
|
||||||
onClick={() => remove(index)}
|
// onClick={() => remove(index)}
|
||||||
>
|
// >
|
||||||
<Icon iconName={IconName.TRASH} size="sm" />
|
// <Icon iconName={IconName.TRASH} size="sm" />
|
||||||
</IconButton>
|
// </IconButton>
|
||||||
</div>
|
// </div>
|
||||||
</>
|
// </>
|
||||||
);
|
// );
|
||||||
})}
|
// })}
|
||||||
</>
|
// </>
|
||||||
)}
|
// )}
|
||||||
{!isDisabled &&
|
// {!isDisabled &&
|
||||||
<div>
|
// <div>
|
||||||
<Button
|
// <Button
|
||||||
onClick={() => {
|
// onClick={() => {
|
||||||
append({
|
// append({
|
||||||
type: '',
|
// type: '',
|
||||||
dateOfIssue: null
|
// dateOfIssue: null
|
||||||
});
|
// });
|
||||||
}}
|
// }}
|
||||||
startContent={<Icon iconName={IconName.PLUS} />}
|
// startContent={<Icon iconName={IconName.PLUS} />}
|
||||||
>
|
// >
|
||||||
Add Endorsement
|
// Add Endorsement
|
||||||
</Button>
|
// </Button>
|
||||||
</div>
|
// </div>
|
||||||
}
|
// }
|
||||||
</div>
|
// </div>
|
||||||
);
|
// );
|
||||||
};
|
// };
|
||||||
|
|
||||||
export default PilotFormEndorsements;
|
// export default PilotFormEndorsements;
|
||||||
|
|||||||
@@ -1,77 +1,77 @@
|
|||||||
import { DatePicker, Select } from '@noahspan/noahspan-components';
|
// import { DatePicker, Select } from '@noahspan/noahspan-components';
|
||||||
import { Controller, useFormContext } from "react-hook-form"
|
// import { Controller, useFormContext } from "react-hook-form"
|
||||||
import { PilotFormMedicalProps } from "./PilotFormMedicalProps.interface";
|
// import { PilotFormMedicalProps } from "./PilotFormMedicalProps.interface";
|
||||||
|
|
||||||
const PilotFormMedical = ({ isDisabled }: PilotFormMedicalProps) => {
|
// const PilotFormMedical = ({ isDisabled }: PilotFormMedicalProps) => {
|
||||||
const {
|
// const {
|
||||||
control,
|
// control,
|
||||||
formState: { errors },
|
// formState: { errors },
|
||||||
setValue
|
// setValue
|
||||||
} = useFormContext();
|
// } = useFormContext();
|
||||||
|
|
||||||
return (
|
// return (
|
||||||
<div>
|
// <div>
|
||||||
<div>
|
// <div>
|
||||||
<h5>Medical</h5>
|
// <h5>Medical</h5>
|
||||||
</div>
|
// </div>
|
||||||
<div>
|
// <div>
|
||||||
<h6>Class</h6>
|
// <h6>Class</h6>
|
||||||
</div>
|
// </div>
|
||||||
<div>
|
// <div>
|
||||||
<Controller
|
// <Controller
|
||||||
name="medicalClass"
|
// name="medicalClass"
|
||||||
control={control}
|
// control={control}
|
||||||
render={({ field: { onChange, value } }) => {
|
// render={({ field: { onChange, value } }) => {
|
||||||
return (
|
// return (
|
||||||
<Select
|
// <Select
|
||||||
disabled={isDisabled}
|
// disabled={isDisabled}
|
||||||
onChange={onChange}
|
// onChange={onChange}
|
||||||
options={
|
// options={
|
||||||
[
|
// [
|
||||||
{
|
// {
|
||||||
label: 'First',
|
// label: 'First',
|
||||||
value: 'first'
|
// value: 'first'
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: 'Second',
|
// label: 'Second',
|
||||||
value: 'second'
|
// value: 'second'
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: 'Third',
|
// label: 'Third',
|
||||||
value: 'third'
|
// value: 'third'
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
label: 'Basic Med',
|
// label: 'Basic Med',
|
||||||
value: 'basicMed'
|
// value: 'basicMed'
|
||||||
}
|
// }
|
||||||
]
|
// ]
|
||||||
}
|
// }
|
||||||
value={value ? value : ''}
|
// value={value ? value : ''}
|
||||||
/>
|
// />
|
||||||
);
|
// );
|
||||||
}}
|
// }}
|
||||||
/>
|
// />
|
||||||
</div>
|
// </div>
|
||||||
<div>
|
// <div>
|
||||||
<h6>Expiration</h6>
|
// <h6>Expiration</h6>
|
||||||
</div>
|
// </div>
|
||||||
<div>
|
// <div>
|
||||||
<Controller
|
// <Controller
|
||||||
name="medicalExpiration"
|
// name="medicalExpiration"
|
||||||
control={control}
|
// control={control}
|
||||||
render={({ field: { onChange, value } }) => {
|
// render={({ field: { onChange, value } }) => {
|
||||||
return (
|
// return (
|
||||||
<DatePicker
|
// <DatePicker
|
||||||
disabled={isDisabled}
|
// disabled={isDisabled}
|
||||||
onChange={onChange}
|
// onChange={onChange}
|
||||||
value={value}
|
// value={value}
|
||||||
/>
|
// />
|
||||||
);
|
// );
|
||||||
}}
|
// }}
|
||||||
/>
|
// />
|
||||||
</div>
|
// </div>
|
||||||
</div>
|
// </div>
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
|
|
||||||
export default PilotFormMedical
|
// export default PilotFormMedical
|
||||||
@@ -4,7 +4,7 @@ import { AxiosError, AxiosResponse } from 'axios';
|
|||||||
import { FormMode } from '../../enums/formMode';
|
import { FormMode } from '../../enums/formMode';
|
||||||
import { initialState, reducer } from './reducer';
|
import { initialState, reducer } from './reducer';
|
||||||
import ConfirmationDialog from '../confirmationDialog/ConfirmationDialog';
|
import ConfirmationDialog from '../confirmationDialog/ConfirmationDialog';
|
||||||
import PilotCard from '../pilotCard/PilotCard';
|
// import PilotCard from '../pilotCard/PilotCard';
|
||||||
import { useUserRole } from '../../hooks/userRole/UseUserRole';
|
import { useUserRole } from '../../hooks/userRole/UseUserRole';
|
||||||
import { UserRole } from '../../enums/userRole';
|
import { UserRole } from '../../enums/userRole';
|
||||||
import httpClient from '../../httpClient/httpClient'
|
import httpClient from '../../httpClient/httpClient'
|
||||||
@@ -31,8 +31,6 @@ const Pilots: React.FC<unknown> = () => {
|
|||||||
`api/pilots`
|
`api/pilots`
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(response)
|
|
||||||
|
|
||||||
if (response.data.length > 0) {
|
if (response.data.length > 0) {
|
||||||
dispatch({ type: 'SET_PILOTS', payload: response.data });
|
dispatch({ type: 'SET_PILOTS', payload: response.data });
|
||||||
|
|
||||||
@@ -179,7 +177,7 @@ const Pilots: React.FC<unknown> = () => {
|
|||||||
<h1>Pilots</h1>
|
<h1>Pilots</h1>
|
||||||
</div>
|
</div>
|
||||||
<div className='col-span-2 justify-self-end self-center'>
|
<div className='col-span-2 justify-self-end self-center'>
|
||||||
{userRole === UserRole.WRITE &&
|
{!state.isLoading && userRole === UserRole.WRITE &&
|
||||||
<button
|
<button
|
||||||
className='btn btn-primary'
|
className='btn btn-primary'
|
||||||
onClick={() => onOpenClosePilotForm(FormMode.ADD)}
|
onClick={() => onOpenClosePilotForm(FormMode.ADD)}
|
||||||
@@ -203,8 +201,8 @@ const Pilots: React.FC<unknown> = () => {
|
|||||||
</Alert>
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className='col-span-12 bg-base-100 p-5 border border-base-100 rounded-lg'>
|
|
||||||
{state.pilots.length > 0 && screenSize !== ScreenSize.SM &&
|
{state.pilots.length > 0 && screenSize !== ScreenSize.SM &&
|
||||||
|
<div className='col-span-12 bg-base-100 p-5 border border-base-100 rounded-lg'>
|
||||||
<table className='table min-w-full h-auto table-auto w-full'>
|
<table className='table min-w-full h-auto table-auto w-full'>
|
||||||
<thead className='[&>tr]:first:rounded-lg bg-base-200'>
|
<thead className='[&>tr]:first:rounded-lg bg-base-200'>
|
||||||
{table.getHeaderGroups().map((headerGroup) => (
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
@@ -259,11 +257,11 @@ const Pilots: React.FC<unknown> = () => {
|
|||||||
</>
|
</>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
}
|
|
||||||
{state.pilots.length > 0 && screenSize === ScreenSize.SM &&
|
|
||||||
<PilotCard pilots={state.pilots} onDelete={onDeletePilot} onOpenCloseForm={onOpenClosePilotForm} />
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
|
{/* {state.pilots.length > 0 && screenSize === ScreenSize.SM &&
|
||||||
|
<PilotCard pilots={state.pilots} onDelete={onDeletePilot} onOpenCloseForm={onOpenClosePilotForm} />
|
||||||
|
} */}
|
||||||
</div>
|
</div>
|
||||||
{state.isFormOpen && (
|
{state.isFormOpen && (
|
||||||
<PilotForm
|
<PilotForm
|
||||||
|
|||||||
@@ -105,10 +105,6 @@ const SiteNav = () => {
|
|||||||
}
|
}
|
||||||
}, [isUserLoggedIn]);
|
}, [isUserLoggedIn]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
console.log(screenSize)
|
|
||||||
}, [screenSize])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="navbar bg-base-100 shadow-sm w-full">
|
<div className="navbar bg-base-100 shadow-sm w-full">
|
||||||
<div className={`navbar-start ${screenSize !== ScreenSize.SM && screenSize !== ScreenSize.MD ? 'ml-8' : ''}`}>
|
<div className={`navbar-start ${screenSize !== ScreenSize.SM && screenSize !== ScreenSize.MD ? 'ml-8' : ''}`}>
|
||||||
@@ -136,7 +132,7 @@ const SiteNav = () => {
|
|||||||
)}
|
)}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div className={`navbar-end ${screenSize !== ScreenSize.SM && screenSize !== ScreenSize.MD ? 'ml-8' : ''}`}>
|
<div className={`navbar-end ${screenSize !== ScreenSize.SM && screenSize !== ScreenSize.MD ? 'mr-8' : ''}`}>
|
||||||
{!isUserLoggedIn &&
|
{!isUserLoggedIn &&
|
||||||
<button className='btn btn-ghost' onClick={() => login()}><FontAwesomeIcon icon={faSignIn} />Sign In</button>
|
<button className='btn btn-ghost' onClick={() => login()}><FontAwesomeIcon icon={faSignIn} />Sign In</button>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ const TracksForm = () => {
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
{logbookContext.state.formMode === FormMode.ADD &&
|
{logbookContext.state.formMode === FormMode.EDIT &&
|
||||||
<div className='col-span-12'>
|
<div className='col-span-12'>
|
||||||
<label
|
<label
|
||||||
className='btn cursor-pointer w-full'
|
className='btn cursor-pointer w-full'
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ httpClient.interceptors.request.use(async (config) => {
|
|||||||
|
|
||||||
if (oidc.isUserLoggedIn) {
|
if (oidc.isUserLoggedIn) {
|
||||||
const { accessToken } = await oidc.getTokens();
|
const { accessToken } = await oidc.getTokens();
|
||||||
console.log(accessToken)
|
|
||||||
config.headers.Authorization = `Bearer ${accessToken}`;
|
config.headers.Authorization = `Bearer ${accessToken}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
dbs:
|
dbs:
|
||||||
- path: /var/lib/data/flying.db
|
- path: /mnt/data/flying.db
|
||||||
replicas:
|
replicas:
|
||||||
- path: /mnt/backup/flying.db
|
- path: /mnt/data/backup/flying.db
|
||||||
@@ -16,11 +16,11 @@ services:
|
|||||||
container_name: restore
|
container_name: restore
|
||||||
image: litestream/litestream:0.3.13
|
image: litestream/litestream:0.3.13
|
||||||
volumes:
|
volumes:
|
||||||
- ./database/flying.db:/var/lib/data/flying.db
|
- ./database/flying.db:/mnt/data/flying.db
|
||||||
- ./database/litestream/litestream.yml:/mnt/litestream/litestream.yml
|
- ./database/litestream/litestream.yml:/mnt/litestream/litestream.yml
|
||||||
- backup:/mnt/data/backup
|
- backup:/mnt/data/backup
|
||||||
- data:/var/lib/data
|
- data:/mnt/data
|
||||||
command: restore -config /mnt/litestream/litestream.yml -if-db-not-exists -if-replica-exists /var/lib/data/flying.db
|
command: restore -config /mnt/litestream/litestream.yml -if-db-not-exists -if-replica-exists /mnt/data/flying.db
|
||||||
|
|
||||||
app:
|
app:
|
||||||
container_name: flying
|
container_name: flying
|
||||||
@@ -31,9 +31,9 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- ./api/.env
|
- ./api/.env
|
||||||
environment:
|
environment:
|
||||||
- DB_PATH=../../var/lib/data/flying.db
|
- DB_PATH=../../mnt/data/flying.db
|
||||||
volumes:
|
volumes:
|
||||||
- data:/var/lib/data
|
- data:/mnt/data
|
||||||
depends_on:
|
depends_on:
|
||||||
restore:
|
restore:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
@@ -44,7 +44,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./database/litestream/litestream.yml:/mnt/litestream/litestream.yml
|
- ./database/litestream/litestream.yml:/mnt/litestream/litestream.yml
|
||||||
- backup:/mnt
|
- backup:/mnt
|
||||||
- data:/var/lib/data
|
- data:/mnt/data
|
||||||
command: replicate -config /mnt/litestream/litestream.yml
|
command: replicate -config /mnt/litestream/litestream.yml
|
||||||
depends_on:
|
depends_on:
|
||||||
app:
|
app:
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
# data "azuread_application" "app_registration" {
|
|
||||||
# provider = azuread.external_tenant
|
|
||||||
# display_name = module.environment.app_reg_name
|
|
||||||
# }
|
|
||||||
|
|
||||||
resource "azurerm_container_app" "container_app" {
|
resource "azurerm_container_app" "container_app" {
|
||||||
name = module.environment.app_name
|
name = module.environment.app_name
|
||||||
container_app_environment_id = data.azurerm_container_app_environment.container_app_environment.id
|
container_app_environment_id = data.azurerm_container_app_environment.container_app_environment.id
|
||||||
@@ -14,7 +9,7 @@ resource "azurerm_container_app" "container_app" {
|
|||||||
max_replicas = 2
|
max_replicas = 2
|
||||||
|
|
||||||
init_container {
|
init_container {
|
||||||
args = ["restore", "-if-db-not-exists", "-if-replica-exists", "/var/lib/data/flying.db"]
|
args = ["restore", "-if-db-not-exists", "-if-replica-exists", "/mnt/data/flying.db"]
|
||||||
cpu = 0.25
|
cpu = 0.25
|
||||||
image = "litestream/litestream:0.5.2"
|
image = "litestream/litestream:0.5.2"
|
||||||
memory = "0.5Gi"
|
memory = "0.5Gi"
|
||||||
@@ -22,12 +17,12 @@ resource "azurerm_container_app" "container_app" {
|
|||||||
|
|
||||||
volume_mounts {
|
volume_mounts {
|
||||||
name = "data"
|
name = "data"
|
||||||
path = "/var/lib/data"
|
path = "/mnt/data"
|
||||||
}
|
}
|
||||||
|
|
||||||
volume_mounts {
|
volume_mounts {
|
||||||
name = "backup"
|
name = "backup"
|
||||||
path = "/mnt/data"
|
path = "/mnt/data/backup"
|
||||||
sub_path = "data"
|
sub_path = "data"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,12 +42,12 @@ resource "azurerm_container_app" "container_app" {
|
|||||||
|
|
||||||
volume_mounts {
|
volume_mounts {
|
||||||
name = "data"
|
name = "data"
|
||||||
path = "/var/lib/data"
|
path = "/mnt/data"
|
||||||
}
|
}
|
||||||
|
|
||||||
volume_mounts {
|
volume_mounts {
|
||||||
name = "backup"
|
name = "backup"
|
||||||
path = "/mnt/data"
|
path = "/mnt/data/backup"
|
||||||
sub_path = "data"
|
sub_path = "data"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +60,7 @@ resource "azurerm_container_app" "container_app" {
|
|||||||
|
|
||||||
container {
|
container {
|
||||||
cpu = 0.25
|
cpu = 0.25
|
||||||
image = "noahspan/flying:19615036250"
|
image = "noahspan/flying:20588458616"
|
||||||
memory = "0.5Gi"
|
memory = "0.5Gi"
|
||||||
name = "flying"
|
name = "flying"
|
||||||
|
|
||||||
@@ -104,6 +99,11 @@ resource "azurerm_container_app" "container_app" {
|
|||||||
value = var.JWKS_URI
|
value = var.JWKS_URI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env {
|
||||||
|
name = "SESSION_SECRET"
|
||||||
|
secret_name = "session-secret"
|
||||||
|
}
|
||||||
|
|
||||||
env {
|
env {
|
||||||
name = "TENANT_ID"
|
name = "TENANT_ID"
|
||||||
value = var.EXTERNAL_TENANT_ID
|
value = var.EXTERNAL_TENANT_ID
|
||||||
@@ -111,7 +111,7 @@ resource "azurerm_container_app" "container_app" {
|
|||||||
|
|
||||||
env {
|
env {
|
||||||
name = "DB_PATH"
|
name = "DB_PATH"
|
||||||
value = "/var/lib/data/flying.db"
|
value = "/mnt/data/flying.db"
|
||||||
}
|
}
|
||||||
|
|
||||||
env {
|
env {
|
||||||
@@ -130,7 +130,7 @@ resource "azurerm_container_app" "container_app" {
|
|||||||
|
|
||||||
volume_mounts {
|
volume_mounts {
|
||||||
name = "data"
|
name = "data"
|
||||||
path = "/var/lib/data"
|
path = "/mnt/data"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,6 +179,11 @@ resource "azurerm_container_app" "container_app" {
|
|||||||
value = var.DOCKER_IO_PASSWORD
|
value = var.DOCKER_IO_PASSWORD
|
||||||
}
|
}
|
||||||
|
|
||||||
|
secret {
|
||||||
|
name = "session-secret"
|
||||||
|
value = var.SESSION_SECRET
|
||||||
|
}
|
||||||
|
|
||||||
lifecycle {
|
lifecycle {
|
||||||
ignore_changes = [ template[0].container[0].image, template[0].container[0].image, template[0].init_container[0].image, registry[0].server ]
|
ignore_changes = [ template[0].container[0].image, template[0].container[0].image, template[0].init_container[0].image, registry[0].server ]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ resource "azurerm_container_app_environment_storage" "container_app_environment_
|
|||||||
account_name = azurerm_storage_account.storage_account.name
|
account_name = azurerm_storage_account.storage_account.name
|
||||||
share_name = azurerm_storage_share.storage_share[0].name
|
share_name = azurerm_storage_share.storage_share[0].name
|
||||||
access_key = azurerm_storage_account.storage_account.primary_access_key
|
access_key = azurerm_storage_account.storage_account.primary_access_key
|
||||||
access_mode = "ReadOnly"
|
access_mode = "ReadWrite"
|
||||||
}
|
}
|
||||||
@@ -36,6 +36,11 @@ variable "EXTERNAL_TENANT_ID" {
|
|||||||
type = string
|
type = string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "SESSION_SECRET" {
|
||||||
|
sensitive = true
|
||||||
|
type = string
|
||||||
|
}
|
||||||
|
|
||||||
variable "TENANT_ID" {
|
variable "TENANT_ID" {
|
||||||
type = string
|
type = string
|
||||||
}
|
}
|
||||||
|
|||||||
455
package-lock.json
generated
455
package-lock.json
generated
@@ -86,7 +86,6 @@
|
|||||||
"@fortawesome/fontawesome-svg-core": "^7.1.0",
|
"@fortawesome/fontawesome-svg-core": "^7.1.0",
|
||||||
"@fortawesome/free-solid-svg-icons": "^7.1.0",
|
"@fortawesome/free-solid-svg-icons": "^7.1.0",
|
||||||
"@fortawesome/react-fontawesome": "^3.1.0",
|
"@fortawesome/react-fontawesome": "^3.1.0",
|
||||||
"@noahspan/noahspan-components": "^2.0.0-alpha-14",
|
|
||||||
"@tailwindcss/typography": "^0.5.19",
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"@tailwindcss/vite": "^4.1.13",
|
"@tailwindcss/vite": "^4.1.13",
|
||||||
"@tanstack/react-table": "^8.21.3",
|
"@tanstack/react-table": "^8.21.3",
|
||||||
@@ -159,71 +158,6 @@
|
|||||||
"react": "^18.0.0 || ^19.0.0"
|
"react": "^18.0.0 || ^19.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"client/node_modules/@noahspan/noahspan-components": {
|
|
||||||
"version": "2.0.0-alpha-14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@noahspan/noahspan-components/-/noahspan-components-2.0.0-alpha-14.tgz",
|
|
||||||
"integrity": "sha512-PlIQa3Np9pOaHFbLe0bIQTIe1jYVEWOTiSYAS3VXhO1MZ7NGlSu8vgBJQ9ireD8NueE+FlYi56n9cNgeDNY6IA==",
|
|
||||||
"dependencies": {
|
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.5.2",
|
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.5.2",
|
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
|
||||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
|
||||||
"@microsoft/microsoft-graph-types": "^2.40.0",
|
|
||||||
"@tanstack/react-table": "^8.17.3",
|
|
||||||
"react-daisyui-timetools": "^2.0.2",
|
|
||||||
"react-day-picker": "^9.9.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20.0.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": "^19.x",
|
|
||||||
"react-dom": "^19.x"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"client/node_modules/@noahspan/noahspan-components/node_modules/@fortawesome/fontawesome-common-types": {
|
|
||||||
"version": "6.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz",
|
|
||||||
"integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"client/node_modules/@noahspan/noahspan-components/node_modules/@fortawesome/fontawesome-svg-core": {
|
|
||||||
"version": "6.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.7.2.tgz",
|
|
||||||
"integrity": "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==",
|
|
||||||
"dependencies": {
|
|
||||||
"@fortawesome/fontawesome-common-types": "6.7.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"client/node_modules/@noahspan/noahspan-components/node_modules/@fortawesome/free-solid-svg-icons": {
|
|
||||||
"version": "6.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.7.2.tgz",
|
|
||||||
"integrity": "sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA==",
|
|
||||||
"dependencies": {
|
|
||||||
"@fortawesome/fontawesome-common-types": "6.7.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"client/node_modules/@noahspan/noahspan-components/node_modules/@fortawesome/react-fontawesome": {
|
|
||||||
"version": "0.2.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.6.tgz",
|
|
||||||
"integrity": "sha512-mtBFIi1UsYQo7rYonYFkjgYKGoL8T+fEH6NGUpvuqtY3ytMsAoDaPo5rk25KuMtKDipY4bGYM/CkmCHA1N3FUg==",
|
|
||||||
"dependencies": {
|
|
||||||
"prop-types": "^15.8.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@fortawesome/fontawesome-svg-core": "~1 || ~6 || ~7",
|
|
||||||
"react": "^16.3 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"client/node_modules/react": {
|
"client/node_modules/react": {
|
||||||
"version": "19.1.1",
|
"version": "19.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz",
|
||||||
@@ -232,20 +166,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"client/node_modules/react-daisyui-timetools": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-daisyui-timetools/-/react-daisyui-timetools-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-ruNo9eUdNm/tlkgo+zd7qZbDgxTObRAH4CW8KBpxpWDTrS0krYuWcFcao9i4wwYeVfPnWrtgw5AsH895EmKgFA==",
|
|
||||||
"peerDependencies": {
|
|
||||||
"@tailwindcss/postcss": "^4.0.12",
|
|
||||||
"daisyui": "^5",
|
|
||||||
"dayjs": "^1.11.13",
|
|
||||||
"postcss": "^8.5.3",
|
|
||||||
"react": "^19.0.0",
|
|
||||||
"react-dom": "^19.0.0",
|
|
||||||
"tailwindcss": "^4.0.12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"client/node_modules/react-dom": {
|
"client/node_modules/react-dom": {
|
||||||
"version": "19.1.1",
|
"version": "19.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz",
|
||||||
@@ -257,18 +177,6 @@
|
|||||||
"react": "^19.1.1"
|
"react": "^19.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@alloc/quick-lru": {
|
|
||||||
"version": "5.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
|
|
||||||
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@ampproject/remapping": {
|
"node_modules/@ampproject/remapping": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
|
||||||
@@ -2317,11 +2225,6 @@
|
|||||||
"google-protobuf": "^3.21.2"
|
"google-protobuf": "^3.21.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@date-fns/tz": {
|
|
||||||
"version": "1.4.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@date-fns/tz/-/tz-1.4.1.tgz",
|
|
||||||
"integrity": "sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA=="
|
|
||||||
},
|
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.21.5",
|
"version": "0.21.5",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
||||||
@@ -2424,36 +2327,6 @@
|
|||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@fortawesome/fontawesome-common-types": {
|
|
||||||
"version": "6.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz",
|
|
||||||
"integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@fortawesome/free-brands-svg-icons": {
|
|
||||||
"version": "6.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.7.2.tgz",
|
|
||||||
"integrity": "sha512-zu0evbcRTgjKfrr77/2XX+bU+kuGfjm0LbajJHVIgBWNIDzrhpRxiCPNT8DW5AdmSsq7Mcf9D1bH0aSeSUSM+Q==",
|
|
||||||
"dependencies": {
|
|
||||||
"@fortawesome/fontawesome-common-types": "6.7.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@fortawesome/free-regular-svg-icons": {
|
|
||||||
"version": "6.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.7.2.tgz",
|
|
||||||
"integrity": "sha512-7Z/ur0gvCMW8G93dXIQOkQqHo2M5HLhYrRVC0//fakJXxcF1VmMPsxnG6Ee8qEylA8b8Q3peQXWMNZ62lYF28g==",
|
|
||||||
"dependencies": {
|
|
||||||
"@fortawesome/fontawesome-common-types": "6.7.2"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@grpc/grpc-js": {
|
"node_modules/@grpc/grpc-js": {
|
||||||
"version": "1.13.4",
|
"version": "1.13.4",
|
||||||
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.4.tgz",
|
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.13.4.tgz",
|
||||||
@@ -3270,6 +3143,7 @@
|
|||||||
"version": "2.40.0",
|
"version": "2.40.0",
|
||||||
"resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-2.40.0.tgz",
|
"resolved": "https://registry.npmjs.org/@microsoft/microsoft-graph-types/-/microsoft-graph-types-2.40.0.tgz",
|
||||||
"integrity": "sha512-1fcPVrB/NkbNcGNfCy+Cgnvwxt6/sbIEEFgZHFBJ670zYLegENYJF8qMo7x3LqBjWX2/Eneq5BVVRCLTmlJN+g==",
|
"integrity": "sha512-1fcPVrB/NkbNcGNfCy+Cgnvwxt6/sbIEEFgZHFBJ670zYLegENYJF8qMo7x3LqBjWX2/Eneq5BVVRCLTmlJN+g==",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@nestjs/axios": {
|
"node_modules/@nestjs/axios": {
|
||||||
@@ -5104,282 +4978,6 @@
|
|||||||
"node": ">= 10"
|
"node": ">= 10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@tailwindcss/postcss": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-BdMjIxy7HUNThK87C7BC8I1rE8BVUsfNQSI5siQ4JK3iIa3w0XyVvVL9SXLWO//CtYTcp1v7zci0fYwJOjB+Zg==",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@alloc/quick-lru": "^5.2.0",
|
|
||||||
"@tailwindcss/node": "4.1.14",
|
|
||||||
"@tailwindcss/oxide": "4.1.14",
|
|
||||||
"postcss": "^8.4.41",
|
|
||||||
"tailwindcss": "4.1.14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/@tailwindcss/node": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw==",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@jridgewell/remapping": "^2.3.4",
|
|
||||||
"enhanced-resolve": "^5.18.3",
|
|
||||||
"jiti": "^2.6.0",
|
|
||||||
"lightningcss": "1.30.1",
|
|
||||||
"magic-string": "^0.30.19",
|
|
||||||
"source-map-js": "^1.2.1",
|
|
||||||
"tailwindcss": "4.1.14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/@tailwindcss/oxide": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw==",
|
|
||||||
"hasInstallScript": true,
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"detect-libc": "^2.0.4",
|
|
||||||
"tar": "^7.5.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
|
||||||
"@tailwindcss/oxide-android-arm64": "4.1.14",
|
|
||||||
"@tailwindcss/oxide-darwin-arm64": "4.1.14",
|
|
||||||
"@tailwindcss/oxide-darwin-x64": "4.1.14",
|
|
||||||
"@tailwindcss/oxide-freebsd-x64": "4.1.14",
|
|
||||||
"@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.14",
|
|
||||||
"@tailwindcss/oxide-linux-arm64-gnu": "4.1.14",
|
|
||||||
"@tailwindcss/oxide-linux-arm64-musl": "4.1.14",
|
|
||||||
"@tailwindcss/oxide-linux-x64-gnu": "4.1.14",
|
|
||||||
"@tailwindcss/oxide-linux-x64-musl": "4.1.14",
|
|
||||||
"@tailwindcss/oxide-wasm32-wasi": "4.1.14",
|
|
||||||
"@tailwindcss/oxide-win32-arm64-msvc": "4.1.14",
|
|
||||||
"@tailwindcss/oxide-win32-x64-msvc": "4.1.14"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/@tailwindcss/oxide-android-arm64": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"android"
|
|
||||||
],
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/@tailwindcss/oxide-darwin-arm64": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
],
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/@tailwindcss/oxide-darwin-x64": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"darwin"
|
|
||||||
],
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/@tailwindcss/oxide-freebsd-x64": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"freebsd"
|
|
||||||
],
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw==",
|
|
||||||
"cpu": [
|
|
||||||
"arm"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/@tailwindcss/oxide-linux-arm64-gnu": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/@tailwindcss/oxide-linux-arm64-musl": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/@tailwindcss/oxide-linux-x64-gnu": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/@tailwindcss/oxide-linux-x64-musl": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"linux"
|
|
||||||
],
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/@tailwindcss/oxide-wasm32-wasi": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ==",
|
|
||||||
"bundleDependencies": [
|
|
||||||
"@napi-rs/wasm-runtime",
|
|
||||||
"@emnapi/core",
|
|
||||||
"@emnapi/runtime",
|
|
||||||
"@tybys/wasm-util",
|
|
||||||
"@emnapi/wasi-threads",
|
|
||||||
"tslib"
|
|
||||||
],
|
|
||||||
"cpu": [
|
|
||||||
"wasm32"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@emnapi/core": "^1.5.0",
|
|
||||||
"@emnapi/runtime": "^1.5.0",
|
|
||||||
"@emnapi/wasi-threads": "^1.1.0",
|
|
||||||
"@napi-rs/wasm-runtime": "^1.0.5",
|
|
||||||
"@tybys/wasm-util": "^0.10.1",
|
|
||||||
"tslib": "^2.4.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA==",
|
|
||||||
"cpu": [
|
|
||||||
"arm64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/@tailwindcss/oxide-win32-x64-msvc": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA==",
|
|
||||||
"cpu": [
|
|
||||||
"x64"
|
|
||||||
],
|
|
||||||
"optional": true,
|
|
||||||
"os": [
|
|
||||||
"win32"
|
|
||||||
],
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/magic-string": {
|
|
||||||
"version": "0.30.19",
|
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
|
|
||||||
"integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/postcss/node_modules/tailwindcss": {
|
|
||||||
"version": "4.1.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.14.tgz",
|
|
||||||
"integrity": "sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA==",
|
|
||||||
"peer": true
|
|
||||||
},
|
|
||||||
"node_modules/@tailwindcss/typography": {
|
"node_modules/@tailwindcss/typography": {
|
||||||
"version": "0.5.19",
|
"version": "0.5.19",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.19.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.19.tgz",
|
||||||
@@ -7974,15 +7572,11 @@
|
|||||||
"version": "5.5.5",
|
"version": "5.5.5",
|
||||||
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.5.5.tgz",
|
"resolved": "https://registry.npmjs.org/daisyui/-/daisyui-5.5.5.tgz",
|
||||||
"integrity": "sha512-ekvI93ZkWIJoCOtDl0D2QMxnWvTejk9V5nWBqRv+7t0xjiBXqAK5U6o6JE2RPvlIC3EqwNyUoIZSdHX9MZK3nw==",
|
"integrity": "sha512-ekvI93ZkWIJoCOtDl0D2QMxnWvTejk9V5nWBqRv+7t0xjiBXqAK5U6o6JE2RPvlIC3EqwNyUoIZSdHX9MZK3nw==",
|
||||||
|
"dev": true,
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/saadeghi/daisyui?sponsor=1"
|
"url": "https://github.com/saadeghi/daisyui?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/date-fns-jalali": {
|
|
||||||
"version": "4.1.0-0",
|
|
||||||
"resolved": "https://registry.npmjs.org/date-fns-jalali/-/date-fns-jalali-4.1.0-0.tgz",
|
|
||||||
"integrity": "sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg=="
|
|
||||||
},
|
|
||||||
"node_modules/dayjs": {
|
"node_modules/dayjs": {
|
||||||
"version": "1.11.18",
|
"version": "1.11.18",
|
||||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz",
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz",
|
||||||
@@ -12362,6 +11956,7 @@
|
|||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||||
},
|
},
|
||||||
@@ -14272,21 +13867,6 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prop-types": {
|
|
||||||
"version": "15.8.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
|
||||||
"dependencies": {
|
|
||||||
"loose-envify": "^1.4.0",
|
|
||||||
"object-assign": "^4.1.1",
|
|
||||||
"react-is": "^16.13.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/prop-types/node_modules/react-is": {
|
|
||||||
"version": "16.13.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
|
||||||
},
|
|
||||||
"node_modules/property-expr": {
|
"node_modules/property-expr": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
|
||||||
@@ -14515,35 +14095,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-day-picker": {
|
|
||||||
"version": "9.11.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-9.11.1.tgz",
|
|
||||||
"integrity": "sha512-l3ub6o8NlchqIjPKrRFUCkTUEq6KwemQlfv3XZzzwpUeGwmDJ+0u0Upmt38hJyd7D/vn2dQoOoLV/qAp0o3uUw==",
|
|
||||||
"dependencies": {
|
|
||||||
"@date-fns/tz": "^1.4.1",
|
|
||||||
"date-fns": "^4.1.0",
|
|
||||||
"date-fns-jalali": "^4.1.0-0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=18"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "individual",
|
|
||||||
"url": "https://github.com/sponsors/gpbl"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": ">=16.8.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-day-picker/node_modules/date-fns": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/kossnocorp"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-dom": {
|
"node_modules/react-dom": {
|
||||||
"version": "18.3.1",
|
"version": "18.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@noahspan/flying",
|
"name": "@noahspan/flying",
|
||||||
"version": "2.0.0-alpha-3",
|
"version": "2.0.0-beta-1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node api/dist/main",
|
"start": "node api/dist/main",
|
||||||
"format": "prettier --write \"**/src/**/*.ts\" \"**/test/**/*.ts\"",
|
"format": "prettier --write \"**/src/**/*.ts\" \"**/test/**/*.ts\"",
|
||||||
|
|||||||
Reference in New Issue
Block a user