From 28b42d4e372564dfb49b67a563fc398e2f6ba9ba Mon Sep 17 00:00:00 2001 From: lfjnascimento Date: Fri, 12 Jul 2024 10:09:43 -0300 Subject: [PATCH] feat: add FilterList component --- dashboard/.eslintrc.cjs | 1 + .../FilterList/FilterList.stories.tsx | 65 ++++++++++ .../src/components/FilterList/FilterList.tsx | 111 ++++++++++++++++++ dashboard/src/locales/messages/index.ts | 1 + 4 files changed, 178 insertions(+) create mode 100644 dashboard/src/components/FilterList/FilterList.stories.tsx create mode 100644 dashboard/src/components/FilterList/FilterList.tsx diff --git a/dashboard/.eslintrc.cjs b/dashboard/.eslintrc.cjs index b1dca6a..db8bae7 100644 --- a/dashboard/.eslintrc.cjs +++ b/dashboard/.eslintrc.cjs @@ -97,6 +97,7 @@ module.exports = { "**/*{.,_}{test,spec}.{ts,tsx}", ".storybook/**", "src/stories/**", + "**/*.stories*", ], }, ], diff --git a/dashboard/src/components/FilterList/FilterList.stories.tsx b/dashboard/src/components/FilterList/FilterList.stories.tsx new file mode 100644 index 0000000..7209bac --- /dev/null +++ b/dashboard/src/components/FilterList/FilterList.stories.tsx @@ -0,0 +1,65 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { fn } from '@storybook/test'; +import { IntlProvider } from 'react-intl'; +import { flatten } from 'flat'; + +import { LOCALES } from '../../locales/constants'; + +import { messages } from '../../locales/messages'; + +import FilterList from './FilterList'; + +const ActionsData = { + onClickItem: fn(), + onClickClean: fn(), +}; + +const meta: Meta = { + title: 'FilterList', + component: FilterList, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], + args: { + ...ActionsData, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + itens: ['linux-5.15.y', 'Status:failed', 'Status: Warnings'], + }, + decorators: [ + (story): JSX.Element => ( + + {story()} + + ), + ], +}; + +export const MultipleLines: Story = { + args: { + itens: [ + 'linux-5.15.y', + 'Status:failed', + 'Status: Warnings', + 'Status:failed', + 'Status: Warnings', + ], + }, + decorators: [ + (story): JSX.Element => ( + +
{story()}
+
+ ), + ], +}; diff --git a/dashboard/src/components/FilterList/FilterList.tsx b/dashboard/src/components/FilterList/FilterList.tsx new file mode 100644 index 0000000..933f675 --- /dev/null +++ b/dashboard/src/components/FilterList/FilterList.tsx @@ -0,0 +1,111 @@ +import { useCallback, useMemo } from 'react'; +import { IoClose } from 'react-icons/io5'; +import classNames from 'classnames'; +import { useIntl } from 'react-intl'; + +import { Button } from '../ui/button'; + +interface IFilterList { + itens: string[]; + onClickItem: (itemIdx: number) => void; + onClickClean: () => void; + removeOnEmpty?: boolean; +} + +interface IFilterItem extends IFilterButton { + idx: number; + onClickItem: (idx: number) => void; +} + +export interface IFilterButton + extends React.ButtonHTMLAttributes { + text: string; + variant?: 'primary' | 'secondary'; + className?: string; +} + +const baseButtonClassNames = + 'text-sm h-10 pr-2 rounded-md flex items-center bg-darkGray hover:bg-mediumGray'; +const primaryClassNames = 'bg-lightBlue text-white'; +const secondaryClassNames = 'bg-darkGray text-black'; + +const FilterButton = ({ + text, + variant = 'secondary', + className, + ...props +}: IFilterButton): JSX.Element => { + const buttonClassNames = classNames( + baseButtonClassNames, + variant === 'primary' ? primaryClassNames : secondaryClassNames, + className, + ); + + return ( + + ); +}; + +const FilterItem = ({ + text, + variant, + onClickItem, + idx, + ...props +}: IFilterItem): JSX.Element => { + const onClickHandler = useCallback( + () => onClickItem(idx), + [onClickItem, idx], + ); + + return ( + + ); +}; + +const FilterList = ({ + itens, + onClickItem, + onClickClean, + removeOnEmpty = false, +}: IFilterList): JSX.Element => { + const intl = useIntl(); + + const buttonList = useMemo( + () => + itens.map((item, idx) => ( + + )), + [itens, onClickItem], + ); + + if (removeOnEmpty && !itens) { + return <>; + } + + return ( +
+ {buttonList} + +
+ ); +}; + +export default FilterList; diff --git a/dashboard/src/locales/messages/index.ts b/dashboard/src/locales/messages/index.ts index 396687f..fa2dbad 100644 --- a/dashboard/src/locales/messages/index.ts +++ b/dashboard/src/locales/messages/index.ts @@ -4,6 +4,7 @@ export const messages = { [LOCALES.EN_US]: { global: { filters: 'Filters', + cleanAll: 'Clean all', }, routes: { deviceMonitor: 'Devices',