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, handleSubmit,
control, control,
reset, reset,
watch,
} = useForm<ICycle>({ } = useForm<ICycle>({
defaultValues, defaultValues,
}); });
const handleCreateUpdateCycle = async (formData: Partial<ICycle>) => { const handleCreateUpdateCycle = async (formData: Partial<ICycle>) => {
await handleFormSubmit(formData); await handleFormSubmit(formData);
reset({
...defaultValues,
});
}; };
useEffect(() => { useEffect(() => {
@ -48,6 +45,15 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
}); });
}, [data, reset]); }, [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 ( return (
<form onSubmit={handleSubmit(handleCreateUpdateCycle)}> <form onSubmit={handleSubmit(handleCreateUpdateCycle)}>
<div className="space-y-5"> <div className="space-y-5">
@ -91,7 +97,13 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
control={control} control={control}
name="start_date" name="start_date"
render={({ field: { value, onChange } }) => ( 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> </div>
@ -100,7 +112,12 @@ export const CycleForm: React.FC<Props> = ({ handleFormSubmit, handleClose, stat
control={control} control={control}
name="end_date" name="end_date"
render={({ field: { value, onChange } }) => ( 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> </div>

View File

@ -13,9 +13,9 @@ import useToast from "hooks/use-toast";
// components // components
import { CycleForm } from "components/cycles"; import { CycleForm } from "components/cycles";
// helper // helper
import { getDateRangeStatus, isDateGreaterThanToday } from "helpers/date-time.helper"; import { getDateRangeStatus } from "helpers/date-time.helper";
// types // types
import type { ICurrentUserResponse, ICycle } from "types"; import type { CycleDateCheckData, ICurrentUserResponse, ICycle } from "types";
// fetch keys // fetch keys
import { import {
COMPLETED_CYCLES_LIST, COMPLETED_CYCLES_LIST,
@ -65,7 +65,6 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
} }
mutate(INCOMPLETE_CYCLES_LIST(projectId.toString())); mutate(INCOMPLETE_CYCLES_LIST(projectId.toString()));
mutate(CYCLES_LIST(projectId.toString())); mutate(CYCLES_LIST(projectId.toString()));
handleClose();
setToastAlert({ setToastAlert({
type: "success", type: "success",
@ -121,8 +120,6 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
} }
} }
handleClose();
setToastAlert({ setToastAlert({
type: "success", type: "success",
title: "Success!", title: "Success!",
@ -138,19 +135,16 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
}); });
}; };
const dateChecker = async (payload: any) => { const dateChecker = async (payload: CycleDateCheckData) => {
try { let status = false;
const res = await cycleService.cycleDateCheck(
workspaceSlug as string, await cycleService
projectId as string, .cycleDateCheck(workspaceSlug as string, projectId as string, payload)
payload .then((res) => {
); status = res.status;
console.log(res); });
return res.status;
} catch (err) { return status;
console.log(err);
return false;
}
}; };
const handleFormSubmit = async (formData: Partial<ICycle>) => { const handleFormSubmit = async (formData: Partial<ICycle>) => {
@ -160,66 +154,34 @@ export const CreateUpdateCycleModal: React.FC<CycleModalProps> = ({
...formData, ...formData,
}; };
if (payload.start_date && payload.end_date) { let isDateValid: boolean = true;
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;
}
if (data?.start_date && data?.end_date) { if (payload.start_date && payload.end_date) {
const isDateValidForExistingCycle = await dateChecker({ if (data?.start_date && data?.end_date)
isDateValid = await dateChecker({
start_date: payload.start_date, start_date: payload.start_date,
end_date: payload.end_date, end_date: payload.end_date,
cycle_id: data.id, cycle_id: data.id,
}); });
else
if (isDateValidForExistingCycle) { isDateValid = await dateChecker({
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({
start_date: payload.start_date, start_date: payload.start_date,
end_date: payload.end_date, end_date: payload.end_date,
}); });
}
if (isDateValid) { if (isDateValid) {
if (data) { if (data) await updateCycle(data.id, payload);
await updateCycle(data.id, payload); else await createCycle(payload);
} else {
await createCycle(payload); handleClose();
} } else
} else {
setToastAlert({ setToastAlert({
type: "error", type: "error",
title: "Error!", title: "Error!",
message: 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 ( return (

View File

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

View File

@ -11,11 +11,21 @@ type Props = {
value: string | null; value: string | null;
onChange: (val: string | null) => void; onChange: (val: string | null) => void;
label: string; 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"> <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"> <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"> <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) => { onChange={(val) => {
if (!val) onChange(""); if (!val) onChange("");
else onChange(renderDateFormat(val)); else onChange(renderDateFormat(val));
if (closeOnSelect) close();
}} }}
dateFormat="dd-MM-yyyy" dateFormat="dd-MM-yyyy"
minDate={minDate}
maxDate={maxDate}
inline inline
/> />
</Popover.Panel> </Popover.Panel>

View File

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

View File

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