import { observer } from "mobx-react-lite"; import { useRouter } from "next/router"; import size from "lodash/size"; // hooks import { useApplication, useIssues, useUser } from "hooks/store"; // components import { EmptyState, getEmptyStateImagePath } from "components/empty-state"; // constants import { EUserProjectRoles } from "constants/project"; import { EIssueFilterType, EIssuesStoreType } from "constants/issue"; // types import { IIssueFilterOptions } from "@plane/types"; interface EmptyStateProps { title: string; image: string; description?: string; comicBox?: { title: string; description: string }; primaryButton?: { text: string; icon?: React.ReactNode; onClick: () => void }; secondaryButton?: { text: string; onClick: () => void }; size?: "lg" | "sm" | undefined; disabled?: boolean | undefined; } export const ProjectEmptyState: React.FC = observer(() => { // router const router = useRouter(); const { workspaceSlug, projectId } = router.query; // store hooks const { commandPalette: commandPaletteStore, eventTracker: { setTrackElement }, } = useApplication(); const { membership: { currentProjectRole }, currentUser, } = useUser(); const { issuesFilter } = useIssues(EIssuesStoreType.PROJECT); const userFilters = issuesFilter?.issueFilters?.filters; const activeLayout = issuesFilter?.issueFilters?.displayFilters?.layout; const currentLayoutEmptyStateImagePath = getEmptyStateImagePath( "empty-filters", activeLayout ?? "list", currentUser?.theme.theme === "light" ); const EmptyStateImagePath = getEmptyStateImagePath("onboarding", "issues", currentUser?.theme.theme === "light"); const issueFilterCount = size( Object.fromEntries( Object.entries(userFilters ?? {}).filter(([key, value]) => value && Array.isArray(value) && value.length > 0) ) ); const handleClearAllFilters = () => { if (!workspaceSlug || !projectId) return; const newFilters: IIssueFilterOptions = {}; Object.keys(userFilters ?? {}).forEach((key) => { newFilters[key as keyof IIssueFilterOptions] = null; }); issuesFilter.updateFilters(workspaceSlug.toString(), projectId.toString(), EIssueFilterType.FILTERS, { ...newFilters, }); }; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER; const emptyStateProps: EmptyStateProps = issueFilterCount > 0 ? { title: "No issues found matching the filters applied", image: currentLayoutEmptyStateImagePath, secondaryButton: { text: "Clear all filters", onClick: handleClearAllFilters, }, } : { title: "Create an issue and assign it to someone, even yourself", description: "Think of issues as jobs, tasks, work, or JTBD. Which we like. An issue and its sub-issues are usually time-based actionables assigned to members of your team. Your team creates, assigns, and completes issues to move your project towards its goal.", image: EmptyStateImagePath, comicBox: { title: "Issues are building blocks in Plane.", description: "Redesign the Plane UI, Rebrand the company, or Launch the new fuel injection system are examples of issues that likely have sub-issues.", }, primaryButton: { text: "Create your first issue", onClick: () => { setTrackElement("PROJECT_EMPTY_STATE"); commandPaletteStore.toggleCreateIssueModal(true, EIssuesStoreType.PROJECT); }, }, size: "lg", disabled: !isEditingAllowed, }; return (
); });