diff --git a/packages/types/src/inbox.d.ts b/packages/types/src/inbox.d.ts
index 68e62f7bf..01a1dfce3 100644
--- a/packages/types/src/inbox.d.ts
+++ b/packages/types/src/inbox.d.ts
@@ -29,6 +29,7 @@ export type TInboxIssueFilter = {
} & {
[key in TInboxIssueFilterDateKeys]: string[] | undefined;
} & {
+ state: string[] | undefined;
status: TInboxIssueStatus[] | undefined;
priority: TIssuePriorities[] | undefined;
labels: string[] | undefined;
diff --git a/web/components/inbox/inbox-filter/applied-filters/index.ts b/web/components/inbox/inbox-filter/applied-filters/index.ts
index 35f0bc261..6113e51dd 100644
--- a/web/components/inbox/inbox-filter/applied-filters/index.ts
+++ b/web/components/inbox/inbox-filter/applied-filters/index.ts
@@ -1,5 +1,6 @@
export * from "./root";
export * from "./status";
+export * from "./state";
export * from "./priority";
export * from "./member";
export * from "./label";
diff --git a/web/components/inbox/inbox-filter/applied-filters/root.tsx b/web/components/inbox/inbox-filter/applied-filters/root.tsx
index 7aa50b0eb..77b29deca 100644
--- a/web/components/inbox/inbox-filter/applied-filters/root.tsx
+++ b/web/components/inbox/inbox-filter/applied-filters/root.tsx
@@ -7,6 +7,7 @@ import {
InboxIssueAppliedFiltersMember,
InboxIssueAppliedFiltersLabel,
InboxIssueAppliedFiltersDate,
+ InboxIssueAppliedFiltersState,
} from "@/components/inbox";
// hooks
import { useProjectInbox } from "@/hooks/store";
@@ -19,6 +20,8 @@ export const InboxIssueAppliedFilters: FC = observer(() => {
{/* status */}
+ {/* state */}
+
{/* priority */}
{/* assignees */}
diff --git a/web/components/inbox/inbox-filter/applied-filters/state.tsx b/web/components/inbox/inbox-filter/applied-filters/state.tsx
new file mode 100644
index 000000000..e4f7f5fbd
--- /dev/null
+++ b/web/components/inbox/inbox-filter/applied-filters/state.tsx
@@ -0,0 +1,52 @@
+import { FC } from "react";
+import { observer } from "mobx-react";
+import { X } from "lucide-react";
+import { StateGroupIcon } from "@plane/ui";
+// hooks
+import { useProjectInbox, useProjectState } from "@/hooks/store";
+
+export const InboxIssueAppliedFiltersState: FC = observer(() => {
+ // hooks
+ const { inboxFilters, handleInboxIssueFilters } = useProjectInbox();
+ const { getStateById } = useProjectState();
+ // derived values
+ const filteredValues = inboxFilters?.state || [];
+ const currentOptionDetail = (stateId: string) => getStateById(stateId) || undefined;
+
+ const handleFilterValue = (value: string): string[] =>
+ filteredValues?.includes(value) ? filteredValues.filter((v) => v !== value) : [...filteredValues, value];
+
+ const clearFilter = () => handleInboxIssueFilters("state", undefined);
+
+ if (filteredValues.length === 0) return <>>;
+ return (
+
+
Status
+ {filteredValues.map((value) => {
+ const optionDetail = currentOptionDetail(value);
+ if (!optionDetail) return <>>;
+ return (
+
+
+
+
+
{optionDetail?.name}
+
handleInboxIssueFilters("state", handleFilterValue(optionDetail?.id))}
+ >
+
+
+
+ );
+ })}
+
+
+
+
+
+ );
+});
diff --git a/web/components/inbox/inbox-filter/filters/filter-selection.tsx b/web/components/inbox/inbox-filter/filters/filter-selection.tsx
index d7bebdc11..fd1dc951c 100644
--- a/web/components/inbox/inbox-filter/filters/filter-selection.tsx
+++ b/web/components/inbox/inbox-filter/filters/filter-selection.tsx
@@ -8,9 +8,10 @@ import {
FilterMember,
FilterDate,
FilterLabels,
+ FilterState,
} from "@/components/inbox/inbox-filter/filters";
// hooks
-import { useMember, useLabel } from "@/hooks/store";
+import { useMember, useLabel, useProjectState } from "@/hooks/store";
export const InboxIssueFilterSelection: FC = observer(() => {
// hooks
@@ -18,6 +19,7 @@ export const InboxIssueFilterSelection: FC = observer(() => {
project: { projectMemberIds },
} = useMember();
const { projectLabels } = useLabel();
+ const { projectStates } = useProjectState();
// states
const [filtersSearchQuery, setFiltersSearchQuery] = useState("");
@@ -47,6 +49,10 @@ export const InboxIssueFilterSelection: FC = observer(() => {
+ {/* state */}
+
+
+
{/* Priority */}
diff --git a/web/components/inbox/inbox-filter/filters/index.ts b/web/components/inbox/inbox-filter/filters/index.ts
index a389dda9d..4cd0d31f1 100644
--- a/web/components/inbox/inbox-filter/filters/index.ts
+++ b/web/components/inbox/inbox-filter/filters/index.ts
@@ -1,5 +1,6 @@
export * from "./filter-selection";
export * from "./status";
+export * from "./state";
export * from "./priority";
export * from "./labels";
export * from "./members";
diff --git a/web/components/inbox/inbox-filter/filters/state.tsx b/web/components/inbox/inbox-filter/filters/state.tsx
new file mode 100644
index 000000000..b3cfad435
--- /dev/null
+++ b/web/components/inbox/inbox-filter/filters/state.tsx
@@ -0,0 +1,84 @@
+import { FC, useState } from "react";
+import { observer } from "mobx-react";
+import { IState } from "@plane/types";
+import { Loader, StateGroupIcon } from "@plane/ui";
+// components
+import { FilterHeader, FilterOption } from "@/components/issues";
+// hooks
+import { useProjectInbox } from "@/hooks/store";
+
+type Props = {
+ states: IState[] | undefined;
+ searchQuery: string;
+};
+
+export const FilterState: FC
= observer((props) => {
+ const { states, searchQuery } = props;
+
+ const [itemsToRender, setItemsToRender] = useState(5);
+ const [previewEnabled, setPreviewEnabled] = useState(true);
+
+ const { inboxFilters, handleInboxIssueFilters } = useProjectInbox();
+
+ const filterValue = inboxFilters?.state || [];
+
+ const appliedFiltersCount = filterValue?.length ?? 0;
+
+ const filteredOptions = states?.filter((state) => state.name.toLowerCase().includes(searchQuery.toLowerCase()));
+
+ const handleViewToggle = () => {
+ if (!filteredOptions) return;
+
+ if (itemsToRender === filteredOptions.length) setItemsToRender(5);
+ else setItemsToRender(filteredOptions.length);
+ };
+
+ const handleFilterValue = (value: string): string[] =>
+ filterValue?.includes(value) ? filterValue.filter((v) => v !== value) : [...filterValue, value];
+
+ return (
+ <>
+ 0 ? ` (${appliedFiltersCount})` : ""}`}
+ isPreviewEnabled={previewEnabled}
+ handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
+ />
+ {previewEnabled && (
+
+ {filteredOptions ? (
+ filteredOptions.length > 0 ? (
+ <>
+ {filteredOptions.slice(0, itemsToRender).map((state) => (
+
handleInboxIssueFilters("state", handleFilterValue(state.id))}
+ icon={}
+ title={state.name}
+ />
+ ))}
+ {filteredOptions.length > 5 && (
+
+ )}
+ >
+ ) : (
+ No matches found
+ )
+ ) : (
+
+
+
+
+
+ )}
+
+ )}
+ >
+ );
+});
diff --git a/web/store/inbox/project-inbox.store.ts b/web/store/inbox/project-inbox.store.ts
index 07013e83d..b253b76fc 100644
--- a/web/store/inbox/project-inbox.store.ts
+++ b/web/store/inbox/project-inbox.store.ts
@@ -216,6 +216,8 @@ export class ProjectInboxStore implements IProjectInboxStore {
set(this, "inboxFilters", undefined);
set(this, ["inboxSorting", "order_by"], "issue__created_at");
set(this, ["inboxSorting", "sort_by"], "desc");
+ set(this, ["inboxIssues"], {});
+ set(this, ["inboxIssuePaginationInfo"], undefined);
if (tab === "closed") set(this, ["inboxFilters", "status"], [-1, 1, 2]);
else set(this, ["inboxFilters", "status"], [-2]);
const { workspaceSlug, projectId } = this.store.app.router;
@@ -224,12 +226,16 @@ export class ProjectInboxStore implements IProjectInboxStore {
handleInboxIssueFilters = (key: T, value: TInboxIssueFilter[T]) => {
set(this.inboxFilters, key, value);
+ set(this, ["inboxIssues"], {});
+ set(this, ["inboxIssuePaginationInfo"], undefined);
const { workspaceSlug, projectId } = this.store.app.router;
if (workspaceSlug && projectId) this.fetchInboxIssues(workspaceSlug, projectId, "filter-loading");
};
handleInboxIssueSorting = (key: T, value: TInboxIssueSorting[T]) => {
set(this.inboxSorting, key, value);
+ set(this, ["inboxIssues"], {});
+ set(this, ["inboxIssuePaginationInfo"], undefined);
const { workspaceSlug, projectId } = this.store.app.router;
if (workspaceSlug && projectId) this.fetchInboxIssues(workspaceSlug, projectId, "filter-loading");
};