Skip to content

Commit

Permalink
Add types and fix comments
Browse files Browse the repository at this point in the history
  • Loading branch information
adhityamamallan committed May 23, 2024
1 parent a677930 commit 75b221b
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 62 deletions.
21 changes: 15 additions & 6 deletions src/components/page-filters/__fixtures__/page-filters.fixtures.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import type { PageQueryParams } from '@/hooks/use-page-query-params/use-page-query-params.types';
import type { PageQueryParam } from '@/hooks/use-page-query-params/use-page-query-params.types';

export const defaultParamA = 'valueA1';
export const defaultParamB = 'valueB1';
export const mockPageQueryParamConfig: PageQueryParams = [
{ key: 'search' },
const defaultParamA = 'valueA1';
const defaultParamB = 'valueB1';

export const mockPageQueryParamConfig: [
PageQueryParam<'search', string>,
PageQueryParam<'paramA', string>,
PageQueryParam<'paramB', string>,
] = [
{
key: 'search',
defaultValue: '',
},
{ key: 'paramA', defaultValue: defaultParamA },
{ key: 'paramB', defaultValue: defaultParamB },
];
] as const;

export const mockQueryParamsValues = {
search: '',
paramA: defaultParamA,
Expand Down
28 changes: 9 additions & 19 deletions src/components/page-filters/__tests__/page-filters.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ import { type PageQueryParamValues } from '@/hooks/use-page-query-params/use-pag

import PageFilters from '../page-filters';
import {
PageFilterComponentProps,
PageFilterConfig,
type PageFilterComponentProps,
type PageFilterConfig,
} from '../page-filters.types';
import {
mockQueryParamsValues,
mockPageQueryParamConfig,
defaultParamA,
defaultParamB,
} from '../__fixtures__/page-filters.fixtures';

const mockSetQueryParams = jest.fn();
Expand All @@ -26,7 +24,7 @@ const MockFilterA = ({
}: PageFilterComponentProps<typeof mockPageQueryParamConfig>) => {
return (
<div>
<div>Value 1: {queryParams.valueA1}</div>
<div>Value 1: {queryParams.paramA}</div>
<div
data-testid="change-filters"
onClick={() => setQueryParams({ paramA: 'valueA2' })}
Expand All @@ -41,7 +39,7 @@ const MockFilterB = ({
}: PageFilterComponentProps<typeof mockPageQueryParamConfig>) => {
return (
<div>
<div>Value 2: {queryParams.valueA1}</div>
<div>Value 2: {queryParams.paramB}</div>
<div
data-testid="change-filters"
onClick={() => setQueryParams({ paramB: 'valueB2' })}
Expand All @@ -56,12 +54,12 @@ const MOCK_FILTERS_CONFIG: Array<
{
id: 'filterA',
component: MockFilterA,
isSet: ({ queryParams }) => queryParams.paramA !== defaultParamA,
params: ['paramA'],
},
{
id: 'filterB',
component: MockFilterB,
isSet: ({ queryParams }) => queryParams.paramB !== defaultParamB,
params: ['paramB'],
},
];

Expand All @@ -71,15 +69,15 @@ afterEach(() => {

describe('PageFilters', () => {
it('should render search bar correctly and call setSearch on input change', async () => {
const { mockSetSearch } = setup({});
setup({});

const searchInput = await screen.findByRole('textbox');

act(() => {
fireEvent.change(searchInput, { target: { value: 'test-search' } });
});

expect(mockSetSearch).toHaveBeenCalledWith('test-search');
expect(mockSetQueryParams).toHaveBeenCalledWith({ search: 'test-search' });
});

it('should show filters when Filters button is clicked, and modify additional filters', async () => {
Expand All @@ -101,7 +99,7 @@ describe('PageFilters', () => {
expect(mockSetQueryParams).toHaveBeenCalledWith({ paramA: 'valueA2' });
});

it('should call resetFilters when clear filters button is pressed', async () => {
it('should reset filters when clear filters button is pressed', async () => {
setup({
valuesOverrides: { paramA: 'valueA2', paramB: 'valueB2' },
});
Expand Down Expand Up @@ -129,8 +127,6 @@ function setup({
PageQueryParamValues<typeof mockPageQueryParamConfig>
>;
}) {
const mockSetSearch = jest.fn();

if (valuesOverrides) {
jest
.spyOn(usePageQueryParamsModule, 'default')
Expand All @@ -142,16 +138,10 @@ function setup({

render(
<PageFilters
search=""
searchId="search"
setSearch={mockSetSearch}
searchPlaceholder="placeholder"
pageFiltersConfig={MOCK_FILTERS_CONFIG}
pageQueryParamsConfig={mockPageQueryParamConfig}
/>
);

return {
mockSetSearch,
};
}
57 changes: 33 additions & 24 deletions src/components/page-filters/page-filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,55 +6,64 @@ import { Input } from 'baseui/input';
import { Props } from './page-filters.types';
import { styled, overrides } from './page-filters.styles';
import {
PageQueryParamKeys,
PageQueryParamSetterValues,
PageQueryParams,
type PageQueryParams,
type PageQueryParamKeys,
type PageQueryParamSetterValues,
} from '@/hooks/use-page-query-params/use-page-query-params.types';
import usePageQueryParams from '@/hooks/use-page-query-params/use-page-query-params';

export default function PageFilters<T extends PageQueryParams>({
search,
export default function PageFilters<
P extends PageQueryParams,
K extends PageQueryParamKeys<P>,
>({
searchId,
setSearch,
searchPlaceholder,
pageFiltersConfig,
pageQueryParamsConfig,
}: Props<T>) {
}: Props<P, K>) {
const [areFiltersShown, setAreFiltersShown] = React.useState(false);
const [queryParams, setQueryParams] = usePageQueryParams(
pageQueryParamsConfig,
{ pageRerender: false }
);

const activeFiltersCount = React.useMemo(
() =>
pageFiltersConfig.filter((pageFilter) =>
pageFilter.isSet({ queryParams })
).length,
[pageFiltersConfig, queryParams]
);
const activeFiltersCount = React.useMemo(() => {
const configsByKey = Object.fromEntries(
pageQueryParamsConfig.map((c) => [c.key, c])
);
return pageFiltersConfig.filter((pageFilter) =>
pageFilter.params.some(
(param) =>
queryParams[param] &&
queryParams[param] !== configsByKey[param].defaultValue
)
).length;
}, [pageFiltersConfig, pageQueryParamsConfig, queryParams]);

const resetAllFilters = React.useCallback(() => {
setQueryParams(
pageQueryParamsConfig.reduce(
(acc: Partial<PageQueryParamSetterValues<T>>, config) => {
const queryParamKey: PageQueryParamKeys<T> = config.key;
if (queryParamKey !== searchId) {
acc[queryParamKey] = undefined;
}
pageFiltersConfig.reduce(
(acc, pageFilter) => {
pageFilter.params.forEach((param) => {
acc[param] = undefined;
});
return acc;
},
{}
{} as Partial<PageQueryParamSetterValues<P>>
)
);
}, [pageQueryParamsConfig, setQueryParams, searchId]);
}, [pageFiltersConfig, setQueryParams]);

return (
<styled.PageFiltersContainer>
<styled.SearchInputContainer>
<Input
value={search}
onChange={(e) => setSearch(e.target.value)}
value={queryParams[searchId]}
onChange={(event) =>
setQueryParams({
[searchId]: event.target.value,
} as Partial<PageQueryParamSetterValues<P>>)
}
placeholder={searchPlaceholder}
startEnhancer={() => <Search />}
clearOnEscape
Expand Down
26 changes: 13 additions & 13 deletions src/components/page-filters/page-filters.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,28 @@ import {
PageQueryParamValues,
PageQueryParams,
} from '@/hooks/use-page-query-params/use-page-query-params.types';
import type React from 'react';

export type PageFilterIsSetProps<T extends PageQueryParams> = {
queryParams: PageQueryParamValues<T>;
export type PageFilterIsSetProps<P extends PageQueryParams> = {
queryParams: PageQueryParamValues<P>;
};

export type PageFilterComponentProps<T extends PageQueryParams> = {
queryParams: PageQueryParamValues<T>;
setQueryParams: PageQueryParamSetter<T>;
};

export type PageFilterConfig<T extends PageQueryParams> = {
id: PageQueryParamKeys<T>;
component: React.ComponentType<PageFilterComponentProps<T>>;
isSet: (props: PageFilterIsSetProps<T>) => boolean;
export type PageFilterConfig<P extends PageQueryParams> = {
id: string;
component: React.ComponentType<PageFilterComponentProps<P>>;
params: Array<PageQueryParamKeys<P>>;
};

export interface Props<T extends PageQueryParams> {
search: string;
searchId: PageQueryParamKeys<T>;
setSearch: (value: string) => void;
export interface Props<
P extends PageQueryParams,
K extends PageQueryParamKeys<P>,
> {
searchId: PageQueryParamValues<P>[K] extends string ? K : never;
searchPlaceholder: string;
pageFiltersConfig: Array<PageFilterConfig<T>>;
pageQueryParamsConfig: T;
pageQueryParamsConfig: P;
pageFiltersConfig: Array<PageFilterConfig<P>>;
}

0 comments on commit 75b221b

Please sign in to comment.