Skip to content

Commit

Permalink
feat(webform): new ABP11 form and updated Upload component (#360)
Browse files Browse the repository at this point in the history
* fix: change Upload to follow other form Input management standard

* feat: add Upload to slots

- also remove unused import

* feat: add new abp form

* fix: verbiage update for abp

* fix: set initializer for upload

* fix: allow ref pass in to be used at some point

* spell check

* fix: wf location and file upload changes

---------

Co-authored-by: Benjamin Paige <[email protected]>
  • Loading branch information
daniel-belcher and benjaminpaige authored Feb 21, 2024
1 parent 6233cf7 commit 7547805
Show file tree
Hide file tree
Showing 18 changed files with 157 additions and 125 deletions.
4 changes: 4 additions & 0 deletions src/packages/shared-types/forms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ export type RHFComponentMap = {
Checkbox: {
options: RHFOption[];
};
Upload: {
maxFiles?: number;
maxSize?: number;
};
FieldArray: {
appendText?: string;
};
Expand Down
1 change: 1 addition & 0 deletions src/services/api/webforms/ABP11/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./v202401";
40 changes: 40 additions & 0 deletions src/services/api/webforms/ABP11/v202401.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { FormSchema } from "shared-types";

export const v202401: FormSchema = {
header: "ABP 11: Payment methodology",
sections: [
{
title: "Alternative Benefit Plans - Payment methodologies",
form: [
{
slots: [
{
rhf: "Checkbox",
name: "economy_and_efficiency_of_plans",
rules: { required: "* Required" },
props: {
options: [
{
label:
"The state or territory provides assurance that, for each benefit provided under an Alternative Benefit Plan that is not provided through managed care, it will use the payment methodology in its approved state plan or hereby submits state plan amendment Attachment 4.19a, 4.19b, or 4.19d, as appropriate, describing the payment methodology for the benefit.",
value: "assures_alternative_benefit_plan_in_accordance",
},
],
},
},
{
rhf: "Upload",
name: "state_plan_attchmnt_alt_payment_method",
label: "State plan amendment attachment",
labelStyling: "font-bold",
description:
"Only required if not using the payment methodology in the approved state plan",
descriptionAbove: true,
props: { maxFiles: 3 },
},
],
},
],
},
],
};
4 changes: 4 additions & 0 deletions src/services/api/webforms/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as ABP1 from "./ABP1";
import * as ABP10 from "./ABP10";
import * as ABP11 from "./ABP11";
import * as ABP3 from "./ABP3";
import * as ABP3_1 from "./ABP3_1";
import { FormSchema } from "shared-types";
Expand All @@ -18,4 +19,7 @@ export const webformVersions: Record<string, Record<string, FormSchema>> = {
ABP10: {
v202401: ABP10.v202401,
},
ABP11: {
v202401: ABP11.v202401,
},
};
149 changes: 76 additions & 73 deletions src/services/ui/src/components/Inputs/upload.tsx
Original file line number Diff line number Diff line change
@@ -1,90 +1,93 @@
import { cn } from "@/lib";
import { useCallback, useState } from "react";
import { useCallback, useState, forwardRef } from "react";
import { useDropzone, FileRejection, Accept } from "react-dropzone";
import * as I from "@/components/Inputs";
import { X } from "lucide-react";
import { FILE_TYPES } from "shared-types/uploads";

type UploadProps = {
maxFiles?: number;
files: File[];
setFiles: (files: File[]) => void;
value?: File[];
onChange: (files: File[]) => void;
setError?: (e: string) => void;
};

export const Upload = ({ maxFiles, files, setFiles }: UploadProps) => {
const [errorMessage, setErrorMessage] = useState<string | null>(null);
export const Upload = forwardRef<HTMLInputElement, UploadProps>(
({ maxFiles, value = [], onChange, setError }, _ref) => {
const [errorMessage, setErrorMessage] = useState<string | null>(null);

const onDrop = useCallback(
(acceptedFiles: File[], fileRejections: FileRejection[]) => {
if (fileRejections.length > 0) {
setErrorMessage(
"Selected file(s) is too large or of a disallowed file type."
);
} else {
setErrorMessage(null);
setFiles([...files, ...acceptedFiles]);
}
},
[files]
);
const onDrop = useCallback(
(acceptedFiles: File[], fileRejections: FileRejection[]) => {
if (fileRejections.length > 0) {
const errormsg =
"Selected file(s) is too large or of a disallowed file type.";
setError ? setError(errormsg) : setErrorMessage(errormsg);
} else {
setErrorMessage(null);
onChange([...value, ...acceptedFiles]);
}
},
[value]
);

const accept: Accept = {};
FILE_TYPES.map((type) =>
accept[type.mime]
? accept[type.mime].push(type.extension)
: (accept[type.mime] = [type.extension])
);
const accept: Accept = {};
FILE_TYPES.map((type) =>
accept[type.mime]
? accept[type.mime].push(type.extension)
: (accept[type.mime] = [type.extension])
);

const { getRootProps, getInputProps, isDragActive } = useDropzone({
onDrop,
accept,
maxFiles,
maxSize: 80 * 1024 * 1024, // 80MB,
});
const { getRootProps, getInputProps, isDragActive } = useDropzone({
onDrop,
accept,
maxFiles,
maxSize: 80 * 1024 * 1024, // 80MB,
});

return (
<>
<div className="my-2 flex gap-2">
{files.map((file) => (
// <div key={file.name} className="my-2 flex gap-2">
<div
className="flex border-2 rounded-md py-1 pl-2.5 pr-1 border-sky-500 items-center"
key={file.name}
>
<span className="text-sky-700">{file.name}</span>
<I.Button
onClick={(e) => {
e.preventDefault();
setFiles(files.filter((a) => a.name !== file.name));
}}
variant="ghost"
className="p-0 h-0"
return (
<>
<div className="my-2 flex gap-2">
{value?.map((file) => (
// <div key={file.name} className="my-2 flex gap-2">
<div
className="flex border-2 rounded-md py-1 pl-2.5 pr-1 border-sky-500 items-center"
key={file.name}
>
<X className="ml-2 text-sky-700 w-5" />
</I.Button>
{/* </div> */}
</div>
))}
</div>
{errorMessage && <span className="text-red-500">{errorMessage}</span>}
<div
{...getRootProps()}
className={cn(
"w-full flex items-center justify-center border border-dashed py-6 rounded-sm",
isDragActive && "border-blue-700"
)}
>
<p>
Drag file here or{" "}
<span className="text-sky-700 underline hover:cursor-pointer">
choose from folder
</span>
</p>
<input {...getInputProps()} />
{/* {isDragActive && <p>Drag is Active</p>} */}
</div>
</>
);
};
<span className="text-sky-700">{file.name}</span>
<I.Button
onClick={(e) => {
e.preventDefault();
onChange(value?.filter((a) => a.name !== file.name));
}}
variant="ghost"
className="p-0 h-0"
>
<X className="ml-2 text-sky-700 w-5" />
</I.Button>
{/* </div> */}
</div>
))}
</div>
{errorMessage && <span className="text-red-500">{errorMessage}</span>}
<div
{...getRootProps()}
className={cn(
"w-full flex items-center justify-center border border-dashed py-6 rounded-sm",
isDragActive && "border-blue-700"
)}
>
<p>
Drag file here or{" "}
<span className="text-sky-700 underline hover:cursor-pointer">
choose from folder
</span>
</p>
<input {...getInputProps()} />
{/* {isDragActive && <p>Drag is Active</p>} */}
</div>
</>
);
}
);

Upload.displayName = "Upload";
1 change: 0 additions & 1 deletion src/services/ui/src/components/RHF/Document.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Control, FieldValues } from "react-hook-form";

import { FormLabel } from "../Inputs";
import { RHFSection } from "./Section";
import { FormSchema } from "shared-types";

Expand Down
8 changes: 8 additions & 0 deletions src/services/ui/src/components/RHF/Slot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
Calendar,
FormField,
Checkbox,
Upload,
} from "../Inputs";
import { RHFFormGroup } from "./FormGroup";
import { CalendarIcon } from "lucide-react";
Expand Down Expand Up @@ -295,6 +296,13 @@ export const RHFSlot = <
</Popover>
);
})()}
{/* ----------------------------------------------------------------------------- */}
{rhf === "Upload" &&
(() => {
const hops = props as RHFComponentMap["Upload"];

return <Upload {...field} {...hops} />;
})()}

