Skip to content

Commit afc4b61

Browse files
gakshitalifeiscontent
authored andcommitted
[WEB-3475] fix: cycle dates dropdown (#6690)
* fix: Handled workspace switcher closing on click * fix: Cycle date picker * fix: Made onSelect optional in range range component
1 parent 1b29b56 commit afc4b61

File tree

3 files changed

+78
-238
lines changed

3 files changed

+78
-238
lines changed

web/core/components/cycles/analytics-sidebar/sidebar-header.tsx

Lines changed: 50 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,15 @@
33
import React, { FC, useEffect, useState } from "react";
44
import { observer } from "mobx-react";
55
import { Controller, useForm } from "react-hook-form";
6-
import {
7-
ArchiveIcon,
8-
ArchiveRestoreIcon,
9-
CalendarCheck2,
10-
CalendarClock,
11-
ChevronRight,
12-
EllipsisIcon,
13-
LinkIcon,
14-
Trash2,
15-
} from "lucide-react";
6+
import { ArchiveIcon, ArchiveRestoreIcon, ChevronRight, EllipsisIcon, LinkIcon, Trash2 } from "lucide-react";
167
// types
178
import { CYCLE_STATUS, CYCLE_UPDATED, EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
189
import { useTranslation } from "@plane/i18n";
1910
import { ICycle } from "@plane/types";
2011
// ui
2112
import { CustomMenu, setToast, TOAST_TYPE } from "@plane/ui";
2213
// components
23-
import { DateDropdown } from "@/components/dropdowns";
14+
import { DateRangeDropdown } from "@/components/dropdowns";
2415
// helpers
2516
import { renderFormattedPayloadDate, getDate } from "@/helpers/date-time.helper";
2617
import { copyUrlToClipboard } from "@/helpers/string.helper";
@@ -63,7 +54,7 @@ export const CycleSidebarHeader: FC<Props> = observer((props) => {
6354
const { t } = useTranslation();
6455

6556
// form info
66-
const { control, reset, getValues } = useForm({
57+
const { control, reset } = useForm({
6758
defaultValues,
6859
});
6960

@@ -110,10 +101,10 @@ export const CycleSidebarHeader: FC<Props> = observer((props) => {
110101
});
111102
};
112103

113-
const submitChanges = (data: Partial<ICycle>, changedProperty: string) => {
104+
const submitChanges = async (data: Partial<ICycle>, changedProperty: string) => {
114105
if (!workspaceSlug || !projectId || !cycleDetails.id) return;
115106

116-
updateCycleDetails(workspaceSlug.toString(), projectId.toString(), cycleDetails.id.toString(), data)
107+
await updateCycleDetails(workspaceSlug.toString(), projectId.toString(), cycleDetails.id.toString(), data)
117108
.then((res) => {
118109
captureCycleEvent({
119110
eventName: CYCLE_UPDATED,
@@ -154,16 +145,22 @@ export const CycleSidebarHeader: FC<Props> = observer((props) => {
154145
}
155146
};
156147

157-
const handleDateChange = async (payload: { start_date?: string | null; end_date?: string | null }) => {
148+
const handleDateChange = async (startDate: Date | undefined, endDate: Date | undefined) => {
158149
let isDateValid = false;
159150

160-
if (cycleDetails?.start_date && cycleDetails?.end_date)
151+
const payload = {
152+
start_date: renderFormattedPayloadDate(startDate) || null,
153+
end_date: renderFormattedPayloadDate(endDate) || null,
154+
};
155+
156+
if (payload?.start_date && payload.end_date) {
161157
isDateValid = await dateChecker({
162158
...payload,
163-
cycle_id: cycleDetails?.id,
159+
cycle_id: cycleDetails.id,
164160
});
165-
else isDateValid = await dateChecker(payload);
166-
161+
} else {
162+
isDateValid = true;
163+
}
167164
if (isDateValid) {
168165
submitChanges(payload, "date_range");
169166
setToast({
@@ -177,7 +174,6 @@ export const CycleSidebarHeader: FC<Props> = observer((props) => {
177174
title: t("project_cycles.action.update.failed.title"),
178175
message: t("project_cycles.action.update.error.already_exists"),
179176
});
180-
reset({ ...cycleDetails });
181177
}
182178
return isDateValid;
183179
};
@@ -288,79 +284,41 @@ export const CycleSidebarHeader: FC<Props> = observer((props) => {
288284
</span>
289285
)}
290286
</div>
291-
<div className="flex items-center gap-2">
292-
<Controller
293-
name="start_date"
294-
control={control}
295-
rules={{ required: "Please select a date" }}
296-
render={({ field: { value, onChange } }) => (
297-
<DateDropdown
298-
value={value ?? null}
299-
onChange={async (val) => {
300-
let isDateValid;
301-
const valDate = val ? renderFormattedPayloadDate(val) : null;
302-
if (getValues("end_date")) {
303-
isDateValid = await handleDateChange({
304-
start_date: valDate,
305-
end_date: renderFormattedPayloadDate(getValues("end_date")),
306-
});
307-
} else {
308-
isDateValid = await handleDateChange({
309-
start_date: valDate,
310-
end_date: valDate,
311-
});
312-
}
313-
isDateValid && onChange(renderFormattedPayloadDate(val));
314-
}}
315-
placeholder={t("common.order_by.start_date")}
316-
icon={<CalendarClock className="h-3 w-3 flex-shrink-0" />}
317-
buttonVariant={value ? "border-with-text" : "border-without-text"}
318-
buttonContainerClassName={`h-6 w-full flex ${!isEditingAllowed || isArchived || isCompleted ? "cursor-not-allowed" : "cursor-pointer"} items-center gap-1.5 text-custom-text-300 rounded text-xs`}
319-
optionsClassName="z-10"
320-
disabled={!isEditingAllowed || isArchived || isCompleted}
321-
showTooltip
322-
maxDate={getDate(getValues("end_date"))}
323-
isClearable={false}
324-
/>
325-
)}
326-
/>
327287

328-
<Controller
329-
name="end_date"
330-
control={control}
331-
rules={{ required: "Please select a date" }}
332-
render={({ field: { value, onChange } }) => (
333-
<DateDropdown
334-
value={getDate(value) ?? null}
335-
onChange={async (val) => {
336-
let isDateValid;
337-
const valDate = val ? renderFormattedPayloadDate(val) : null;
338-
if (getValues("start_date")) {
339-
isDateValid = await handleDateChange({
340-
end_date: valDate,
341-
start_date: renderFormattedPayloadDate(getValues("start_date")),
342-
});
343-
} else {
344-
isDateValid = await handleDateChange({
345-
end_date: valDate,
346-
start_date: valDate,
347-
});
348-
}
349-
isDateValid && onChange(renderFormattedPayloadDate(val));
350-
}}
351-
placeholder={t("common.order_by.due_date")}
352-
icon={<CalendarCheck2 className="h-3 w-3 flex-shrink-0" />}
353-
buttonVariant={value ? "border-with-text" : "border-without-text"}
354-
buttonContainerClassName={`h-6 w-full flex ${!isEditingAllowed || isArchived || isCompleted ? "cursor-not-allowed" : "cursor-pointer"} items-center gap-1.5 text-custom-text-300 rounded text-xs`}
355-
optionsClassName="z-10"
356-
disabled={!isEditingAllowed || isArchived || isCompleted}
357-
showTooltip
358-
minDate={getDate(getValues("start_date"))}
359-
isClearable={false}
360-
/>
361-
)}
362-
/>
363-
</div>
288+
<Controller
289+
control={control}
290+
name="start_date"
291+
render={({ field: { value: startDateValue, onChange: onChangeStartDate } }) => (
292+
<Controller
293+
control={control}
294+
name="end_date"
295+
render={({ field: { value: endDateValue, onChange: onChangeEndDate } }) => (
296+
<DateRangeDropdown
297+
className="h-7"
298+
buttonVariant="border-with-text"
299+
minDate={new Date()}
300+
value={{
301+
from: getDate(startDateValue),
302+
to: getDate(endDateValue),
303+
}}
304+
onSelect={async (val) => {
305+
const isDateValid = await handleDateChange(val?.from, val?.to);
306+
if (isDateValid) {
307+
onChangeStartDate(val?.from ? renderFormattedPayloadDate(val.from) : null);
308+
onChangeEndDate(val?.to ? renderFormattedPayloadDate(val.to) : null);
309+
}
310+
}}
311+
placeholder={{
312+
from: "Start date",
313+
to: "End date",
314+
}}
315+
required={cycleDetails.status !== "draft"}
316+
disabled={!isEditingAllowed || isArchived || isCompleted}
317+
/>
318+
)}
319+
/>
320+
)}
321+
/>
364322
</div>
365323
</>
366324
);

0 commit comments

Comments
 (0)