Feature/4 pilots add #20

Merged
noahspannbauer merged 64 commits from feature/4-pilots---add into main 2024-09-23 21:52:59 -04:00
9 changed files with 303 additions and 171 deletions
Showing only changes of commit 61c06d83a4 - Show all commits

View File

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

View File

@@ -88,9 +88,9 @@ const App: React.FC<unknown> = () => {
<>
<SiteNav handleSignIn={handleSignIn} handleSignOut={handleSignOut} />
<Routes>
{useFeatureFlag('flying-pilots')?.enabled && (
{/* {useFeatureFlag('flying-pilots')?.enabled && ( */}
<Route path="/" element={<Pilots />} />
)}
{/* )} */}
</Routes>
</>
);

View File

@@ -4,9 +4,15 @@ import {
Accordion,
AccordionBody,
AccordionHeader,
Input
ChevronDown,
ChevronUp,
DatePicker,
Input,
Option,
Select
} from '@noahspan/noahspan-components';
// import PilotFormCertificates from '../pilotFormCertificates/PilotFormCertificates';
import PilotFormCertificates from '../pilotFormCertificates/PilotFormCertificates';
import PilotFormEndorsements from '../pilotFormEndorsements/PilotFormEndorsements';
const PilotForm: React.FC<unknown> = () => {
const [open, setOpen] = useState<number>(0);
@@ -23,25 +29,28 @@ const PilotForm: React.FC<unknown> = () => {
return (
<FormProvider {...methods}>
<form className="m-10" onSubmit={handleSubmit(onSubmit)}>
<Accordion open={open === 1}>
<Accordion
open={open === 1}
icon={open === 1 ? <ChevronDown /> : <ChevronUp />}
>
<AccordionHeader onClick={() => handleOpen(1)}>Info</AccordionHeader>
<AccordionBody>
<div className="grid grid-cols-3 gap-4">
<div className="col-span-2">
<div className="col-span-3">
<Controller
name="firstName"
control={control}
render={({ field }) => (
<Input
className="w-full"
disabled={field.disabled}
label="First Name"
value={field.value}
variant="standard"
/>
)}
/>
</div>
<div className="col-span-2">
<div className="col-span-3">
<Controller
name="lastName"
control={control}
@@ -50,12 +59,11 @@ const PilotForm: React.FC<unknown> = () => {
disabled={field.disabled}
label="Last Name"
value={field.value}
variant="standard"
/>
)}
/>
</div>
<div className="col-span-2">
<div className="col-span-3">
<Controller
name="address"
control={control}
@@ -64,12 +72,11 @@ const PilotForm: React.FC<unknown> = () => {
disabled={field.disabled}
label="Address"
value={field.value}
variant="standard"
/>
)}
/>
</div>
<div className="col-span-2">
<div className="col-span-3">
<Controller
name="city"
control={control}
@@ -82,7 +89,7 @@ const PilotForm: React.FC<unknown> = () => {
)}
/>
</div>
<div className="col-span-2">
<div className="col-span-3">
<Controller
name="state"
control={control}
@@ -95,7 +102,7 @@ const PilotForm: React.FC<unknown> = () => {
)}
/>
</div>
<div className="col-span-2">
<div className="col-span-3">
<Controller
name="postalCode"
control={control}
@@ -111,58 +118,59 @@ const PilotForm: React.FC<unknown> = () => {
</div>
</AccordionBody>
</Accordion>
{/* <Accordion>
<AccordionItem title='Certificates'>
<Accordion
open={open === 2}
icon={open === 2 ? <ChevronDown /> : <ChevronUp />}
>
<AccordionHeader onClick={() => handleOpen(2)}>
Certificates
</AccordionHeader>
<AccordionBody>
<PilotFormCertificates certificates={[]} />
</AccordionItem>
</AccordionBody>
</Accordion>
<Accordion>
<AccordionItem title='Endorsements'>
</AccordionItem>
<Accordion
open={open === 3}
icon={open === 3 ? <ChevronDown /> : <ChevronUp />}
>
<AccordionHeader onClick={() => handleOpen(3)}>
Endorsements
</AccordionHeader>
<AccordionBody>
<PilotFormEndorsements endorsements={[]} />
</AccordionBody>
</Accordion>
<Accordion>
<AccordionItem title="Medical">
<div className="grid grid-cols-2 gap-4">
<div className="self-center">
<label>Class</label>
</div>
<div>
<Accordion
open={open === 4}
icon={open === 4 ? <ChevronDown /> : <ChevronUp />}
>
<AccordionHeader onClick={() => handleOpen(4)}>
Medical
</AccordionHeader>
<AccordionBody>
<div className="grid grid-cols-3 gap-4">
<Controller
name="medicalClass"
control={control}
render={({ field }) => (
<Select value={field.value}>
<Option value={first}>
First
</Option>
<Option>
Second
</Option>
<Option>
Third
</Option>
<Option>
Basic Med
</Option>
<Select label="Class" value={field.value}>
<Option>First</Option>
<Option>Second</Option>
<Option>Third</Option>
<Option>Basic Med</Option>
</Select>
)}
/>
</div>
<div className="self-center">
<label>Expires</label>
</div>
<div>
<div className="col-span-3">
<Controller
name="medicalExpiration"
control={control}
render={({ field }) => <DatePicker />}
/>
</div>
</div>
</AccordionItem>
</Accordion> */}
</AccordionBody>
</Accordion>
</form>
</FormProvider>
);

