fix : module and cycle invalid date fix (#605)

* fix: module and cycle modal invalid date validation

* fix: cycle and module sidebar invalid date
This commit is contained in:
Anmol Singh Bhatia 2023-03-30 16:00:48 +05:30 committed by GitHub
parent a94e38c093
commit f5f90dab69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 148 additions and 52 deletions

View File

@ -11,7 +11,7 @@ import useToast from "hooks/use-toast";
// ui
import { CustomDatePicker, Input, PrimaryButton, SecondaryButton, TextArea } from "components/ui";
// helpers
import { getDateRangeStatus } from "helpers/date-time.helper";
import { getDateRangeStatus, isDateRangeValid } from "helpers/date-time.helper";
// types
import { ICycle } from "types";
@ -141,12 +141,22 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
value={value}
onChange={(val) => {
onChange(val);
val && watch("end_date") && cycleStatus != "current"
? dateChecker({
start_date: val,
end_date: watch("end_date"),
})
: "";
if (val && watch("end_date")) {
if (isDateRangeValid(val, `${watch("end_date")}`)) {
cycleStatus != "current" &&
dateChecker({
start_date: val,
end_date: watch("end_date"),
});
} else {
setIsDateValid(false);
setToastAlert({
type: "error",
title: "Error!",
message: "You have enter invalid date.",
});
}
}
}}
error={errors.start_date ? true : false}
/>
@ -169,12 +179,22 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
value={value}
onChange={(val) => {
onChange(val);
val && watch("start_date") && cycleStatus != "current"
? dateChecker({
start_date: watch("start_date"),
end_date: val,
})
: "";
if (watch("start_date") && val) {
if (isDateRangeValid(`${watch("start_date")}`, val)) {
cycleStatus != "current" &&
dateChecker({
start_date: watch("start_date"),
end_date: val,
});
} else {
setIsDateValid(false);
setToastAlert({
type: "error",
title: "Error!",
message: "You have enter invalid date.",
});
}
}
}}
error={errors.end_date ? true : false}
/>

View File

@ -35,7 +35,7 @@ import { ExclamationIcon } from "components/icons";
// helpers
import { capitalizeFirstLetter, copyTextToClipboard } from "helpers/string.helper";
import { groupBy } from "helpers/array.helper";
import { renderDateFormat, renderShortDate } from "helpers/date-time.helper";
import { isDateRangeValid, renderDateFormat, renderShortDate } from "helpers/date-time.helper";
// types
import { ICycle, IIssue } from "types";
// fetch-keys
@ -55,8 +55,6 @@ export const CycleDetailsSidebar: React.FC<Props> = ({
isCompleted,
}) => {
const [cycleDeleteModal, setCycleDeleteModal] = useState(false);
const [startDateRange, setStartDateRange] = useState<Date | null>(new Date());
const [endDateRange, setEndDateRange] = useState<Date | null>(null);
const router = useRouter();
const { workspaceSlug, projectId, cycleId } = router.query;
@ -89,7 +87,7 @@ export const CycleDetailsSidebar: React.FC<Props> = ({
...groupBy(issues ?? [], "state_detail.group"),
};
const { reset } = useForm({
const { reset, watch } = useForm({
defaultValues,
});
@ -190,17 +188,32 @@ export const CycleDetailsSidebar: React.FC<Props> = ({
>
<Popover.Panel className="absolute top-10 -right-5 z-20 transform overflow-hidden">
<DatePicker
selected={startDateRange}
selected={
watch("start_date")
? new Date(`${watch("start_date")}`)
: new Date()
}
onChange={(date) => {
submitChanges({
start_date: renderDateFormat(date),
});
setStartDateRange(date);
if (date && watch("end_date")) {
if (
isDateRangeValid(renderDateFormat(date), `${watch("end_date")}`)
) {
submitChanges({
start_date: renderDateFormat(date),
});
} else {
setToastAlert({
type: "error",
title: "Error!",
message: "You have enter invalid date.",
});
}
}
}}
selectsStart
startDate={startDateRange}
endDate={endDateRange}
maxDate={endDateRange}
startDate={new Date(`${watch("start_date")}`)}
endDate={new Date(`${watch("end_date")}`)}
maxDate={new Date(`${watch("end_date")}`)}
shouldCloseOnSelect
inline
/>
@ -237,18 +250,34 @@ export const CycleDetailsSidebar: React.FC<Props> = ({
>
<Popover.Panel className="absolute top-10 -right-5 z-20 transform overflow-hidden">
<DatePicker
selected={endDateRange}
selected={
watch("end_date") ? new Date(`${watch("end_date")}`) : new Date()
}
onChange={(date) => {
submitChanges({
end_date: renderDateFormat(date),
});
setEndDateRange(date);
if (watch("start_date") && date) {
if (
isDateRangeValid(
`${watch("start_date")}`,
renderDateFormat(date)
)
) {
submitChanges({
end_date: renderDateFormat(date),
});
} else {
setToastAlert({
type: "error",
title: "Error!",
message: "You have enter invalid date.",
});
}
}
}}
selectsEnd
startDate={startDateRange}
endDate={endDateRange}
// minDate={startDateRange}
startDate={new Date(`${watch("start_date")}`)}
endDate={new Date(`${watch("end_date")}`)}
minDate={new Date(`${watch("start_date")}`)}
shouldCloseOnSelect
inline
/>
</Popover.Panel>

View File

@ -1,11 +1,15 @@
import { useEffect } from "react";
import { useEffect, useState } from "react";
// react-hook-form
import { Controller, useForm } from "react-hook-form";
// hooks
import useToast from "hooks/use-toast";
// components
import { ModuleLeadSelect, ModuleMembersSelect, ModuleStatusSelect } from "components/modules";
// ui
import { CustomDatePicker, Input, PrimaryButton, SecondaryButton, TextArea } from "components/ui";
// helper
import { isDateRangeValid } from "helpers/date-time.helper";
// types
import { IModule } from "types";
@ -25,10 +29,13 @@ const defaultValues: Partial<IModule> = {
};
export const ModuleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, status, data }) => {
const [isDateValid, setIsDateValid] = useState(true);
const { setToastAlert } = useToast();
const {
register,
formState: { errors, isSubmitting },
handleSubmit,
watch,
control,
reset,
} = useForm<IModule>({
@ -94,7 +101,25 @@ export const ModuleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, sta
control={control}
name="start_date"
render={({ field: { value, onChange } }) => (
<CustomDatePicker renderAs="input" value={value} onChange={onChange} />
<CustomDatePicker
renderAs="input"
value={value}
onChange={(val) => {
onChange(val);
if (val && watch("target_date")) {
if (isDateRangeValid(val, `${watch("target_date")}`)) {
setIsDateValid(true);
} else {
setIsDateValid(false);
setToastAlert({
type: "error",
title: "Error!",
message: "You have enter invalid date.",
});
}
}
}}
/>
)}
/>
</div>
@ -106,7 +131,25 @@ export const ModuleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, sta
control={control}
name="target_date"
render={({ field: { value, onChange } }) => (
<CustomDatePicker renderAs="input" value={value} onChange={onChange} />
<CustomDatePicker
renderAs="input"
value={value}
onChange={(val) => {
onChange(val);
if (watch("start_date") && val) {
if (isDateRangeValid(`${watch("start_date")}`, val)) {
setIsDateValid(true);
} else {
setIsDateValid(false);
setToastAlert({
type: "error",
title: "Error!",
message: "You have enter invalid date.",
});
}
}
}}
/>
)}
/>
</div>
@ -133,7 +176,7 @@ export const ModuleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, sta
</div>
<div className="mt-5 flex justify-end gap-2">
<SecondaryButton onClick={handleClose}>Cancel</SecondaryButton>
<PrimaryButton type="submit" loading={isSubmitting}>
<PrimaryButton type="submit" loading={isSubmitting || isDateValid ? false : true}>
{status
? isSubmitting
? "Updating Module..."

View File

@ -32,7 +32,7 @@ import { CustomMenu, CustomSelect, Loader, ProgressBar } from "components/ui";
// icon
import { ExclamationIcon } from "components/icons";
// helpers
import { renderDateFormat, renderShortDate } from "helpers/date-time.helper";
import { isDateRangeValid, renderDateFormat, renderShortDate } from "helpers/date-time.helper";
import { capitalizeFirstLetter, copyTextToClipboard } from "helpers/string.helper";
import { groupBy } from "helpers/array.helper";
// types
@ -67,8 +67,6 @@ export const ModuleDetailsSidebar: React.FC<Props> = ({
}) => {
const [moduleDeleteModal, setModuleDeleteModal] = useState(false);
const [moduleLinkModal, setModuleLinkModal] = useState(false);
const [startDateRange, setStartDateRange] = useState<Date | null>(new Date());
const [endDateRange, setEndDateRange] = useState<Date | null>(null);
const router = useRouter();
const { workspaceSlug, projectId, moduleId } = router.query;
@ -257,17 +255,20 @@ export const ModuleDetailsSidebar: React.FC<Props> = ({
>
<Popover.Panel className="absolute top-10 -right-5 z-20 transform overflow-hidden">
<DatePicker
selected={startDateRange}
selected={
watch("start_date")
? new Date(`${watch("start_date")}`)
: new Date()
}
onChange={(date) => {
submitChanges({
start_date: renderDateFormat(date),
});
setStartDateRange(date);
}}
selectsStart
startDate={startDateRange}
endDate={endDateRange}
maxDate={endDateRange}
startDate={new Date(`${watch("start_date")}`)}
endDate={new Date(`${watch("target_date")}`)}
maxDate={new Date(`${watch("target_date")}`)}
shouldCloseOnSelect
inline
/>
@ -303,18 +304,19 @@ export const ModuleDetailsSidebar: React.FC<Props> = ({
>
<Popover.Panel className="absolute top-10 -right-5 z-20 transform overflow-hidden">
<DatePicker
selected={endDateRange}
selected={
watch("target_date") ? new Date(`${watch("target_date")}`) : new Date()
}
onChange={(date) => {
submitChanges({
target_date: renderDateFormat(date),
});
setEndDateRange(date);
}}
selectsEnd
startDate={startDateRange}
endDate={endDateRange}
// minDate={startDateRange}
startDate={new Date(`${watch("start_date")}`)}
endDate={new Date(`${watch("target_date")}`)}
minDate={new Date(`${watch("start_date")}`)}
shouldCloseOnSelect
inline
/>
</Popover.Panel>

View File

@ -169,3 +169,5 @@ export const renderShortTime = (date: string | Date) => {
return hours + ":" + minutes;
};
export const isDateRangeValid = (startDate: string, endDate: string)=> new Date(startDate) < new Date(endDate);