Skip to content

Commit

Permalink
feat(#70): add custom accordion component
Browse files Browse the repository at this point in the history
  • Loading branch information
mari1912 committed Jul 16, 2024
1 parent fb51955 commit 1b93a17
Show file tree
Hide file tree
Showing 2 changed files with 239 additions and 0 deletions.
98 changes: 98 additions & 0 deletions dashboard/src/components/Accordion/Accordion.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import type { Meta, StoryObj } from '@storybook/react';

import Accordion, { IAccordionItems } from './Accordion';

const meta = {
title: 'Accordion',
component: Accordion,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
} satisfies Meta<typeof Accordion>;

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

const itemsBuild: IAccordionItems[] = [
{
trigger: {
config: 'config',
compiler: 'compiler',
date: 'dd/mm/yyyy',
buildErrors: 5,
buildTime: '500 seconds',
status: 'valid',
},
content: <span>AAAAa</span>,
},
{
trigger: {
config: 'config',
compiler: 'compiler',
date: 'dd/mm/yyyy',
buildErrors: 5,
buildTime: '500 seconds',
status: 'valid',
},
content: <span>AAAAa</span>,
},
{
trigger: {
config: 'config',
compiler: 'compiler',
date: 'dd/mm/yyyy',
buildErrors: 5,
buildTime: '500 seconds',
status: 'valid',
},
content: <span>AAAAa</span>,
},
];

const headersBuild = [
'config',
'compiler',
'date',
'build errors',
'build time',
'status',
];

const itemsTest: IAccordionItems[] = [
{
trigger: {
testPlans: 'aaaaaaa',
testErrors: 5,
testSuccessfull: 12,
status: 'invalid',
},
content: <span>AAAAa</span>,
},
{
trigger: {
testPlans: 'aaaaaaasdkjmla',
testErrors: 5,
testSuccessfull: 12,
status: 'valid',
},
content: <span>BBB</span>,
},
];
const headersTest = ['test plan', 'test results', 'status'];

export const Builds: Story = {
args: {
items: itemsBuild,
headers: headersBuild,
type: 'build',
},
};

export const Tests: Story = {
args: {
items: itemsTest,
headers: headersTest,
type: 'test',
},
};
141 changes: 141 additions & 0 deletions dashboard/src/components/Accordion/Accordion.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import { ReactNode, useMemo } from 'react';

import { MdCheck, MdClose } from 'react-icons/md';

import { TableBody, TableCell, TableRow } from '../ui/table';
import BaseTable from '../Table/BaseTable';
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from '../ui/collapsible';
import ColoredCircle from '../ColoredCircle/ColoredCircle';
import { ComponentType } from '../ListingComponentItem/ListingComponentItem';

export interface IAccordion {
headers: string[];
items: IAccordionItems[];
type: 'build' | 'test';
}

export interface IAccordionItems {
trigger: AccordionItemBuildsTrigger | AccordionItemTestsTrigger;
content?: ReactNode;
}

interface ICustomAccordionTableBody {
items: IAccordionItems[];
type: 'build' | 'test';
}

export type AccordionItemBuildsTrigger = {
config?: string;
compiler?: string;
date?: string;
buildErrors?: number;
buildTime?: string;
status?: 'valid' | 'invalid';
};

export type AccordionItemTestsTrigger = {
testPlans?: string;
testSuccessfull?: number;
testErrors?: number;
status?: 'valid' | 'invalid';
};

const Accordion = ({ headers, items, type }: IAccordion): JSX.Element => {
const accordionTableHeader = useMemo(
() => headers.map(header => <span key={header}>{header}</span>),
[headers],
);

return (
<BaseTable
headers={accordionTableHeader}
body={<AccordionTableBody items={items} type={type} />}
/>
);
};

const AccordionTableBody = ({
items,
type,
}: ICustomAccordionTableBody): JSX.Element => {
const accordionItems = useMemo(
() =>
items.map((item, index) => (
<Collapsible key={index} asChild>
<>
<CollapsibleTrigger asChild>
<TableRow>
{type === 'build' ? (
<AccordionBuildsTrigger trigger={item.trigger} />
) : (
<AccordionTestsTrigger trigger={item.trigger} />
)}
</TableRow>
</CollapsibleTrigger>
<CollapsibleContent>{item.content}</CollapsibleContent>
</>
</Collapsible>
)),
[items, type],
);

return <TableBody>{accordionItems}</TableBody>;
};

const AccordionBuildsTrigger = ({ trigger }: IAccordionItems): JSX.Element => {
const triggerInfo = trigger as AccordionItemBuildsTrigger;
return (
<>
<TableCell>{triggerInfo.config}</TableCell>
<TableCell>{triggerInfo.compiler}</TableCell>
<TableCell>{triggerInfo.date}</TableCell>
<TableCell>
<ColoredCircle
className="max-w-6"
quantity={triggerInfo.buildErrors ?? 0}
type={ComponentType.Error}
/>
</TableCell>
<TableCell>{triggerInfo.buildTime}</TableCell>
<TableCell>
{triggerInfo.status === 'valid' ? (
<MdCheck className="text-green" />
) : (
<MdClose className="text-red" />
)}
</TableCell>
</>
);
};

const AccordionTestsTrigger = ({ trigger }: IAccordionItems): JSX.Element => {
const triggerInfo = trigger as AccordionItemTestsTrigger;
return (
<>
<TableCell>{triggerInfo.testPlans}</TableCell>
<TableCell className="flex flex-row gap-1">
<ColoredCircle
quantity={triggerInfo.testErrors ?? 0}
type={ComponentType.Error}
/>
<ColoredCircle
quantity={triggerInfo.testSuccessfull ?? 0}
type={ComponentType.Warning}
/>
</TableCell>
<TableCell>
{triggerInfo.status === 'valid' ? (
<MdCheck className="text-green" />
) : (
<MdClose className="text-red" />
)}
</TableCell>
</>
);
};

export default Accordion;

0 comments on commit 1b93a17

Please sign in to comment.