Skip to content

Commit

Permalink
JNG-6075 improve card filters (#502)
Browse files Browse the repository at this point in the history
  • Loading branch information
noherczeg authored Jan 2, 2025
1 parent 6c3366d commit b915167
Showing 1 changed file with 58 additions and 17 deletions.
Original file line number Diff line number Diff line change
@@ -1,29 +1,38 @@
{{> fragment.header.hbs }}

import { type FC, useState, useCallback } from 'react';
import Box from '@mui/material/Box';
import Grid from '@mui/material/Grid';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import FormGroup from '@mui/material/FormGroup';
import FormControlLabel from '@mui/material/FormControlLabel';
import Checkbox from '@mui/material/Checkbox';
import TextField from '@mui/material/TextField';
import { debounce } from '@mui/material/utils';
import { FilterType } from '~/components-api';
import { useL10N } from '~/l10n/l10n-context';
import { useTranslation } from 'react-i18next';
import { debounceInputs } from '~/config';

export interface CardsFilterDefinition<T> {
type: FilterType;
operator?: any;
field: keyof T;
label: string;
values: { value: any, label: string }[];
inputType: 'options' | 'text',
searchLabel?: string;
allowSearch?: boolean;
values?: { value: any, label: string }[];
}

export const CardsFilter: FC<{ filterDefinitions: CardsFilterDefinition<any>[], onFiltersChanged?: (values: Record<string, any>) => void }> = ({ filterDefinitions, onFiltersChanged }) => {
const { locale: l10nLocale } = useL10N();
const { t } = useTranslation();

const [values, setValues] = useState<Record<string, any>>({});
const [searchValues, setSearchValues] = useState<Record<string, any>>({});
const [visibleValues, setVisibleValues] = useState<Record<string, any[]>>({});

const updateValue = useCallback((field: string, value: any) => {
const newValues = {
Expand All @@ -34,6 +43,11 @@ export const CardsFilter: FC<{ filterDefinitions: CardsFilterDefinition<any>[],
onFiltersChanged?.(newValues);
}, [values, onFiltersChanged]);

const updateValueDebounced = useCallback(
debounce(updateValue, debounceInputs),
[values, onFiltersChanged, updateValue],
);

const clearFilters = useCallback(() => {
// We need to explicitly null out values because our filter may refer to Transfer fields which are not in the list
// of columns. Other framework features rely on column info for e.g. queryCustomizer cleanup.
Expand All @@ -57,22 +71,49 @@ export const CardsFilter: FC<{ filterDefinitions: CardsFilterDefinition<any>[],
</Grid>
{filterDefinitions.map(d => (
<Grid item xs={12} key={d.field as string}>
<Typography variant="subtitle1">
{d.label}:
</Typography>
<FormGroup>
{d.values.map(v => (
<FormControlLabel
key={`${d.label}-${v.value}`}
control={<Checkbox
size="small"
checked={values[d.field as string] === v.value}
onClick={() => updateValue(d.field as string, v.value)}
/>}
label={v.label}
/>
))}
</FormGroup>
<Typography variant="subtitle1">{d.label}:</Typography>
{d.allowSearch ? (
<TextField
size="small"
variant="standard"
label={d.searchLabel}
defaultValue={searchValues[d.field as string]}
onChange={(evt) => {
setSearchValues((prev) => {
return {
...prev,
[d.field as string]: evt.target.value,
};
});
if (d.inputType === 'text') {
updateValueDebounced(d.field as string, evt.target.value);
}
} }
/>
) : null}
{d.values ? <Box sx={ { maxHeight: 170, overflowX: 'scroll' } }>
<FormGroup>
{d.values
.filter((v) =>
searchValues[d.field as string]
? v.label.toLowerCase().includes(searchValues[d.field as string].toLowerCase())
: true,
)
.map((v) => (
<FormControlLabel
key={`${d.label}-${v.value}`}
control={
<Checkbox
size="small"
checked={values[d.field as string] === v.value}
onClick={() => updateValue(d.field as string, v.value)}
/>
}
label={v.label}
/>
))}
</FormGroup>
</Box> : null}
</Grid>
))}
</Grid>
Expand Down

0 comments on commit b915167

Please sign in to comment.