adding endorsements to pilot form #58

Merged
noahspannbauer merged 1 commits from feature/56-add-endorsements-to-pilot-form into main 2025-03-02 12:43:33 -05:00
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 {
partitionkey: string;
rowKey: string;
type: string;
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,
medicalClass: pilotDto.medicalClass,
medicalExpiration: pilotDto.medicalExpiration,
certificates: JSON.stringify(pilotDto.certificates)
certificates: JSON.stringify(pilotDto.certificates),
endorsements: JSON.stringify(pilotDto.endorsements)
}
return await this.pilotService.create(pilot);
@@ -99,7 +100,8 @@ export class PilotController {
phone: pilotDto.phone,
medicalClass: pilotDto.medicalClass,
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);

View File

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

View File

@@ -14,4 +14,5 @@ export class Pilot {
@EntityString() medicalClass?: string;
@EntityString() medicalExpiration: 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 { Person } from '@microsoft/microsoft-graph-types';
import PilotFormCertificates from '../pilotFormCertificates/PilotFormCertificates';
import PilotFormEndorsements from '../pilotFormEndorsements/PilotFormEndorsements';
import PilotFormMedical from '../pilotFormMedical/PilotFormMedical';
const PilotForm: React.FC<IPilotFormProps> = ({
@@ -55,7 +56,8 @@ const PilotForm: React.FC<IPilotFormProps> = ({
phone: '',
medicalClass: '',
medicalExpiration: '',
certificates: []
certificates: [],
endorsements: []
};
const methods = useForm({
defaultValues: defaultValues
@@ -135,7 +137,6 @@ const PilotForm: React.FC<IPilotFormProps> = ({
onOpenClose(FormMode.CANCEL);
} catch (error) {
const axiosError = error as AxiosError;
console.log(axiosError)
const responseData = axiosError.response?.data as any;
console.log(responseData.message);
@@ -165,7 +166,8 @@ const PilotForm: React.FC<IPilotFormProps> = ({
const pilot = response.data;
pilot.certificates = JSON.parse(pilot.certificates);
pilot.endorsements = JSON.parse(pilot.endorsements)
console.log(pilot)
setSelectedPerson({
userPrincipalName: pilot.id,
displayName: pilot.name
@@ -381,7 +383,10 @@ const PilotForm: React.FC<IPilotFormProps> = ({
/>
</Grid>
<Grid size={12}>
<PilotFormCertificates certificates={[]} isDisabled={isDisabled} />
<PilotFormCertificates isDisabled={isDisabled} />
</Grid>
<Grid size={12}>
<PilotFormEndorsements isDisabled={isDisabled} />
</Grid>
<Grid display="flex" gap={2} justifyContent="right" size={12}>
<Button
@@ -412,43 +417,6 @@ const PilotForm: React.FC<IPilotFormProps> = ({
)}
</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>
</FormProvider>
</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';
const PilotFormCertificates = ({
certificates,
isDisabled
}: PilotFormCertificatesProps ) => {
const {
@@ -137,6 +136,7 @@ const PilotFormCertificates = ({
})}
</>
)}
{!isDisabled &&
<Grid display="flex" justifyContent="right" size={12}>
<Button
onClick={() => {
@@ -152,6 +152,7 @@ const PilotFormCertificates = ({
Add Certificate
</Button>
</Grid>
}
</Grid>
);
};

View File

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