first commit
This commit is contained in:
122
calcom/packages/ui/components/form/inputs/HintOrErrors.tsx
Normal file
122
calcom/packages/ui/components/form/inputs/HintOrErrors.tsx
Normal file
@@ -0,0 +1,122 @@
|
||||
import type { FieldValues } from "react-hook-form";
|
||||
import { useFormContext } from "react-hook-form";
|
||||
|
||||
import { Icon } from "../../..";
|
||||
import { InputError } from "./InputError";
|
||||
|
||||
type hintsOrErrorsProps = {
|
||||
hintErrors?: string[];
|
||||
fieldName: string;
|
||||
t: (key: string) => string;
|
||||
};
|
||||
|
||||
export function HintsOrErrors<T extends FieldValues = FieldValues>({
|
||||
hintErrors,
|
||||
fieldName,
|
||||
t,
|
||||
}: hintsOrErrorsProps) {
|
||||
const methods = useFormContext() as ReturnType<typeof useFormContext> | null;
|
||||
/* If there's no methods it means we're using these components outside a React Hook Form context */
|
||||
if (!methods) return null;
|
||||
const { formState } = methods;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const fieldErrors: FieldErrors<T> | undefined = formState.errors[fieldName];
|
||||
|
||||
if (!hintErrors && fieldErrors && !fieldErrors.message) {
|
||||
// no hints passed, field errors exist and they are custom ones
|
||||
return (
|
||||
<div className="text-gray text-default mt-2 flex items-center text-sm">
|
||||
<ul className="ml-2">
|
||||
{Object.keys(fieldErrors).map((key: string) => {
|
||||
return (
|
||||
<li key={key} className="text-blue-700">
|
||||
{t(`${fieldName}_hint_${key}`)}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (hintErrors && fieldErrors) {
|
||||
// hints passed, field errors exist
|
||||
return (
|
||||
<div className="text-gray text-default mt-2 flex items-center text-sm">
|
||||
<ul className="ml-2">
|
||||
{hintErrors.map((key: string) => {
|
||||
const submitted = formState.isSubmitted;
|
||||
const error = fieldErrors[key] || fieldErrors.message;
|
||||
return (
|
||||
<li
|
||||
key={key}
|
||||
data-testid="hint-error"
|
||||
className={error !== undefined ? (submitted ? "text-red-500" : "") : "text-green-600"}>
|
||||
{error !== undefined ? (
|
||||
submitted ? (
|
||||
<Icon
|
||||
name="x"
|
||||
size="12"
|
||||
strokeWidth="3"
|
||||
className="-ml-1 inline-block ltr:mr-2 rtl:ml-2"
|
||||
/>
|
||||
) : (
|
||||
<Icon
|
||||
name="circle"
|
||||
fill="currentColor"
|
||||
size="5"
|
||||
className="inline-block ltr:mr-2 rtl:ml-2"
|
||||
/>
|
||||
)
|
||||
) : (
|
||||
<Icon
|
||||
name="check"
|
||||
size="12"
|
||||
strokeWidth="3"
|
||||
className="-ml-1 inline-block ltr:mr-2 rtl:ml-2"
|
||||
/>
|
||||
)}
|
||||
{t(`${fieldName}_hint_${key}`)}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// errors exist, not custom ones, just show them as is
|
||||
if (fieldErrors) {
|
||||
return <InputError message={fieldErrors.message} />;
|
||||
}
|
||||
|
||||
if (!hintErrors) return null;
|
||||
|
||||
// hints passed, no errors exist, proceed to just show hints
|
||||
return (
|
||||
<div className="text-gray text-default mt-2 flex items-center text-sm">
|
||||
<ul className="ml-2">
|
||||
{hintErrors.map((key: string) => {
|
||||
// if field was changed, as no error exist, show checked status and color
|
||||
const dirty = formState.dirtyFields[fieldName];
|
||||
return (
|
||||
<li key={key} className={!!dirty ? "text-green-600" : ""}>
|
||||
{!!dirty ? (
|
||||
<Icon
|
||||
name="check"
|
||||
size="12"
|
||||
strokeWidth="3"
|
||||
className="-ml-1 inline-block ltr:mr-2 rtl:ml-2"
|
||||
/>
|
||||
) : (
|
||||
<Icon name="circle" fill="currentColor" size="5" className="inline-block ltr:mr-2 rtl:ml-2" />
|
||||
)}
|
||||
{t(`${fieldName}_hint_${key}`)}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user