Skip to content

Commit

Permalink
feat: add FilterList component
Browse files Browse the repository at this point in the history
  • Loading branch information
lfjnascimento committed Jul 12, 2024
1 parent c994f47 commit 58be575
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 70 deletions.
1 change: 1 addition & 0 deletions dashboard/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ module.exports = {
"**/*{.,_}{test,spec}.{ts,tsx}",
".storybook/**",
"src/stories/**",
"**/*.stories*",
],
},
],
Expand Down
28 changes: 0 additions & 28 deletions dashboard/src/components/FilterButton/FilterButton.stories.tsx

This file was deleted.

42 changes: 0 additions & 42 deletions dashboard/src/components/FilterButton/FilterButton.tsx

This file was deleted.

65 changes: 65 additions & 0 deletions dashboard/src/components/FilterList/FilterList.stories.tsx
Original file line number Diff line number Diff line change
@@ -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<typeof FilterList> = {
title: 'FilterList',
component: FilterList,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
args: {
...ActionsData,
},
};

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
itens: ['linux-5.15.y', 'Status:failed', 'Status: Warnings'],
},
decorators: [
(story): JSX.Element => (
<IntlProvider
messages={flatten(messages[LOCALES.EN_US])}
locale={LOCALES.EN_US}
>
{story()}
</IntlProvider>
),
],
};

export const MultipleLines: Story = {
args: {
itens: [
'linux-5.15.y',
'Status:failed',
'Status: Warnings',
'Status:failed',
'Status: Warnings',
],
},
decorators: [
(story): JSX.Element => (
<IntlProvider locale="en">
<div className="w-[500px]">{story()}</div>
</IntlProvider>
),
],
};
111 changes: 111 additions & 0 deletions dashboard/src/components/FilterList/FilterList.tsx
Original file line number Diff line number Diff line change
@@ -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<HTMLButtonElement> {
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 (
<Button className={buttonClassNames} {...props}>
{text}
<IoClose className="size-6" />
</Button>
);
};

const FilterItem = ({
text,
variant,
onClickItem,
idx,
...props
}: IFilterItem): JSX.Element => {
const onClickHandler = useCallback(
() => onClickItem(idx),
[onClickItem, idx],
);

return (
<FilterButton
text={text}
variant={variant}
onClick={onClickHandler}
{...props}
/>
);
};

const FilterList = ({
itens,
onClickItem,
onClickClean,
removeOnEmpty = false,
}: IFilterList): JSX.Element => {
const intl = useIntl();

const buttonList = useMemo(
() =>
itens.map((item, idx) => (
<FilterItem
key={idx + item}
text={item}
onClickItem={onClickItem}
idx={idx}
/>
)),
[itens, onClickItem],
);

if (removeOnEmpty && !itens) {
return <></>;
}

return (
<div className="flex flex-wrap gap-4">
{buttonList}
<FilterButton
text={intl.formatMessage({ id: 'global.cleanAll' })}
variant="primary"
onClick={onClickClean}
/>
</div>
);
};

export default FilterList;
1 change: 1 addition & 0 deletions dashboard/src/locales/messages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const messages = {
[LOCALES.EN_US]: {
global: {
filters: 'Filters',
cleanAll: 'Clean all',
},
routes: {
deviceMonitor: 'Devices',
Expand Down

0 comments on commit 58be575

Please sign in to comment.