adding endorsements to pilot form

This commit is contained in:
2025-03-02 11:42:03 -06:00
parent 8f1dc5cb61
commit da5a76f252
18 changed files with 170 additions and 310 deletions

View File

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

View File

@@ -1,6 +1,4 @@
export class Endorsement { export class Endorsement {
partitionkey: string;
rowKey: string;
type: string; type: string;
issueDate: Date; issueDate: Date;
} }

View File

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

View File

@@ -1,6 +0,0 @@
export class Medical {
partitionKey: string;
rowKey: string;
certificateClass: string;
certificateExpiration: Date;
}

View File

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

View File

@@ -66,7 +66,8 @@ export class PilotController {
phone: pilotDto.phone, phone: pilotDto.phone,
medicalClass: pilotDto.medicalClass, medicalClass: pilotDto.medicalClass,
medicalExpiration: pilotDto.medicalExpiration, medicalExpiration: pilotDto.medicalExpiration,
certificates: JSON.stringify(pilotDto.certificates) certificates: JSON.stringify(pilotDto.certificates),
endorsements: JSON.stringify(pilotDto.endorsements)
} }
return await this.pilotService.create(pilot); return await this.pilotService.create(pilot);
@@ -99,7 +100,8 @@ export class PilotController {
phone: pilotDto.phone, phone: pilotDto.phone,
medicalClass: pilotDto.medicalClass, medicalClass: pilotDto.medicalClass,
medicalExpiration: pilotDto.medicalExpiration, medicalExpiration: pilotDto.medicalExpiration,
certificates: JSON.stringify(pilotDto.certificates) certificates: JSON.stringify(pilotDto.certificates),
endorsements: JSON.stringify(pilotDto.endorsements)
} }
return await this.pilotService.update(partitionKey, rowKey, pilot); return await this.pilotService.update(partitionKey, rowKey, pilot);

View File

@@ -1,4 +1,5 @@
import { Certificate } from "./certificate/certificate.entity"; import { Certificate } from "./certificate/certificate.entity";
import { Endorsement } from "./endorsement/endorsement.entity";
export class PilotDto { export class PilotDto {
partitionKey: string; partitionKey: string;
@@ -14,4 +15,5 @@ export class PilotDto {
medicalClass?: string; medicalClass?: string;
medicalExpiration?: string; medicalExpiration?: string;
certificates: Certificate; certificates: Certificate;
endorsements: Endorsement
} }

View File

@@ -14,4 +14,5 @@ export class Pilot {
@EntityString() medicalClass?: string; @EntityString() medicalClass?: string;
@EntityString() medicalExpiration: string; @EntityString() medicalExpiration: string;
@EntityString() certificates: string; @EntityString() certificates: string;
@EntityString() endorsements: string;
} }

View File

