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

[박경서] week13 #493

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
4 changes: 4 additions & 0 deletions .babelrc
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

종민님한테도 코드 리뷰 했던 거지만 next 버전이 올라가면서 이런 방법도 생겼다는 걸 알려드리고 싶었습니다!
현재 코드에서 방법 1 사용하셨는데, 방법 2 로도 가능합니다!
링크

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

최고!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 신기하네요. 감사합니다!

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"presets": ["next/babel"],
"plugins": [["styled-components", { "ssr": true }]]
}
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"extends": "next/core-web-vitals"
"extends": ["next/babel", "next/core-web-vitals"]
}
15 changes: 15 additions & 0 deletions .github/delete-merged-branch-config.yml
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

머지한 후, 브랜치 자동 삭제해주는 기능이군요 👍🏻

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호랏

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 좋은 기능이네요

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오.. 그런 기능이었군요..!

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: delete branch on close pr

on:
pull_request:
types: [closed]

permissions:
pull-requests: write

jobs:
delete-branch:
runs-on: ubuntu-latest
steps:
- name: delete branch
uses: SvanBoxel/delete-merged-branch@main
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# Kakao
.env

# dependencies
/node_modules
/.pnp
Expand Down
4 changes: 4 additions & 0 deletions assets/icon/eye-off.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions assets/icon/eye-on.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 52 additions & 0 deletions components/Card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { dateCalculator } from './dateCalculator';
import * as C from './styled-component/CardStyledComponent';
import { ItemState } from '../pages/sharedPage';
import styled from 'styled-components';
import Image from 'next/image';

interface CardProps {
item: ItemState;
}

const Div = styled.div`
position: relative;
width: 340px;
height: 234px;
`;
Comment on lines +11 to +15
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C. 으로 시작하는 Styled Components와 Div의 Naming이 구분되어서 혹시 다른 의도가 있는 코드인가요??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전에 한번 styled-components로 바꾼 뒤에 추가적으로 Image 컴포넌트 때문에 필요한 거라 여기에 그냥 적어뒀습니다!


export default function Card({ item }: CardProps) {
const apiDate = new Date(item.createdAt);
const elapsedTime = dateCalculator(apiDate);
const year = apiDate.getFullYear();
const month = apiDate.getMonth() + 1;
const days = apiDate.getDate();

if (item.imageSource === undefined) {
item.imageSource = '/no-image.svg';
}

return (
<C.CardWrapperLink href={item.url} target="_blank">
<C.CardBox>
<C.CardImgDiv>
<Div>
<Image
className="card-img"
fill
sizes="100%"
src={item.imageSource}
alt={item.title}
style={{ objectFit: 'cover' }}
priority
/>
</Div>
</C.CardImgDiv>
<C.CardText>
<C.CardTimeAgo>{elapsedTime}</C.CardTimeAgo>
<C.TextDescription>{item.description}</C.TextDescription>
<C.CardYear>{`${year}. ${month}. ${days}`}</C.CardYear>
</C.CardText>
</C.CardBox>
</C.CardWrapperLink>
);
}
43 changes: 43 additions & 0 deletions components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import styled from 'styled-components';
import * as F from './styled-component/FooterStyledComponent';
import Image from 'next/image';
import Link from 'next/link';

const Div = styled.div`
position: relative;
width: 20px;
height: 20px;
`;
export default function Footer() {
return (
<F.FooterContainer>
<F.FoterLeft>©codeit - 2023</F.FoterLeft>
<F.FooterMidle>
<F.PolicyNFaqA href="./policy.html">Privacy Policy</F.PolicyNFaqA>
<F.PolicyNFaqA href="./faq.html">FAQ</F.PolicyNFaqA>
</F.FooterMidle>
<F.FooterRight>
<Link href="https://www.facebook.com">
<Div>
<Image src="/facebook.svg" fill alt="facebook" />
</Div>
</Link>
<Link href="https://www.twitter.com">
<Div>
<Image src="/twitter.svg" fill alt="twitter" />
</Div>
</Link>
<Link href="https://www.youtube.com">
<Div>
<Image src="/youtube.svg" fill alt="youtube" />
</Div>
</Link>
<Link href="https://www.instagram.com">
<Div>
<Image src="/insta.svg" fill alt="instagram" />
</Div>
</Link>
</F.FooterRight>
</F.FooterContainer>
);
}
98 changes: 98 additions & 0 deletions components/Input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import Image from 'next/image';
import { ChangeEvent, useState } from 'react';
import eyeOff from 'assets/icon/eye-off.svg';
import eyeOn from 'assets/icon/eye-on.svg';
import styled, { css } from 'styled-components';

const Div = styled.div`
position: relative;
display: flex;
align-items: center;
width: 350px;
`;

const StyledInput = styled.input<{ isError: boolean }>`
display: flex;
width: 100%;
padding: 18px 15px;
justify-content: center;
align-items: center;
border-radius: 8px;
color: #373740;
border: 1px solid #ccd5e3;
outline: none;
&:focus {
border-color: #6d6afe;
}

${({ isError }) =>
isError &&
css`
border-color: #ff5b56;

&:focus {
border-color: #ff5b56;
}
`}
`;

const ErrorText = styled.h4`
color: #ff5b56;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: normal;
margin-top: 6px;
`;

const StyledButton = styled.button`
position: absolute;
border: none;
cursor: pointer;
right: 15px;
background-color: #fff;
`;

