adding pilot

This commit is contained in:
2024-08-16 19:23:54 -05:00
parent 0d7f6b850d
commit 9e1e69d996
14 changed files with 284 additions and 272 deletions

View File

@@ -20,6 +20,7 @@
"start:azure": "npm run build && func host start" "start:azure": "npm run build && func host start"
}, },
"dependencies": { "dependencies": {
"@azure/data-tables": "^13.2.2",
"@azure/functions": "^1.0.3", "@azure/functions": "^1.0.3",
"@nestjs/azure-database": "^3.0.0", "@nestjs/azure-database": "^3.0.0",
"@nestjs/azure-func-http": "^0.10.0", "@nestjs/azure-func-http": "^0.10.0",
@@ -28,7 +29,7 @@
"@nestjs/core": "^10.0.0", "@nestjs/core": "^10.0.0",
"@nestjs/passport": "^10.0.3", "@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.0.0", "@nestjs/platform-express": "^10.0.0",
"@noahspan/noahspan-modules": "^0.3.5", "@noahspan/noahspan-modules": "^0.3.9",
"@schematics/angular": "^17.3.7", "@schematics/angular": "^17.3.7",
"dotenv": "^16.4.5", "dotenv": "^16.4.5",
"reflect-metadata": "0.1.13", "reflect-metadata": "0.1.13",

View File

@@ -1,12 +1,4 @@
import { import { Controller, Get, Headers, Query } from '@nestjs/common';
Body,
Controller,
Get,
Headers,
Post,
Query,
UnprocessableEntityException
} from '@nestjs/common';
import { import {
AppConfigService, AppConfigService,
MsGraphService, MsGraphService,
@@ -16,8 +8,6 @@ import { FeatureFlagValue } from '@azure/app-configuration';
import { Public } from '@noahspan/noahspan-modules'; import { Public } from '@noahspan/noahspan-modules';
import { Person } from '@microsoft/microsoft-graph-types'; import { Person } from '@microsoft/microsoft-graph-types';
import { AppService } from './app.service'; import { AppService } from './app.service';
import { PilotDTO } from './pilot/pilot.dto';
import { PilotService } from './pilot/pilot.service';
@Controller() @Controller()
export class AppController { export class AppController {

View File

@@ -10,7 +10,6 @@ import {
import { ConfigModule } from '@nestjs/config'; import { ConfigModule } from '@nestjs/config';
import { APP_GUARD } from '@nestjs/core'; import { APP_GUARD } from '@nestjs/core';
import { PilotModule } from './pilot/pilot.module'; import { PilotModule } from './pilot/pilot.module';
import { PilotController } from './pilot/pilot.controller';
@Module({ @Module({
imports: [ imports: [
@@ -33,7 +32,7 @@ import { PilotController } from './pilot/pilot.controller';
}), }),
PilotModule PilotModule
], ],
controllers: [AppController, PilotController], controllers: [AppController],
providers: [ providers: [
{ {
provide: APP_GUARD, provide: APP_GUARD,

View File

@@ -1,18 +1,25 @@
import { Body, Controller, Get, Post, Put, Query } from '@nestjs/common'; import {
import { Public } from '@noahspan/noahspan-modules'; Body,
import { PilotDTO } from './pilot.dto'; Controller,
import { Pilot } from './pilot.entity'; Get,
Post,
Put,
Query,
UnprocessableEntityException
} from '@nestjs/common';
import { PilotInfoService } from './info/pilot-info.service';
import { PilotInfoDto } from './info/pilot-info.dto';
@Controller('pilots') @Controller('pilots')
export class PilotController { export class PilotController {
constructor() {} constructor(private readonly pilotInfoService: PilotInfoService) {}
@Public()
@Post() @Post()
async createPilot(@Body() pilotDto: PilotDTO) { async createPilot(@Body() pilotInfoData: PilotInfoDto): Promise<void> {
const pilot = new Pilot(); try {
Object.assign(pilot, pilotDto); return await this.pilotInfoService.create(pilotInfoData);
} catch (error) {
console.log(pilot); throw new UnprocessableEntityException(error);
}
} }
} }

View File

@@ -1,11 +0,0 @@
import { Certificate } from './certificate/certificate.entity';
import { Endorsement } from './endorsement/endorsement.entity';
import { Medical } from './medical/medical.entity';
import { Profile } from './profile/profile.entity';
export class PilotDTO {
profile?: Profile;
medical?: Medical;
certificate?: Certificate;
endosement?: Endorsement;
}

View File

@@ -1,11 +0,0 @@
import { Certificate } from './certificate/certificate.entity';
import { Endorsement } from './endorsement/endorsement.entity';
import { Medical } from './medical/medical.entity';
import { Profile } from './profile/profile.entity';
export class Pilot {
profile: Profile;
medical: Medical;
certificates: Certificate;
endorsements: Endorsement;
}

View File

@@ -1,17 +1,16 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { PilotController } from './pilot.controller'; import { PilotController } from './pilot.controller';
import { PilotService } from './pilot.service'; import { TableModule } from '@noahspan/noahspan-modules';
import { AzureTableStorageModule } from '@nestjs/azure-database'; import { PilotInfoService } from './info/pilot-info.service';
import { Pilot } from './pilot.entity';
@Module({ @Module({
imports: [ imports: [
AzureTableStorageModule.forFeature(Pilot, { TableModule.register({
table: 'Pilot', accountName: process.env.AZURE_STORAGE_ACCOUNT_NAME,
createTableIfNotExists: true accountKey: process.env.AZURE_STORAGE_ACCOUNT_KEY
}) })
], ],
controllers: [PilotController], controllers: [PilotController],
providers: [PilotService] providers: [PilotInfoService]
}) })
export class PilotModule {} export class PilotModule {}

View File

@@ -1,17 +0,0 @@
import { Inject, Injectable } from '@nestjs/common';
import { Repository, InjectRepository } from '@nestjs/azure-database';
import { Medical } from './medical/medical.entity';
import { Profile } from './profile/profile.entity';
import { ProfileService } from './profile/profile.service';
import { Pilot } from './pilot.entity';
@Injectable()
export class PilotService {
constructor(
@InjectRepository(Pilot) private readonly pilotRepository: Repository<Pilot>
) {}
async create(pilot: Pilot): Promise<Pilot> {
return await this.pilotRepository.create(pilot);
}
}

View File

@@ -1,18 +0,0 @@
import {
EntityDateTime,
EntityPartitionKey,
EntityRowKey,
EntityString
} from '@nestjs/azure-database';
@EntityPartitionKey('pilot')
@EntityRowKey('id')
export class Profile {
@EntityString() firstName: string;
@EntityString() lastName: string;
@EntityString() address: string;
@EntityString() city: string;
@EntityString() state: string;
@EntityString() postalCode: string;
@EntityDateTime() lastFlightReview: Date;
}

View File

@@ -1,37 +0,0 @@
import { Injectable } from '@nestjs/common';
import { Repository, InjectRepository } from '@nestjs/azure-database';
import { Profile } from './profile.entity';
@Injectable()
export class ProfileService {
private readonly partitionKey: string = 'profile';
constructor(
@InjectRepository(Profile)
private readonly profileRepository: Repository<Profile>
) {}
async find(rowKey: string): Promise<Profile> {
return await this.profileRepository.find(this.partitionKey, rowKey);
}
async findAll(): Promise<Profile[]> {
return await this.profileRepository.findAll();
}
async create(profile: Profile): Promise<Profile> {
return await this.profileRepository.create(profile);
}
async update(rowKey: string, profile: Profile): Promise<Profile> {
return await this.profileRepository.update(
this.partitionKey,
rowKey,
profile
);
}
async delete(rowKey: string): Promise<void> {
await this.profileRepository.delete(this.partitionKey, rowKey);
}
}

View File

@@ -16,7 +16,7 @@
"@fortawesome/free-regular-svg-icons": "^6.5.2", "@fortawesome/free-regular-svg-icons": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^6.5.2", "@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/react-fontawesome": "^0.2.2", "@fortawesome/react-fontawesome": "^0.2.2",
"@noahspan/noahspan-components": "^0.5.9", "@noahspan/noahspan-components": "^0.6.2",
"axios": "^1.7.2", "axios": "^1.7.2",
"framer-motion": "^11.1.7", "framer-motion": "^11.1.7",
"react": "^18.2.0", "react": "^18.2.0",

View File

@@ -1,4 +1,4 @@
import { useState } from 'react'; import { useEffect, useState } from 'react';
import { import {
useForm, useForm,
Controller, Controller,
@@ -15,9 +15,11 @@ import {
Input, Input,
Option, Option,
PeoplePicker, PeoplePicker,
SaveIcon,
Select, Select,
StateSelect, StateSelect,
Typography Typography,
XmarkIcon
} from '@noahspan/noahspan-components'; } from '@noahspan/noahspan-components';
import { IPilotFormProps } from './IPilotFormProps'; import { IPilotFormProps } from './IPilotFormProps';
import PilotFormCertificates from '../pilotFormCertificates/PilotFormCertificates'; import PilotFormCertificates from '../pilotFormCertificates/PilotFormCertificates';
@@ -28,8 +30,10 @@ import { useHttpClient } from '../../hooks/httpClient/UseHttpClient';
import { useAccessToken } from '../../hooks/accessToken/UseAcessToken'; import { useAccessToken } from '../../hooks/accessToken/UseAcessToken';
import { IPilotFormCertificates } from '../pilotFormCertificates/IPilotFormCertificates'; import { IPilotFormCertificates } from '../pilotFormCertificates/IPilotFormCertificates';
import { IPilotFormEndorsements } from '../pilotFormEndorsements/IPilotFormEndorsements'; import { IPilotFormEndorsements } from '../pilotFormEndorsements/IPilotFormEndorsements';
import { EventMessage, EventPayload, EventType } from '@azure/msal-browser';
const PilotForm: React.FC<IPilotFormProps> = ({ const PilotForm: React.FC<IPilotFormProps> = ({
pilotId,
isDrawerOpen, isDrawerOpen,
onOpenCloseDrawer onOpenCloseDrawer
}: IPilotFormProps) => { }: IPilotFormProps) => {
@@ -40,8 +44,14 @@ const PilotForm: React.FC<IPilotFormProps> = ({
const { getAccessToken } = useAccessToken(); const { getAccessToken } = useAccessToken();
const methods = useForm(); const methods = useForm();
const onSubmit = (data: unknown) => { const handlePeoplePickerOnClick = (
console.log(data); event: React.MouseEvent<HTMLDivElement>
) => {
const divElement: HTMLDivElement = event.target as HTMLDivElement;
methods.setValue('id', divElement.id);
methods.setValue('name', divElement.textContent);
setPeoplePickerResults([]);
}; };
const handlePeoplePickerOnChange = async ( const handlePeoplePickerOnChange = async (
@@ -71,6 +81,21 @@ const PilotForm: React.FC<IPilotFormProps> = ({
} }
}; };
const onSubmit = async (data: unknown) => {
console.log(data);
const accessToken: string = await getAccessToken();
const response: AxiosResponse = await httpClient.post(`api/pilots`, data, {
headers: {
Authorization: accessToken
}
});
};
useEffect(() => {
console.log(methods.formState.errors);
}, [methods.formState.errors]);
return ( return (
<Drawer <Drawer
open={isDrawerOpen} open={isDrawerOpen}
@@ -83,10 +108,6 @@ const PilotForm: React.FC<IPilotFormProps> = ({
<form onSubmit={methods.handleSubmit(onSubmit)}> <form onSubmit={methods.handleSubmit(onSubmit)}>
<DrawerBody> <DrawerBody>
<div className="grid grid-cols-4 gap-4"> <div className="grid grid-cols-4 gap-4">
<div className="col-span-4">
<Typography variant="h5">Info</Typography>
<hr className="my-3" />
</div>
<div className="col-span-1"> <div className="col-span-1">
<Typography variant="h6">Name *</Typography> <Typography variant="h6">Name *</Typography>
</div> </div>
@@ -94,6 +115,7 @@ const PilotForm: React.FC<IPilotFormProps> = ({
<Controller <Controller
name="name" name="name"
control={methods.control} control={methods.control}
rules={{ required: 'A name must be selected' }}
render={({ field: { disabled, value } }) => ( render={({ field: { disabled, value } }) => (
<PeoplePicker <PeoplePicker
results={peoplePickerResults} results={peoplePickerResults}
@@ -103,82 +125,120 @@ const PilotForm: React.FC<IPilotFormProps> = ({
className: 'before:content-none after:content-none' className: 'before:content-none after:content-none'
}, },
onChange: (event) => handlePeoplePickerOnChange(event), onChange: (event) => handlePeoplePickerOnChange(event),
error: methods.formState.errors.name ? true : false,
helperText: methods.formState.errors.name
? methods.formState.errors.name.message?.toString()
: undefined,
value: value value: value
}} }}
listItemProps={{
children: null,
onClick: handlePeoplePickerOnClick
}}
loading={isPeoplePickerLoading} loading={isPeoplePickerLoading}
/> />
)} )}
/> />
</div> </div>
<div className="col-span-1"> <div className="col-span-1">
<Typography variant="h6">Address</Typography> <Typography variant="h6">Address *</Typography>
</div> </div>
<div className="col-span-3"> <div className="col-span-3">
<Controller <Controller
name="address" name="address"
control={methods.control} control={methods.control}
rules={{ required: true }} rules={{ required: 'An address is required' }}
render={({ field }) => ( render={({ field: { disabled, onChange, value } }) => (
<Input <Input
className="!border-t-blue-gray-200 focus:!border-t-gray-900" className="!border-t-blue-gray-200 focus:!border-t-gray-900"
disabled={disabled}
labelProps={{ labelProps={{
className: 'before:content-none after:content-none' className: 'before:content-none after:content-none'
}} }}
{...field} error={methods.formState.errors.address ? true : false}
helperText={
methods.formState.errors.address
? methods.formState.errors.address.message?.toString()
: undefined
}
onChange={onChange}
value={value}
/> />
)} )}
/> />
</div> </div>
<div className="col-span-1"> <div className="col-span-1">
<Typography variant="h6">City</Typography> <Typography variant="h6">City *</Typography>
</div> </div>
<div className="col-span-3"> <div className="col-span-3">
<Controller <Controller
name="city" name="city"
control={methods.control} control={methods.control}
rules={{ required: true }} rules={{ required: 'A city is required' }}
render={({ field }) => ( render={({ field: { disabled, onChange, value } }) => (
<Input <Input
disabled={disabled}
labelProps={{ labelProps={{
className: 'before:content-none after:content-none' className: 'before:content-none after:content-none'
}} }}
{...field} error={methods.formState.errors.city ? true : false}
helperText={
methods.formState.errors.city
? methods.formState.errors.city.message?.toString()
: undefined
}
onChange={onChange}
value={value}
/> />
)} )}
/> />
</div> </div>
<div className="col-span-1"> <div className="col-span-1">
<Typography variant="h6">State</Typography> <Typography variant="h6">State *</Typography>
</div> </div>
<div className="col-span-3"> <div className="col-span-3">
<Controller <Controller
name="state" name="state"
control={methods.control} control={methods.control}
render={({ field }) => ( rules={{ required: 'A state must be selected' }}
// <Input render={({ field: { disabled, onChange, value } }) => (
// labelProps={{ <StateSelect
// className: 'before:content-none after:content-none' disabled={disabled}
// }} error={methods.formState.errors.state ? true : false}
// {...field} helperText={
// /> methods.formState.errors.state
<StateSelect variant="outlined" /> ? methods.formState.errors.state.message?.toString()
: undefined
}
onChange={onChange}
value={value}
variant="outlined"
/>
)} )}
/> />
</div> </div>
<div className="col-span-1"> <div className="col-span-1">
<Typography variant="h6">Postal Code</Typography> <Typography variant="h6">Postal Code *</Typography>
</div> </div>
<div className="col-span-3"> <div className="col-span-3">
<Controller <Controller
name="postalCode" name="postalCode"
control={methods.control} control={methods.control}
rules={{ required: true }} rules={{ required: 'A postal code is required' }}
render={({ field }) => ( render={({ field: { disabled, onChange, value } }) => (
<Input <Input
disabled={disabled}
labelProps={{ labelProps={{
className: 'before:content-none after:content-none' className: 'before:content-none after:content-none'
}} }}
{...field} error={methods.formState.errors.postalCode ? true : false}
helperText={
methods.formState.errors.postalCode
? methods.formState.errors.postalCode.message?.toString()
: undefined
}
onChange={onChange}
value={value}
/> />
)} )}
/> />
@@ -190,13 +250,26 @@ const PilotForm: React.FC<IPilotFormProps> = ({
<Controller <Controller
name="email" name="email"
control={methods.control} control={methods.control}
rules={{ required: true }} rules={{
render={({ field }) => ( pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Invalid email address'
}
}}
render={({ field: { disabled, onChange, value } }) => (
<Input <Input
disabled={disabled}
labelProps={{ labelProps={{
className: 'before:content-none after:content-none' className: 'before:content-none after:content-none'
}} }}
{...field} error={methods.formState.errors.email ? true : false}
helperText={
methods.formState.errors.email
? methods.formState.errors.email.message?.toString()
: undefined
}
onChange={onChange}
value={value}
/> />
)} )}
/> />
@@ -208,120 +281,157 @@ const PilotForm: React.FC<IPilotFormProps> = ({
<Controller <Controller
name="phone" name="phone"
control={methods.control} control={methods.control}
rules={{ required: true }} rules={{
render={({ field }) => ( pattern: {
value: /^[0-9]{3}[-\s\.][0-9]{3}[-\s\.][0-9]{4}$/i,
message: 'Enter phone number as 123-456-7890'
}
}}
render={({ field: { disabled, onChange, value } }) => (
<Input <Input
disabled={disabled}
labelProps={{ labelProps={{
className: 'before:content-none after:content-none' className: 'before:content-none after:content-none'
}} }}
{...field} error={methods.formState.errors.phone ? true : false}
helperText={
methods.formState.errors.phone
? methods.formState.errors.phone.message?.toString()
: undefined
}
onChange={onChange}
value={value}
/> />
)} )}
/> />
</div> </div>
<div className="col-span-1"> {pilotId && (
<Typography variant="h6">Last Review</Typography> <>
</div> <div className="col-span-1">
<div className="col-span-3"> <Typography variant="h6">Last Review</Typography>
<Controller </div>
name="lastReview" <div className="col-span-3">
control={methods.control} <Controller
render={({ field }) => { name="lastReview"
return ( control={methods.control}
<DatePicker render={({ field }) => {
handleDateChanged={(date: string) => { return (
methods.setValue('lastReview', date); <DatePicker
}} handleDateChanged={(date: string) => {
inputProps={{ methods.setValue('lastReview', date);
value: field.value }}
}} inputProps={{
/> value: field.value
); }}
}} />
/> );
</div> }}
<div className="col-span-4"> />
<Typography variant="h5">Certificates</Typography> </div>
<hr className="my-3" /> </>
</div> )}
<PilotFormCertificates certificates={[]} /> {pilotId && (
<div className="col-span-4"> <>
<Typography variant="h5">Endorsements</Typography> <div className="col-span-4">
<hr className="my-3" /> <Typography variant="h5">Medical</Typography>
</div> <hr className="my-3" />
<PilotFormEndorsements endorsements={[]} /> </div>
<div className="col-span-4"> <div className="col-span-1">
<Typography variant="h5">Medical</Typography> <Typography variant="h6">Class</Typography>
<hr className="my-3" /> </div>
</div> <div className="col-span-3">
<div className="col-span-1"> <Controller
<Typography variant="h6">Class</Typography> name="medicalClass"
</div> control={methods.control}
<div className="col-span-3"> render={({ field }) => {
<Controller return (
name="medicalClass" <Select
control={methods.control} labelProps={{
render={({ field }) => { className:
return ( 'before:content-none after:content-none'
<Select }}
labelProps={{ {...field}
className: 'before:content-none after:content-none' >
}} <Option key="first" value="First">
{...field} First
> </Option>
<Option key="first" value="First"> <Option key="second" value="Second">
First Second
</Option> </Option>
<Option key="second" value="Second"> <Option key="third" value="Third">
Second Third
</Option> </Option>
<Option key="third" value="Third"> <Option key="basicMed" value="Basic Med">
Third Basic Med
</Option> </Option>
<Option key="basicMed" value="Basic Med"> </Select>
Basic Med );
</Option> }}
</Select> />
); </div>
}} <div className="col-span-1">
/> <Typography variant="h6">Expiration Date</Typography>
</div> </div>
<div className="col-span-1"> <div className="col-span-3">
<Typography variant="h6">Expiration Date</Typography> <Controller
</div> name="medicalExpiration"
<div className="col-span-3"> control={methods.control}
<Controller render={({ field }) => {
name="medicalExpiration" return (
control={methods.control} <DatePicker
render={({ field }) => { handleDateChanged={(date: string) => {
return ( methods.setValue('medicalExpiration', date);
<DatePicker }}
handleDateChanged={(date: string) => { inputProps={{
methods.setValue('medicalExpiration', date); value: field.value
}} }}
inputProps={{ />
value: field.value );
}} }}
/> />
); </div>
}} </>
/> )}
</div> {pilotId && (
<>
<div className="col-span-4">
<Typography variant="h5">Certificates</Typography>
<hr className="my-3" />
</div>
<PilotFormCertificates certificates={[]} />
</>
)}
{pilotId && (
<>
<div className="col-span-4">
<Typography variant="h5">Endorsements</Typography>
<hr className="my-3" />
</div>
<PilotFormEndorsements endorsements={[]} />
</>
)}
</div> </div>
</DrawerBody> </DrawerBody>
<DrawerFooter> <DrawerFooter>
<div className="flex gap-2 justify-end justify-self-center"> <div className="flex gap-2 justify-end justify-self-center pt-4">
<div> <div>
<Button <Button
className="flex items-center gap-3"
variant="outlined" variant="outlined"
onClick={onOpenCloseDrawer} onClick={onOpenCloseDrawer}
data-testid="pilot-drawer-cancel-button" data-testid="pilot-drawer-cancel-button"
> >
<XmarkIcon size="lg" />
Cancel Cancel
</Button> </Button>
</div> </div>
<div> <div>
<Button variant="filled" type="submit"> <Button
className="flex items-center gap-3"
variant="filled"
type="submit"
>
<SaveIcon size="lg" />
Save Save
</Button> </Button>
</div> </div>

View File

@@ -1,6 +1,12 @@
import { useState } from 'react'; import { useState } from 'react';
import PilotForm from '../pilotForm/PilotForm'; import PilotForm from '../pilotForm/PilotForm';
import { Button, PlusIcon, DatePicker } from '@noahspan/noahspan-components'; import {
Button,
Card,
PlusIcon,
DatePicker,
Typography
} from '@noahspan/noahspan-components';
const Pilots: React.FC<unknown> = () => { const Pilots: React.FC<unknown> = () => {
const [isDrawerOpen, setIsDrawerOpen] = useState(false); const [isDrawerOpen, setIsDrawerOpen] = useState(false);
@@ -10,10 +16,9 @@ const Pilots: React.FC<unknown> = () => {
const [date, setDate] = useState(); const [date, setDate] = useState();
return ( return (
<div className="container mx-auto"> <Card>
<div className="px-6"> <div className="px-6">
<h1 role="heading">Pilots</h1> <Typography variant="h3">Pilots</Typography>
<PlusIcon size="2xl" />
<Button <Button
className="flex items-center gap-3" className="flex items-center gap-3"
variant="filled" variant="filled"
@@ -24,19 +29,12 @@ const Pilots: React.FC<unknown> = () => {
Add Pilot Add Pilot
</Button> </Button>
<DatePicker
handleDateChanged={(date) => console.log(date)}
inputProps={{
value: date
}}
/>
<PilotForm <PilotForm
isDrawerOpen={isDrawerOpen} isDrawerOpen={isDrawerOpen}
onOpenCloseDrawer={onOpenCloseDrawer} onOpenCloseDrawer={onOpenCloseDrawer}
/> />
</div> </div>
</div> </Card>
); );
}; };

18
package-lock.json generated
View File

@@ -30,6 +30,7 @@
"version": "0.0.1", "version": "0.0.1",
"license": "UNLICENSED", "license": "UNLICENSED",
"dependencies": { "dependencies": {
"@azure/data-tables": "^13.2.2",
"@azure/functions": "^1.0.3", "@azure/functions": "^1.0.3",
"@nestjs/azure-database": "^3.0.0", "@nestjs/azure-database": "^3.0.0",
"@nestjs/azure-func-http": "^0.10.0", "@nestjs/azure-func-http": "^0.10.0",
@@ -38,7 +39,7 @@
"@nestjs/core": "^10.0.0", "@nestjs/core": "^10.0.0",
"@nestjs/passport": "^10.0.3", "@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.0.0", "@nestjs/platform-express": "^10.0.0",
"@noahspan/noahspan-modules": "^0.3.5", "@noahspan/noahspan-modules": "^0.3.9",
"@schematics/angular": "^17.3.7", "@schematics/angular": "^17.3.7",
"dotenv": "^16.4.5", "dotenv": "^16.4.5",
"reflect-metadata": "0.1.13", "reflect-metadata": "0.1.13",
@@ -74,7 +75,7 @@
"@fortawesome/free-regular-svg-icons": "^6.5.2", "@fortawesome/free-regular-svg-icons": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^6.5.2", "@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/react-fontawesome": "^0.2.2", "@fortawesome/react-fontawesome": "^0.2.2",
"@noahspan/noahspan-components": "^0.5.9", "@noahspan/noahspan-components": "^0.6.2",
"axios": "^1.7.2", "axios": "^1.7.2",
"framer-motion": "^11.1.7", "framer-motion": "^11.1.7",
"react": "^18.2.0", "react": "^18.2.0",
@@ -3385,9 +3386,9 @@
"link": true "link": true
}, },
"node_modules/@noahspan/noahspan-components": { "node_modules/@noahspan/noahspan-components": {
"version": "0.5.9", "version": "0.6.2",
"resolved": "https://registry.npmjs.org/@noahspan/noahspan-components/-/noahspan-components-0.5.9.tgz", "resolved": "https://registry.npmjs.org/@noahspan/noahspan-components/-/noahspan-components-0.6.2.tgz",
"integrity": "sha512-McUwtMGvs13h0Jq1R2vxcRWh4c41xSwK54NbdKJhPAKfZ9GRjwWHCtxhrh43XG4SeI4GJGlnLpAw4+D6UTsmaQ==", "integrity": "sha512-ptdDx/HinOW5e9JnbVBGLotXV2W1gPYGu/qLId6ZEDLVVr26NBiMgg2bY6IP1pvKgeGz8xJYa7FQr3XZ5DgAsg==",
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.5.2", "@fortawesome/fontawesome-svg-core": "^6.5.2",
"@fortawesome/free-brands-svg-icons": "^6.5.2", "@fortawesome/free-brands-svg-icons": "^6.5.2",
@@ -3419,11 +3420,12 @@
} }
}, },
"node_modules/@noahspan/noahspan-modules": { "node_modules/@noahspan/noahspan-modules": {
"version": "0.3.5", "version": "0.3.9",
"resolved": "https://registry.npmjs.org/@noahspan/noahspan-modules/-/noahspan-modules-0.3.5.tgz", "resolved": "https://registry.npmjs.org/@noahspan/noahspan-modules/-/noahspan-modules-0.3.9.tgz",
"integrity": "sha512-VUCEtJcFTcrVyROMDpP8a90LFez5VPzo//0pUdHlpV7KqIDPRPpp7z/RXkXoUBYM0g06kS2CD5t3ZtzyIewBNg==", "integrity": "sha512-gRW+DiXQP+/0vHvEBi5yijQwwUnP+z5YxlSU7Q/bzm7YdUv5ecbZrz4is+BzH1S6Ctds9DeoQKtvb9xbAKwg8w==",
"dependencies": { "dependencies": {
"@azure/app-configuration": "^1.6.0", "@azure/app-configuration": "^1.6.0",
"@azure/data-tables": "^13.2.2",
"@azure/identity": "^4.2.0", "@azure/identity": "^4.2.0",
"@azure/msal-node": "^2.9.2", "@azure/msal-node": "^2.9.2",
"@microsoft/microsoft-graph-client": "^3.0.7", "@microsoft/microsoft-graph-client": "^3.0.7",