diff --git a/apps/app/components/core/filters/due-date-filter-modal.tsx b/apps/app/components/core/filters/date-filter-modal.tsx similarity index 90% rename from apps/app/components/core/filters/due-date-filter-modal.tsx rename to apps/app/components/core/filters/date-filter-modal.tsx index 9556bd193..abc2cc7c4 100644 --- a/apps/app/components/core/filters/due-date-filter-modal.tsx +++ b/apps/app/components/core/filters/date-filter-modal.tsx @@ -11,15 +11,18 @@ import { Dialog, Transition } from "@headlessui/react"; // hooks import useIssuesView from "hooks/use-issues-view"; // components -import { DueDateFilterSelect } from "./due-date-filter-select"; +import { DateFilterSelect } from "./date-filter-select"; // ui import { PrimaryButton, SecondaryButton } from "components/ui"; // icons import { XMarkIcon } from "@heroicons/react/20/solid"; // helpers import { renderDateFormat, renderShortDateWithYearFormat } from "helpers/date-time.helper"; +import { IIssueFilterOptions } from "types"; type Props = { + title: string; + field: keyof IIssueFilterOptions; isOpen: boolean; handleClose: () => void; }; @@ -36,7 +39,7 @@ const defaultValues: TFormValues = { date2: new Date(new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()), }; -export const DueDateFilterModal: React.FC = ({ isOpen, handleClose }) => { +export const DateFilterModal: React.FC = ({ title, field, isOpen, handleClose }) => { const { filters, setFilters } = useIssuesView(); const router = useRouter(); @@ -51,11 +54,11 @@ export const DueDateFilterModal: React.FC = ({ isOpen, handleClose }) => if (filterType === "range") { setFilters( - { target_date: [`${renderDateFormat(date1)};after`, `${renderDateFormat(date2)};before`] }, + { [field]: [`${renderDateFormat(date1)};after`, `${renderDateFormat(date2)};before`] }, !Boolean(viewId) ); } else { - const filteredArray = filters?.target_date?.filter((item) => { + const filteredArray = (filters?.[field] as string[])?.filter((item) => { if (item?.includes(filterType)) return false; return true; @@ -64,13 +67,13 @@ export const DueDateFilterModal: React.FC = ({ isOpen, handleClose }) => const filterOne = filteredArray && filteredArray?.length > 0 ? filteredArray[0] : null; if (filterOne) setFilters( - { target_date: [filterOne, `${renderDateFormat(date1)};${filterType}`] }, + { [field]: [filterOne, `${renderDateFormat(date1)};${filterType}`] }, !Boolean(viewId) ); else setFilters( { - target_date: [`${renderDateFormat(date1)};${filterType}`], + [field]: [`${renderDateFormat(date1)};${filterType}`], }, !Boolean(viewId) ); @@ -116,7 +119,7 @@ export const DueDateFilterModal: React.FC = ({ isOpen, handleClose }) => control={control} name="filterType" render={({ field: { value, onChange } }) => ( - + )} /> void; }; @@ -19,29 +20,31 @@ type DueDate = { const dueDateRange: DueDate[] = [ { - name: "Due date before", + name: "before", value: "before", icon: , }, { - name: "Due date after", + name: "after", value: "after", icon: , }, { - name: "Due date range", + name: "range", value: "range", icon: , }, ]; -export const DueDateFilterSelect: React.FC = ({ value, onChange }) => ( +export const DateFilterSelect: React.FC = ({ title, value, onChange }) => ( {dueDateRange.find((item) => item.value === value)?.icon} - {dueDateRange.find((item) => item.value === value)?.name} + + {title} {dueDateRange.find((item) => item.value === value)?.name} + } onChange={onChange} @@ -50,7 +53,7 @@ export const DueDateFilterSelect: React.FC = ({ value, onChange }) => ( <> {option.icon} - {option.name} + {title} {option.name} ))} diff --git a/apps/app/components/core/filters/filters-list.tsx b/apps/app/components/core/filters/filters-list.tsx index ffe596258..8192bdf7d 100644 --- a/apps/app/components/core/filters/filters-list.tsx +++ b/apps/app/components/core/filters/filters-list.tsx @@ -240,6 +240,34 @@ export const FiltersList: React.FC = ({ ); }) + : key === "start_date" + ? filters.start_date?.map((date: string) => { + if (filters.start_date && filters.start_date.length <= 0) return null; + + const splitDate = date.split(";"); + + return ( +
+
+ + {splitDate[1]} {renderShortDateWithYearFormat(splitDate[0])} + + + setFilters({ + start_date: filters.start_date?.filter((d: any) => d !== date), + }) + } + > + + +
+ ); + }) : key === "target_date" ? filters.target_date?.map((date: string) => { if (filters.target_date && filters.target_date.length <= 0) return null; diff --git a/apps/app/components/core/filters/index.ts b/apps/app/components/core/filters/index.ts index 01c371911..d6455151e 100644 --- a/apps/app/components/core/filters/index.ts +++ b/apps/app/components/core/filters/index.ts @@ -1,4 +1,4 @@ -export * from "./due-date-filter-modal"; -export * from "./due-date-filter-select"; +export * from "./date-filter-modal"; +export * from "./date-filter-select"; export * from "./filters-list"; export * from "./issues-view-filter"; diff --git a/apps/app/components/core/filters/issues-view-filter.tsx b/apps/app/components/core/filters/issues-view-filter.tsx index 2fa80c975..37aab34e9 100644 --- a/apps/app/components/core/filters/issues-view-filter.tsx +++ b/apps/app/components/core/filters/issues-view-filter.tsx @@ -119,14 +119,11 @@ export const IssuesFilterView: React.FC = () => { onSelect={(option) => { const key = option.key as keyof typeof filters; - if (key === "target_date") { - const valueExists = checkIfArraysHaveSameElements( - filters.target_date ?? [], - option.value - ); + if (key === "start_date" || key === "target_date") { + const valueExists = checkIfArraysHaveSameElements(filters[key] ?? [], option.value); setFilters({ - target_date: valueExists ? null : option.value, + [key]: valueExists ? null : option.value, }); } else { const valueExists = filters[key]?.includes(option.value); diff --git a/apps/app/components/core/views/issues-view.tsx b/apps/app/components/core/views/issues-view.tsx index d3d76f805..5f33a6cb0 100644 --- a/apps/app/components/core/views/issues-view.tsx +++ b/apps/app/components/core/views/issues-view.tsx @@ -478,6 +478,7 @@ export const IssuesView: React.FC = ({ labels: null, priority: null, state: null, + start_date: null, target_date: null, type: null, }) diff --git a/apps/app/components/issues/my-issues/my-issues-select-filters.tsx b/apps/app/components/issues/my-issues/my-issues-select-filters.tsx index e3d2cdff0..58cc63679 100644 --- a/apps/app/components/issues/my-issues/my-issues-select-filters.tsx +++ b/apps/app/components/issues/my-issues/my-issues-select-filters.tsx @@ -7,7 +7,7 @@ import useSWR from "swr"; // services import issuesService from "services/issues.service"; // components -import { DueDateFilterModal } from "components/core"; +import { DateFilterModal } from "components/core"; // ui import { MultiLevelDropdown } from "components/ui"; // icons @@ -20,7 +20,7 @@ import { IIssueFilterOptions, IQuery } from "types"; import { WORKSPACE_LABELS } from "constants/fetch-keys"; // constants import { GROUP_CHOICES, PRIORITIES } from "constants/project"; -import { DUE_DATES } from "constants/due-dates"; +import { DATE_FILTER_OPTIONS } from "constants/filters"; type Props = { filters: Partial | IQuery; @@ -35,7 +35,14 @@ export const MyIssuesSelectFilters: React.FC = ({ direction = "right", height = "md", }) => { - const [isDueDateFilterModalOpen, setIsDueDateFilterModalOpen] = useState(false); + const [isDateFilterModalOpen, setIsDateFilterModalOpen] = useState(false); + const [dateFilterType, setDateFilterType] = useState<{ + title: string; + type: "start_date" | "target_date"; + }>({ + title: "", + type: "start_date", + }); const [fetchLabels, setFetchLabels] = useState(false); const router = useRouter(); @@ -50,10 +57,12 @@ export const MyIssuesSelectFilters: React.FC = ({ return ( <> - {isDueDateFilterModalOpen && ( - setIsDueDateFilterModalOpen(false)} + {isDateFilterModalOpen && ( + setIsDateFilterModalOpen(false)} /> )} = ({ })), }, { - id: "target_date", - label: "Due date", - value: DUE_DATES, + id: "start_date", + label: "Start date", + value: DATE_FILTER_OPTIONS, hasChildren: true, children: [ - ...(DUE_DATES?.map((option) => ({ + ...(DATE_FILTER_OPTIONS?.map((option) => ({ + id: option.name, + label: option.name, + value: { + key: "start_date", + value: option.value, + }, + selected: checkIfArraysHaveSameElements(filters?.start_date ?? [], option.value), + })) ?? []), + { + id: "custom", + label: "Custom", + value: "custom", + element: ( + + ), + }, + ], + }, + { + id: "target_date", + label: "Due date", + value: DATE_FILTER_OPTIONS, + hasChildren: true, + children: [ + ...(DATE_FILTER_OPTIONS?.map((option) => ({ id: option.name, label: option.name, value: { @@ -152,7 +197,13 @@ export const MyIssuesSelectFilters: React.FC = ({ value: "custom", element: ( + ), + }, + ], + }, + { + id: "target_date", + label: "Due date", + value: DATE_FILTER_OPTIONS, + hasChildren: true, + children: [ + ...DATE_FILTER_OPTIONS.map((option) => ({ id: option.name, label: option.name, value: { @@ -203,7 +248,13 @@ export const SelectFilters: React.FC = ({ value: "custom", element: (