Skip to content

Commit

Permalink
feat: integrate custom filters on dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
awinogradov committed Apr 20, 2023
1 parent 1b9182c commit 3d54b03
Show file tree
Hide file tree
Showing 3 changed files with 340 additions and 166 deletions.
115 changes: 89 additions & 26 deletions src/components/FiltersPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import React, { useCallback } from 'react';
import styled from 'styled-components';
import { useTranslations } from 'next-intl';
import { gapM, gapS, gray5, textColor } from '@taskany/colors';
import { Badge, Text, Input, nullable } from '@taskany/bricks';
import { gapM, gapS, gray5, gray6, gray9, textColor } from '@taskany/colors';
import { Badge, Text, Input, StarIcon, nullable, StarFilledIcon } from '@taskany/bricks';

import { Filter } from '../../graphql/@generated/genql';
import type { QueryState } from '../hooks/useUrlFilterParams';

import { PageContent } from './Page';
import { StateFilterDropdown } from './StateFilterDropdown';
Expand All @@ -12,8 +15,11 @@ import { LimitFilterDropdown } from './LimitFilterDropdown';
import { PriorityFilterDropdown } from './PriorityFilterDropdown';
import { EstimateFilterDropdown } from './EstimateFilterDropdown';
import { ProjectFilterDropdown } from './ProjectFilterDropdown';
import { PresetFilterDropdown } from './PresetFilterDropdown';

