From 39f6cbd66cd095380794ca7a918411535feabc19 Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Wed, 17 Jul 2024 11:30:58 +0200 Subject: [PATCH] feat: insights filters (#7608) --- frontend/src/component/insights/Insights.tsx | 81 ++++++++++++++----- .../component/insights/InsightsFilters.tsx | 69 ++++++++++++++++ .../InsightsHeader/InsightsHeader.tsx | 1 + .../api/getters/useInsights/useInsights.ts | 4 +- 4 files changed, 134 insertions(+), 21 deletions(-) create mode 100644 frontend/src/component/insights/InsightsFilters.tsx diff --git a/frontend/src/component/insights/Insights.tsx b/frontend/src/component/insights/Insights.tsx index ac23815df2..c3f3340e37 100644 --- a/frontend/src/component/insights/Insights.tsx +++ b/frontend/src/component/insights/Insights.tsx @@ -11,8 +11,9 @@ import { InsightsHeader } from './components/InsightsHeader/InsightsHeader'; import { useInsightsData } from './hooks/useInsightsData'; import { InsightsCharts } from './InsightsCharts'; import { LegacyInsightsCharts } from './LegacyInsightsCharts'; -import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { useUiFlag } from 'hooks/useUiFlag'; +import { InsightsFilters } from './InsightsFilters'; +import { FilterItemParam } from '../../utils/serializeQueryParams'; const StickyWrapper = styled(Box, { shouldForwardProp: (prop) => prop !== 'scrolled', @@ -33,7 +34,7 @@ const StyledProjectSelect = styled(ProjectSelect)(({ theme }) => ({ }, })); -export const Insights: VFC = () => { +const LegacyInsights = () => { const [scrolled, setScrolled] = useState(false); const { insights, loading, error } = useInsights(); const stateConfig = { @@ -61,8 +62,6 @@ export const Insights: VFC = () => { window.addEventListener('scroll', handleScroll); } - const isInsightsV2Enabled = useUiFlag('insightsV2'); - return ( <> @@ -77,23 +76,65 @@ export const Insights: VFC = () => { } /> - - } - elseShow={ - - } + ); }; + +const NewInsights = () => { + const [scrolled, setScrolled] = useState(false); + + const stateConfig = { + projects: FilterItemParam, + from: FilterItemParam, + to: FilterItemParam, + }; + const [state, setState] = usePersistentTableState('insights', stateConfig); + const { insights, loading, error } = useInsights( + state.from?.values[0], + state.to?.values[0], + ); + + const projects = state.projects?.values ?? [allOption.id]; + + const insightsData = useInsightsData(insights, projects); + + const handleScroll = () => { + if (!scrolled && window.scrollY > 0) { + setScrolled(true); + } else if (scrolled && window.scrollY === 0) { + setScrolled(false); + } + }; + + if (typeof window !== 'undefined') { + window.addEventListener('scroll', handleScroll); + } + + return ( + <> + + + } + /> + + + + ); +}; + +export const Insights: VFC = () => { + const isInsightsV2Enabled = useUiFlag('insightsV2'); + if (isInsightsV2Enabled) return ; + return ; +}; diff --git a/frontend/src/component/insights/InsightsFilters.tsx b/frontend/src/component/insights/InsightsFilters.tsx new file mode 100644 index 0000000000..375226c1fd --- /dev/null +++ b/frontend/src/component/insights/InsightsFilters.tsx @@ -0,0 +1,69 @@ +import { type FC, useEffect, useState } from 'react'; +import useProjects from 'hooks/api/getters/useProjects/useProjects'; +import { + type FilterItemParamHolder, + Filters, + type IFilterItem, +} from 'component/filter/Filters/Filters'; + +interface IFeatureToggleFiltersProps { + state: FilterItemParamHolder; + onChange: (value: FilterItemParamHolder) => void; +} + +export const InsightsFilters: FC = ({ + state, + onChange, +}) => { + const { projects } = useProjects(); + + const [availableFilters, setAvailableFilters] = useState([]); + + useEffect(() => { + const projectsOptions = (projects || []).map((project) => ({ + label: project.name, + value: project.id, + })); + + const hasMultipleProjects = projectsOptions.length > 1; + + const availableFilters: IFilterItem[] = [ + { + label: 'Date From', + icon: 'today', + options: [], + filterKey: 'from', + dateOperators: ['IS'], + }, + { + label: 'Date To', + icon: 'today', + options: [], + filterKey: 'to', + dateOperators: ['IS'], + }, + ...(hasMultipleProjects + ? ([ + { + label: 'Project', + icon: 'topic', + options: projectsOptions, + filterKey: 'projects', + singularOperators: ['IS'], + pluralOperators: ['IS_ANY_OF'], + }, + ] as IFilterItem[]) + : []), + ]; + + setAvailableFilters(availableFilters); + }, [JSON.stringify(projects)]); + + return ( + + ); +}; diff --git a/frontend/src/component/insights/components/InsightsHeader/InsightsHeader.tsx b/frontend/src/component/insights/components/InsightsHeader/InsightsHeader.tsx index 1d4125fb8a..7a2dee00e2 100644 --- a/frontend/src/component/insights/components/InsightsHeader/InsightsHeader.tsx +++ b/frontend/src/component/insights/components/InsightsHeader/InsightsHeader.tsx @@ -18,6 +18,7 @@ type DashboardHeaderProps = { const StyledActionsContainer = styled('div')(({ theme }) => ({ display: 'flex', + alignItems: 'center', gap: theme.spacing(1), [theme.breakpoints.down('md')]: { flexDirection: 'column', diff --git a/frontend/src/hooks/api/getters/useInsights/useInsights.ts b/frontend/src/hooks/api/getters/useInsights/useInsights.ts index 7c3fd913d7..c522df362b 100644 --- a/frontend/src/hooks/api/getters/useInsights/useInsights.ts +++ b/frontend/src/hooks/api/getters/useInsights/useInsights.ts @@ -12,9 +12,11 @@ interface IUseInsightsDataOutput { } export const useInsights = ( + from = '', + to = '', options?: SWRConfiguration, ): IUseInsightsDataOutput => { - const path = formatApiPath('api/admin/insights'); + const path = formatApiPath(`api/admin/insights?from=${from}&to=${to}`); const { data, error } = useSWR( path,