Skip to content
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

Feature/#28 personal profile #36

Merged
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
13 changes: 13 additions & 0 deletions components/Layout/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import * as S from './styles';
import Header from 'components/header/Header';
const Layout: React.FC = ({ children }) => {
return (
<>
<Header />
<S.Wrapper>{children}</S.Wrapper>
</>
);
};

export default Layout;
7 changes: 7 additions & 0 deletions components/Layout/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import styled from 'styled-components';

export const Wrapper = styled.div`
max-width: ${(props) => props.theme.desktop};
padding: 0 30px;
margin: 0 auto;
`;
21 changes: 21 additions & 0 deletions components/Profile/Banner/AddImage/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';

import ImageUploadWrapper from 'components/common/ImageUploadWrapper';
import { AddImageWrapper, AddImageSvg, AddImageText } from 'components/common/Atomic/AddItem';

interface Props {
text: string;
}

const AddImage: React.FC<Props> = ({ text }) => {
return (
<ImageUploadWrapper name="banner">
<AddImageWrapper>
<AddImageSvg width={80} height={80} />
<AddImageText>{text}</AddImageText>
</AddImageWrapper>
</ImageUploadWrapper>
);
};

export default AddImage;
16 changes: 16 additions & 0 deletions components/Profile/Banner/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React, { useState } from 'react';
import { useRecoilValue } from 'recoil';

import * as S from './styles';

import AddImage from './AddImage';

import { userRegisterInfoState, UserRegisterInfoType } from 'recoil/auth';

const Banner: React.FC = () => {
const [banner, setBanner] = useState<string>();

return <S.BannerWrapper url={banner}>{!banner && <AddImage text="프로필 배너를 추가 해주세요." />}</S.BannerWrapper>;
};

export default Banner;
15 changes: 15 additions & 0 deletions components/Profile/Banner/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import styled from 'styled-components';
import { styledProps } from './types';

export const BannerWrapper = styled.div<styledProps>`
width: 100%;
height: 280px;
background-color: ${(props) => props.theme.color.backgroundGray};
background-image: ${(props) => props.url && `url(${props.url})`};
background-repeat: no-repeat;
background-position: center;
background-size: cover;
display: flex;
justify-content: center;
align-items: center;
`;
6 changes: 6 additions & 0 deletions components/Profile/Banner/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { DefaultTheme } from 'styled-components';

export interface styledProps {
url?: string | ArrayBuffer | null;
theme: DefaultTheme;
}
23 changes: 23 additions & 0 deletions components/Profile/ItemList/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React, { useEffect } from 'react';
import * as S from './styles';
import AddItemCard from 'components/common/AddItemCard';
import Thumbnail from 'components/common/Thumbnail';
interface Props {
itemList: string[]; //데이터 형식에따라 타입 변환할 것
}
const ItemList: React.FC<Props> = ({ itemList }) => {
useEffect(() => {
console.log(itemList);
}, [itemList]);
return (
<S.ItemListWrapper>
{itemList.length ? (
itemList.map((item, i) => <Thumbnail key={i} item={item}></Thumbnail>)
) : (
<AddItemCard></AddItemCard>
)}
</S.ItemListWrapper>
);
};

export default ItemList;
9 changes: 9 additions & 0 deletions components/Profile/ItemList/styles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import styled from 'styled-components';

export const ItemListWrapper = styled.div`
display: grid;
grid-template-columns: repeat(auto-fill, minmax(363px, 1fr));

row-gap: 25px;
column-gap: 24px;
`;
89 changes: 89 additions & 0 deletions components/Profile/UserInfo/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import React, { useState } from 'react';
import * as S from './styles';
import Image from 'next/image';
import {
ProfileEditButton,
UploadProductButton,
FollowButton,
MessageButton,
} from 'components/common/Atomic/Tabs/Button';
import { Keyword } from 'components/common/Atomic/Tabs/Keyword';
import { numberWithCommas } from 'utils/numberWithCommas';

const UserInfo = () => {
const [userName, setUserName] = useState<string>('Andre');
const [abilties, setAbiliies] = useState<string[]>([
'일러스트레이션',
'그래픽 디자인',
'일러스트레이션',
'그래픽 디자인',
'일러스트레이션',
'그래픽 디자인',
'일러스트레이션',
'그래픽 디자인',
'일러스트레이션',
'그래픽',
'마케팅',
]);
const [followers, setFollowers] = useState<number>(10214);
const [followings, setFollowings] = useState<number>(35150);
const [currentUser, setCurrentUser] = useState<boolean>(false);
const [intro, setIntro] = useState<string>(
'사용자 소개입니다.사용자 소개입니다.사용자 소개입니다.사용자 소개입니다.사용자 소개입니다.사용자 소개입니다.사용자 소개입니다.사용자 소개입니다.사용자 소개입니다.사용자 소개입니다.사용자 소개입니다.사용자 소개입니다.사용자 소개입니다.'
);
const handler = () => {
setCurrentUser(!currentUser);
};
return (
<S.InfoWrapper>
<S.ProfileImg>
<Image src="/images/profile_off.svg" onClick={handler} width={120} height={120} />
</S.ProfileImg>
<S.InfoSection>
<h1>{userName}</h1>
<S.InfoDescription>
<div style={{ width: '400px' }}>
{abilties.map((ability, i) => (
<Keyword key={i}>{ability}</Keyword>
))}
</div>
<S.FollowInfo>
<span>팔로워</span>
<span>{numberWithCommas(followers)}</span>
<span>팔로잉</span>
<span>{numberWithCommas(followings)}</span>
</S.FollowInfo>
<p>{intro}</p>
</S.InfoDescription>
</S.InfoSection>
<S.InfoAside>
{currentUser ? (
<>
{' '}
<ProfileEditButton>
<Image src="/images/profile-edit.svg" width={24} height={24} />
<span>프로필 수정</span>
</ProfileEditButton>
<UploadProductButton bgColor>
<Image src="/images/profile-edit-write2.svg" width={24} height={24} />
<span>작품 업로드</span>
</UploadProductButton>
</>
) : (
<>
<FollowButton bgColor>
<Image src="/images/icon-add-round.svg" width={24} height={24} />
<span>팔로우</span>
</FollowButton>
<MessageButton>
<Image src="/images/icon-message.svg" width={24} height={24} />
<span>메시지</span>
</MessageButton>
</>
)}
</S.InfoAside>
</S.InfoWrapper>
);
};

