fix: form validations (#213)

This commit is contained in:
Aaryan Khandelwal 2023-01-31 18:10:50 +05:30 committed by GitHub
parent 27e3364a1f
commit 60a35e6af1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 68 additions and 21 deletions

View File

@ -18,6 +18,7 @@ const RemirrorRichTextEditor = dynamic(() => import("components/rich-text-editor
});
// types
import { IIssue } from "types";
import useToast from "hooks/use-toast";
export interface IssueDescriptionFormValues {
name: string;
@ -31,7 +32,16 @@ export interface IssueDetailsProps {
}
export const IssueDescriptionForm: FC<IssueDetailsProps> = ({ issue, handleFormSubmit }) => {
const { handleSubmit, watch, setValue, reset } = useForm<IIssue>({
const { setToastAlert } = useToast();
const {
handleSubmit,
watch,
setValue,
reset,
formState: { errors },
setError,
} = useForm<IIssue>({
defaultValues: {
name: "",
description: "",
@ -41,13 +51,31 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = ({ issue, handleFormS
const handleDescriptionFormSubmit = useCallback(
(formData: Partial<IIssue>) => {
if (!formData.name || formData.name === "") {
setToastAlert({
type: "error",
title: "Error in saving!",
message: "Title is required.",
});
return;
}
if (formData.name.length > 255) {
setToastAlert({
type: "error",
title: "Error in saving!",
message: "Title cannot have more than 255 characters.",
});
return;
}
handleFormSubmit({
name: formData.name ?? "",
description: formData.description,
description_html: formData.description_html,
});
},
[handleFormSubmit]
[handleFormSubmit, setToastAlert]
);
const debounceHandler = useMemo(
@ -83,9 +111,8 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = ({ issue, handleFormS
}}
mode="transparent"
className="text-xl font-medium"
required={true}
/>
<span>{errors.name ? errors.name.message : null}</span>
<RemirrorRichTextEditor
value={watch("description")}
placeholder="Describe the issue..."

View File

@ -197,7 +197,7 @@ export const IssueForm: FC<IssueFormProps> = ({
required: "Title is required",
maxLength: {
value: 255,
message: "Name should be less than 255 characters",
message: "Title should be less than 255 characters",
},
}}
/>

View File

@ -93,9 +93,8 @@ export const CreateProjectModal: React.FC<Props> = (props) => {
const projectIdentifier = watch("identifier") ?? "";
useEffect(() => {
if (projectName && isChangeIdentifierRequired) {
if (projectName && isChangeIdentifierRequired)
setValue("identifier", projectName.replace(/ /g, "").toUpperCase().substring(0, 3));
}
}, [projectName, projectIdentifier, setValue, isChangeIdentifierRequired]);
useEffect(() => () => setIsChangeIdentifierRequired(true), [isOpen]);
@ -215,6 +214,10 @@ export const CreateProjectModal: React.FC<Props> = (props) => {
register={register}
validations={{
required: "Name is required",
maxLength: {
value: 255,
message: "Name should be less than 255 characters",
},
}}
/>
</div>

View File

@ -162,6 +162,10 @@ const CreateUpdateCycleModal: React.FC<Props> = ({ isOpen, setIsOpen, data, proj
register={register}
validations={{
required: "Name is required",
maxLength: {
value: 255,
message: "Name should be less than 255 characters",
},
}}
/>
</div>

View File

@ -13,7 +13,7 @@ import stateService from "services/state.service";
// hooks
import useToast from "hooks/use-toast";
// ui
import { Button, Input, Select } from "components/ui";
import { Button, CustomSelect, Input, Select } from "components/ui";
// types
import type { IState } from "types";
// fetch-keys
@ -183,18 +183,27 @@ export const CreateUpdateStateInline: React.FC<Props> = ({
autoComplete="off"
/>
{data && (
<Select
id="group"
<Controller
name="group"
error={errors.group}
register={register}
validations={{
required: true,
}}
options={Object.keys(GROUP_CHOICES).map((key) => ({
value: key,
label: GROUP_CHOICES[key as keyof typeof GROUP_CHOICES],
}))}
control={control}
render={({ field: { value, onChange } }) => (
<CustomSelect
value={value}
onChange={onChange}
label={
Object.keys(GROUP_CHOICES).find((k) => k === value.toString())
? GROUP_CHOICES[value.toString() as keyof typeof GROUP_CHOICES]
: "Select group"
}
input
>
{Object.keys(GROUP_CHOICES).map((key) => (
<CustomSelect.Option key={key} value={key}>
{GROUP_CHOICES[key as keyof typeof GROUP_CHOICES]}
</CustomSelect.Option>
))}
</CustomSelect>
)}
/>
)}
<Input
@ -209,7 +218,7 @@ export const CreateUpdateStateInline: React.FC<Props> = ({
Cancel
</Button>
<Button theme="primary" disabled={isSubmitting} type="submit">
{isSubmitting ? "Loading..." : data ? "Update" : "Create"}
{isSubmitting ? (data ? "Updating..." : "Creating...") : data ? "Update" : "Create"}
</Button>
</form>
);

View File

@ -178,6 +178,10 @@ const CreateUpdateModuleModal: React.FC<Props> = ({ isOpen, setIsOpen, data, pro
register={register}
validations={{
required: "Name is required",
maxLength: {
value: 255,
message: "Name should be less than 255 characters",
},
}}
/>
</div>

View File

@ -32,7 +32,7 @@ export const CustomDatePicker: React.FC<Props> = ({
renderAs === "input"
? "block bg-transparent text-sm focus:outline-none rounded-md border border-gray-300 px-3 py-2 w-full cursor-pointer"
: renderAs === "button"
? "w-full cursor-pointer rounded-md border px-2 py-1 text-xs shadow-sm duration-300 hover:bg-gray-100 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
? "w-full rounded-md border px-2 py-1 text-xs shadow-sm hover:bg-gray-100 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 duration-300 cursor-pointer"
: ""
} ${error ? "border-red-500 bg-red-200" : ""} bg-transparent caret-transparent`}
isClearable={isClearable}