diff --git a/src/components/Table/Inputs/Select.tsx b/src/components/Table/Inputs/Select.tsx new file mode 100644 index 0000000..c9383ec --- /dev/null +++ b/src/components/Table/Inputs/Select.tsx @@ -0,0 +1,47 @@ +import React, { useMemo, type ChangeEventHandler } from 'react'; + +export type DataItem = Record; + +interface Props { + onChange: (value: string | null) => void; + data: DataItem[]; + keyData: string; +} + +export default function Select({ + data, + keyData, + onChange, +}: Props): JSX.Element { + const options = useMemo(() => { + let options = data.map((item) => item[keyData]); + + options = [...new Set(options)]; + + options = options.map((item, idx) => ( + + )); + + options.unshift( + , + ); + + return options; + }, [data, keyData]); + + return ( + + ); +} diff --git a/src/components/Table.tsx b/src/components/Table/Table.tsx similarity index 74% rename from src/components/Table.tsx rename to src/components/Table/Table.tsx index f5fbdf6..0fa23c1 100644 --- a/src/components/Table.tsx +++ b/src/components/Table/Table.tsx @@ -1,5 +1,6 @@ import React, { useMemo, useState } from 'react'; import usePagination, { Offset } from 'src/hooks/usePagination'; +import Select from './Inputs/Select'; export type DataItem = Record; @@ -7,6 +8,8 @@ export enum HeaderType { Index, String, Number, + Select, + Multiple, } export interface Header { @@ -22,11 +25,10 @@ interface Props { } interface Filter { - type: HeaderType, - value: string, + type: HeaderType; + value: string; } - export default function Table({ data, headers }: Props): JSX.Element { const [filters, setFilters] = useState>({}); @@ -36,15 +38,17 @@ export default function Table({ data, headers }: Props): JSX.Element { return data.search(filter.value) !== -1; case HeaderType.Number: return data === filter.value; + case HeaderType.Select: + return data === filter.value; } return true; - } + }; const filteredItems = useMemo(() => { return data.filter((item) => { - return Object.entries(filters).every( - ([key, filter]) => resolveFilterByType(filter, item[key]), + return Object.entries(filters).every(([key, filter]) => + resolveFilterByType(filter, item[key]), ); }); }, [data, filters]); @@ -53,7 +57,11 @@ export default function Table({ data, headers }: Props): JSX.Element { items: filteredItems, }); - const handleUpdateFilters = (name: string, type: HeaderType, value: any): void => { + const handleUpdateFilters = ( + name: string, + type: HeaderType, + value: any, + ): void => { setFilters((prev) => { if (value === null) { // eslint-disable-next-line @typescript-eslint/no-dynamic-delete @@ -63,7 +71,6 @@ export default function Table({ data, headers }: Props): JSX.Element { return { ...prev, [name]: { value, type } }; }); - }; function formatCell(data: DataItem, header: Header): JSX.Element { @@ -77,6 +84,16 @@ export default function Table({ data, headers }: Props): JSX.Element { ); } + if (header.type === HeaderType.Multiple) { + return ( +
    + {data[header.key].map((item: JSX.Element, idx: number) => ( +
  • {item}
  • + ))} +
+ ); + } + return data[header.key]; } @@ -86,7 +103,11 @@ export default function Table({ data, headers }: Props): JSX.Element { return ( { - handleUpdateFilters(header.key, header.type, e.target.value ?? null); + handleUpdateFilters( + header.key, + header.type, + e.target.value ?? null, + ); }} /> ); @@ -95,7 +116,21 @@ export default function Table({ data, headers }: Props): JSX.Element { { - handleUpdateFilters(header.key, header.type, e.target.value !== '' ? parseInt(e.target.value) : null); + handleUpdateFilters( + header.key, + header.type, + e.target.value !== '' ? parseInt(e.target.value) : null, + ); + }} + /> + ); + case HeaderType.Select: + return ( +