View File

@@ -1,104 +1,98 @@
// import { IPilotFormCertificates } from './IPilotFormCertificates';
import { IPilotFormCertificates } from './IPilotFormCertificates';
// import { Button, DatePicker, Input, Select, SelectItem } from '@nextui-org/react';
// import { Controller, useFieldArray, useFormContext } from 'react-hook-form'
import {
Button,
DatePicker,
Input,
Option,
Select
} from '@noahspan/noahspan-components';
import { Controller, useFieldArray, useFormContext } from 'react-hook-form';
// const PilotFormCertificates: React.FC<IPilotFormCertificates> = ({ certificates }: IPilotFormCertificates) => {
// const { control, formState: { errors } } = useFormContext();
const PilotFormCertificates: React.FC<IPilotFormCertificates> = ({
certificates
}: IPilotFormCertificates) => {
const {
control,
formState: { errors }
} = useFormContext();
// const { fields, append, remove } = useFieldArray({
// name: 'certificates',
// control
// })
const { fields, append, remove } = useFieldArray({
name: 'certificates',
control
});
// return (
// <div className='grid grid-cols-4 gap-4'>
// <div className='self-center'>
// <label>Type</label>
// </div>
// <div className='self-center'>
// <label>Number</label>
// </div>
// <div className='self-center '>
// <label>Date of Issue</label>
// </div>
// <div className='self-center'>
return (
<div className="grid grid-cols-4 gap-4">
{fields.map((field, index) => {
return (
<>
{/* // <div key={field.id}> */}
<div>
<Controller
name={`certificates.${index}.type`}
control={control}
render={({ field }) => {
return (
<Select label="Type" {...field}>
<Option key="student" value="Student">
Student
</Option>
<Option key="private" value="Private">
Private
</Option>
<Option key="instrument" value="Instrument">
Instrument
</Option>
<Option key="recreational" value="Recreational">
Recreational
</Option>
<Option key="sport" value="Sport">
Sport
</Option>
</Select>
);
}}
/>
</div>
<div>
<Controller
name={`certificates.${index}.number`}
control={control}
render={({ field }) => {
return <Input label="Number" {...field} />;
}}
/>
</div>
<div>
<Controller
name={`certificates.${index}.dateOfIssue`}
control={control}
render={({ field }) => {
return <DatePicker />;
}}
/>
</div>
<div>
<Button onClick={() => remove(index)}>Remove</Button>
</div>
{/* </div> */}
</>
);
})}
<Button
onClick={() => {
append({
type: '',
number: '',
dateOfIssue: null
});
}}
>
Add
</Button>
</div>
);
};
// </div>
// {fields.map((field, index) => {
// return (
// <>
// {/* // <div key={field.id}> */}
// <div>
// <Controller
// name={`certificates.${index}.type`}
// control={control}
// render={({ field }) => {
// console.log(field)
// return (
// <Select {...field}>
// <SelectItem key="student" value="Student">
// Student
// </SelectItem>
// <SelectItem key="private" value="Private">
// Private
// </SelectItem>
// <SelectItem key="instrument" value="Instrument">
// Instrument
// </SelectItem>
// <SelectItem key="recreational" value="Recreational">
// Recreational
// </SelectItem>
// <SelectItem key="sport" value="Sport">
// Sport
// </SelectItem>
// </Select>
// )
// }}
// />
// </div>
// <div>
// <Controller
// name={`certificates.${index}.number`}
// control={control}
// render={({ field }) => {
// return (
// <Input {...field} />
// )
// }}
// />
// </div>
// <div>
// <Controller
// name={`certificates.${index}.dateOfIssue`}
// control={control}
// render={({ field }) => {
// return (
// <DatePicker {...field} />
// )
// }}
// />
// </div>
// <div>
// <Button onClick={() => remove(index)}>Remove</Button>
// </div>
// {/* </div> */}
// </>
// )
// })}
// <Button
// onClick={() => {
// append({
// type: '',
// number: '',
// dateOfIssue: null
// });
// }}
// >
// Add
// </Button>
// </div>
// )
// }
// export default PilotFormCertificates;
export default PilotFormCertificates;

View File

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

View File

