fix: create cycle modal (#1631)

* fix: cycle date select in the modal

* chore: update remove assignee issue activity
This commit is contained in:
Aaryan Khandelwal 2023-07-23 22:54:17 +05:30 committed by GitHub
parent 464c13fcd0
commit fe60771943
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 96 additions and 99 deletions

View File

@ -29,16 +29,13 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
handleSubmit,
control,
reset,
watch,
} = useForm<ICycle>({
defaultValues,
});
const handleCreateUpdateCycle = async (formData: Partial<ICycle>) => {
await handleFormSubmit(formData);
reset({
...defaultValues,
});
};
useEffect(() => {
@ -48,6 +45,15 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
});
}, [data, reset]);
const startDate = watch("start_date");
const endDate = watch("end_date");
const minDate = startDate ? new Date(startDate) : new Date();
minDate.setDate(minDate.getDate() + 1);
const maxDate = endDate ? new Date(endDate) : null;
maxDate?.setDate(maxDate.getDate() - 1);
return (
<form onSubmit={handleSubmit(handleCreateUpdateCycle)}>
<div className="space-y-5">
@ -91,7 +97,13 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
control={control}
name="start_date"
render={({ field: { value, onChange } }) => (
<DateSelect label="Start date" value={value} onChange={(val) => onChange(val)} />
<DateSelect
label="Start date"
value={value}
onChange={(val) => onChange(val)}
minDate={new Date()}
maxDate={maxDate ?? undefined}
/>
)}
/>
</div>
@ -100,7 +112,12 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
control={control}
name="end_date"
render={({ field: { value, onChange } }) => (
<DateSelect label="End date" value={value} onChange={(val) => onChange(val)} />
<DateSelect
label="End date"
value={value}
onChange={(val) => onChange(val)}
minDate={minDate}
/>
)}
/>
</div>

View File

@ -13,9 +13,9 @@ import useToast from "hooks/use-toast";
// components
import { CycleForm } from "components/cycles";
// helper
import { getDateRangeStatus, isDateGreaterThanToday } from "helpers/date-time.helper";
import { getDateRangeStatus } from "helpers/date-time.helper";
// types
import type { ICurrentUserResponse, ICycle } from "types";
import type { CycleDateCheckData, ICurrentUserResponse, ICycle } from "types";
// fetch keys
import {
COMPLETED_CYCLES_LIST,
@ -65,7 +65,6 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
}
mutate(INCOMPLETE_CYCLES_LIST(projectId.toString()));
mutate(CYCLES_LIST(projectId.toString()));
handleClose();
setToastAlert({
type: "success",
@ -121,8 +120,6 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
}
}
handleClose();
setToastAlert({
type: "success",
title: "Success!",
@ -138,19 +135,16 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
});
};
const dateChecker = async (payload: any) => {
try {
const res = await cycleService.cycleDateCheck(
workspaceSlug as string,
projectId as string,
payload
);
console.log(res);
return res.status;
} catch (err) {
console.log(err);
return false;
}
const dateChecker = async (payload: CycleDateCheckData) => {
let status = false;
await cycleService
.cycleDateCheck(workspaceSlug as string, projectId as string, payload)
.then((res) => {
status = res.status;
});
return status;
};
const handleFormSubmit = async (formData: Partial<ICycle>) => {
@ -160,66 +154,34 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
...formData,
};
if (payload.start_date && payload.end_date) {
if (!isDateGreaterThanToday(payload.end_date)) {
setToastAlert({
type: "error",
title: "Error!",
message: "Unable to create cycle in past date. Please enter a valid date.",
});
handleClose();
return;
}
let isDateValid: boolean = true;
if (data?.start_date && data?.end_date) {
const isDateValidForExistingCycle = await dateChecker({
if (payload.start_date && payload.end_date) {
if (data?.start_date && data?.end_date)
isDateValid = await dateChecker({
start_date: payload.start_date,
end_date: payload.end_date,
cycle_id: data.id,
});
if (isDateValidForExistingCycle) {
await updateCycle(data.id, payload);
return;
} else {
setToastAlert({
type: "error",
title: "Error!",
message:
"You have a cycle already on the given dates, if you want to create your draft cycle you can do that by removing dates",
});
handleClose();
return;
}
}
const isDateValid = await dateChecker({
else
isDateValid = await dateChecker({
start_date: payload.start_date,
end_date: payload.end_date,
});
}
if (isDateValid) {
if (data) {
await updateCycle(data.id, payload);
} else {
await createCycle(payload);
}
} else {
if (data) await updateCycle(data.id, payload);
else await createCycle(payload);
handleClose();
} else
setToastAlert({
type: "error",
title: "Error!",
message:
"You have a cycle already on the given dates, if you want to create your draft cycle you can do that by removing dates",
"You already have a cycle on the given dates, if you want to create a draft cycle, remove the dates.",
});
handleClose();
}
} else {
if (data) {
await updateCycle(data.id, payload);
} else {
await createCycle(payload);
}
}
};
return (

View File

@ -27,22 +27,23 @@ const activityDetails: {
icon: React.ReactNode;
};
} = {
assignee: {
message: (activity) => (
<>
removed the assignee{" "}
<span className="font-medium text-custom-text-100">{activity.old_value}</span>.
</>
),
icon: <Icon iconName="group" className="!text-sm" aria-hidden="true" />,
},
assignees: {
message: (activity) => (
message: (activity) => {
if (activity.old_value === "")
return (
<>
added a new assignee{" "}
<span className="font-medium text-custom-text-100">{activity.new_value}</span>.
</>
),
);
else
return (
<>
removed the assignee{" "}
<span className="font-medium text-custom-text-100">{activity.old_value}</span>.
</>
);
},
icon: <Icon iconName="group" className="!text-sm" aria-hidden="true" />,
},
archived_at: {

View File

@ -11,11 +11,21 @@ type Props = {
value: string | null;
onChange: (val: string | null) => void;
label: string;
minDate?: Date;
maxDate?: Date;
closeOnSelect?: boolean;
};
export const DateSelect: React.FC<Props> = ({ value, onChange, label }) => (
export const DateSelect: React.FC<Props> = ({
value,
onChange,
label,
minDate,
maxDate,
closeOnSelect = true,
}) => (
<Popover className="relative flex items-center justify-center rounded-lg">
{({ open }) => (
{({ close }) => (
<>
<Popover.Button className="flex cursor-pointer items-center rounded-md border border-custom-border-200 text-xs shadow-sm duration-300 hover:bg-custom-background-80">
<span className="flex items-center justify-center gap-2 px-2 py-1 text-xs text-custom-text-200">
@ -50,8 +60,12 @@ export const DateSelect: React.FC<Props> = ({ value, onChange, label }) => (
onChange={(val) => {
if (!val) onChange("");
else onChange(renderDateFormat(val));
if (closeOnSelect) close();
}}
dateFormat="dd-MM-yyyy"
minDate={minDate}
maxDate={maxDate}
inline
/>
</Popover.Panel>

View File

@ -3,7 +3,7 @@ import APIService from "services/api.service";
import trackEventServices from "services/track-event.service";
// types
import type { ICurrentUserResponse, ICycle, IIssue, IIssueViewOptions } from "types";
import type { CycleDateCheckData, ICurrentUserResponse, ICycle, IIssue } from "types";
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
@ -148,10 +148,7 @@ class ProjectCycleServices extends APIService {
async cycleDateCheck(
workspaceSlug: string,
projectId: string,
data: {
start_date: string;
end_date: string;
}
data: CycleDateCheckData
): Promise<any> {
return this.post(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/date-check/`,

View File

@ -85,3 +85,9 @@ export type SelectCycleType =
| undefined;
export type SelectIssue = (IIssue & { actionType: "edit" | "delete" | "create" }) | null;
export type CycleDateCheckData = {
start_date: string;
end_date: string;
cycle_id?: string;
};