From 09e2db558d56243cdd58a3d41f336ac9942f984f Mon Sep 17 00:00:00 2001 From: aleidk Date: Sat, 7 Oct 2023 13:03:35 -0300 Subject: [PATCH] finish functionality of number filter Also refactor filter logic --- src/components/Table/Inputs/NumberInput.tsx | 47 +++++++++++------ src/components/Table/Inputs/index.tsx | 56 +++++++++++++++++++++ src/components/Table/Table.tsx | 30 +++-------- 3 files changed, 95 insertions(+), 38 deletions(-) diff --git a/src/components/Table/Inputs/NumberInput.tsx b/src/components/Table/Inputs/NumberInput.tsx index 20e461a..63a89be 100644 --- a/src/components/Table/Inputs/NumberInput.tsx +++ b/src/components/Table/Inputs/NumberInput.tsx @@ -1,4 +1,4 @@ -import React, { type ChangeEventHandler } from 'react'; +import React, { useState, type ChangeEventHandler, useEffect } from 'react'; interface Props { onChange: (value: string | string[] | number | number[] | null) => void; @@ -6,20 +6,39 @@ interface Props { } export default function NumberInput({ keyData, onChange }: Props): JSX.Element { - const onSelectChange: ChangeEventHandler = ({ - target, - }): void => { - const value = parseInt(target.value); - onChange(isNaN(value) ? null : value); - }; + const [value, setValue] = useState(''); + const [operator, setOperator] = useState('='); + + useEffect(() => { + onChange([operator, value === '' ? null : parseFloat(value)]); + }, [value, operator]); return ( - +
+ + { + setValue(target.value); + }} + /> +
); } diff --git a/src/components/Table/Inputs/index.tsx b/src/components/Table/Inputs/index.tsx index bb9a46a..fa0fba7 100644 --- a/src/components/Table/Inputs/index.tsx +++ b/src/components/Table/Inputs/index.tsx @@ -1,4 +1,60 @@ +import { HeaderType } from '../Table.tsx'; + export { default as SelectInput } from './SelectInput.tsx'; export { default as NumberInput } from './NumberInput.tsx'; export type DataItem = Record; + +export interface Filter { + type: HeaderType; + value: string | string[] | number | number[]; +} + +const filterString = (value: Filter['value'], data: any): boolean => { + return data.search(value) !== -1; +}; +const filterNumber = (value: Filter['value'], data: any): boolean => { + const [operator, numberValue] = value; + + if (numberValue === null) return true; + + switch (operator) { + case '=': + return data === numberValue; + case '<': + return data < numberValue; + case '>': + return data > numberValue; + case '<=': + return data <= numberValue; + case '>=': + return data >= numberValue; + + default: + return data === numberValue; + } +}; +const filterSelect = (value: Filter['value'], data: any): boolean => { + return data === value; +}; +const filterMultiple = (value: Filter['value'], data: any): boolean => { + if (typeof value === 'string') { + return data.includes(value); + } + return value.every((filter: string) => data.includes(filter)); +}; + +export const resolveFilterByType = (filter: Filter, data: any): boolean => { + switch (filter.type) { + case HeaderType.String: + return filterString(filter.value, data); + case HeaderType.Number: + return filterNumber(filter.value, data); + case HeaderType.Select: + return filterSelect(filter.value, data); + case HeaderType.Multiple: + return filterMultiple(filter.value, data); + } + + return true; +}; diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx index c5c8842..2b56aae 100644 --- a/src/components/Table/Table.tsx +++ b/src/components/Table/Table.tsx @@ -1,6 +1,11 @@ import React, { useMemo, useState } from 'react'; import usePagination, { Offset } from 'src/hooks/usePagination'; -import { SelectInput, NumberInput } from './Inputs'; +import { + SelectInput, + NumberInput, + resolveFilterByType, + type Filter, +} from './Inputs'; export type DataItem = Record; @@ -24,32 +29,9 @@ interface Props { headers: Header[]; } -interface Filter { - type: HeaderType; - value: string | string[] | number | number[]; -} - export default function Table({ data, headers }: Props): JSX.Element { const [filters, setFilters] = useState>({}); - const resolveFilterByType = (filter: Filter, data: any): boolean => { - switch (filter.type) { - case HeaderType.String: - return data.search(filter.value) !== -1; - case HeaderType.Number: - return data === filter.value; - case HeaderType.Select: - return data === filter.value; - case HeaderType.Multiple: - if (typeof filter.value === 'string') { - return data.includes(filter.value); - } - return filter.value.every((filter: string) => data.includes(filter)); - } - - return true; - }; - const filteredItems = useMemo(() => { return data.filter((item) => { return Object.entries(filters).every(([key, filter]) =>