@@ -0,0 +1,95 @@
import { IPilotFormEndorsements } from './IPilotFormEndorsements';
// import { Button, DatePicker, Input, Select, SelectItem } from '@nextui-org/react';
import {
Button,
DatePicker,
Input,
Option,
Select
} from '@noahspan/noahspan-components';
import { Controller, useFieldArray, useFormContext } from 'react-hook-form';
const PilotFormEndorsements: React.FC<IPilotFormEndorsements> = ({
endorsements
}: IPilotFormEndorsements) => {
const {
control,
formState: { errors }
} = useFormContext();
const { fields, append, remove } = useFieldArray({
name: 'endorsements',
control
});
return (
<div className="grid grid-cols-4 gap-4">
{fields.map((field, index) => {
return (
<>
{/* // <div key={field.id}> */}
<div>
<Controller
name={`endorsements.${index}.type`}
control={control}
render={({ field }) => {
return (
<Select label="Type" {...field}>
<Option key="student" value="Student">
Complex
</Option>
<Option key="private" value="Private">
High Performance
</Option>
<Option key="instrument" value="Instrument">
High Altitude
</Option>
<Option key="recreational" value="Recreational">
Tailwheel
</Option>
</Select>
);
}}
/>
</div>
<div>
<Controller
name={`endorsements.${index}.number`}
control={control}
render={({ field }) => {
return <Input label="Number" {...field} />;
}}
/>
</div>
<div>
<Controller
name={`endorsements.${index}.dateOfIssue`}
control={control}
render={({ field }) => {
return <DatePicker />;
}}
/>
</div>
<div>
<Button onClick={() => remove(index)}>Remove</Button>
</div>
{/* </div> */}
</>
);
})}
<Button
onClick={() => {
append({
type: '',
number: '',
dateOfIssue: null
});
}}
>
Add
</Button>
</div>
);
};
export default PilotFormEndorsements;

View File

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

View File

@@ -1,6 +1,6 @@
import { useState } from 'react';
import PilotForm from '../pilotForm/PilotForm';
import { Button, Drawer } from '@noahspan/noahspan-components';
import { Button, DatePicker, Drawer } from '@noahspan/noahspan-components';
const Pilots: React.FC<unknown> = () => {
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
@@ -20,6 +20,7 @@ const Pilots: React.FC<unknown> = () => {
>
New
</Button>
<DatePicker />
<Drawer
open={isDrawerOpen}
placement="right"
@@ -27,6 +28,7 @@ const Pilots: React.FC<unknown> = () => {
data-testid="pilot-drawer"
>
<PilotForm />
{/* <DrawerContent>
<DrawerHeader>
<h2>Add Pilot</h2>

35
package-lock.json generated
View File

@@ -77,7 +77,7 @@
"@fortawesome/free-regular-svg-icons": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/react-fontawesome": "^0.2.2",
"@noahspan/noahspan-components": "^0.3.1",
"@noahspan/noahspan-components": "^0.3.5",
"axios": "^1.7.2",
"framer-motion": "^11.1.7",
"react": "^18.2.0",
@@ -3503,9 +3503,9 @@
"link": true
},
"node_modules/@noahspan/noahspan-components": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/@noahspan/noahspan-components/-/noahspan-components-0.3.1.tgz",
"integrity": "sha512-KTYndPCABLFPhhhRuZJrl8O25ex4q671lDpiEZ7sOSSXVi85tPcBjsBWo6KiC2+skIwBC58Iuek9Y8Mi1z/QYw==",
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@noahspan/noahspan-components/-/noahspan-components-0.3.5.tgz",
"integrity": "sha512-7sRZO7rs5/WhCmio7ex0z9iAB6/xH+zomAJjGgUfs5IAVxKIOVy1euSe9d3Re9tg9BS3pLecXkO0kNKsJaGuUQ==",
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.5.2",
"@fortawesome/free-brands-svg-icons": "^6.5.2",
@@ -3514,7 +3514,9 @@
"@fortawesome/react-fontawesome": "^0.2.0",
"@material-tailwind/react": "^2.1.9",
"@tanstack/react-table": "^8.17.3",
"framer-motion": "^11.1.9"
"date-fns": "^3.6.0",
"framer-motion": "^11.1.9",
"react-day-picker": "^8.10.1"
},
"engines": {
"node": ">=18.0.0"
@@ -3524,6 +3526,15 @@
"react-dom": "^18.2.0"
}
},
"node_modules/@noahspan/noahspan-components/node_modules/date-fns": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/kossnocorp"
}
},
"node_modules/@noahspan/noahspan-modules": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/@noahspan/noahspan-modules/-/noahspan-modules-0.3.4.tgz",
@@ -6041,7 +6052,6 @@
"version": "2.30.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.21.0"
},
@@ -11025,6 +11035,19 @@
"node": ">=0.10.0"
}
},
"node_modules/react-day-picker": {
"version": "8.10.1",
"resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz",
"integrity": "sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==",
"funding": {
"type": "individual",
"url": "https://github.com/sponsors/gpbl"
},
"peerDependencies": {
"date-fns": "^2.28.0 || ^3.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/react-dom": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",