mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: filters view more and less buttons (#2583)
Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com>
This commit is contained in:
parent
36152ea2fa
commit
d63e7cf254
@ -9,15 +9,14 @@ import { IUserLite } from "types";
|
||||
type Props = {
|
||||
appliedFilters: string[] | null;
|
||||
handleUpdate: (val: string) => void;
|
||||
itemsToRender: number;
|
||||
members: IUserLite[] | undefined;
|
||||
searchQuery: string;
|
||||
viewButtons: React.ReactNode;
|
||||
};
|
||||
|
||||
export const FilterAssignees: React.FC<Props> = (props) => {
|
||||
const { appliedFilters, handleUpdate, itemsToRender, members, searchQuery, viewButtons } = props;
|
||||
const { appliedFilters, handleUpdate, members, searchQuery } = props;
|
||||
|
||||
const [itemsToRender, setItemsToRender] = useState(5);
|
||||
const [previewEnabled, setPreviewEnabled] = useState(true);
|
||||
|
||||
const appliedFiltersCount = appliedFilters?.length ?? 0;
|
||||
@ -26,6 +25,13 @@ export const FilterAssignees: React.FC<Props> = (props) => {
|
||||
member.display_name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
const handleViewToggle = () => {
|
||||
if (!filteredOptions) return;
|
||||
|
||||
if (itemsToRender === filteredOptions.length) setItemsToRender(5);
|
||||
else setItemsToRender(filteredOptions.length);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<FilterHeader
|
||||
@ -47,7 +53,15 @@ export const FilterAssignees: React.FC<Props> = (props) => {
|
||||
title={member.display_name}
|
||||
/>
|
||||
))}
|
||||
{viewButtons}
|
||||
{filteredOptions.length > 5 && (
|
||||
<button
|
||||
type="button"
|
||||
className="text-custom-primary-100 text-xs font-medium ml-8"
|
||||
onClick={handleViewToggle}
|
||||
>
|
||||
{itemsToRender === filteredOptions.length ? "View less" : "View all"}
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<p className="text-xs text-custom-text-400 italic">No matches found</p>
|
||||
|
@ -9,15 +9,14 @@ import { IUserLite } from "types";
|
||||
type Props = {
|
||||
appliedFilters: string[] | null;
|
||||
handleUpdate: (val: string) => void;
|
||||
itemsToRender: number;
|
||||
members: IUserLite[] | undefined;
|
||||
searchQuery: string;
|
||||
viewButtons: React.ReactNode;
|
||||
};
|
||||
|
||||
export const FilterCreatedBy: React.FC<Props> = (props) => {
|
||||
const { appliedFilters, handleUpdate, itemsToRender, members, searchQuery, viewButtons } = props;
|
||||
const { appliedFilters, handleUpdate, members, searchQuery } = props;
|
||||
|
||||
const [itemsToRender, setItemsToRender] = useState(5);
|
||||
const [previewEnabled, setPreviewEnabled] = useState(true);
|
||||
|
||||
const appliedFiltersCount = appliedFilters?.length ?? 0;
|
||||
@ -26,6 +25,13 @@ export const FilterCreatedBy: React.FC<Props> = (props) => {
|
||||
member.display_name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
const handleViewToggle = () => {
|
||||
if (!filteredOptions) return;
|
||||
|
||||
if (itemsToRender === filteredOptions.length) setItemsToRender(5);
|
||||
else setItemsToRender(filteredOptions.length);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<FilterHeader
|
||||
@ -47,7 +53,15 @@ export const FilterCreatedBy: React.FC<Props> = (props) => {
|
||||
title={member.display_name}
|
||||
/>
|
||||
))}
|
||||
{viewButtons}
|
||||
{filteredOptions.length > 5 && (
|
||||
<button
|
||||
type="button"
|
||||
className="text-custom-primary-100 text-xs font-medium ml-8"
|
||||
onClick={handleViewToggle}
|
||||
>
|
||||
{itemsToRender === filteredOptions.length ? "View less" : "View all"}
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<p className="text-xs text-custom-text-400 italic">No matches found</p>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useState } from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
import { Search, X } from "lucide-react";
|
||||
// components
|
||||
import {
|
||||
FilterAssignees,
|
||||
@ -14,15 +14,10 @@ import {
|
||||
FilterStateGroup,
|
||||
FilterTargetDate,
|
||||
} from "components/issues";
|
||||
// icons
|
||||
import { Search, X } from "lucide-react";
|
||||
// helpers
|
||||
import { getStatesList } from "helpers/state.helper";
|
||||
// types
|
||||
import { IIssueFilterOptions, IIssueLabels, IProject, IStateResponse, IUserLite } from "types";
|
||||
// constants
|
||||
import { ILayoutDisplayFiltersOptions, ISSUE_PRIORITIES, ISSUE_STATE_GROUPS } from "constants/issue";
|
||||
import { DATE_FILTER_OPTIONS } from "constants/filters";
|
||||
import { ILayoutDisplayFiltersOptions } from "constants/issue";
|
||||
|
||||
type Props = {
|
||||
filters: IIssueFilterOptions;
|
||||
@ -34,129 +29,11 @@ type Props = {
|
||||
states?: IStateResponse | undefined;
|
||||
};
|
||||
|
||||
type ViewButtonProps = {
|
||||
handleLess: () => void;
|
||||
handleMore: () => void;
|
||||
isViewLessVisible: boolean;
|
||||
isViewMoreVisible: boolean;
|
||||
};
|
||||
|
||||
const ViewButtons = ({ handleLess, handleMore, isViewLessVisible, isViewMoreVisible }: ViewButtonProps) => (
|
||||
<div className="flex items-center gap-2 ml-7 mt-1">
|
||||
{/* TODO: handle view more and less in a better way */}
|
||||
{isViewMoreVisible && (
|
||||
<button className="text-custom-primary-100 text-xs font-medium" onClick={handleMore}>
|
||||
View more
|
||||
</button>
|
||||
)}
|
||||
{isViewLessVisible && (
|
||||
<button className="text-custom-primary-100 text-xs font-medium" onClick={handleLess}>
|
||||
View less
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
export const FilterSelection: React.FC<Props> = observer((props) => {
|
||||
const { filters, handleFiltersUpdate, layoutDisplayFiltersOptions, labels, members, projects, states } = props;
|
||||
|
||||
const [filtersSearchQuery, setFiltersSearchQuery] = useState("");
|
||||
|
||||
const statesList = getStatesList(states);
|
||||
|
||||
const [filtersToRender, setFiltersToRender] = useState<{
|
||||
[key in keyof IIssueFilterOptions]: {
|
||||
currentLength: number;
|
||||
totalLength: number;
|
||||
};
|
||||
}>({
|
||||
assignees: {
|
||||
currentLength: 5,
|
||||
totalLength: members?.length ?? 0,
|
||||
},
|
||||
mentions: {
|
||||
currentLength: 5,
|
||||
totalLength: members?.length ?? 0,
|
||||
},
|
||||
created_by: {
|
||||
currentLength: 5,
|
||||
totalLength: members?.length ?? 0,
|
||||
},
|
||||
labels: {
|
||||
currentLength: 5,
|
||||
totalLength: labels?.length ?? 0,
|
||||
},
|
||||
priority: {
|
||||
currentLength: 5,
|
||||
totalLength: ISSUE_PRIORITIES.length,
|
||||
},
|
||||
project: {
|
||||
currentLength: 5,
|
||||
totalLength: projects?.length ?? 0,
|
||||
},
|
||||
state_group: {
|
||||
currentLength: 5,
|
||||
totalLength: ISSUE_STATE_GROUPS.length,
|
||||
},
|
||||
state: {
|
||||
currentLength: 5,
|
||||
totalLength: statesList?.length ?? 0,
|
||||
},
|
||||
start_date: {
|
||||
currentLength: 5,
|
||||
totalLength: DATE_FILTER_OPTIONS.length + 1,
|
||||
},
|
||||
target_date: {
|
||||
currentLength: 5,
|
||||
totalLength: DATE_FILTER_OPTIONS.length + 1,
|
||||
},
|
||||
});
|
||||
|
||||
const handleViewMore = (filterName: keyof IIssueFilterOptions) => {
|
||||
const filterDetails = filtersToRender[filterName];
|
||||
|
||||
if (!filterDetails) return;
|
||||
|
||||
if (filterDetails.currentLength <= filterDetails.totalLength)
|
||||
setFiltersToRender((prev) => ({
|
||||
...prev,
|
||||
[filterName]: {
|
||||
...prev[filterName],
|
||||
currentLength: filterDetails.currentLength + 5,
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
const handleViewLess = (filterName: keyof IIssueFilterOptions) => {
|
||||
const filterDetails = filtersToRender[filterName];
|
||||
|
||||
if (!filterDetails) return;
|
||||
|
||||
setFiltersToRender((prev) => ({
|
||||
...prev,
|
||||
[filterName]: {
|
||||
...prev[filterName],
|
||||
currentLength: 5,
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
const isViewMoreVisible = (filterName: keyof IIssueFilterOptions): boolean => {
|
||||
const filterDetails = filtersToRender[filterName];
|
||||
|
||||
if (!filterDetails) return false;
|
||||
|
||||
return filterDetails.currentLength < filterDetails.totalLength;
|
||||
};
|
||||
|
||||
const isViewLessVisible = (filterName: keyof IIssueFilterOptions): boolean => {
|
||||
const filterDetails = filtersToRender[filterName];
|
||||
|
||||
if (!filterDetails) return false;
|
||||
|
||||
return filterDetails.currentLength > 5;
|
||||
};
|
||||
|
||||
const isFilterEnabled = (filter: keyof IIssueFilterOptions) => layoutDisplayFiltersOptions?.filters.includes(filter);
|
||||
|
||||
return (
|
||||
@ -186,16 +63,7 @@ export const FilterSelection: React.FC<Props> = observer((props) => {
|
||||
<FilterPriority
|
||||
appliedFilters={filters.priority ?? null}
|
||||
handleUpdate={(val) => handleFiltersUpdate("priority", val)}
|
||||
itemsToRender={filtersToRender.priority?.currentLength ?? 0}
|
||||
searchQuery={filtersSearchQuery}
|
||||
viewButtons={
|
||||
<ViewButtons
|
||||
isViewLessVisible={isViewLessVisible("priority")}
|
||||
isViewMoreVisible={isViewMoreVisible("priority")}
|
||||
handleLess={() => handleViewLess("priority")}
|
||||
handleMore={() => handleViewMore("priority")}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -206,16 +74,7 @@ export const FilterSelection: React.FC<Props> = observer((props) => {
|
||||
<FilterStateGroup
|
||||
appliedFilters={filters.state_group ?? null}
|
||||
handleUpdate={(val) => handleFiltersUpdate("state_group", val)}
|
||||
itemsToRender={filtersToRender.state_group?.currentLength ?? 0}
|
||||
searchQuery={filtersSearchQuery}
|
||||
viewButtons={
|
||||
<ViewButtons
|
||||
isViewLessVisible={isViewLessVisible("state_group")}
|
||||
isViewMoreVisible={isViewMoreVisible("state_group")}
|
||||
handleLess={() => handleViewLess("state_group")}
|
||||
handleMore={() => handleViewMore("state_group")}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -226,17 +85,8 @@ export const FilterSelection: React.FC<Props> = observer((props) => {
|
||||
<FilterState
|
||||
appliedFilters={filters.state ?? null}
|
||||
handleUpdate={(val) => handleFiltersUpdate("state", val)}
|
||||
itemsToRender={filtersToRender.state?.currentLength ?? 0}
|
||||
searchQuery={filtersSearchQuery}
|
||||
states={states}
|
||||
viewButtons={
|
||||
<ViewButtons
|
||||
isViewLessVisible={isViewLessVisible("state")}
|
||||
isViewMoreVisible={isViewMoreVisible("state")}
|
||||
handleLess={() => handleViewLess("state")}
|
||||
handleMore={() => handleViewMore("state")}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -247,17 +97,8 @@ export const FilterSelection: React.FC<Props> = observer((props) => {
|
||||
<FilterAssignees
|
||||
appliedFilters={filters.assignees ?? null}
|
||||
handleUpdate={(val) => handleFiltersUpdate("assignees", val)}
|
||||
itemsToRender={filtersToRender.assignees?.currentLength ?? 0}
|
||||
members={members}
|
||||
searchQuery={filtersSearchQuery}
|
||||
viewButtons={
|
||||
<ViewButtons
|
||||
isViewLessVisible={isViewLessVisible("assignees")}
|
||||
isViewMoreVisible={isViewMoreVisible("assignees")}
|
||||
handleLess={() => handleViewLess("assignees")}
|
||||
handleMore={() => handleViewMore("assignees")}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -268,17 +109,8 @@ export const FilterSelection: React.FC<Props> = observer((props) => {
|
||||
<FilterMentions
|
||||
appliedFilters={filters.mentions ?? null}
|
||||
handleUpdate={(val) => handleFiltersUpdate("mentions", val)}
|
||||
itemsToRender={filtersToRender.mentions?.currentLength ?? 0}
|
||||
members={members}
|
||||
searchQuery={filtersSearchQuery}
|
||||
viewButtons={
|
||||
<ViewButtons
|
||||
isViewLessVisible={isViewLessVisible("mentions")}
|
||||
isViewMoreVisible={isViewMoreVisible("mentions")}
|
||||
handleLess={() => handleViewLess("mentions")}
|
||||
handleMore={() => handleViewMore("mentions")}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -289,17 +121,8 @@ export const FilterSelection: React.FC<Props> = observer((props) => {
|
||||
<FilterCreatedBy
|
||||
appliedFilters={filters.created_by ?? null}
|
||||
handleUpdate={(val) => handleFiltersUpdate("created_by", val)}
|
||||
itemsToRender={filtersToRender.created_by?.currentLength ?? 0}
|
||||
members={members}
|
||||
searchQuery={filtersSearchQuery}
|
||||
viewButtons={
|
||||
<ViewButtons
|
||||
isViewLessVisible={isViewLessVisible("created_by")}
|
||||
isViewMoreVisible={isViewMoreVisible("created_by")}
|
||||
handleLess={() => handleViewLess("created_by")}
|
||||
handleMore={() => handleViewMore("created_by")}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -310,17 +133,8 @@ export const FilterSelection: React.FC<Props> = observer((props) => {
|
||||
<FilterLabels
|
||||
appliedFilters={filters.labels ?? null}
|
||||
handleUpdate={(val) => handleFiltersUpdate("labels", val)}
|
||||
itemsToRender={filtersToRender.labels?.currentLength ?? 0}
|
||||
labels={labels}
|
||||
searchQuery={filtersSearchQuery}
|
||||
viewButtons={
|
||||
<ViewButtons
|
||||
isViewLessVisible={isViewLessVisible("labels")}
|
||||
isViewMoreVisible={isViewMoreVisible("labels")}
|
||||
handleLess={() => handleViewLess("labels")}
|
||||
handleMore={() => handleViewMore("labels")}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -332,16 +146,7 @@ export const FilterSelection: React.FC<Props> = observer((props) => {
|
||||
appliedFilters={filters.project ?? null}
|
||||
projects={projects}
|
||||
handleUpdate={(val) => handleFiltersUpdate("project", val)}
|
||||
itemsToRender={filtersToRender.project?.currentLength ?? 0}
|
||||
searchQuery={filtersSearchQuery}
|
||||
viewButtons={
|
||||
<ViewButtons
|
||||
isViewLessVisible={isViewLessVisible("project")}
|
||||
isViewMoreVisible={isViewMoreVisible("project")}
|
||||
handleLess={() => handleViewLess("project")}
|
||||
handleMore={() => handleViewMore("project")}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -352,7 +157,6 @@ export const FilterSelection: React.FC<Props> = observer((props) => {
|
||||
<FilterStartDate
|
||||
appliedFilters={filters.start_date ?? null}
|
||||
handleUpdate={(val) => handleFiltersUpdate("start_date", val)}
|
||||
itemsToRender={filtersToRender.start_date?.currentLength ?? 0}
|
||||
searchQuery={filtersSearchQuery}
|
||||
/>
|
||||
</div>
|
||||
@ -364,7 +168,6 @@ export const FilterSelection: React.FC<Props> = observer((props) => {
|
||||
<FilterTargetDate
|
||||
appliedFilters={filters.target_date ?? null}
|
||||
handleUpdate={(val) => handleFiltersUpdate("target_date", val)}
|
||||
itemsToRender={filtersToRender.target_date?.currentLength ?? 0}
|
||||
searchQuery={filtersSearchQuery}
|
||||
/>
|
||||
</div>
|
||||
|
@ -14,21 +14,27 @@ const LabelIcons = ({ color }: { color: string }) => (
|
||||
type Props = {
|
||||
appliedFilters: string[] | null;
|
||||
handleUpdate: (val: string) => void;
|
||||
itemsToRender: number;
|
||||
labels: IIssueLabels[] | undefined;
|
||||
searchQuery: string;
|
||||
viewButtons: React.ReactNode;
|
||||
};
|
||||
|
||||
export const FilterLabels: React.FC<Props> = (props) => {
|
||||
const { appliedFilters, handleUpdate, itemsToRender, labels, searchQuery, viewButtons } = props;
|
||||
const { appliedFilters, handleUpdate, labels, searchQuery } = props;
|
||||
|
||||
const [itemsToRender, setItemsToRender] = useState(5);
|
||||
const [previewEnabled, setPreviewEnabled] = useState(true);
|
||||
|
||||
const appliedFiltersCount = appliedFilters?.length ?? 0;
|
||||
|
||||
const filteredOptions = labels?.filter((label) => label.name.toLowerCase().includes(searchQuery.toLowerCase()));
|
||||
|
||||
const handleViewToggle = () => {
|
||||
if (!filteredOptions) return;
|
||||
|
||||
if (itemsToRender === filteredOptions.length) setItemsToRender(5);
|
||||
else setItemsToRender(filteredOptions.length);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<FilterHeader
|
||||
@ -50,7 +56,15 @@ export const FilterLabels: React.FC<Props> = (props) => {
|
||||
title={label.name}
|
||||
/>
|
||||
))}
|
||||
{viewButtons}
|
||||
{filteredOptions.length > 5 && (
|
||||
<button
|
||||
type="button"
|
||||
className="text-custom-primary-100 text-xs font-medium ml-8"
|
||||
onClick={handleViewToggle}
|
||||
>
|
||||
{itemsToRender === filteredOptions.length ? "View less" : "View all"}
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<p className="text-xs text-custom-text-400 italic">No matches found</p>
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
// components
|
||||
import { FilterHeader, FilterOption } from "components/issues";
|
||||
// ui
|
||||
@ -10,15 +9,14 @@ import { IUserLite } from "types";
|
||||
type Props = {
|
||||
appliedFilters: string[] | null;
|
||||
handleUpdate: (val: string) => void;
|
||||
itemsToRender: number;
|
||||
members: IUserLite[] | undefined;
|
||||
searchQuery: string;
|
||||
viewButtons: React.ReactNode;
|
||||
};
|
||||
|
||||
export const FilterMentions: React.FC<Props> = (props) => {
|
||||
const { appliedFilters, handleUpdate, itemsToRender, members, searchQuery, viewButtons } = props;
|
||||
const { appliedFilters, handleUpdate, members, searchQuery } = props;
|
||||
|
||||
const [itemsToRender, setItemsToRender] = useState(5);
|
||||
const [previewEnabled, setPreviewEnabled] = useState(true);
|
||||
|
||||
const appliedFiltersCount = appliedFilters?.length ?? 0;
|
||||
@ -27,6 +25,13 @@ export const FilterMentions: React.FC<Props> = (props) => {
|
||||
member.display_name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
const handleViewToggle = () => {
|
||||
if (!filteredOptions) return;
|
||||
|
||||
if (itemsToRender === filteredOptions.length) setItemsToRender(5);
|
||||
else setItemsToRender(filteredOptions.length);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<FilterHeader
|
||||
@ -48,7 +53,15 @@ export const FilterMentions: React.FC<Props> = (props) => {
|
||||
title={member.display_name}
|
||||
/>
|
||||
))}
|
||||
{viewButtons}
|
||||
{filteredOptions.length > 5 && (
|
||||
<button
|
||||
type="button"
|
||||
className="text-custom-primary-100 text-xs font-medium ml-8"
|
||||
onClick={handleViewToggle}
|
||||
>
|
||||
{itemsToRender === filteredOptions.length ? "View less" : "View all"}
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<p className="text-xs text-custom-text-400 italic">No matches found</p>
|
||||
|
@ -51,13 +51,11 @@ const PriorityIcons = ({
|
||||
type Props = {
|
||||
appliedFilters: string[] | null;
|
||||
handleUpdate: (val: string) => void;
|
||||
itemsToRender: number;
|
||||
searchQuery: string;
|
||||
viewButtons: React.ReactNode;
|
||||
};
|
||||
|
||||
export const FilterPriority: React.FC<Props> = observer((props) => {
|
||||
const { appliedFilters, handleUpdate, itemsToRender, searchQuery, viewButtons } = props;
|
||||
const { appliedFilters, handleUpdate, searchQuery } = props;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = useState(true);
|
||||
|
||||
@ -75,18 +73,15 @@ export const FilterPriority: React.FC<Props> = observer((props) => {
|
||||
{previewEnabled && (
|
||||
<div>
|
||||
{filteredOptions.length > 0 ? (
|
||||
<>
|
||||
{filteredOptions.slice(0, itemsToRender).map((priority) => (
|
||||
<FilterOption
|
||||
key={priority.key}
|
||||
isChecked={appliedFilters?.includes(priority.key) ? true : false}
|
||||
onClick={() => handleUpdate(priority.key)}
|
||||
icon={<PriorityIcons priority={priority.key} />}
|
||||
title={priority.title}
|
||||
/>
|
||||
))}
|
||||
{viewButtons}
|
||||
</>
|
||||
filteredOptions.map((priority) => (
|
||||
<FilterOption
|
||||
key={priority.key}
|
||||
isChecked={appliedFilters?.includes(priority.key) ? true : false}
|
||||
onClick={() => handleUpdate(priority.key)}
|
||||
icon={<PriorityIcons priority={priority.key} />}
|
||||
title={priority.title}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<p className="text-xs text-custom-text-400 italic">No matches found</p>
|
||||
)}
|
||||
|
@ -12,21 +12,27 @@ import { IProject } from "types";
|
||||
type Props = {
|
||||
appliedFilters: string[] | null;
|
||||
handleUpdate: (val: string) => void;
|
||||
itemsToRender: number;
|
||||
projects: IProject[] | undefined;
|
||||
searchQuery: string;
|
||||
viewButtons: React.ReactNode;
|
||||
};
|
||||
|
||||
export const FilterProjects: React.FC<Props> = (props) => {
|
||||
const { appliedFilters, handleUpdate, itemsToRender, projects, searchQuery, viewButtons } = props;
|
||||
const { appliedFilters, handleUpdate, projects, searchQuery } = props;
|
||||
|
||||
const [itemsToRender, setItemsToRender] = useState(5);
|
||||
const [previewEnabled, setPreviewEnabled] = useState(true);
|
||||
|
||||
const appliedFiltersCount = appliedFilters?.length ?? 0;
|
||||
|
||||
const filteredOptions = projects?.filter((project) => project.name.toLowerCase().includes(searchQuery.toLowerCase()));
|
||||
|
||||
const handleViewToggle = () => {
|
||||
if (!filteredOptions) return;
|
||||
|
||||
if (itemsToRender === filteredOptions.length) setItemsToRender(5);
|
||||
else setItemsToRender(filteredOptions.length);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<FilterHeader
|
||||
@ -62,7 +68,15 @@ export const FilterProjects: React.FC<Props> = (props) => {
|
||||
title={project.name}
|
||||
/>
|
||||
))}
|
||||
{viewButtons}
|
||||
{filteredOptions.length > 5 && (
|
||||
<button
|
||||
type="button"
|
||||
className="text-custom-primary-100 text-xs font-medium ml-8"
|
||||
onClick={handleViewToggle}
|
||||
>
|
||||
{itemsToRender === filteredOptions.length ? "View less" : "View all"}
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<p className="text-xs text-custom-text-400 italic">No matches found</p>
|
||||
|
@ -10,12 +10,11 @@ import { DATE_FILTER_OPTIONS } from "constants/filters";
|
||||
type Props = {
|
||||
appliedFilters: string[] | null;
|
||||
handleUpdate: (val: string | string[]) => void;
|
||||
itemsToRender: number;
|
||||
searchQuery: string;
|
||||
};
|
||||
|
||||
export const FilterStartDate: React.FC<Props> = observer((props) => {
|
||||
const { appliedFilters, handleUpdate, itemsToRender, searchQuery } = props;
|
||||
const { appliedFilters, handleUpdate, searchQuery } = props;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = useState(true);
|
||||
const [isDateFilterModalOpen, setIsDateFilterModalOpen] = useState(false);
|
||||
@ -43,7 +42,7 @@ export const FilterStartDate: React.FC<Props> = observer((props) => {
|
||||
<div>
|
||||
{filteredOptions.length > 0 ? (
|
||||
<>
|
||||
{filteredOptions.slice(0, itemsToRender).map((option) => (
|
||||
{filteredOptions.map((option) => (
|
||||
<FilterOption
|
||||
key={option.value}
|
||||
isChecked={appliedFilters?.includes(option.value) ? true : false}
|
||||
|
@ -11,20 +11,26 @@ import { ISSUE_STATE_GROUPS } from "constants/issue";
|
||||
type Props = {
|
||||
appliedFilters: string[] | null;
|
||||
handleUpdate: (val: string) => void;
|
||||
itemsToRender: number;
|
||||
searchQuery: string;
|
||||
viewButtons: React.ReactNode;
|
||||
};
|
||||
|
||||
export const FilterStateGroup: React.FC<Props> = observer((props) => {
|
||||
const { appliedFilters, handleUpdate, itemsToRender, searchQuery, viewButtons } = props;
|
||||
const { appliedFilters, handleUpdate, searchQuery } = props;
|
||||
|
||||
const [itemsToRender, setItemsToRender] = useState(5);
|
||||
const [previewEnabled, setPreviewEnabled] = useState(true);
|
||||
|
||||
const appliedFiltersCount = appliedFilters?.length ?? 0;
|
||||
|
||||
const filteredOptions = ISSUE_STATE_GROUPS.filter((s) => s.key.includes(searchQuery.toLowerCase()));
|
||||
|
||||
const handleViewToggle = () => {
|
||||
if (!filteredOptions) return;
|
||||
|
||||
if (itemsToRender === filteredOptions.length) setItemsToRender(5);
|
||||
else setItemsToRender(filteredOptions.length);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<FilterHeader
|
||||
@ -45,7 +51,15 @@ export const FilterStateGroup: React.FC<Props> = observer((props) => {
|
||||
title={stateGroup.title}
|
||||
/>
|
||||
))}
|
||||
{viewButtons}
|
||||
{filteredOptions.length > 5 && (
|
||||
<button
|
||||
type="button"
|
||||
className="text-custom-primary-100 text-xs font-medium ml-8"
|
||||
onClick={handleViewToggle}
|
||||
>
|
||||
{itemsToRender === filteredOptions.length ? "View less" : "View all"}
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<p className="text-xs text-custom-text-400 italic">No matches found</p>
|
||||
|
@ -12,15 +12,14 @@ import { IStateResponse } from "types";
|
||||
type Props = {
|
||||
appliedFilters: string[] | null;
|
||||
handleUpdate: (val: string) => void;
|
||||
itemsToRender: number;
|
||||
searchQuery: string;
|
||||
states: IStateResponse | undefined;
|
||||
viewButtons: React.ReactNode;
|
||||
};
|
||||
|
||||
export const FilterState: React.FC<Props> = (props) => {
|
||||
const { appliedFilters, handleUpdate, itemsToRender, searchQuery, states, viewButtons } = props;
|
||||
const { appliedFilters, handleUpdate, searchQuery, states } = props;
|
||||
|
||||
const [itemsToRender, setItemsToRender] = useState(5);
|
||||
const [previewEnabled, setPreviewEnabled] = useState(true);
|
||||
|
||||
const statesList = getStatesList(states);
|
||||
@ -29,6 +28,13 @@ export const FilterState: React.FC<Props> = (props) => {
|
||||
|
||||
const filteredOptions = statesList?.filter((s) => s.name.toLowerCase().includes(searchQuery.toLowerCase()));
|
||||
|
||||
const handleViewToggle = () => {
|
||||
if (!filteredOptions) return;
|
||||
|
||||
if (itemsToRender === filteredOptions.length) setItemsToRender(5);
|
||||
else setItemsToRender(filteredOptions.length);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<FilterHeader
|
||||
@ -50,7 +56,15 @@ export const FilterState: React.FC<Props> = (props) => {
|
||||
title={state.name}
|
||||
/>
|
||||
))}
|
||||
{viewButtons}
|
||||
{filteredOptions.length > 5 && (
|
||||
<button
|
||||
type="button"
|
||||
className="text-custom-primary-100 text-xs font-medium ml-8"
|
||||
onClick={handleViewToggle}
|
||||
>
|
||||
{itemsToRender === filteredOptions.length ? "View less" : "View all"}
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<p className="text-xs text-custom-text-400 italic">No matches found</p>
|
||||
|
@ -10,12 +10,11 @@ import { DATE_FILTER_OPTIONS } from "constants/filters";
|
||||
type Props = {
|
||||
appliedFilters: string[] | null;
|
||||
handleUpdate: (val: string | string[]) => void;
|
||||
itemsToRender: number;
|
||||
searchQuery: string;
|
||||
};
|
||||
|
||||
export const FilterTargetDate: React.FC<Props> = observer((props) => {
|
||||
const { appliedFilters, handleUpdate, itemsToRender, searchQuery } = props;
|
||||
const { appliedFilters, handleUpdate, searchQuery } = props;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = useState(true);
|
||||
const [isDateFilterModalOpen, setIsDateFilterModalOpen] = useState(false);
|
||||
@ -43,7 +42,7 @@ export const FilterTargetDate: React.FC<Props> = observer((props) => {
|
||||
<div>
|
||||
{filteredOptions.length > 0 ? (
|
||||
<>
|
||||
{filteredOptions.slice(0, itemsToRender).map((option) => (
|
||||
{filteredOptions.map((option) => (
|
||||
<FilterOption
|
||||
key={option.value}
|
||||
isChecked={appliedFilters?.includes(option.value) ? true : false}
|
||||
|
Loading…
Reference in New Issue
Block a user