1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-06 00:07:44 +01:00
unleash.unleash/frontend/src/component/project/ProjectCard/ProjectCard.tsx
Tymoteusz Czech 6030900b40
refactor: replace IProjectCard with openapi type (#8043)
Makes type consistent between frontend and schema generated from backend.
2024-09-02 13:25:28 +00:00

116 lines
4.2 KiB
TypeScript

import {
StyledProjectCard,
StyledCardTitle,
StyledProjectCardBody,
StyledIconBox,
} from './ProjectCard.styles';
import { ProjectCardFooter } from './ProjectCardFooter/ProjectCardFooter';
import { ProjectModeBadge } from './ProjectModeBadge/ProjectModeBadge';
import { ProjectIcon } from 'component/common/ProjectIcon/ProjectIcon';
import { FavoriteAction } from './FavoriteAction/FavoriteAction';
import { Box, styled } from '@mui/material';
import { flexColumn } from 'themes/themeStyles';
import { TimeAgo } from 'component/common/TimeAgo/TimeAgo';
import { ProjectLastSeen } from './ProjectLastSeen/ProjectLastSeen';
import { Highlighter } from 'component/common/Highlighter/Highlighter';
import { useSearchHighlightContext } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
import { ProjectMembers } from './ProjectCardFooter/ProjectMembers/ProjectMembers';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { DEFAULT_PROJECT_ID } from 'hooks/api/getters/useDefaultProject/useDefaultProjectId';
import type { ProjectSchema } from 'openapi';
const StyledUpdated = styled('span')(({ theme }) => ({
color: theme.palette.text.secondary,
fontSize: theme.fontSizes.smallerBody,
}));
const StyledCount = styled('strong')(({ theme }) => ({
fontWeight: theme.typography.fontWeightMedium,
}));
const StyledInfo = styled('div')(({ theme }) => ({
display: 'grid',
gridTemplate: '1rem 1rem / 1fr 1fr',
gridAutoFlow: 'column',
alignItems: 'center',
justifyContent: 'space-between',
marginTop: theme.spacing(1),
fontSize: theme.fontSizes.smallerBody,
}));
const StyledHeader = styled('div')(({ theme }) => ({
gap: theme.spacing(1),
display: 'flex',
width: '100%',
alignItems: 'center',
}));
type ProjectCardProps = ProjectSchema & { onHover?: () => void };
export const ProjectCard = ({
name,
featureCount,
health,
memberCount = 0,
onHover,
id,
mode,
favorite = false,
owners,
createdAt,
lastUpdatedAt,
lastReportedFlagUsage,
}: ProjectCardProps) => {
const { searchQuery } = useSearchHighlightContext();
return (
<StyledProjectCard onMouseEnter={onHover}>
<StyledProjectCardBody>
<StyledHeader>
<StyledIconBox>
<ProjectIcon />
</StyledIconBox>
<Box
data-loading
sx={(theme) => ({
...flexColumn,
margin: theme.spacing(1, 'auto', 1, 0),
})}
>
<StyledCardTitle lines={1} sx={{ margin: 0 }}>
<Highlighter search={searchQuery}>
{name}
</Highlighter>
</StyledCardTitle>
<StyledUpdated>
Updated{' '}
<TimeAgo date={lastUpdatedAt || createdAt} />
</StyledUpdated>
</Box>
<ProjectModeBadge mode={mode} />
<FavoriteAction id={id} isFavorite={favorite} />
</StyledHeader>
<StyledInfo>
<div data-loading>
<StyledCount>{featureCount}</StyledCount> flag
{featureCount === 1 ? '' : 's'}
</div>
<div data-loading>
<StyledCount>{health}%</StyledCount> health
</div>
<div />
<div data-loading>
<ProjectLastSeen date={lastReportedFlagUsage} />
</div>
</StyledInfo>
</StyledProjectCardBody>
<ProjectCardFooter id={id} owners={owners}>
<ConditionallyRender
condition={id !== DEFAULT_PROJECT_ID}
show={<ProjectMembers count={memberCount} members={[]} />}
/>
</ProjectCardFooter>
</StyledProjectCard>
);
};