@@ -23,6 +23,7 @@ import { useIsAuthenticated } from '@azure/msal-react';
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 PilotFormMedical from '../pilotFormMedical/PilotFormMedical'; import PilotFormMedical from '../pilotFormMedical/PilotFormMedical';
const PilotForm: React.FC<IPilotFormProps> = ({ const PilotForm: React.FC<IPilotFormProps> = ({
@@ -55,7 +56,8 @@ const PilotForm: React.FC<IPilotFormProps> = ({
phone: '', phone: '',
medicalClass: '', medicalClass: '',
medicalExpiration: '', medicalExpiration: '',
certificates: [] certificates: [],
endorsements: []
}; };
const methods = useForm({ const methods = useForm({
defaultValues: defaultValues defaultValues: defaultValues
@@ -135,7 +137,6 @@ const PilotForm: React.FC<IPilotFormProps> = ({
onOpenClose(FormMode.CANCEL); onOpenClose(FormMode.CANCEL);
} catch (error) { } catch (error) {
const axiosError = error as AxiosError; const axiosError = error as AxiosError;
console.log(axiosError)
const responseData = axiosError.response?.data as any; const responseData = axiosError.response?.data as any;
console.log(responseData.message); console.log(responseData.message);
@@ -163,9 +164,10 @@ const PilotForm: React.FC<IPilotFormProps> = ({
config config
); );
const pilot = response.data; const pilot = response.data;
pilot.certificates = JSON.parse(pilot.certificates);
pilot.certificates = JSON.parse(pilot.certificates);
pilot.endorsements = JSON.parse(pilot.endorsements)
console.log(pilot)
setSelectedPerson({ setSelectedPerson({
userPrincipalName: pilot.id, userPrincipalName: pilot.id,
displayName: pilot.name displayName: pilot.name
@@ -381,7 +383,10 @@ const PilotForm: React.FC<IPilotFormProps> = ({
/> />
</Grid> </Grid>
<Grid size={12}> <Grid size={12}>
<PilotFormCertificates certificates={[]} isDisabled={isDisabled} /> <PilotFormCertificates isDisabled={isDisabled} />
</Grid>
<Grid size={12}>
<PilotFormEndorsements isDisabled={isDisabled} />
</Grid> </Grid>
<Grid display="flex" gap={2} justifyContent="right" size={12}> <Grid display="flex" gap={2} justifyContent="right" size={12}>
<Button <Button
@@ -412,43 +417,6 @@ const PilotForm: React.FC<IPilotFormProps> = ({
)} )}
</Grid> </Grid>
</Grid> </Grid>
{/* {pilotId && (
<>
<div className="col-span-1">
<Typography variant="h6">Last Review</Typography>
</div>
<div className="col-span-3">
<Controller
name="lastReview"
control={methods.control}
render={({ field }) => {
return (
<DatePicker
handleDateChanged={(date: string) => {
methods.setValue('lastReview', date);
}}
inputProps={{
value: field.value
}}
/>
);
}}
/>
</div>
</>
)} */}
{/* {pilotId && (
<>
<div className="col-span-4">
<Typography variant="h5">Endorsements</Typography>
<hr className="my-3" />
</div>
<PilotFormEndorsements endorsements={[]} />
</>
)} */}
</form> </form>
</FormProvider> </FormProvider>
</Drawer> </Drawer>

View File

@@ -1,5 +0,0 @@
export interface Certificate {
type: string;
number: string;
dateOfIssue: Date;
};

View File

@@ -13,7 +13,6 @@ import {
import { Controller, useFieldArray, useFormContext } from 'react-hook-form'; import { Controller, useFieldArray, useFormContext } from 'react-hook-form';
const PilotFormCertificates = ({ const PilotFormCertificates = ({
certificates,
isDisabled isDisabled
}: PilotFormCertificatesProps ) => { }: PilotFormCertificatesProps ) => {
const { const {
@@ -137,21 +136,23 @@ const PilotFormCertificates = ({
})} })}
</> </>
)} )}
<Grid display="flex" justifyContent="right" size={12}> {!isDisabled &&
<Button <Grid display="flex" justifyContent="right" size={12}>
onClick={() => { <Button
append({ onClick={() => {
type: '', append({
number: '', type: '',
dateOfIssue: null number: '',
}); dateOfIssue: null
}} });
startIcon={<Icon iconName={IconName.PLUS} />} }}
variant="contained" startIcon={<Icon iconName={IconName.PLUS} />}
> variant="contained"
Add Certificate >
</Button> Add Certificate
</Grid> </Button>
</Grid>
}
</Grid> </Grid>
); );
}; };

View File

@@ -1,6 +1,3 @@
import { Certificate } from './Certificate.interface';
export interface PilotFormCertificatesProps { export interface PilotFormCertificatesProps {
certificates: Certificate[];
isDisabled: boolean; isDisabled: boolean;
} }

View File

@@ -1,5 +0,0 @@
import { Endorsement } from './endorsement.type';
export interface IPilotFormEndorsements {
endorsements: Endorsement[];
}

View File

@@ -1,120 +1,135 @@
// import { IPilotFormEndorsements } from './IPilotFormEndorsements'; import { PilotFormEndorsementsProps } from './PilotFormEndorsementsProps.interface';
// import { import {
// Button, Button,
// DatePicker, DatePicker,
// Input, Grid,
// Option, Icon,
// PlusIcon, IconButton,
// Select, IconName,
// TrashIcon, Select,
// Typography Typography
// } from '@noahspan/noahspan-components'; } from '@noahspan/noahspan-components';
// import { Controller, useFieldArray, useFormContext } from 'react-hook-form'; import { Controller, useFieldArray, useFormContext } from 'react-hook-form';
// const PilotFormEndorsements: React.FC<IPilotFormEndorsements> = ({ const PilotFormEndorsements = ({
// endorsements isDisabled
// }: IPilotFormEndorsements) => { }: 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 (
// <> <Grid
// {fields.length > 0 && ( container
// <> spacing={2}
// <div className="col-span-1"> >
// <Typography variant="h6">Type</Typography> <Grid size={12}>
// </div> <Typography variant="h5">Endorsements</Typography>
// <div className="col-span-1"> </Grid>
// <Typography variant="h6">Date of Issue</Typography> {fields.length > 0 && (
// </div> <>
// <div className="col-span-1"></div> <Grid size={8}>
// <div className="col-span-1"></div> <Typography variant="h6">Type</Typography>
// </> </Grid>
// )} <Grid size={3}>
// {fields.map((field, index) => { <Typography variant="h6">Date of Issue</Typography>
// return ( </Grid>
// <> <Grid size={1}></Grid>
// <div className="col-span-1"> {fields.map((field, index) => {
// <Controller return (
// name={`endorsements.${index}.type`} <>
// control={control} <Grid size={8}>
// render={({ field }) => { <Controller
// return ( name={`endorsements.${index}.type`}
// <Select label="Type" {...field}> control={control}
// <Option key="complex" value="Complex"> render={({ field: { onChange, value } }) => {
// Complex return (
// </Option> <Select
// <Option key="highPerformance" value="High Performance"> disabled={isDisabled}
// High Performance fullWidth
// </Option> onChange={onChange}
// <Option key="highAltitude" value="High Altitude"> options={
// High Altitude [
// </Option> {
// <Option key="tailwheel" value="Tailwheel"> label: 'Complex',
// Tailwheel value: 'complex'
// </Option> },
// </Select> {
// ); label: 'High Performance',
// }} value: 'highPerfomance'
// /> },
// </div> {
// <div className="col-span-1"> label: 'High Altitude',
// <Controller value: 'highAltitude'
// name={`endorsements.${index}.dateOfIssue`} },
// control={control} {
// render={({ field }) => { label: 'Tailwheel',
// return ( value: 'tailwheel'
// <DatePicker }
// handleDateChanged={(date: string) => { ]
// setValue(`endorsements.${index}.dateOfIssue`, date); }
// }} value={value ? value : ''}
// inputProps={{ />
// value: field.value );
// }} }}
// /> />
// ); </Grid>
// }} <Grid size={3}>
// /> <Controller
// </div> name={`endorsements.${index}.dateOfIssue`}
// <div className="col-span-1"> control={control}
// <Button render={({ field: { onChange, value } }) => {
// className="flex items-center gap-3" return (
// onClick={() => remove(index)} <DatePicker
// variant="outlined" disabled={isDisabled}
// > onChange={onChange}
// <TrashIcon size="lg" /> value={value}
// Delete />
// </Button> );
// </div> }}
// </> />
// ); </Grid>
// })} <Grid size={1}>
// <div className="col-span-4"> <IconButton
// <Button disabled={isDisabled}
// className="flex items-center gap-3" onClick={() => remove(index)}
// onClick={() => { sx={{
// append({ marginTop: '-5px'
// type: '', }}
// number: '', >
// dateOfIssue: null <Icon iconName={IconName.TRASH} size="sm" />
// }); </IconButton>
// }} </Grid>
// variant="outlined" </>
// > );
// <PlusIcon size="lg" /> })}
// Add Endorsement </>
// </Button> )}
// </div> {!isDisabled &&
// </> <Grid display="flex" justifyContent="right" size={12}>
// ); <Button
// }; onClick={() => {
append({
type: '',
dateOfIssue: null
});
}}
startIcon={<Icon iconName={IconName.PLUS} />}
variant="contained"
>
Add Endorsement
</Button>
</Grid>
}
</Grid>
);
};
// export default PilotFormEndorsements; export default PilotFormEndorsements;

View File

@@ -0,0 +1,3 @@
export interface PilotFormEndorsementsProps {
isDisabled: boolean;
}

View File

@@ -1,5 +0,0 @@
export type Endorsement = {
type: string;
number: string;
dateOfIssue: Date;
};

View File

@@ -47,6 +47,7 @@ const PilotFormMedical = ({ isDisabled }: PilotFormMedicalProps) => {
} }
] ]
} }
value={value ? value : ''}
/> />
); );
}} }}

View File

@@ -36,7 +36,7 @@ const Pilots: React.FC<unknown> = () => {
`api/pilots`, `api/pilots`,
config config
); );
console.log(response.data)
if (response.data.length > 0) { if (response.data.length > 0) {
dispatch({ type: 'SET_PILOTS', payload: response.data }); dispatch({ type: 'SET_PILOTS', payload: response.data });