New folder structure for website (#4159)

New folder structure
This commit is contained in:
Félix Malfait
2024-02-23 17:42:13 +01:00
committed by GitHub
parent 06c4665a44
commit 5de1c2c31d
65 changed files with 128 additions and 537 deletions

View File

@ -0,0 +1,32 @@
'use client';
import { ResponsiveTimeRange } from '@nivo/calendar';
import { CardContainer } from '@/app/_components/contributors/CardContainer';
import { Title } from '@/app/_components/contributors/Title';
export const ActivityLog = ({
data,
}: {
data: { value: number; day: string }[];
}) => {
if (!data.length) {
return null;
}
return (
<CardContainer>
<Title>Activity</Title>
<div style={{ width: '100%', height: '214px' }}>
<ResponsiveTimeRange
data={data}
emptyColor="#F4EFFF"
colors={['#E9DFFF', '#B28FFE', '#915FFD']}
dayBorderWidth={2}
dayBorderColor="#ffffff"
dayRadius={4}
daySpacing={2}
/>
</div>
</CardContainer>
);
};

View File

@ -0,0 +1,80 @@
'use client';
import styled from '@emotion/styled';
import Link from 'next/link';
export interface User {
id: string;
avatarUrl: string;
}
const AvatarGridContainer = styled.div`
margin: 0 auto;
max-width: 1024px;
justify-items: center;
display: flex;
justify-content: center;
gap: 32px;
flex-wrap: wrap;
`;
const AvatarItem = styled.div`
position: relative;
width: 124px;
height: 124px;
border: 3px solid #141414;
border-radius: 16px;
overflow: hidden;
transition: 200ms;
&:hover {
-webkit-box-shadow: -6px 6px 0px 1px rgba(0, 0, 0, 1);
-moz-box-shadow: -6px 6px 0px 1px rgba(0, 0, 0, 1);
box-shadow: -6px 6px 0px 1px rgba(0, 0, 0, 1);
}
img {
width: 100%;
height: auto;
display: block;
}
.username {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
background-color: rgba(0, 0, 0, 0.7);
color: white;
text-align: center;
visibility: hidden;
opacity: 0;
transition:
opacity 0.3s ease,
visibility 0.3s;
}
&:hover .username {
visibility: visible;
opacity: 1;
}
`;
import React from 'react';
const AvatarGrid = ({ users }: { users: User[] }) => {
return (
<AvatarGridContainer>
{users.map((user) => (
<Link href={`/contributors/${user.id}`} key={`l_${user.id}`}>
<AvatarItem key={user.id}>
<img src={user.avatarUrl} alt={user.id} />
<span className="username">{user.id}</span>
</AvatarItem>
</Link>
))}
</AvatarGridContainer>
);
};
export default AvatarGrid;

View File

@ -0,0 +1,16 @@
'use client';
import { Breadcrumbs } from '@/app/_components/ui/layout/Breadcrumbs';
const BREADCRUMB_ITEMS = [
{
uri: '/contributors',
label: 'Contributors',
},
];
export const Breadcrumb = ({ active }: { active: string }) => {
return (
<Breadcrumbs items={BREADCRUMB_ITEMS} activePage={active} separator="/" />
);
};

View File

@ -0,0 +1,17 @@
import styled from '@emotion/styled';
export const CardContainer = styled.div`
border: 3px solid #141414;
width: 100%;
border-radius: 12px;
padding: 40px;
display: flex;
gap: 32px;
flex-direction: column;
background-color: #fafafa;
@media (max-width: 810px) {
gap: 16px;
padding: 24px;
}
`;

View File

@ -0,0 +1,26 @@
'use client';
import styled from '@emotion/styled';
const Container = styled.div`
display: flex;
flex-direction: column;
align-items: flex-start;
width: 100%;
max-width: 898px;
padding: 40px;
gap: 40px;
@media (max-width: 809px) {
width: 100%;
padding: 40px 24px 40px 24px;
}
`;
export const ContentContainer = ({
children,
}: {
children?: React.ReactNode;
}) => {
return <Container>{children}</Container>;
};

View File

@ -0,0 +1,25 @@
'use client';
import styled from '@emotion/styled';
const Title = styled.h2`
font-size: 56px;
font-weight: 600;
color: #b3b3b3;
margin-bottom: 0px;
margin-top: 64px;
@media (max-width: 810px) {
font-size: 28px;
}
`;
export const Header = () => {
return (
<>
<Title>
Our amazing <br /> <span style={{ color: 'black' }}>Contributors</span>
</Title>
</>
);
};

View File

@ -0,0 +1,102 @@
'use client';
import styled from '@emotion/styled';
import { format } from 'date-fns';
import { GithubIcon } from '@/app/_components/ui/icons/SvgIcons';
const ProfileContainer = styled.div`
display: flex;
gap: 32px;
width: 100%;
align-items: center;
`;
const Avatar = styled.div`
border: 3px solid #141414;
width: 96px;
height: 96px;
border-radius: 16px;
overflow: hidden;
flex-shrink: 0;
img {
width: 100%;
display: block;
height: 100%;
object-fit: cover;
}
`;
const Details = styled.div`
display: flex;
flex-direction: column;
gap: 4px;
.username {
font-size: 40px;
font-weight: 700;
line-height: 48px;
margin: 0;
display: flex;
gap: 12px;
@media (max-width: 810px) {
font-size: 24px;
line-height: 28.8px;
}
}
.duration {
font-size: 24px;
font-weight: 400;
color: #818181;
margin: 0;
@media (max-width: 810px) {
font-size: 20px;
line-height: 28px;
}
}
`;
const StyledGithubIcon = styled(GithubIcon)`
@media (max-width: 810px) {
width: 20px;
height: 20px;
}
`;
interface ProfileCardProps {
username: string;
avatarUrl: string;
firstContributionAt: string;
}
export const ProfileCard = ({
username,
avatarUrl,
firstContributionAt,
}: ProfileCardProps) => {
return (
<ProfileContainer>
<Avatar>
<img src={avatarUrl} alt={username} />
</Avatar>
<Details>
<h3 className="username">
@{username}
<a href={`https://github.com/${username}`} target="_blank">
<StyledGithubIcon size="M" color="rgba(0,0,0,1)" />
</a>
</h3>
{firstContributionAt && (
<p className="duration">
Contributing since{' '}
{format(new Date(firstContributionAt), 'MMMM yyyy')}
</p>
)}
</Details>
</ProfileContainer>
);
};

View File

@ -0,0 +1,86 @@
'use client';
import styled from '@emotion/styled';
import { CardContainer } from '@/app/_components/contributors/CardContainer';
const Container = styled(CardContainer)`
flex-direction: row;
@media (max-width: 810px) {
flex-direction: column;
}
.item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
flex-grow: 1;
flex-basis: 0;
.title {
font-size: 24px;
color: #b3b3b3;
margin: 0;
@media (max-width: 810px) {
font-size: 20px;
}
}
.value {
font-size: 56px;
font-weight: 700;
color: #474747;
@media (max-width: 810px) {
font-size: 32px;
}
}
}
.separator {
width: 2px;
background-color: #141414;
border-radius: 40px;
@media (max-width: 810px) {
width: 100%;
height: 2px;
}
}
`;
interface ProfileInfoProps {
mergedPRsCount: number;
rank: string;
activeDays: number;
}
export const ProfileInfo = ({
mergedPRsCount,
rank,
activeDays,
}: ProfileInfoProps) => {
return (
<>
<Container>
<div className="item">
<p className="title">Merged PR</p>
<span className="value">{mergedPRsCount}</span>
</div>
<div className="separator"></div>
<div className="item">
<p className="title">Rank</p>
<span className="value">{rank}%</span>
</div>
<div className="separator"></div>
<div className="item">
<p className="title">Active Days</p>
<span className="value">{activeDays}</span>
</div>
</Container>
</>
);
};

View File

@ -0,0 +1,109 @@
import { Tooltip } from 'react-tooltip';
import styled from '@emotion/styled';
import { format } from 'date-fns';
import { PullRequestIcon } from '@/app/_components/ui/icons/SvgIcons';
import { formatIntoRelativeDate } from '@/shared-utils/formatIntoRelativeDate';
const StyledTooltip = styled(Tooltip)``;
const Item = styled.div`
display: flex;
gap: 17px;
`;
const StyledTitle = styled.a`
font-size: 24px;
font-weight: 400;
color: #474747;
margin: 0;
text-decoration: none;
@media (max-width: 810px) {
font-size: 20px;
}
`;
const StyledPrLink = styled.a`
cursor: pointer;
text-decoration: none;
&:hover {
text-decoration: underline;
color: #474747;
}
`;
const StyledDescription = styled.div`
font-size: 20px;
line-height: 28px;
font-weight: 500;
color: #b3b3b3;
@media (max-width: 810px) {
font-size: 18px;
}
`;
const StyledPullRequestIcon = styled(PullRequestIcon)`
@media screen {
width: 20px;
height: 20px;
}
`;
interface PullRequestItemProps {
id: string;
title: string;
url: string;
createdAt: string;
mergedAt: string | null;
authorId: string;
}
export const PullRequestItem = ({
id,
title,
url,
createdAt,
mergedAt,
authorId,
}: PullRequestItemProps) => {
const prNumber = url.split('/').slice(-1)[0];
return (
<Item key={id}>
<div>
<StyledPullRequestIcon
color={mergedAt ? '#915FFD' : '#1A7F37'}
size="M"
/>
</div>
<div>
<StyledTitle href={url} target="_blank">
{title}
</StyledTitle>
<StyledDescription>
<StyledPrLink
href={'https://github.com/twentyhq/twenty/pull/' + prNumber}
target="__blank"
>
#{prNumber}
</StyledPrLink>{' '}
by {authorId} was {mergedAt ? `merged` : `opened`}{' '}
<span id={`date-${prNumber}`}>
{formatIntoRelativeDate(mergedAt ? mergedAt : createdAt)}
</span>
<StyledTooltip
anchorSelect={`#date-${prNumber}`}
content={format(
new Date(mergedAt ? mergedAt : createdAt),
'dd MMMM yyyy',
)}
clickable
noArrow
/>
</StyledDescription>
</div>
</Item>
);
};

View File

@ -0,0 +1,44 @@
'use client';
import styled from '@emotion/styled';
import { CardContainer } from '@/app/_components/contributors/CardContainer';
import { PullRequestItem } from '@/app/_components/contributors/PullRequestItem';
import { Title } from '@/app/_components/contributors/Title';
const List = styled.div`
display: flex;
gap: 24px;
flex-direction: column;
`;
interface PullRequestsProps {
list: {
id: string;
title: string;
url: string;
createdAt: string;
mergedAt: string | null;
authorId: string;
}[];
}
export const PullRequests = ({ list }: PullRequestsProps) => {
return (
<CardContainer>
<Title>Pull Requests</Title>
<List>
{list.map((pr) => (
<PullRequestItem
key={pr.id}
id={pr.id}
title={pr.title}
url={pr.url}
createdAt={pr.createdAt}
mergedAt={pr.mergedAt}
authorId={pr.authorId}
/>
))}
</List>
</CardContainer>
);
};

View File

@ -0,0 +1,38 @@
'use client';
import styled from '@emotion/styled';
import { CardContainer } from '@/app/_components/contributors/CardContainer';
import { HeartIcon } from '@/app/_components/ui/icons/SvgIcons';
const StyledTitle = styled.div`
display: flex;
font-size: 24px;
font-weight: 500;
gap: 8px;
@media (max-width: 810px) {
font-size: 20px;
}
`;
const StyledHeartIcon = styled(HeartIcon)`
@media (max-width: 810px) {
width: 16px !important;
height: 16px !important;
}
`;
interface ThankYouProps {
authorId: string;
}
export const ThankYou = ({ authorId }: ThankYouProps) => {
return (
<CardContainer>
<StyledTitle>
Thank you @{authorId} <StyledHeartIcon color="#333333" size="18px" />
</StyledTitle>
</CardContainer>
);
};

View File

@ -0,0 +1,13 @@
import styled from '@emotion/styled';
export const Title = styled.h3`
margin: 0;
font-size: 32px;
line-height: 41.6px;
font-weight: 500;
@media (max-width: 810px) {
font-size: 24px;
line-height: 31.2px;
}
`;