/** * Copyright (c) 2023-present Plane Software, Inc. and contributors * SPDX-License-Identifier: AGPL-3.0-only * See the LICENSE file for details. */ import { useCallback, useEffect, useRef, useState } from "react"; import { observer } from "mobx-react"; import { CloseOutline, FilterOutline, SearchOutline } from "@makeplane/propel/icons"; // plane imports import { useOutsideClickDetector } from "@plane/hooks"; import { IconButton } from "@plane/propel/icon-button"; import { useTranslation } from "@plane/i18n"; import type { TCycleFilters } from "@plane/types"; import { cn, calculateTotalFilters } from "@plane/utils"; // components import { FiltersDropdown } from "@/components/issues/issue-layouts/filters"; // hooks import { useCycleFilter } from "@/hooks/store/use-cycle-filter"; // local imports import { CycleFiltersSelection } from "./dropdowns"; type Props = { projectId: string; }; export const CyclesViewHeader = observer(function CyclesViewHeader(props: Props) { const { projectId } = props; // refs const inputRef = useRef(null); // hooks const { currentProjectFilters, searchQuery, updateFilters, updateSearchQuery } = useCycleFilter(); const { t } = useTranslation(); // states const [isSearchOpen, setIsSearchOpen] = useState(searchQuery !== "" ? true : false); // outside click detector hook useOutsideClickDetector(inputRef, () => { if (isSearchOpen && searchQuery.trim() === "") setIsSearchOpen(false); }); const handleFilters = useCallback( (key: keyof TCycleFilters, value: string | string[]) => { if (!projectId) return; const newValues = currentProjectFilters?.[key] ?? []; if (Array.isArray(value)) value.forEach((val) => { if (!newValues.includes(val)) newValues.push(val); else newValues.splice(newValues.indexOf(val), 1); }); else { if (currentProjectFilters?.[key]?.includes(value)) newValues.splice(newValues.indexOf(value), 1); else newValues.push(value); } updateFilters(projectId, { [key]: newValues }); }, [currentProjectFilters, projectId, updateFilters] ); const handleInputKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Escape") { if (searchQuery && searchQuery.trim() !== "") updateSearchQuery(""); else { setIsSearchOpen(false); inputRef.current?.blur(); } } }; const isFiltersApplied = calculateTotalFilters(currentProjectFilters ?? {}) !== 0; useEffect(() => { if (searchQuery.trim() !== "") setIsSearchOpen(true); }, [searchQuery]); return (
{!isSearchOpen ? ( { setIsSearchOpen(true); inputRef.current?.focus(); }} icon={SearchOutline} /> ) : (
updateSearchQuery(e.target.value)} onKeyDown={handleInputKeyDown} /> {isSearchOpen && ( )}
)} } title={t("common.filters")} placement="bottom-end" isFiltersApplied={isFiltersApplied} >
); });