interface FiltersPanelProps {
queryState: QueryState;
queryString?: string;
count?: number;
filteredCount?: number;
priority?: React.ComponentProps<typeof PriorityFilterDropdown>['priority'];
Expand All @@ -22,7 +28,9 @@ interface FiltersPanelProps {
projects?: React.ComponentProps<typeof ProjectFilterDropdown>['projects'];
tags?: React.ComponentProps<typeof TagsFilterDropdown>['tags'];
estimates?: React.ComponentProps<typeof EstimateFilterDropdown>['estimates'];
filterValues: [string[], string[], string[], string[], string[], string[], string, number | undefined];
presets?: Filter[];
currentPreset?: Filter;
loading?: boolean;
children?: React.ReactNode;

onSearchChange: (search: string) => void;
Expand All @@ -33,13 +41,41 @@ interface FiltersPanelProps {
onTagChange?: React.ComponentProps<typeof TagsFilterDropdown>['onChange'];
onEstimateChange?: React.ComponentProps<typeof EstimateFilterDropdown>['onChange'];
onLimitChange?: React.ComponentProps<typeof LimitFilterDropdown>['onChange'];
onPresetChange?: React.ComponentProps<typeof PresetFilterDropdown>['onChange'];
onFilterStar?: () => void;
}

const StyledFiltersPanel = styled.div`
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const StyledFiltersPanel = styled(({ loading, ...props }) => <div {...props} />)<{ loading?: boolean }>`
margin: ${gapM} 0;
padding: ${gapS} 0;
background-color: ${gray5};
animation-name: bkgChange;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
transition: background-color 200ms ease-in-out;
@keyframes bkgChange {
0% {
background-color: ${gray5};
}
50.0% {
background-color: ${gray6};
}
100.0% {
background-color: ${gray5};
}
}
${({ loading }) =>
loading &&
`
animation-play-state: running;
animation-duration: 1s;
`}
`;

const StyledFiltersContent = styled(PageContent)`
Expand All @@ -61,7 +97,17 @@ const StyledFiltersMenu = styled.div`
padding-left: ${gapM};
`;

const StyledFiltersAction = styled.div`
display: inline-block;
padding-left: ${gapS};
padding-right: ${gapS};
vertical-align: middle;
cursor: pointer;
`;

export const FiltersPanel: React.FC<FiltersPanelProps> = ({
queryState,
queryString,
count,
filteredCount,
states,
Expand All @@ -70,7 +116,10 @@ export const FiltersPanel: React.FC<FiltersPanelProps> = ({
projects,
tags,
estimates,
filterValues,
presets,
currentPreset,
loading,
children,
onPriorityChange,
onSearchChange,
onStateChange,
Expand All @@ -79,21 +128,11 @@ export const FiltersPanel: React.FC<FiltersPanelProps> = ({
onTagChange,
onEstimateChange,
onLimitChange,
children,
onPresetChange,
onFilterStar,
}) => {
const t = useTranslations('FiltersPanel');

const [
priorityFilter,
stateFilter,
tagsFilter,
estimateFilter,
ownerFilter,
projectFilter,
searchFilter,
limitFilter,
] = filterValues;

const onSearchInputChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
onSearchChange(e.currentTarget.value);
Expand All @@ -102,9 +141,9 @@ export const FiltersPanel: React.FC<FiltersPanelProps> = ({
);

return (
<StyledFiltersPanel>
<StyledFiltersPanel loading={loading}>
<StyledFiltersContent>
<Input placeholder={t('Search')} value={searchFilter} onChange={onSearchInputChange} />
<Input placeholder={t('Search')} value={queryState.fulltextFilter} onChange={onSearchInputChange} />

<StyledFiltersMenuWrapper>
{nullable(count, () => (
Expand All @@ -129,7 +168,7 @@ export const FiltersPanel: React.FC<FiltersPanelProps> = ({
<PriorityFilterDropdown
text={t('Priority')}
priority={pr}
value={priorityFilter}
value={queryState.priorityFilter}
onChange={onPriorityChange}
/>
))}
Expand All @@ -140,7 +179,7 @@ export const FiltersPanel: React.FC<FiltersPanelProps> = ({
<StateFilterDropdown
text={t('State')}
states={st}
value={stateFilter}
value={queryState.stateFilter}
onChange={onStateChange}
/>
))}
Expand All @@ -151,7 +190,7 @@ export const FiltersPanel: React.FC<FiltersPanelProps> = ({
<UserFilterDropdown
text={t('Owner')}
activity={u}
value={ownerFilter}
value={queryState.ownerFilter}
onChange={onUserChange}
/>
))}
Expand All @@ -162,7 +201,7 @@ export const FiltersPanel: React.FC<FiltersPanelProps> = ({
<ProjectFilterDropdown
text={t('Project')}
projects={pr}
value={projectFilter}
value={queryState.projectFilter}
onChange={onProjectChange}
/>
))}
Expand All @@ -173,7 +212,7 @@ export const FiltersPanel: React.FC<FiltersPanelProps> = ({
<TagsFilterDropdown
text={t('Tags')}
tags={ta}
value={tagsFilter}
value={queryState.tagsFilter}
onChange={onTagChange}
/>
))}
Expand All @@ -184,15 +223,37 @@ export const FiltersPanel: React.FC<FiltersPanelProps> = ({
<EstimateFilterDropdown
text={t('Estimate')}
estimates={e}
value={estimateFilter}
value={queryState.estimateFilter}
onChange={onEstimateChange}
/>
))}

{onLimitChange &&
nullable(limitFilter, (lf) => (
nullable(queryState.limitFilter, (lf) => (
<LimitFilterDropdown text={t('Limit')} value={lf} onChange={onLimitChange} />
))}

{Boolean(presets?.length) &&
nullable(presets, (pr) => (
<PresetFilterDropdown
text={'Preset'}
presets={pr}
value={currentPreset ? currentPreset.id : undefined}
onChange={onPresetChange}
/>
))}

{Boolean(queryString) && !currentPreset && (
<StyledFiltersAction onClick={onFilterStar}>
<StarIcon size="s" color={gray9} noWrap />
</StyledFiltersAction>
)}

{currentPreset && (
<StyledFiltersAction onClick={onFilterStar}>
<StarFilledIcon size="s" color={gray9} noWrap />
</StyledFiltersAction>
)}
</StyledFiltersMenu>
</StyledFiltersMenuWrapper>

Expand All @@ -203,3 +264,5 @@ export const FiltersPanel: React.FC<FiltersPanelProps> = ({
</StyledFiltersPanel>
);
};

FiltersPanel.whyDidYouRender = true;
Loading

0 comments on commit 3d54b03

Please sign in to comment.