initial setup, formik, fields, layout
This commit is contained in:
parent
765cc0c7cf
commit
b23d706180
16 changed files with 578 additions and 53 deletions
|
|
@ -2,8 +2,8 @@ import "styles/tailwind.css"
|
|||
|
||||
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>{children}</body>
|
||||
<html lang="en" className="h-full">
|
||||
<body className="h-full">{children}</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
66
app/page.tsx
66
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 (
|
||||
<>
|
||||
<section className="bg-white dark:bg-gray-900">
|
||||
<div className="mx-auto grid max-w-screen-xl px-4 py-8 text-center lg:py-16">
|
||||
<div className="mx-auto place-self-center">
|
||||
<h1 className="mb-4 max-w-2xl text-4xl font-extrabold leading-none tracking-tight dark:text-white md:text-5xl xl:text-6xl">
|
||||
Next.js Enterprise Boilerplate
|
||||
</h1>
|
||||
<p className="mb-6 max-w-2xl font-light text-gray-500 dark:text-gray-400 md:text-lg lg:mb-8 lg:text-xl">
|
||||
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.
|
||||
</p>
|
||||
<Button href="https://github.com/Blazity/next-enterprise" className="mr-3">
|
||||
Get started
|
||||
</Button>
|
||||
<Button
|
||||
href="https://vercel.com/new/git/external?repository-url=https://github.com/Blazity/next-enterprise"
|
||||
intent="secondary"
|
||||
>
|
||||
Deploy Now
|
||||
</Button>
|
||||
<section className="flex min-h-full grow items-center justify-center bg-slate-200 p-4">
|
||||
<div className="max-w-screen-lg grow rounded-3xl bg-white p-8">
|
||||
{/* Close button */}
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-950 text-white">
|
||||
<FontAwesomeIcon icon={faXmark} className="h-6 w-6" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section className="bg-white dark:bg-gray-900">
|
||||
<div className="mx-auto max-w-screen-xl px-4 py-8 sm:py-16 lg:px-6">
|
||||
<div className="justify-center space-y-8 md:grid md:grid-cols-2 md:gap-12 md:space-y-0 lg:grid-cols-3">
|
||||
{LP_GRID_ITEMS.map((singleItem) => (
|
||||
<div key={singleItem.title} className="flex flex-col items-center justify-center text-center">
|
||||
<div className="mb-4 flex h-10 w-10 items-center justify-center rounded-full bg-primary-100 p-1.5 text-blue-700 dark:bg-primary-900 lg:h-12 lg:w-12">
|
||||
{singleItem.icon}
|
||||
</div>
|
||||
<h3 className="mb-2 text-xl font-bold dark:text-white">{singleItem.title}</h3>
|
||||
<p className="text-gray-500 dark:text-gray-400">{singleItem.description}</p>
|
||||
</div>
|
||||
))}
|
||||
{/* Title */}
|
||||
<div className="flex justify-center">
|
||||
<h1 className="border-grey-300 w-fit border-b pb-4 text-3xl text-indigo-900">Document Upload</h1>
|
||||
</div>
|
||||
{/* Form layout */}
|
||||
<div className="flex gap-14">
|
||||
<Form />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
38
components/Form/ClientField.tsx
Normal file
38
components/Form/ClientField.tsx
Normal file
|
|
@ -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<ClientFieldProps> = ({ testingCenters, clients }) => {
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
{testingCenters.map((testingCenter) => (
|
||||
<div key={Utils.camelize(testingCenter)} className="flex gap-14 items-center">
|
||||
<span>{testingCenter}</span>
|
||||
<div className="flex gap-2 items-center">
|
||||
<SelectInput name={Utils.camelize(testingCenter)}>
|
||||
<option value="">Select Client</option>
|
||||
{clients.map((option: string) => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</SelectInput>
|
||||
<FontAwesomeIcon icon={faClock}/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ClientField
|
||||
10
components/Form/ErrorMessage.tsx
Normal file
10
components/Form/ErrorMessage.tsx
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import React from "react"
|
||||
|
||||
const ErrorMessage = ({ touched, error }: { touched: boolean; error?: string }) => {
|
||||
if (touched && error) {
|
||||
return <p className="mt-1">{error}</p>
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export default ErrorMessage
|
||||
67
components/Form/FileInput.tsx
Normal file
67
components/Form/FileInput.tsx
Normal file
|
|
@ -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<FileInputProps> = ({ label, ...props }) => {
|
||||
const { required } = props;
|
||||
const [field, meta] = useField(props);
|
||||
const { setFieldValue } = useFormikContext();
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
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<HTMLDivElement>) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
const files = event.dataTransfer.files;
|
||||
if (files && files.length > 0) {
|
||||
const file = files[0];
|
||||
setFieldValue(props.name, file);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="mb-4">
|
||||
<label className="text-md" htmlFor={props.name}>
|
||||
{label}
|
||||
<RequiredAsterisk required={required} />
|
||||
</label>
|
||||
<div className="drop-area" onClick={handleClick} onDrop={handleDrop} onDragOver={(e) => e.preventDefault()}>
|
||||
<div>
|
||||
<FontAwesomeIcon icon={faFile} />
|
||||
<h4>Drag & Drop Here or Browse</h4>
|
||||
</div>
|
||||
<button type="button">Upload Manifest</button>
|
||||
</div>
|
||||
<input
|
||||
type="file"
|
||||
className="hidden"
|
||||
ref={fileInputRef}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<ErrorMessage touched={meta.touched} error={meta.error} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FileInput;
|
||||
57
components/Form/RadioGroup.tsx
Normal file
57
components/Form/RadioGroup.tsx
Normal file
|
|
@ -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 (
|
||||
<div className="mb-4">
|
||||
<label className="text-md" htmlFor={label}>
|
||||
{label}
|
||||
</label>
|
||||
<RequiredAsterisk required={required} />
|
||||
<RadioGroup.Root
|
||||
className="flex gap-3"
|
||||
value={field.value}
|
||||
onValueChange={handleChange}
|
||||
aria-label={label}
|
||||
>
|
||||
{options.map((option) => (
|
||||
<div className="flex items-center" key={option}>
|
||||
<RadioGroup.Item
|
||||
className="hover:bg-violet3 h-[25px] w-[25px] cursor-default rounded-full border bg-white outline-none focus:shadow-[0_0_0_2px]"
|
||||
value={option}
|
||||
id={`${name}-${option}`}
|
||||
>
|
||||
<RadioGroup.Indicator className="relative flex h-full w-full items-center justify-center after:block after:h-[11px] after:w-[11px] after:rounded-[50%] after:bg-violet-400 after:content-['']" />
|
||||
</RadioGroup.Item>
|
||||
<label className="pl-[15px] text-[15px] leading-none" htmlFor={`${name}-${option}`}>
|
||||
{option}
|
||||
</label>
|
||||
</div>
|
||||
))}
|
||||
</RadioGroup.Root>
|
||||
<ErrorMessage touched={meta.touched} error={meta.error} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default RadioGroupField
|
||||
7
components/Form/RequiredAsterisk.tsx
Normal file
7
components/Form/RequiredAsterisk.tsx
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import React from "react"
|
||||
|
||||
const RequiredAsterisk = ({ required }: { required?: boolean }) => {
|
||||
return required ? <span className="text-sm"> *</span> : null
|
||||
}
|
||||
|
||||
export default RequiredAsterisk
|
||||
24
components/Form/SelectInput.tsx
Normal file
24
components/Form/SelectInput.tsx
Normal file
|
|
@ -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 (
|
||||
<div className="">
|
||||
{label && (
|
||||
<label className="text-md" htmlFor={props.id || props.name}>
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
<RequiredAsterisk required={required} />
|
||||
<select className="h-10 w-full rounded-lg border px-3 text-base shadow-sm" {...field} {...restProps} />
|
||||
<ErrorMessage touched={meta.touched} error={meta.error} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SelectInput
|
||||
20
components/Form/StatusField.tsx
Normal file
20
components/Form/StatusField.tsx
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import React from "react"
|
||||
|
||||
const StatusField = ({
|
||||
label,
|
||||
statusLabel,
|
||||
statusColor,
|
||||
}: {
|
||||
label: string
|
||||
statusLabel: string
|
||||
statusColor: string
|
||||
}) => {
|
||||
return (
|
||||
<div>
|
||||
<h4>{label}</h4>
|
||||
<span className={statusColor}>{statusLabel}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default StatusField
|
||||
38
components/Form/ToggleField.tsx
Normal file
38
components/Form/ToggleField.tsx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import { useField } from "formik";
|
||||
import React, { useState } from "react";
|
||||
import ErrorMessage from "./ErrorMessage";
|
||||
import RequiredAsterisk from "./RequiredAsterisk";
|
||||
import * as SwitchPrimitive from "@radix-ui/react-switch";
|
||||
|
||||
const ToggleField = ({
|
||||
children,
|
||||
...props
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
} & React.InputHTMLAttributes<HTMLInputElement>) => {
|
||||
const { required, ...restProps } = props;
|
||||
const [field, meta] = useField({ ...(restProps as { name: string }), type: "checkbox" });
|
||||
const [checked, setChecked] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
<label className="flex items-center gap-2">
|
||||
{children}
|
||||
<RequiredAsterisk required={required} />
|
||||
</label>
|
||||
<SwitchPrimitive.Root
|
||||
className="relative h-[25px] w-[42px] cursor-default rounded-full bg-black shadow-[0_2px_10px] outline-none focus:shadow-[0_0_0_2px] focus:shadow-black"
|
||||
checked={checked}
|
||||
onCheckedChange={(isChecked) => {
|
||||
setChecked(isChecked);
|
||||
field.onChange({ target: { name: field.name, value: isChecked } });
|
||||
}}
|
||||
>
|
||||
<SwitchPrimitive.Thumb className="block h-[21px] w-[21px] translate-x-0.5 rounded-full bg-white shadow-[0_2px_2px] shadow-black transition-transform duration-100 will-change-transform data-[state=checked]:translate-x-[19px]" />
|
||||
</SwitchPrimitive.Root>
|
||||
<ErrorMessage touched={meta.touched} error={meta.error} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ToggleField;
|
||||
10
components/Form/Utils.ts
Normal file
10
components/Form/Utils.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
export class Utils {
|
||||
//Function to convert strings to camel case
|
||||
static camelize = (str: string) => {
|
||||
return str
|
||||
.replace(/(?:^\w|[A-Z]|\b\w)/g, function (word, index) {
|
||||
return index === 0 ? word.toLowerCase() : word.toUpperCase()
|
||||
})
|
||||
.replace(/\s+/g, "")
|
||||
}
|
||||
}
|
||||
0
components/Form/data.tsx
Normal file
0
components/Form/data.tsx
Normal file
172
components/Form/index.tsx
Normal file
172
components/Form/index.tsx
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
"use client"
|
||||
|
||||
import React, { useState } from "react";
|
||||
|
||||
//Dependencies
|
||||
import { Formik, Form } from "formik";
|
||||
import * as Yup from "yup";
|
||||
import axios from "axios";
|
||||
|
||||
//Input fields
|
||||
import SelectInput from "./SelectInput";
|
||||
import RadioGroup from "./RadioGroup";
|
||||
import FileInput from "./FileInput";
|
||||
import ToggleField from "./ToggleField";
|
||||
import StatusField from "./StatusField";
|
||||
import ClientField from "./ClientField";
|
||||
|
||||
interface FormValues {
|
||||
importName: string;
|
||||
manifestFile: File | null;
|
||||
splitSchedule: string;
|
||||
client: string;
|
||||
testingCenter: string;
|
||||
toleranceWindow: boolean;
|
||||
}
|
||||
|
||||
const initialValues: FormValues = {
|
||||
importName: '',
|
||||
manifestFile: null,
|
||||
splitSchedule: '',
|
||||
client: '',
|
||||
testingCenter: '',
|
||||
toleranceWindow: false,
|
||||
};
|
||||
|
||||
const validationSchema = Yup.object({
|
||||
importName: Yup.string()
|
||||
.required('Import name is required')
|
||||
.oneOf(["Import ABC", "Import DEF", "Import GHI"], "Invalid Import Name"),
|
||||
manifestFile: Yup.mixed()
|
||||
.required('A file is required')
|
||||
.nullable(), // Allows for null values, adjust based on your logic for file handling
|
||||
splitSchedule: Yup.string()
|
||||
.required('This field is required')
|
||||
.oneOf(["Yes", "No"], "Invalid Option"),
|
||||
client: Yup.string()
|
||||
.required('Client selection is required')
|
||||
.oneOf(["Single", "Multiple"], "Invalid Client Type"),
|
||||
testingCenter: Yup.string()
|
||||
.required('Testing center selection is required'), // Assuming a selection is required
|
||||
toleranceWindow: Yup.boolean()
|
||||
.required('Tolerance window selection is required'), // Assuming this is a boolean represented by a toggle
|
||||
});
|
||||
|
||||
|
||||
const data = {
|
||||
importNames: ["Import ABC", "Import DEF", "Import GHI"],
|
||||
splitScheduleOptions: ["Yes", "No"],
|
||||
clientOptions: ["Single", "Multiple"],
|
||||
testingCenterOptions: ["testing center 1", "testing center 2", "testing center 3", "testing center 4"],
|
||||
clientsOptions: ["client 1", "client 2", "client 3"],
|
||||
};
|
||||
|
||||
const FormComponent: React.FC = () => {
|
||||
const [formSubmitted, setFormSubmitted] = useState(false);
|
||||
|
||||
const submitForm = (values: FormValues) => {
|
||||
return axios.post(
|
||||
`/api/submitForm`,
|
||||
{
|
||||
submissionData: values,
|
||||
},
|
||||
{
|
||||
// options
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={async (values, { setSubmitting }) => {
|
||||
try {
|
||||
console.log(values);
|
||||
await submitForm(values);
|
||||
setFormSubmitted(true);
|
||||
} catch (error) {
|
||||
console.error("Error submitting form:", error);
|
||||
} finally {
|
||||
setSubmitting(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{formik => (
|
||||
<Form>
|
||||
<div className="flex flex-col lg:flex-row gap-4 lg:gap-16">
|
||||
<div className="flex flex-col grow lg:max-w-[500px]">
|
||||
<SelectInput
|
||||
key="importName"
|
||||
name="importName"
|
||||
label="Select Import Name:"
|
||||
required
|
||||
>
|
||||
<option value="">Select Import Name:</option>
|
||||
{data.importNames.map(option => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</SelectInput>
|
||||
<FileInput
|
||||
label="Select a manifest that you'd like to import"
|
||||
name="manifestFile"
|
||||
required
|
||||
/>
|
||||
<StatusField
|
||||
label="Elapse Data Checking:"
|
||||
statusLabel="No Elapsed Dates!"
|
||||
statusColor="text-green-500"
|
||||
/>
|
||||
<ToggleField
|
||||
key="toleranceWindow"
|
||||
name="toleranceWindow"
|
||||
required={true}
|
||||
>Tolerance Window:</ToggleField>
|
||||
</div>
|
||||
<div className="flex flex-col grow lg:max-w-[350px]">
|
||||
<RadioGroup
|
||||
key="splitSchedule"
|
||||
name="splitSchedule"
|
||||
label="Split schedule using social distancing?"
|
||||
options={data.splitScheduleOptions}
|
||||
required={true}
|
||||
/>
|
||||
<StatusField
|
||||
label="Location Checking:"
|
||||
statusLabel="All Available!"
|
||||
statusColor="text-green-500"
|
||||
/>
|
||||
<RadioGroup
|
||||
key="client"
|
||||
name="client"
|
||||
label="Client"
|
||||
options={data.clientOptions}
|
||||
required={true}
|
||||
/>
|
||||
<ClientField
|
||||
testingCenters={data.testingCenterOptions}
|
||||
clients={data.clientsOptions}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="mx-auto mt-4"
|
||||
type="submit"
|
||||
disabled={formik.isSubmitting}
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
export default FormComponent;
|
||||
|
||||
0
components/Form/types.ts
Normal file
0
components/Form/types.ts
Normal file
|
|
@ -23,6 +23,11 @@
|
|||
"coupling-graph": "npx madge --extensions js,jsx,ts,tsx,css,md,mdx ./ --exclude '.next|tailwind.config.js|reset.d.ts|prettier.config.js|postcss.config.js|playwright.config.ts|next.config.js|next-env.d.ts|instrumentation.ts|e2e/|README.md|.storybook/|.eslintrc.js' --image graph.svg"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^6.5.1",
|
||||
"@fortawesome/free-brands-svg-icons": "^6.5.1",
|
||||
"@fortawesome/free-regular-svg-icons": "^6.5.1",
|
||||
"@fortawesome/free-solid-svg-icons": "^6.5.1",
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@next/bundle-analyzer": "^14.0.3",
|
||||
"@radix-ui/react-accordion": "^1.1.2",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
|
|
@ -48,12 +53,14 @@
|
|||
"@t3-oss/env-nextjs": "^0.7.1",
|
||||
"@vercel/otel": "^0.3.0",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"formik": "^2.4.5",
|
||||
"lodash": "^4.17.21",
|
||||
"next": "^14.0.3",
|
||||
"next-compose-plugins": "^2.2.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"tailwind-merge": "^2.0.0",
|
||||
"yup": "^1.3.3",
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
111
yarn.lock
111
yarn.lock
|
|
@ -1492,6 +1492,46 @@
|
|||
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.1.6.tgz#22958c042e10b67463997bd6ea7115fe28cbcaf9"
|
||||
integrity sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==
|
||||
|
||||
"@fortawesome/fontawesome-common-types@6.5.1":
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.1.tgz#fdb1ec4952b689f5f7aa0bffe46180bb35490032"
|
||||
integrity sha512-GkWzv+L6d2bI5f/Vk6ikJ9xtl7dfXtoRu3YGE6nq0p/FFqA1ebMOAWg3XgRyb0I6LYyYkiAo+3/KrwuBp8xG7A==
|
||||
|
||||
"@fortawesome/fontawesome-svg-core@^6.5.1":
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.1.tgz#9d56d46bddad78a7ebb2043a97957039fcebcf0a"
|
||||
integrity sha512-MfRCYlQPXoLlpem+egxjfkEuP9UQswTrlCOsknus/NcMoblTH2g0jPrapbcIb04KGA7E2GZxbAccGZfWoYgsrQ==
|
||||
dependencies:
|
||||
"@fortawesome/fontawesome-common-types" "6.5.1"
|
||||
|
||||
"@fortawesome/free-brands-svg-icons@^6.5.1":
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.5.1.tgz#e948cc02404277cb8ad40fe3573ca75f2830e876"
|
||||
integrity sha512-093l7DAkx0aEtBq66Sf19MgoZewv1zeY9/4C7vSKPO4qMwEsW/2VYTUTpBtLwfb9T2R73tXaRDPmE4UqLCYHfg==
|
||||
dependencies:
|
||||
"@fortawesome/fontawesome-common-types" "6.5.1"
|
||||
|
||||
"@fortawesome/free-regular-svg-icons@^6.5.1":
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.5.1.tgz#c98a91d2c9137ed54a7aa2362a916f46503e0627"
|
||||
integrity sha512-m6ShXn+wvqEU69wSP84coxLbNl7sGVZb+Ca+XZq6k30SzuP3X4TfPqtycgUh9ASwlNh5OfQCd8pDIWxl+O+LlQ==
|
||||
dependencies:
|
||||
"@fortawesome/fontawesome-common-types" "6.5.1"
|
||||
|
||||
"@fortawesome/free-solid-svg-icons@^6.5.1":
|
||||
version "6.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.1.tgz#737b8d787debe88b400ab7528f47be333031274a"
|
||||
integrity sha512-S1PPfU3mIJa59biTtXJz1oI0+KAXW6bkAb31XKhxdxtuXDiUIFsih4JR1v5BbxY7hVHsD1RKq+jRkVRaf773NQ==
|
||||
dependencies:
|
||||
"@fortawesome/fontawesome-common-types" "6.5.1"
|
||||
|
||||
"@fortawesome/react-fontawesome@^0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz#d90dd8a9211830b4e3c08e94b63a0ba7291ddcf4"
|
||||
integrity sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==
|
||||
dependencies:
|
||||
prop-types "^15.8.1"
|
||||
|
||||
"@grpc/grpc-js@^1.7.1":
|
||||
version "1.9.5"
|
||||
resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.9.5.tgz#22e283754b7b10d1ad26c3fb21849028dcaabc53"
|
||||
|
|
@ -4945,6 +4985,14 @@
|
|||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/hoist-non-react-statics@^3.3.1":
|
||||
version "3.3.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz#dab7867ef789d87e2b4b0003c9d65c49cc44a494"
|
||||
integrity sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
hoist-non-react-statics "^3.3.0"
|
||||
|
||||
"@types/html-minifier-terser@^6.0.0":
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35"
|
||||
|
|
@ -7506,6 +7554,11 @@ deep-is@^0.1.3:
|
|||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
|
||||
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
|
||||
|
||||
deepmerge@^2.1.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
|
||||
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
|
||||
|
||||
deepmerge@^4.2.2:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
|
||||
|
|
@ -8999,6 +9052,20 @@ form-data@^4.0.0:
|
|||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
formik@^2.4.5:
|
||||
version "2.4.5"
|
||||
resolved "https://registry.yarnpkg.com/formik/-/formik-2.4.5.tgz#f899b5b7a6f103a8fabb679823e8fafc7e0ee1b4"
|
||||
integrity sha512-Gxlht0TD3vVdzMDHwkiNZqJ7Mvg77xQNfmBRrNtvzcHZs72TJppSTDKHpImCMJZwcWPBJ8jSQQ95GJzXFf1nAQ==
|
||||
dependencies:
|
||||
"@types/hoist-non-react-statics" "^3.3.1"
|
||||
deepmerge "^2.1.1"
|
||||
hoist-non-react-statics "^3.3.0"
|
||||
lodash "^4.17.21"
|
||||
lodash-es "^4.17.21"
|
||||
react-fast-compare "^2.0.1"
|
||||
tiny-warning "^1.0.2"
|
||||
tslib "^2.0.0"
|
||||
|
||||
forwarded@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
||||
|
|
@ -9543,6 +9610,13 @@ hmac-drbg@^1.0.1:
|
|||
minimalistic-assert "^1.0.0"
|
||||
minimalistic-crypto-utils "^1.0.1"
|
||||
|
||||
hoist-non-react-statics@^3.3.0:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
||||
dependencies:
|
||||
react-is "^16.7.0"
|
||||
|
||||
homedir-polyfill@^1.0.0:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8"
|
||||
|
|
@ -13241,6 +13315,11 @@ prop-types@^15.7.2, prop-types@^15.8.1:
|
|||
object-assign "^4.1.1"
|
||||
react-is "^16.13.1"
|
||||
|
||||
property-expr@^2.0.5:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.6.tgz#f77bc00d5928a6c748414ad12882e83f24aec1e8"
|
||||
integrity sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==
|
||||
|
||||
proto-list@~1.2.1:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
|
||||
|
|
@ -13484,6 +13563,11 @@ react-element-to-jsx-string@^15.0.0:
|
|||
is-plain-object "5.0.0"
|
||||
react-is "18.1.0"
|
||||
|
||||
react-fast-compare@^2.0.1:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
|
||||
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
|
||||
|
||||
react-inspector@^6.0.0:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-inspector/-/react-inspector-6.0.2.tgz#aa3028803550cb6dbd7344816d5c80bf39d07e9d"
|
||||
|
|
@ -13494,7 +13578,7 @@ react-is@18.1.0:
|
|||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.1.0.tgz#61aaed3096d30eacf2a2127118b5b41387d32a67"
|
||||
integrity sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==
|
||||
|
||||
react-is@^16.13.1:
|
||||
react-is@^16.13.1, react-is@^16.7.0:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
|
|
@ -14993,6 +15077,11 @@ timers-browserify@^2.0.12:
|
|||
dependencies:
|
||||
setimmediate "^1.0.4"
|
||||
|
||||
tiny-case@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tiny-case/-/tiny-case-1.0.3.tgz#d980d66bc72b5d5a9ca86fb7c9ffdb9c898ddd03"
|
||||
integrity sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==
|
||||
|
||||
tiny-invariant@^1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642"
|
||||
|
|
@ -15003,6 +15092,11 @@ tiny-relative-date@^1.3.0:
|
|||
resolved "https://registry.yarnpkg.com/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz#fa08aad501ed730f31cc043181d995c39a935e07"
|
||||
integrity sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A==
|
||||
|
||||
tiny-warning@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
|
||||
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
|
||||
|
||||
tmp@^0.0.33:
|
||||
version "0.0.33"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
||||
|
|
@ -15037,6 +15131,11 @@ toidentifier@1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
|
||||
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
|
||||
|
||||
toposort@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
|
||||
integrity sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==
|
||||
|
||||
totalist@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df"
|
||||
|
|
@ -16074,6 +16173,16 @@ yocto-queue@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251"
|
||||
integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==
|
||||
|
||||
yup@^1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/yup/-/yup-1.3.3.tgz#d2f6020ad1679754c5f8178a29243d5447dead04"
|
||||
integrity sha512-v8QwZSsHH2K3/G9WSkp6mZKO+hugKT1EmnMqLNUcfu51HU9MDyhlETT/JgtzprnrnQHPWsjc6MUDMBp/l9fNnw==
|
||||
dependencies:
|
||||
property-expr "^2.0.5"
|
||||
tiny-case "^1.0.3"
|
||||
toposort "^2.0.2"
|
||||
type-fest "^2.19.0"
|
||||
|
||||
zod@^3.22.4:
|
||||
version "3.22.4"
|
||||
resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue