Skip to content

Commit

Permalink
feat(ProjectListItemCollapsible): component composition step 1
Browse files Browse the repository at this point in the history
  • Loading branch information
asabotovich committed Jun 21, 2023
1 parent b9e0281 commit f29104d
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 233 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { routes } from '../../hooks/router';
import { Page, PageContent } from '../Page';
import { PageSep } from '../PageSep';
import { ExplorePageLayout } from '../ExplorePageLayout/ExplorePageLayout';
import { ProjectListContainer, ProjectListItem } from '../ProjectListItem/ProjectListItem';
import { ProjectListContainer, ProjectListItem } from '../ProjectListItem';
import { trpc } from '../../utils/trpcClient';

import { tr } from './ExploreTopProjectsPage.i18n';
Expand Down
2 changes: 1 addition & 1 deletion src/components/ExporeProjectsPage/ExporeProjectsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { routes } from '../../hooks/router';
import { Page, PageContent } from '../Page';
import { PageSep } from '../PageSep';
import { ExplorePageLayout } from '../ExplorePageLayout/ExplorePageLayout';
import { ProjectListItem, ProjectListContainer } from '../ProjectListItem/ProjectListItem';
import { ProjectListItem, ProjectListContainer } from '../ProjectListItem';
import { trpc } from '../../utils/trpcClient';

import { tr } from './ExporeProjectsPage.i18n';
Expand Down
79 changes: 79 additions & 0 deletions src/components/ProjectListItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { FC, ReactNode } from 'react';
import Link from 'next/link';
import { EyeIcon, StarFilledIcon, Text, nullable } from '@taskany/bricks';

import { ActivityByIdReturnType } from '../../trpc/inferredTypes';

import { Table, TableCell, TableRow } from './Table';
import { UserGroup } from './UserGroup';

interface ProjectListItemProps {
href?: string;
children?: ReactNode;
title: string;
owner?: ActivityByIdReturnType;
participants?: ActivityByIdReturnType[];
starred?: boolean;
watching?: boolean;
}

export const ProjectListContainer: FC<{ children: ReactNode; offset?: number }> = ({ children, offset = 0 }) => (
<Table columns={5} offset={offset}>
{children}
</Table>
);

export const ProjectListItem: React.FC<ProjectListItemProps> = ({
href,
children,
title,
owner,
participants,
starred,
watching,
}) => {
const row = (
<TableRow>
<TableCell>
<Text size="l" weight="bold">
{title}
</Text>
{children}
</TableCell>

<TableCell>
{nullable(owner, (o) => (
<UserGroup users={[o]} />
))}
</TableCell>

<TableCell>{nullable(participants, (p) => (p.length ? <UserGroup users={p} /> : null))}</TableCell>

<TableCell>
{nullable(starred, () => (
<StarFilledIcon size="s" />
))}
</TableCell>

<TableCell>
{nullable(watching, () => (
<EyeIcon size="s" />
))}
</TableCell>
</TableRow>
);

return href ? (
<Link href={href} passHref>
{row}
</Link>
) : (
row
);
};

export const ProjectItemStandalone: React.FC<ProjectListItemProps> = (props) => (
<ProjectListContainer>
<ProjectListItem {...props} />
</ProjectListContainer>
);
209 changes: 0 additions & 209 deletions src/components/ProjectListItem/ProjectListItem.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React, { MouseEvent, ReactNode, useCallback, useEffect, useMemo, useState } from 'react';
import styled from 'styled-components';
import { Button } from '@taskany/bricks';
import { gapS } from '@taskany/colors';

import { ProjectByIdReturnType } from '../../../trpc/inferredTypes';
import { GoalsListContainer } from '../GoalListItem';
import { Collapsable, collapseOffset } from '../CollapsableItem';
import { ProjectListContainer, ProjectListItem } from '../ProjectListItem';

import { tr } from './ProjectListItem.i18n';

const StyledGoalsButton = styled(Button)`
margin-left: ${gapS};
cursor: pointer;
`;

interface ProjectListItemCollapsableProps {
href: string;
project: NonNullable<ProjectByIdReturnType>;
goals?: ReactNode;
children?: ReactNode;
onCollapsedChange?: (value: boolean) => void;
onGoalsCollapsedChange?: (value: boolean) => void;
loading?: boolean;
deep?: number;
}

export const ProjectListItemCollapsable: React.FC<ProjectListItemCollapsableProps> = ({
project,
onCollapsedChange,
onGoalsCollapsedChange,
children,
loading = false,
goals,
deep = 0,
}) => {
const [collapsed, setIsCollapsed] = useState(true);
const [collapsedGoals, setIsCollapsedGoals] = useState(true);

const offset = collapseOffset * (collapsed ? deep - 1 : deep);
const childs = useMemo(() => project.children.map(({ id }) => id), [project]);

const onClickEnabled = childs.length;

useEffect(() => {
onCollapsedChange?.(collapsed);
}, [collapsed, onCollapsedChange]);

useEffect(() => {
onGoalsCollapsedChange?.(collapsedGoals);
}, [collapsedGoals, onGoalsCollapsedChange]);

const onClick = useCallback(() => {
if (onClickEnabled) {
setIsCollapsed((value) => !value);
}
}, [onClickEnabled]);

const onHeaderButtonClick = useCallback((e: MouseEvent) => {
e.stopPropagation();

setIsCollapsedGoals((value) => !value);
}, []);

return (
<Collapsable
collapsed={collapsed || loading}
onClick={onClick}
header={
<ProjectListContainer offset={offset}>
<ProjectListItem
title={project.title}
owner={project.activity}
participants={project.participants}
starred={project._isStarred}
watching={project._isWatching}
>
<StyledGoalsButton onClick={onHeaderButtonClick} text={tr('Goals')} />
</ProjectListItem>
</ProjectListContainer>
}
content={children}
deep={deep}
>
{!collapsedGoals && <GoalsListContainer offset={offset}>{goals}</GoalsListContainer>}
</Collapsable>
);
};
Loading

0 comments on commit f29104d

Please sign in to comment.