diff --git a/app/layout.tsx b/app/layout.tsx index a872374..8acd5b9 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -2,8 +2,8 @@ import "styles/tailwind.css" export default function RootLayout({ children }: { children: React.ReactNode }) { return ( - - {children} + + {children} ) } diff --git a/app/page.tsx b/app/page.tsx index 52ce217..3726b4b 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,62 +1,28 @@ import { Metadata } from "next" -import { Button } from "components/Button/Button" -import { LP_GRID_ITEMS } from "lp-items" +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" +import { faXmark } from "@fortawesome/free-solid-svg-icons" +import Form from "components/Form" export const metadata: Metadata = { - title: "Next.js Enterprise Boilerplate", - twitter: { - card: "summary_large_image", - }, - openGraph: { - url: "https://next-enterprise.vercel.app/", - images: [ - { - width: 1200, - height: 630, - url: "https://raw.githubusercontent.com/Blazity/next-enterprise/main/.github/assets/project-logo.png", - }, - ], - }, + title: "Form Components", } export default function Web() { return ( <> -
-
-
-

- Next.js Enterprise Boilerplate -

-

- Jumpstart your enterprise project with our feature-packed, high-performance Next.js boilerplate! - Experience rapid UI development, AI-powered code reviews, and an extensive suite of tools for a smooth and - enjoyable development process. -

- - +
+
+ {/* Close button */} +
+
-
-
-
-
-
- {LP_GRID_ITEMS.map((singleItem) => ( -
-
- {singleItem.icon} -
-

{singleItem.title}

-

{singleItem.description}

-
- ))} + {/* Title */} +
+

Document Upload

+
+ {/* Form layout */} +
+
diff --git a/components/Form/ClientField.tsx b/components/Form/ClientField.tsx new file mode 100644 index 0000000..da2bc68 --- /dev/null +++ b/components/Form/ClientField.tsx @@ -0,0 +1,38 @@ +import React from "react" +import SelectInput from "./SelectInput" +import { Utils } from "./Utils" +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome" +import { faClock } from "@fortawesome/free-regular-svg-icons" + +// Define a type for your props to improve type-checking +type ClientFieldProps = { + testingCenters: string[] + clients: string[] +} + +// Destructure the props in the function parameter +const ClientField: React.FC = ({ testingCenters, clients }) => { + return ( +
+ {testingCenters.map((testingCenter) => ( +
+ {testingCenter} +
+ + + {clients.map((option: string) => ( + + ))} + + +
+ +
+ ))} +
+ ) +} + +export default ClientField diff --git a/components/Form/ErrorMessage.tsx b/components/Form/ErrorMessage.tsx new file mode 100644 index 0000000..4b3534d --- /dev/null +++ b/components/Form/ErrorMessage.tsx @@ -0,0 +1,10 @@ +import React from "react" + +const ErrorMessage = ({ touched, error }: { touched: boolean; error?: string }) => { + if (touched && error) { + return

{error}

+ } + return null +} + +export default ErrorMessage diff --git a/components/Form/FileInput.tsx b/components/Form/FileInput.tsx new file mode 100644 index 0000000..25b7a3b --- /dev/null +++ b/components/Form/FileInput.tsx @@ -0,0 +1,67 @@ +import { useField, useFormikContext } from "formik"; +import React, { useRef } from "react"; +import ErrorMessage from "./ErrorMessage"; +import RequiredAsterisk from "./RequiredAsterisk"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faFile } from "@fortawesome/free-solid-svg-icons"; + + +interface FileInputProps { + label: string; + required?: boolean; + name:string; +} + +const FileInput: React.FC = ({ label, ...props }) => { + const { required } = props; + const [field, meta] = useField(props); + const { setFieldValue } = useFormikContext(); + const fileInputRef = useRef(null); + + const handleChange = (event: React.ChangeEvent) => { + const { files } = event.target; + const file = files ? files[0] : null; + setFieldValue(props.name, file); // Directly use setFieldValue to update Formik's state + }; + + const handleClick = () => { + if (fileInputRef.current) { + fileInputRef.current.click(); + } + }; + + const handleDrop = (event: React.DragEvent) => { + event.preventDefault(); + event.stopPropagation(); + const files = event.dataTransfer.files; + if (files && files.length > 0) { + const file = files[0]; + setFieldValue(props.name, file); + } + }; + + return ( +
+ +
e.preventDefault()}> +
+ +

Drag & Drop Here or Browse

+
+ +
+ + +
+ ); +}; + +export default FileInput; diff --git a/components/Form/RadioGroup.tsx b/components/Form/RadioGroup.tsx new file mode 100644 index 0000000..9886d69 --- /dev/null +++ b/components/Form/RadioGroup.tsx @@ -0,0 +1,57 @@ +import { useField } from "formik" +import React from "react" +import ErrorMessage from "./ErrorMessage" +import RequiredAsterisk from "./RequiredAsterisk" +import * as RadioGroup from "@radix-ui/react-radio-group" + +const RadioGroupField = ({ + name, + label, + options, + ...props +}: { + name: string + label: string + options: string[] + [x: string]: any // Allow any other props +}) => { + const { required, ...restProps } = props + const [field, meta, helpers] = useField({ ...restProps, name }) + + const handleChange = (value: string) => { + helpers.setValue(value) + } + + return ( +
+ + + + {options.map((option) => ( +
+ + + + +
+ ))} +
+ +
+ ) +} + +export default RadioGroupField diff --git a/components/Form/RequiredAsterisk.tsx b/components/Form/RequiredAsterisk.tsx new file mode 100644 index 0000000..2fb2585 --- /dev/null +++ b/components/Form/RequiredAsterisk.tsx @@ -0,0 +1,7 @@ +import React from "react" + +const RequiredAsterisk = ({ required }: { required?: boolean }) => { + return required ? * : null +} + +export default RequiredAsterisk diff --git a/components/Form/SelectInput.tsx b/components/Form/SelectInput.tsx new file mode 100644 index 0000000..0aece61 --- /dev/null +++ b/components/Form/SelectInput.tsx @@ -0,0 +1,24 @@ +import { useField } from "formik" +import React from "react" +import ErrorMessage from "./ErrorMessage" +import RequiredAsterisk from "./RequiredAsterisk" + +const SelectInput = ({ label, ...props }: { label?: string; name: string; [x: string]: any }) => { + const { required, ...restProps } = props + const [field, meta] = useField(restProps) + + return ( +
+ {label && ( + + )} + +