{/* ----------------------------------------------------------------------------- */}
{rhf === "FieldArray" && (
Expand Down
3 changes: 3 additions & 0 deletions src/services/ui/src/components/RHF/utils/initializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ export const slotInitializer = (ACC: GL, SLOT: T.RHFSlotProps): GL => {
case "FieldGroup":
ACC[SLOT.name] = [SLOT.fields?.reduce(fieldInitializer, {})];
break;
case "Upload":
ACC[SLOT.name] = [];
break;
case "Input":
case "Select":
case "Textarea":
Expand Down
6 changes: 6 additions & 0 deletions src/services/ui/src/components/Webform/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ export const Webforms = () => {
>
ABP 10
</Link>
<Link
path="/webform/:id/:version"
params={{ id: "abp11", version: 202401 }}
>
ABP 11
</Link>
<Link path="/guides/abp">Implementation Guide</Link>
</div>
</section>
Expand Down
2 changes: 1 addition & 1 deletion src/services/ui/src/pages/actions/renderSlots.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const SlotAttachments = <
return (
<FormItem {...props}>
<FormLabel>{label}</FormLabel>
<Upload files={field?.value ?? []} setFiles={field.onChange} />
<Upload {...field} />
{message}
</FormItem>
);
Expand Down
5 changes: 1 addition & 4 deletions src/services/ui/src/pages/form/chip-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,7 @@ export const ChipSpaFormPage = () => {
At least one attachment is required
</Inputs.FormDescription>
)}
<Inputs.Upload
files={field?.value ?? []}
setFiles={field.onChange}
/>
<Inputs.Upload {...field} />
<Inputs.FormMessage />
</Inputs.FormItem>
)}
Expand Down
5 changes: 1 addition & 4 deletions src/services/ui/src/pages/form/medicaid-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,7 @@ export const MedicaidSpaFormPage = () => {
: ""}
</Inputs.FormDescription>
}
<Inputs.Upload
files={field?.value ?? []}
setFiles={field.onChange}
/>
<Inputs.Upload {...field} />
<Inputs.FormMessage />
</Inputs.FormItem>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,7 @@ export const Capitated1915BWaiverAmendmentPage = () => {
<Inputs.FormLabel className="font-semibold">
Waiver Authority
</Inputs.FormLabel>
<span className="text-lg font-thin">
1915(b)
</span>
<span className="text-lg font-thin">1915(b)</span>
</div>
<Inputs.FormField
control={form.control}
Expand Down Expand Up @@ -233,10 +231,7 @@ export const Capitated1915BWaiverAmendmentPage = () => {
{label}
{required ? <Inputs.RequiredIndicator /> : null}
</Inputs.FormLabel>
<Inputs.Upload
files={field?.value ?? []}
setFiles={field.onChange}
/>
<Inputs.Upload {...field} />
<Inputs.FormMessage />
</Inputs.FormItem>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,7 @@ export const Capitated1915BWaiverInitialPage = () => {
<Inputs.FormLabel className="font-semibold">
Waiver Authority
</Inputs.FormLabel>
<span className="text-lg font-thin">
1915(b)
</span>
<span className="text-lg font-thin">1915(b)</span>
</div>
<Inputs.FormField
control={form.control}
Expand Down Expand Up @@ -204,10 +202,7 @@ export const Capitated1915BWaiverInitialPage = () => {
{label}
{required ? <Inputs.RequiredIndicator /> : null}
</Inputs.FormLabel>
<Inputs.Upload
files={field?.value ?? []}
setFiles={field.onChange}
/>
<Inputs.Upload {...field} />
<Inputs.FormMessage />
</Inputs.FormItem>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,7 @@ export const Capitated1915BWaiverRenewalPage = () => {
<Inputs.FormLabel className="font-semibold">
Waiver Authority
</Inputs.FormLabel>
<span className="text-lg font-thin">
1915(b)
</span>
<span className="text-lg font-thin">1915(b)</span>
</div>
<Inputs.FormField
control={form.control}
Expand Down Expand Up @@ -262,10 +260,7 @@ export const Capitated1915BWaiverRenewalPage = () => {
{label}
{required ? <Inputs.RequiredIndicator /> : null}
</Inputs.FormLabel>
<Inputs.Upload
files={field?.value ?? []}
setFiles={field.onChange}
/>
<Inputs.Upload {...field} />
<Inputs.FormMessage />
</Inputs.FormItem>
)}
Expand Down
Loading

0 comments on commit 7547805

Please sign in to comment.