export default UserInfo;
57 changes: 57 additions & 0 deletions components/Profile/UserInfo/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import styled from 'styled-components';
import Image from 'next/image';
export const InfoWrapper = styled.div`
padding: 24px;
position: relative;
margin-bottom: 80px;
display: flex;
`;

export const ProfileImg = styled.div``;

export const InfoSection = styled.div`
margin-left: 24px;
width: 610px;

& > h1{
font-size: 20px;
line-height: 1.3;
font-weight : ${({ theme }) => theme.fontWeight.bold}
color: ${({ theme }) => theme.color.profileNameBlack};
margin-bottom: 16px;
}
`;

export const InfoDescription = styled.div`
display: flex;
flex-direction: column;
flex-wrap: wrap;

p {
color: ${({ theme }) => theme.color.gray_700};
font-weight: ${({ theme }) => theme.fontWeight.medium};
font-size: 12px;
line-height: 1.416666;
}
`;

export const InfoAside = styled.div`
position: absolute;
right: 24px;
`;

export const FollowInfo = styled.div`
margin-bottom: 8px;
span {
font-weight: 400;
font-size: 12px;
line-height: 1.833333;
letter-spacing: -0.01em;
color: ${({ theme }) => theme.color.gray_700};
margin-right: 16px;
}

span:nth-child(2n-1) {
margin-right: 4px;
}
`;
31 changes: 31 additions & 0 deletions components/common/AddItemCard/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import styled from 'styled-components';
import { AddImageWrapper, AddImageSvg } from '../Atomic/AddItem';
const AddItem = () => {
return (
<AddItemCard>
<AddImageWrapper>
<AddImageText>게시물을 추가 해주세요.</AddImageText>
<AddImageSvg width={80} height={80} />
</AddImageWrapper>
</AddItemCard>
);
};

export default AddItem;

const AddItemCard = styled.div`
width: 363px;
height: 280px;
background-color: ${({ theme }) => theme.color.gray_100};
display: flex;
align-items: center;
justify-content: center;
border-radius: 10px;
`;

const AddImageText = styled.span`
color: ${(props) => props.theme.color.addTextGray};
font-size: 14px;
margin-bottom: 16px;
`;
24 changes: 24 additions & 0 deletions components/common/Atomic/AddItem/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import styled, { DefaultTheme } from 'styled-components';
import Image from 'next/image';

export const AddImageWrapper = styled.div`
cursor: pointer;
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
`;

export const AddImageSvg = styled(Image).attrs((props) => ({
src: '/images/add_project_default.svg',
}))`
display: block;
border-radius: 50%;
`;

export const AddImageText = styled.span<{ theme: DefaultTheme }>`
color: ${(props) => props.theme.color.addTextGray};
font-size: 14px;
margin-top: 16px;
`;
50 changes: 50 additions & 0 deletions components/common/Atomic/Tabs/Button/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import styled, { css } from 'styled-components';

export const DefaultButton = styled.button<{ bgColor?: boolean }>`
height: 40px;
border-radius: 30px;
display: inline-flex;
align-items: center;
justify-content: center;

${({ bgColor, theme }) => {
const color = bgColor ? theme.color.DefaultPrimaryGreen : theme.color.backgroundGray;
const pressed = bgColor ? theme.color.PressedPrimaryGreen : theme.color.backgroundHoverGray;
return css`
background-color: ${color};
&: hover {
background-color: ${pressed};
}
&: active {
background-color: ${pressed};
}
`;
}}

& + & {
margin-left: 16px;
}

& > span {
font-size: 16px;
font-weight: ${({ theme }) => theme.fontWeight.medium};
line-height: 1.448125;
margin-left: 4px;
}
`;

export const ProfileEditButton = styled(DefaultButton)`
padding: 10px 24px 10px 20px;
`;

export const UploadProductButton = styled(DefaultButton)`
padding: 10px 24px 10px 20px;
`;

export const FollowButton = styled(DefaultButton)`
padding: 10px 16px;
`;

export const MessageButton = styled(DefaultButton)`
padding: 10px 16px;
`;
16 changes: 16 additions & 0 deletions components/common/Atomic/Tabs/Keyword/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import styled from 'styled-components';

export const Keyword = styled.span`
display: inline-block;
height: 24px;
padding: 4px 8px;
border-radius: 12px;
font-size: 12px;
font-weight: ${({ theme }) => theme.fontWeight.medium};
line-height: 1.4166666;

background-color: ${({ theme }) => theme.color.backgroundGray};

margin-right: 8px;
margin-bottom: 8px;
`;
Loading