Add a clear button that reset the filters values.

This commit is contained in:
Alexander Navarro 2023-11-04 19:49:25 -03:00
parent e6df894c85
commit b1979d7351
5 changed files with 143 additions and 97 deletions

View file

@ -6,6 +6,9 @@
padding: var(--prj-spacing-1);
background-color: var(--bg-color);
color: var(--text-color);
display: flex;
gap: var(--prj-spacing-1);
}
.input {
@ -16,9 +19,6 @@
font-size: 0.8em;
}
.realInput {
}
.selectedItem {
background-color: var(--prj-surface-3);
color: var(--prj-text);

View file

@ -11,12 +11,14 @@ interface Props {
options: [{ label: string; value: any }];
keyData: string;
isMultiple?: boolean;
value?: string | string[];
}
export default function SelectInput({
options,
isMultiple = false,
onChange,
value = [],
}: Props): JSX.Element {
const [selected, setSelected] = useState<string[]>([]);
const [filteredOptions, setFilteredOptions] = useState<Props['options']>([]);
@ -33,12 +35,12 @@ export default function SelectInput({
return;
}
onChange(isMultiple ? selected : selected.at(0));
onChange(isMultiple ? selected : selected[0]);
}, [selected]);
const handleFocusInput = (): void => {
setIsOptionsOpen(true);
inputRef.current.focus();
inputRef.current?.focus();
};
const handleAddElement = (item: any): void => {
@ -49,6 +51,9 @@ export default function SelectInput({
return [item];
});
setIsOptionsOpen(false);
if (inputRef.current === null) return;
inputRef.current.value = '';
};
@ -111,6 +116,14 @@ export default function SelectInput({
onChange={handleFilterOptions}
/>
</div>
<button
onClick={() => {
onChange(null);
setSelected([]);
}}
>
X
</button>
<div className={styles.optionList} hidden={!isOptionsOpen}>
{filteredOptions.map((item, idx) => (
<button

View file

@ -1,4 +1,4 @@
import React, { useMemo, useState } from 'react';
import React, { useMemo, useRef, useState } from 'react';
import usePagination, { Offset } from 'src/hooks/usePagination';
import {
SelectFilter,
@ -29,8 +29,11 @@ interface Props {
headers: Header[];
}
type Value = string | string[] | number | number[] | null;
export default function Table({ data, headers }: Props): JSX.Element {
const [filters, setFilters] = useState<Record<string, Filter>>({});
const filtersKey = useRef(crypto.randomUUID());
const filteredItems = useMemo(() => {
return data.filter((item) => {
@ -86,49 +89,31 @@ export default function Table({ data, headers }: Props): JSX.Element {
}
function formatFilter(header: Header): JSX.Element {
const baseProps = {
key: header.key + filtersKey.current,
keyData: header.key,
value: filters[header.key]?.value,
onChange: (value: Value) => {
handleUpdateFilters(header.key, header.type, value);
},
};
switch (header.type) {
case HeaderType.String:
return (
<input
onChange={(e) => {
handleUpdateFilters(
header.key,
header.type,
e.target.value ?? null,
);
baseProps.onChange(e.target.value);
}}
key={baseProps.key}
/>
);
case HeaderType.Number:
return (
<NumberInput
keyData={header.key}
onChange={(value) => {
handleUpdateFilters(header.key, header.type, value);
}}
/>
);
return <NumberInput {...baseProps} />;
case HeaderType.Select:
return (
<SelectFilter
data={data}
keyData={header.key}
onChange={(value) => {
handleUpdateFilters(header.key, header.type, value);
}}
/>
);
return <SelectFilter data={data} {...baseProps} />;
case HeaderType.Multiple:
return (
<SelectFilter
isMultiple
data={data}
keyData={header.key}
onChange={(value) => {
handleUpdateFilters(header.key, header.type, value);
}}
/>
);
return <SelectFilter {...baseProps} isMultiple data={data} />;
default:
break;
@ -139,32 +124,47 @@ export default function Table({ data, headers }: Props): JSX.Element {
return (
<>
<table style={{ width: '100%' }}>
<thead>
<tr>
{headers.map((item, idx) => (
<th key={idx}>
<div className="vstack">
{item.header}
{formatFilter(item)}
</div>
</th>
))}
</tr>
</thead>
<section className="hstack">
<button
className="ml-auto"
onClick={() => {
// FIXME: this clear the filters but not the value of the inputs
setFilters({});
filtersKey.current = crypto.randomUUID();
}}
>
Clear Filters
</button>
</section>
<tbody>
{items.map((item, idx) => (
<tr key={idx}>
{headers.map((header, hidx) => (
<td key={hidx}>{formatCell(item, header)}</td>
<section className="mt-1 overflow-scroll">
<table>
<thead>
<tr>
{headers.map((item, idx) => (
<th key={idx}>
<div className="vstack">
{item.header}
{formatFilter(item)}
</div>
</th>
))}
</tr>
))}
</tbody>
</table>
</thead>
<section>
<tbody>
{items.map((item, idx) => (
<tr key={idx}>
{headers.map((header, hidx) => (
<td key={hidx}>{formatCell(item, header)}</td>
))}
</tr>
))}
</tbody>
</table>
</section>
<section className="mt-1">
<button
onClick={() => {
changeOffset(Offset.First);