function Input() {
const [isError, setIsError] = useState(false);
const [isVisible, setIsVisible] = useState(false);
const [value, setValue] = useState('');

const handleVisibility = () => setIsVisible(!isVisible);
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
Comment on lines +57 to +62
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setter함수 내에 state를 그대로 쓰는 게 안티패턴이라고 본 것이 기억나네요

https://sangcho.tistory.com/entry/Commons-Mistakes-with-React-useState

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 감사합니다!

setIsError(false);
setValue(e.target.value);
};

function blurHandler() {
if (value === '') {
setIsError(true);
}
}

return (
<div style={{ backgroundColor: '#f0f6ff' }}>
<Div>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거는 모든 팀원들한테 해당하는 건데 저희 Styled~ 라고 네이밍 했으니까
이것도 Styled~로 시작하는 네이밍으로 하면 좋을 것 같습니다 😶

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

바꾸겠습니다!

<StyledInput
placeholder="내용 입력"
isError={isError}
type={isVisible ? 'text' : 'password'}
value={value}
onChange={handleChange}
onBlur={blurHandler}
/>
<StyledButton onClick={handleVisibility}>
<Image
src={isVisible ? eyeOn : eyeOff}
width={16}
height={16}
alt="비밀번호 숨기기 버튼"
/>
</StyledButton>
</Div>
{isError && <ErrorText>내용을 다시 작성해주세요</ErrorText>}
</div>
);
}

export default Input;
54 changes: 54 additions & 0 deletions components/Nav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { useState, useEffect } from 'react';
import { getData } from '../pages/api/api';
import Profile from './Profile';
import * as N from './styled-component/NavStyledComponent';
import Image from 'next/image';
import { useRouter } from 'next/router';
import Link from 'next/link';

export interface LoginState {
id: number;
name: string;
email: string;
profileImageSource: string;
created_at: string;
image_source: string;
auth_id: string;
}

export default function Nav() {
const [login, setLogin] = useState<LoginState>();
const router = useRouter();

const url = router.pathname;

const handleLoad = async () => {
if (url === '/shared') {
const data = await getData('sample/user');
setLogin(data);
} else if (url === '/folder') {
const { data } = await getData('users/1');
setLogin(data);
Comment on lines +29 to +31
Copy link
Collaborator

@qooktree1 qooktree1 Dec 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DEFAULT USER ID와 같이 공통으로 쓰일 것 같은 상수는 따로 관리해서 import 받는 것도 좋을 것 같아요 :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

상수화 해보겠습니다!

}
};

useEffect(() => {
handleLoad();
}, []);
return (
<N.NavContainer>
<N.NavWrapper>
<Link href="/">
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지금은 잠깐 만들어 놓은 /페이지로 이동하지만 시간이 나면 첫 주차 때 만든 홈페이지로 이동하게 끔 수정하겠습니다.

<N.NavLibraryImg>
<Image src="/linkbrary.svg" fill priority alt="libraryLogo" />
</N.NavLibraryImg>
</Link>
{login?.id ? (
<Profile item={login} />
) : (
<N.NavLoginButton onClick={handleLoad}>로그인</N.NavLoginButton>
)}
</N.NavWrapper>
</N.NavContainer>
);
}
25 changes: 25 additions & 0 deletions components/Profile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as N from './styled-component/NavStyledComponent';
import { LoginState } from './Nav';

interface ProfileProps {
item: LoginState;
}

export default function Profile({ item }: ProfileProps) {
return (
<N.ProfileDiv>
<N.ProfileDivLogo>
{item.id ? (
<N.ProfileHumanImg src={item.profileImageSource} alt="profileImg" />
) : (
<N.ProfileHumanImg src={item.image_source} alt="profileImg" />
)}
</N.ProfileDivLogo>
{item.id ? (
<N.ProfileDivMail>{item.email}</N.ProfileDivMail>
) : (
<N.ProfileDivMail>{item.email}</N.ProfileDivMail>
)}
</N.ProfileDiv>
);
}
66 changes: 66 additions & 0 deletions components/SharedHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { getData } from '../pages/api/api';
import { useCallback, useState, useEffect } from 'react';
import * as N from './styled-component/NavStyledComponent';
import Image from 'next/image';
import styled from 'styled-components';

interface UserState {
id: number;
name: string;
profileImageSource: string;
}

const Div = styled.div`
position: relative;
width: 188px;
height: 48px;
`;

const SmileDiv = styled.div`
position: relative;
width: 60;
height: 60px;
`;

export default function SharedHeader() {
const [user, setUser] = useState<UserState>({
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 하나의 state로 객체로 관리하는 것을 연습해봐야겠네요 👍

id: 1,
name: '',
profileImageSource: '',
});

const handleLoad = useCallback(async () => {
const { folder } = await getData('sample/folder');
setUser(folder.owner);
}, []);
useEffect(() => {
handleLoad();
}, [handleLoad]);

return (
<N.NavContainer>
<N.SharedNavWrapper>
<N.SharedNavLogo>
<SmileDiv>
<Image
src={user.profileImageSource}
fill
sizes="100%"
alt="profileImg"
/>
</SmileDiv>
<N.SharedNavDiv className="nav2-div">{user?.name}</N.SharedNavDiv>
</N.SharedNavLogo>
<Div>
<Image
src="/favorites.svg"
fill
sizes="100%"
alt="starImg"
priority
/>
</Div>
</N.SharedNavWrapper>
</N.NavContainer>
);
}
Loading