From 00077db60f60a8e87750224ffe8878f2fcfe8175 Mon Sep 17 00:00:00 2001 From: okxint Date: Tue, 4 Aug 2026 12:03:31 +0530 Subject: [PATCH] fix: expose completed_at filter in frontend issue views --- packages/types/src/view-props.d.ts | 1 + .../filters/header/filters/completed-at.tsx | 76 +++++++++++++++++++ .../header/filters/filters-selection.tsx | 12 +++ .../filters/header/filters/index.ts | 1 + web/core/constants/issue.ts | 5 ++ 5 files changed, 95 insertions(+) create mode 100644 web/core/components/issues/issue-layouts/filters/header/filters/completed-at.tsx diff --git a/packages/types/src/view-props.d.ts b/packages/types/src/view-props.d.ts index dca1a652c62..01554ede244 100644 --- a/packages/types/src/view-props.d.ts +++ b/packages/types/src/view-props.d.ts @@ -98,6 +98,7 @@ export interface IIssueFilterOptions { state_group?: string[] | null; subscriber?: string[] | null; target_date?: string[] | null; + completed_at?: string[] | null; issue_type?: string[] | null; } diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/completed-at.tsx b/web/core/components/issues/issue-layouts/filters/header/filters/completed-at.tsx new file mode 100644 index 00000000000..716abd4accb --- /dev/null +++ b/web/core/components/issues/issue-layouts/filters/header/filters/completed-at.tsx @@ -0,0 +1,76 @@ +import React, { useState } from "react"; +import { observer } from "mobx-react"; + +// components +import { DateFilterModal } from "@/components/core"; +import { FilterHeader, FilterOption } from "@/components/issues"; +// constants +import { DATE_AFTER_FILTER_OPTIONS } from "@/constants/filters"; + +type Props = { + appliedFilters: string[] | null; + handleUpdate: (val: string | string[]) => void; + searchQuery: string; +}; + +export const FilterCompletedAt: React.FC = observer((props) => { + const { appliedFilters, handleUpdate, searchQuery } = props; + + const [previewEnabled, setPreviewEnabled] = useState(true); + const [isDateFilterModalOpen, setIsDateFilterModalOpen] = useState(false); + + const appliedFiltersCount = appliedFilters?.length ?? 0; + + const filteredOptions = DATE_AFTER_FILTER_OPTIONS.filter((d) => + d.name.toLowerCase().includes(searchQuery.toLowerCase()) + ); + + const isCustomDateSelected = () => { + const isCustomDateApplied = appliedFilters?.filter((f) => f.includes("-")) || []; + return isCustomDateApplied.length > 0 ? true : false; + }; + const handleCustomDate = () => { + if (isCustomDateSelected()) { + const updateAppliedFilters = appliedFilters?.filter((f) => f.includes("-")) || []; + handleUpdate(updateAppliedFilters); + } else setIsDateFilterModalOpen(true); + }; + + return ( + <> + {isDateFilterModalOpen && ( + setIsDateFilterModalOpen(false)} + isOpen={isDateFilterModalOpen} + onSelect={(val) => handleUpdate(val)} + title="Completed date" + /> + )} + 0 ? ` (${appliedFiltersCount})` : ""}`} + isPreviewEnabled={previewEnabled} + handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)} + /> + {previewEnabled && ( +
+ {filteredOptions.length > 0 ? ( + <> + {filteredOptions.map((option) => ( + handleUpdate(option.value)} + title={option.name} + multiple + /> + ))} + + + ) : ( +

No matches found

+ )} +
+ )} + + ); +}); diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx b/web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx index 37eee9e936f..01f35dd2c8a 100644 --- a/web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx +++ b/web/core/components/issues/issue-layouts/filters/header/filters/filters-selection.tsx @@ -25,6 +25,7 @@ import { FilterCycle, FilterModule, FilterIssueGrouping, + FilterCompletedAt, } from "@/components/issues"; // hooks import { useMember } from "@/hooks/store"; @@ -278,6 +279,17 @@ export const FilterSelection: React.FC = observer((props) => { /> )} + + {/* completed_at */} + {isFilterEnabled("completed_at") && ( +
+ handleFiltersUpdate("completed_at", val)} + searchQuery={filtersSearchQuery} + /> +
+ )} ); diff --git a/web/core/components/issues/issue-layouts/filters/header/filters/index.ts b/web/core/components/issues/issue-layouts/filters/header/filters/index.ts index ab5756bf4d7..639935113d7 100644 --- a/web/core/components/issues/issue-layouts/filters/header/filters/index.ts +++ b/web/core/components/issues/issue-layouts/filters/header/filters/index.ts @@ -11,3 +11,4 @@ export * from "./state"; export * from "./cycle"; export * from "./module"; export * from "./target-date"; +export * from "./completed-at"; diff --git a/web/core/constants/issue.ts b/web/core/constants/issue.ts index 02d7ee01ad3..5e87822415c 100644 --- a/web/core/constants/issue.ts +++ b/web/core/constants/issue.ts @@ -212,6 +212,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: TIssueFiltersToDisplayByPageType = "labels", "start_date", "target_date", + "completed_at", "issue_type", ], display_properties: ISSUE_DISPLAY_PROPERTIES_KEYS, @@ -322,6 +323,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: TIssueFiltersToDisplayByPageType = "labels", "start_date", "target_date", + "completed_at", "issue_type", ], display_properties: ISSUE_DISPLAY_PROPERTIES_KEYS, @@ -347,6 +349,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: TIssueFiltersToDisplayByPageType = "labels", "start_date", "target_date", + "completed_at", "issue_type", ], display_properties: ISSUE_DISPLAY_PROPERTIES_KEYS, @@ -395,6 +398,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: TIssueFiltersToDisplayByPageType = "labels", "start_date", "target_date", + "completed_at", "issue_type", ], display_properties: ISSUE_DISPLAY_PROPERTIES_KEYS, @@ -419,6 +423,7 @@ export const ISSUE_DISPLAY_FILTERS_BY_LAYOUT: TIssueFiltersToDisplayByPageType = "labels", "start_date", "target_date", + "completed_at", "issue_type", ], display_properties: ["key", "issue_type"],