Skip to content

Commit

Permalink
'Remove tsdf' button (#675)
Browse files Browse the repository at this point in the history
* add remove TSDF from manifest button

* put all TSDF related section into new component

* useReadOnly hook used to read/write whether a manifest is readOnly or not

* useUserSiteIds hook for retrieving a list of the EPA site IDs the user has access to in their profile. The array contains a list of objects containing the site IDs and the site permissions

* implement useReadOnly custom hook in remaining components and update test suite to use new custom useReadOnly hook
  • Loading branch information
dpgraham4401 authored Jan 6, 2024
1 parent fc2ae37 commit efc377a
Show file tree
Hide file tree
Showing 29 changed files with 365 additions and 154 deletions.
4 changes: 3 additions & 1 deletion client/src/components/Manifest/Actions/ManifestCancelBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { ManifestContext } from 'components/Manifest/ManifestForm';
import { Manifest } from 'components/Manifest/manifestSchema';
import { HtButton } from 'components/UI';
import { useReadOnly } from 'hooks/manifest';
import React, { useContext } from 'react';
import { useFormContext } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';

export function ManifestCancelBtn() {
const form = useFormContext<Manifest>();
const navigate = useNavigate();
const { readOnly, trackingNumber, viewingAsSiteId } = useContext(ManifestContext);
const { trackingNumber, viewingAsSiteId } = useContext(ManifestContext);
const [readOnly] = useReadOnly();
if (readOnly) return <></>;
return (
<HtButton
Expand Down
4 changes: 3 additions & 1 deletion client/src/components/Manifest/Actions/ManifestEditBtn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { faPenToSquare } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { ManifestContext } from 'components/Manifest/ManifestForm';
import { HtButton } from 'components/UI';
import { useReadOnly } from 'hooks/manifest';
import React, { useContext } from 'react';
import { ButtonProps } from 'react-bootstrap';
import { useNavigate } from 'react-router-dom';
Expand All @@ -10,7 +11,8 @@ interface ManifestEditBtnProps extends ButtonProps {}

export function ManifestEditBtn({ children, ...props }: ManifestEditBtnProps) {
const navigate = useNavigate();
const { readOnly, trackingNumber, viewingAsSiteId } = useContext(ManifestContext);
const { trackingNumber, viewingAsSiteId } = useContext(ManifestContext);
const [readOnly] = useReadOnly();
if (!readOnly) return <></>;
return (
<HtButton
Expand Down
4 changes: 3 additions & 1 deletion client/src/components/Manifest/Actions/ManifestFABs.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import '@testing-library/jest-dom';
import { ManifestFABs } from 'components/Manifest/Actions/ManifestFABs';
import { ManifestContext } from 'components/Manifest/ManifestForm';
import { ManifestStatus } from 'components/Manifest/manifestSchema';
import { useReadOnly } from 'hooks/manifest';
import React from 'react';
import { cleanup, renderWithProviders, screen } from 'test-utils';
import { afterEach, describe, expect, test } from 'vitest';
Expand All @@ -15,9 +16,10 @@ const TestComponent = ({
signAble: boolean;
readOnly: boolean;
}) => {
useReadOnly(readOnly);
return (
// @ts-ignore
<ManifestContext.Provider value={{ status, signAble, readOnly }}>
<ManifestContext.Provider value={{ status, signAble }}>
<ManifestFABs onSignClick={() => undefined} />
</ManifestContext.Provider>
);
Expand Down
4 changes: 3 additions & 1 deletion client/src/components/Manifest/Actions/ManifestFABs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ManifestSaveBtn } from 'components/Manifest/Actions/ManifestSaveBtn';
import { ManifestContext } from 'components/Manifest/ManifestForm';
import { QuickSignBtn } from 'components/Manifest/QuickerSign';
import { FloatingActionBtn } from 'components/UI';
import { useReadOnly } from 'hooks/manifest';
import React, { ReactElement, useContext } from 'react';
import { manifest } from 'services';

Expand All @@ -11,7 +12,8 @@ interface ManifestActionBtnsProps {
}

export function ManifestFABs({ onSignClick }: ManifestActionBtnsProps) {
const { nextSigningSite, readOnly, signAble } = useContext(ManifestContext);
const { nextSigningSite, signAble } = useContext(ManifestContext);
const [readOnly] = useReadOnly();
const rcraSiteType = manifest.siteTypeToRcraSiteType(nextSigningSite?.siteType);
let component: ReactElement | undefined = undefined;
if (!readOnly) {
Expand Down
6 changes: 3 additions & 3 deletions client/src/components/Manifest/Actions/ManifestSaveBtn.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { faFloppyDisk } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { ManifestContext } from 'components/Manifest/ManifestForm';
import { HtButton } from 'components/UI';
import React, { useContext } from 'react';
import { useReadOnly } from 'hooks/manifest';
import React from 'react';
import { ButtonProps } from 'react-bootstrap';

interface ManifestSaveBtnProps extends ButtonProps {}

export function ManifestSaveBtn({ children, ...props }: ManifestSaveBtnProps) {
const { readOnly } = useContext(ManifestContext);
const [readOnly] = useReadOnly();
if (readOnly) return <></>;
return (
<HtButton variant="success" type="submit" name="save" {...props}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,14 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Manifest } from 'components/Manifest';
import { WasteLine } from 'components/Manifest/WasteLine';
import { HtForm } from 'components/UI';
import { useReadOnly } from 'hooks/manifest';
import React from 'react';
import { Button, Col, Form, Row } from 'react-bootstrap';
import { useFieldArray, useFormContext } from 'react-hook-form';

interface AdditionalFormProps {
readOnly?: boolean;
}

// ToDo: this is POC source, clean up work appreciated
// see this example from react-hook-form
// https://codesandbox.io/s/6j1760jkjk
export function AdditionalInfoForm({ readOnly }: AdditionalFormProps) {
export function AdditionalInfoForm() {
const { register, control } = useFormContext<Manifest | WasteLine>();
const [readOnly] = useReadOnly();
const { fields, append, remove } = useFieldArray<Manifest | WasteLine, 'additionalInfo.comments'>(
{
control,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ afterEach(() => {

describe('AdditionalInfoForm', () => {
test('renders with basic information inputs', () => {
renderWithProviders(<AdditionalInfoForm readOnly={false} />);
renderWithProviders(<AdditionalInfoForm />);
expect(screen.getByLabelText(/Special Handling Instructions/i)).toBeInTheDocument();
});
test('initially has zero comments and Adds on click', async () => {
renderWithProviders(<AdditionalInfoForm readOnly={false} />);
renderWithProviders(<AdditionalInfoForm />, {
preloadedState: { manifest: { readOnly: false } },
});
expect(screen.queryAllByTitle(/Remove/i, { exact: false }).length).toBe(0);
const numberButtonClick = 3;
for (let i = 0; i < numberButtonClick; i++) {
Expand Down
5 changes: 3 additions & 2 deletions client/src/components/Manifest/Contact/ContactForm.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { Manifest } from 'components/Manifest';
import { PhoneForm } from 'components/Manifest/Contact/PhoneForm';
import { HtForm } from 'components/UI';
import { useReadOnly } from 'hooks/manifest';
import React from 'react';
import { Col, Form, Row } from 'react-bootstrap';
import { useFormContext } from 'react-hook-form';

interface ContactFormProps {
handlerType: 'generator' | 'designatedFacility';
readOnly?: boolean;
}

export function ContactForm({ handlerType, readOnly }: ContactFormProps) {
export function ContactForm({ handlerType }: ContactFormProps) {
const [readOnly] = useReadOnly();
const namePrefix = `${handlerType}.contact`;
const { register } = useFormContext<Manifest>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ afterEach(() => {

describe('Manifest General Info Form', () => {
test('renders', () => {
renderWithProviders(<GeneralInfoForm isDraft={true} readOnly={false} />);
renderWithProviders(<GeneralInfoForm isDraft={true} />);
});
test('is editable if not readOnly', () => {
renderWithProviders(<GeneralInfoForm isDraft={true} readOnly={false} />);
renderWithProviders(<GeneralInfoForm isDraft={true} />, {
preloadedState: { manifest: { readOnly: false } },
});
expect(screen.getByLabelText(/Potential Ship Date/i)).toBeEnabled();
});
});
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { ManifestStatusSelect } from 'components/Manifest/GeneralInfo/ManifestStatusSelect';
import { ManifestTypeSelect } from 'components/Manifest/GeneralInfo/ManifestTypeSelect';
import { Manifest, SubmissionType } from 'components/Manifest/manifestSchema';
import { HtForm, InfoIconTooltip } from 'components/UI';
import { useReadOnly } from 'hooks/manifest';
import React from 'react';
import { Col, Form, Row } from 'react-bootstrap';
import { useFormContext } from 'react-hook-form';
import { ManifestTypeSelect } from 'components/Manifest/GeneralInfo/ManifestTypeSelect';

interface GeneralInfoFormProps {
manifestData?: Partial<Manifest>;
Expand All @@ -19,7 +20,8 @@ const submissionTypeOptions: Array<{ value: SubmissionType; label: string }> = [
{ value: 'Image', label: 'Image Only' },
];

export function GeneralInfoForm({ manifestData, readOnly, isDraft }: GeneralInfoFormProps) {
export function GeneralInfoForm({ manifestData, isDraft }: GeneralInfoFormProps) {
const [readOnly] = useReadOnly();
const manifestForm = useFormContext<Manifest>();
const { errors } = manifestForm.formState;
return (
Expand Down
10 changes: 3 additions & 7 deletions client/src/components/Manifest/Handler/GeneratorForm.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
import { Manifest } from 'components/Manifest';
import { AddressForm } from 'components/Manifest/Address';
import { HtForm } from 'components/UI';
import { useReadOnly } from 'hooks/manifest';
import { ReactElement, useEffect, useState } from 'react';
import { Col, Form, Row } from 'react-bootstrap';
import { useFormContext } from 'react-hook-form';

interface GeneratorFormProps {
readOnly?: boolean;
}

/**
* A form for the generator section of a manifest.
* Currently, we only support using for the generator since it's the only handler type that
* can be manually entered for an electronic/hybrid manifest.
* @param readOnly
* @constructor
*/
export function GeneratorForm({ readOnly }: GeneratorFormProps): ReactElement {
export function GeneratorForm(): ReactElement {
const [mailCheck, setMailCheck] = useState(false);
const {
register,
Expand All @@ -25,8 +21,8 @@ export function GeneratorForm({ readOnly }: GeneratorFormProps): ReactElement {
watch,
formState: { errors },
} = useFormContext<Manifest>();
const [readOnly] = useReadOnly();

// If
useEffect(() => {
const siteAddress = getValues(`generator.siteAddress`);
if (!mailCheck) {
Expand Down
78 changes: 78 additions & 0 deletions client/src/components/Manifest/Handler/TsdfSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { ErrorMessage } from '@hookform/error-message';
import { Handler, Manifest } from 'components/Manifest/manifestSchema';
import { QuickSignBtn } from 'components/Manifest/QuickerSign';
import { RcraSiteDetails } from 'components/RcraSite';
import { HtButton } from 'components/UI';
import { useReadOnly } from 'hooks/manifest';
import React from 'react';
import { Alert, Col } from 'react-bootstrap';
import { useFormContext } from 'react-hook-form';

interface TsdfSectionProps {
tsdf?: Handler;
setupSign: () => void;
signAble: boolean;
toggleTsdfFormShow: () => void;
}

export function TsdfSection({ tsdf, signAble, setupSign, toggleTsdfFormShow }: TsdfSectionProps) {
const {
formState: { errors },
...manifestForm
} = useFormContext<Manifest>();
const [readOnly] = useReadOnly();

return (
<>
{tsdf ? (
<>
<RcraSiteDetails handler={tsdf} />
<div className="d-flex justify-content-between">
{/* Button to bring up the Quicker Sign modal*/}
<Col className="text-end">
<QuickSignBtn
siteType={'Tsdf'}
mtnHandler={tsdf}
onClick={setupSign}
disabled={tsdf.signed || !signAble}
/>
</Col>
</div>
</>
) : (
<></>
)}

{tsdf && !readOnly && (
<HtButton
onClick={() => {
manifestForm.setValue('designatedFacility', undefined);
}}
children={'Remove TSDF'}
variant="outline-danger"
horizontalAlign
/>
)}
{!tsdf && (
<HtButton
onClick={toggleTsdfFormShow}
children={'Add TSDF'}
variant="outline-primary"
horizontalAlign
/>
)}
<ErrorMessage
errors={errors}
name={'designatedFacility'}
render={({ message }) => {
if (!message) return null;
return (
<Alert variant="danger" className="text-center m-3">
{message}
</Alert>
);
}}
/>
</>
);
}
Loading

0 comments on commit efc377a

Please sign in to comment.