Skip to content

Implementation and Enhancement of RepositoryCard #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 40 additions & 6 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@emotion/styled": "^11.11.0",
"@faker-js/faker": "^8.1.0",
"@iconify/react": "^4.1.1",
"@mui/icons-material": "^5.15.14",
"@mui/lab": "^5.0.0-alpha.147",
"@mui/material": "^5.14.12",
"@vercel/analytics": "^1.2.2",
Expand Down
194 changes: 188 additions & 6 deletions client/src/components/repository/repository.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,191 @@
/* eslint-disable import/no-extraneous-dependencies */
import React from 'react';
import PropTypes from 'prop-types';
import { format, formatDistanceToNow } from 'date-fns';

const Repository = () => (
<div>
<button type="button">Click me</button>
</div>
);
import Box from '@mui/material/Box';
import Menu from '@mui/material/Menu';
import Card from '@mui/material/Card';
import Chip from '@mui/material/Chip';
import Link from '@mui/material/Link';
import Stack from '@mui/material/Stack';
import Button from '@mui/material/Button';
import Avatar from '@mui/material/Avatar';
import MenuItem from '@mui/material/MenuItem';
import StarIcon from '@mui/icons-material/Star';
import IconButton from '@mui/material/IconButton';
import CardHeader from '@mui/material/CardHeader';
import Typography from '@mui/material/Typography';
import ShareIcon from '@mui/icons-material/Share';
import TodayIcon from '@mui/icons-material/Today';
import CardContent from '@mui/material/CardContent';
import ThumbUpIcon from '@mui/icons-material/ThumbUp';
import BookmarkIcon from '@mui/icons-material/Bookmark';
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
import ForkRightIcon from '@mui/icons-material/ForkRight';
import VisibilityIcon from '@mui/icons-material/Visibility';
import ExpandCircleDownIcon from '@mui/icons-material/ExpandCircleDown';
import ChatBubbleOutlineIcon from '@mui/icons-material/ChatBubbleOutline';

export default Repository;
const RepositoryCard = ({
full_name = '',
description = '',
owner = {},
homepage = '',
stargazers_count = 0,
watchers_count = 0,
forks_count = 0,
updated_at = '',
topics = [],
license = {},
created_at = '',
language = '',
html_url = '',
languageData = {},
}) => {
const timeSinceCreation = formatDistanceToNow(new Date(created_at), { addSuffix: true });
const formattedUpdatedAt = format(new Date(updated_at), 'MMM dd, yyyy');
const totalLinesOfCode = Object.values(languageData).reduce((a, b) => a + b, 0);

const [anchorEl, setAnchorEl] = React.useState(null);
const open = Boolean(anchorEl);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};

return (
<Card>
<CardHeader
avatar={<Avatar src={owner.avatar_url} />}
title={full_name}
subheader={timeSinceCreation}
/>

<CardContent>
<Stack spacing={2}>
<Stack>
<Typography variant="body2" color="text.secondary">
{description}
</Typography>
</Stack>
<Stack direction="row" spacing={1} mt={1}>
{Object.entries(languageData).map(([lng, linesOfCode]) => (
<Chip
key={lng}
label={`${lng}: ${((linesOfCode / totalLinesOfCode) * 100).toFixed(2)}%`}
variant="outlined"
size="small"
/>
))}
</Stack>
<Stack direction="row" spacing={1} mt={1}>
{topics.map((topic) => (
<Chip key={topic} label={topic} variant="outlined" size="small" />
))}
</Stack>
<Stack direction="row" spacing={1} mt={1}>
<Box display="flex" alignItems="center">
<StarIcon />
<Typography variant="body2" ml={0.5}>
{stargazers_count}
</Typography>
</Box>
<Box display="flex" alignItems="center">
<VisibilityIcon />
<Typography variant="body2" ml={0.5}>
{watchers_count}
</Typography>
</Box>
<Box display="flex" alignItems="center">
<ForkRightIcon />
<Typography variant="body2" ml={0.5}>
{forks_count}
</Typography>
</Box>
</Stack>
<Stack>
<Box display="flex" alignItems="center">
<TodayIcon />
<Typography variant="body2" ml={0.5}>
Updated on {formattedUpdatedAt}
</Typography>
</Box>
</Stack>
<Stack spacing={2} direction="row">
{homepage && (
<Link href={homepage} target="_blank" rel="noopener noreferrer">
{homepage}
</Link>
)}
{html_url && (
<Link href={html_url} target="_blank" rel="noopener noreferrer">
{html_url}
</Link>
)}
</Stack>
<Stack>
{license && (
<Box display="flex" alignItems="center">
<Link href={license.url} target="_blank" variant="body2" color="text.secondary">
License: {license.name}
</Link>
</Box>
)}
</Stack>
</Stack>
</CardContent>
<CardContent>
<Stack direction="row">
<IconButton>
<ShareIcon />
</IconButton>
<IconButton>
<BookmarkIcon />
</IconButton>
<IconButton>
<ChatBubbleOutlineIcon />
</IconButton>
<IconButton>
<ThumbUpIcon />
</IconButton>
<IconButton onClick={handleClick}>
<MoreHorizIcon />
</IconButton>
<Button variant="text" endIcon={<ExpandCircleDownIcon />}>
Details
</Button>
<Menu anchorEl={anchorEl} open={open} onClose={handleClose}>
<MenuItem onClick={handleClose}>Option 1</MenuItem>
<MenuItem onClick={handleClose}>Option 2</MenuItem>
</Menu>
</Stack>
</CardContent>
</Card>
);
};

RepositoryCard.propTypes = {
full_name: PropTypes.string,
description: PropTypes.string,
owner: PropTypes.shape({
avatar_url: PropTypes.string,
}),
homepage: PropTypes.string,
stargazers_count: PropTypes.number,
forks_count: PropTypes.number,
updated_at: PropTypes.string,
topics: PropTypes.arrayOf(PropTypes.string),
license: PropTypes.shape({
name: PropTypes.string,
}),
created_at: PropTypes.string,
language: PropTypes.string,
html_url: PropTypes.string,
watchers_count: PropTypes.number,
languageData: PropTypes.object,
};

export default RepositoryCard;
Loading