diff --git a/apps/app/components/core/issues-view-filter.tsx b/apps/app/components/core/issues-view-filter.tsx index a3e2af412..a3a5621c7 100644 --- a/apps/app/components/core/issues-view-filter.tsx +++ b/apps/app/components/core/issues-view-filter.tsx @@ -2,33 +2,22 @@ import React from "react"; import { useRouter } from "next/router"; -import useSWR from "swr"; - -// services -import projectService from "services/project.service"; -import issuesService from "services/issues.service"; -import stateService from "services/state.service"; // hooks import useIssuesProperties from "hooks/use-issue-properties"; import useIssuesView from "hooks/use-issues-view"; // headless ui import { Popover, Transition } from "@headlessui/react"; // components -import { PRIORITIES } from "constants/project"; +import { SelectFilters } from "components/views"; // ui -import { Avatar, CustomMenu, MultiLevelDropdown } from "components/ui"; +import { CustomMenu } from "components/ui"; // icons import { ChevronDownIcon, ListBulletIcon } from "@heroicons/react/24/outline"; import { Squares2X2Icon } from "@heroicons/react/20/solid"; -import { getStateGroupIcon } from "components/icons"; -import { getPriorityIcon } from "components/icons/priority-icon"; // helpers import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper"; -import { getStatesList } from "helpers/state.helper"; // types -import { IIssueLabels, Properties } from "types"; -// fetch-keys -import { PROJECT_ISSUE_LABELS, PROJECT_MEMBERS, STATE_LIST } from "constants/fetch-keys"; +import { Properties } from "types"; // constants import { GROUP_BY_OPTIONS, ORDER_BY_OPTIONS, FILTER_ISSUE_OPTIONS } from "constants/issue"; @@ -57,28 +46,6 @@ export const IssuesFilterView: React.FC = () => { projectId as string ); - const { data: states } = useSWR( - workspaceSlug && projectId ? STATE_LIST(projectId as string) : null, - workspaceSlug && projectId - ? () => stateService.getStates(workspaceSlug as string, projectId as string) - : null - ); - const statesList = getStatesList(states ?? {}); - - const { data: members } = useSWR( - projectId ? PROJECT_MEMBERS(projectId as string) : null, - workspaceSlug && projectId - ? () => projectService.projectMembers(workspaceSlug as string, projectId as string) - : null - ); - - const { data: issueLabels } = useSWR( - workspaceSlug && projectId ? PROJECT_ISSUE_LABELS(projectId as string) : null, - workspaceSlug && projectId - ? () => issuesService.getIssueLabels(workspaceSlug as string, projectId as string) - : null - ); - return (
@@ -101,8 +68,8 @@ export const IssuesFilterView: React.FC = () => {
- { setFilters( { @@ -116,71 +83,6 @@ export const IssuesFilterView: React.FC = () => { ); }} direction="left" - options={[ - { - id: "priority", - label: "Priority", - value: PRIORITIES, - children: [ - ...PRIORITIES.map((priority) => ({ - id: priority ?? "none", - label: ( -
- {getPriorityIcon(priority)} {priority ?? "None"} -
- ), - value: { - key: "priority", - value: priority, - }, - selected: filters?.priority?.includes(priority ?? "none"), - })), - ], - }, - { - id: "state", - label: "State", - value: statesList, - children: [ - ...statesList.map((state) => ({ - id: state.id, - label: ( -
- {getStateGroupIcon(state.group, "16", "16", state.color)} {state.name} -
- ), - value: { - key: "state", - value: state.id, - }, - selected: filters?.state?.includes(state.id), - })), - ], - }, - { - id: "assignees", - label: "Assignees", - value: members, - children: [ - ...(members?.map((member) => ({ - id: member.member.id, - label: ( -
- - {member.member.first_name && member.member.first_name !== "" - ? member.member.first_name - : member.member.email} -
- ), - value: { - key: "assignees", - value: member.member.id, - }, - selected: filters?.assignees?.includes(member.member.id), - })) ?? []), - ], - }, - ]} /> {({ open }) => ( diff --git a/apps/app/components/icons/index.ts b/apps/app/components/icons/index.ts index f9f395880..61be2d691 100644 --- a/apps/app/components/icons/index.ts +++ b/apps/app/components/icons/index.ts @@ -24,6 +24,7 @@ export * from "./layer-diagonal-icon"; export * from "./lock-icon"; export * from "./menu-icon"; export * from "./plus-icon"; +export * from "./priority-icon"; export * from "./question-mark-circle-icon"; export * from "./setting-icon"; export * from "./signal-cellular-icon"; diff --git a/apps/app/components/views/form.tsx b/apps/app/components/views/form.tsx index ed2e0933e..8a9dd2e95 100644 --- a/apps/app/components/views/form.tsx +++ b/apps/app/components/views/form.tsx @@ -6,14 +6,7 @@ import useSWR from "swr"; import { useForm } from "react-hook-form"; // ui -import { - Avatar, - Input, - MultiLevelDropdown, - PrimaryButton, - SecondaryButton, - TextArea, -} from "components/ui"; +import { Avatar, Input, PrimaryButton, SecondaryButton, TextArea } from "components/ui"; // types import { IView } from "types"; // constant @@ -23,11 +16,12 @@ import { getStatesList } from "helpers/state.helper"; // services import stateService from "services/state.service"; import projectService from "services/project.service"; +// components +import { SelectFilters } from "components/views"; // icons import { getStateGroupIcon } from "components/icons"; import { getPriorityIcon } from "components/icons/priority-icon"; // components -import { PRIORITIES } from "constants/project"; type Props = { handleFormSubmit: (values: IView) => Promise; @@ -139,8 +133,8 @@ export const ViewForm: React.FC = ({ />
- { const key = option.key as keyof typeof filters; @@ -156,72 +150,6 @@ export const ViewForm: React.FC = ({ }); } }} - direction="right" - options={[ - { - id: "priority", - label: "Priority", - value: PRIORITIES, - children: [ - ...PRIORITIES.map((priority) => ({ - id: priority ?? "none", - label: ( -
- {getPriorityIcon(priority)} {priority ?? "None"} -
- ), - value: { - key: "priority", - value: priority, - }, - selected: filters?.priority?.includes(priority ?? "none"), - })), - ], - }, - { - id: "state", - label: "State", - value: statesList, - children: [ - ...statesList.map((state) => ({ - id: state.id, - label: ( -
- {getStateGroupIcon(state.group, "16", "16", state.color)} {state.name} -
- ), - value: { - key: "state", - value: state.id, - }, - selected: filters?.state?.includes(state.id), - })), - ], - }, - { - id: "assignee", - label: "Assignee", - value: members, - children: [ - ...(members?.map((member) => ({ - id: member.member.id, - label: ( -
- - {member.member.first_name && member.member.first_name !== "" - ? member.member.first_name - : member.member.email} -
- ), - value: { - key: "assignees", - value: member.member.id, - }, - selected: filters?.assignees?.includes(member.member.id), - })) ?? []), - ], - }, - ]} />
@@ -257,8 +185,9 @@ export const ViewForm: React.FC = ({ else if (queryKey === "assignees") return (
- {filters.assignees?.map((assigneeID) => { - const member = members?.find((member) => member.member.id === assigneeID); + {filters.assignees?.map((assigneeId) => { + const member = members?.find((member) => member.member.id === assigneeId); + if (!member) return null; return (
diff --git a/apps/app/components/views/index.ts b/apps/app/components/views/index.ts index 9a2c56a4e..cad0d63d8 100644 --- a/apps/app/components/views/index.ts +++ b/apps/app/components/views/index.ts @@ -1,3 +1,4 @@ export * from "./delete-view-modal"; export * from "./form"; export * from "./modal"; +export * from "./select-filters"; diff --git a/apps/app/components/views/select-filters.tsx b/apps/app/components/views/select-filters.tsx new file mode 100644 index 000000000..496147be1 --- /dev/null +++ b/apps/app/components/views/select-filters.tsx @@ -0,0 +1,118 @@ +import { useRouter } from "next/router"; + +import useSWR from "swr"; + +// services +import stateService from "services/state.service"; +import projectService from "services/project.service"; +// ui +import { Avatar, MultiLevelDropdown } from "components/ui"; +// icons +import { getPriorityIcon, getStateGroupIcon } from "components/icons"; +// helpers +import { getStatesList } from "helpers/state.helper"; +// types +import { IIssueFilterOptions, IQuery } from "types"; +// fetch-keys +import { PROJECT_MEMBERS, STATE_LIST } from "constants/fetch-keys"; +// constants +import { PRIORITIES } from "constants/project"; + +type Props = { + filters: IIssueFilterOptions | IQuery; + onSelect: (option: any) => void; + direction?: "left" | "right"; +}; + +export const SelectFilters: React.FC = ({ filters, onSelect, direction = "right" }) => { + const router = useRouter(); + const { workspaceSlug, projectId } = router.query; + + const { data: states } = useSWR( + workspaceSlug && projectId ? STATE_LIST(projectId as string) : null, + workspaceSlug && projectId + ? () => stateService.getStates(workspaceSlug as string, projectId as string) + : null + ); + const statesList = getStatesList(states ?? {}); + + const { data: members } = useSWR( + projectId ? PROJECT_MEMBERS(projectId as string) : null, + workspaceSlug && projectId + ? () => projectService.projectMembers(workspaceSlug as string, projectId as string) + : null + ); + + return ( + ({ + id: priority ?? "none", + label: ( +
+ {getPriorityIcon(priority)} {priority ?? "None"} +
+ ), + value: { + key: "priority", + value: priority, + }, + selected: filters?.priority?.includes(priority ?? "none"), + })), + ], + }, + { + id: "state", + label: "State", + value: statesList, + children: [ + ...statesList.map((state) => ({ + id: state.id, + label: ( +
+ {getStateGroupIcon(state.group, "16", "16", state.color)} {state.name} +
+ ), + value: { + key: "state", + value: state.id, + }, + selected: filters?.state?.includes(state.id), + })), + ], + }, + { + id: "assignees", + label: "Assignees", + value: members, + children: [ + ...(members?.map((member) => ({ + id: member.member.id, + label: ( +
+ + {member.member.first_name && member.member.first_name !== "" + ? member.member.first_name + : member.member.email} +
+ ), + value: { + key: "assignees", + value: member.member.id, + }, + selected: filters?.assignees?.includes(member.member.id), + })) ?? []), + ], + }, + ]} + /> + ); +}; diff --git a/apps/app/pages/[workspaceSlug]/projects/[projectId]/views/index.tsx b/apps/app/pages/[workspaceSlug]/projects/[projectId]/views/index.tsx index 631705627..56b007a04 100644 --- a/apps/app/pages/[workspaceSlug]/projects/[projectId]/views/index.tsx +++ b/apps/app/pages/[workspaceSlug]/projects/[projectId]/views/index.tsx @@ -116,7 +116,7 @@ const ProjectViews: NextPage = () => { /> ) ) : ( - +