-
Notifications
You must be signed in to change notification settings - Fork 44
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
[김법균] Week14 #458
The head ref may contain hidden characters: "part3-\uAE40\uBC95\uADE0"
[김법균] Week14 #458
Changes from 56 commits
4ff3eac
afc85a4
51cd32b
4b13e67
80657d1
5a20445
71fc42e
c06e1ef
7450edd
d494e1c
6524c10
2e998f1
df4176b
9543365
d85cd76
54a6d86
38f02df
0ef3b30
abf2956
235a8a2
9c7af94
0a80ad0
c661db3
25948dd
572c3a1
ea1481f
ff659cd
be585da
7adf8d7
bb1eb95
318d23e
ae1190f
ebec153
92f5aea
c55266b
a21a6b4
006447c
13d1c7a
8ca6d8d
db72aea
1702d39
bbc6fc3
70edc32
24f16bb
4e99ba4
facb247
12e3cb5
84fe27d
43417d3
fd4f1bb
50cef44
4df5259
1cdb459
1d56499
23340a5
4df9304
b740fc5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
{ | ||
"extends": "next/core-web-vitals" | ||
"extends": "next" | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 역시 말씀드리지만, javascript project convention에 따라 파일명을 제작하는게 좋겠어요 파일 이름의 경우, lowercase와 underscore의 조합으로만 작성을 하고, 리액트 프로젝트 컨벤션에 따라 콤포넌트만 PascalCase 또는 snake-case로 작성을 하는건 어떨까요? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
.account { | ||
display: flex; | ||
align-items: center; | ||
gap: 6px; | ||
} | ||
.userProfileImg { | ||
width: 28px; | ||
aspect-ratio: 1/1; | ||
border-radius: 50%; | ||
} | ||
|
||
.userEmail { | ||
width: fit-content; | ||
font-size: 14px; | ||
@media (max-width: 767px) { | ||
position: absolute; | ||
width: 1px; | ||
height: 1px; | ||
clip: rect(0 0 0 0); | ||
overflow: hidden; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import styles from './Account.module.scss'; | ||
|
||
interface AccountProps { | ||
profileImgSource?: string; | ||
userEmail: string; | ||
Comment on lines
+4
to
+5
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. prop으로 전달받는 요소의 경우, 우리 프로젝트에서 전반적으로 사용되는 유저 데이터가 존재하나요?
|
||
} | ||
|
||
const Account = ({ profileImgSource, userEmail }: AccountProps) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. account라기 보단 user-profile이라는 콤포넌트가 더 적합한 이름으로 보이는데 어떻게 생각하시나요? |
||
return ( | ||
<div className={styles.account}> | ||
<img | ||
src={profileImgSource} | ||
alt='User Profile' | ||
className={styles.userProfileImg} | ||
/> | ||
<span className={styles.userEmail}>{userEmail}</span> | ||
</div> | ||
); | ||
}; | ||
export default Account; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
.authPageHeader { | ||
display: flex; | ||
flex-direction: column; | ||
gap: 16px; | ||
align-items: center; | ||
} | ||
|
||
.logo { | ||
position: relative; | ||
width: 218px; | ||
height: 38px; | ||
} | ||
|
||
.membershipPromptBar { | ||
display: flex; | ||
gap: 8px; | ||
font-family: inherit; | ||
} | ||
|
||
.membershipPromptText { | ||
font-family: inherit; | ||
} | ||
|
||
.membershipPromptLink { | ||
text-decoration: underline; | ||
color: var(--Linkbrary-primary-color); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import Link from 'next/link'; | ||
import Image from 'next/image'; | ||
import styles from './AuthHeader.module.css'; | ||
|
||
interface AuthHeaderProps { | ||
text: string; | ||
linkText: string; | ||
link: string; | ||
} | ||
|
||
export default function AuthHeader({ text, linkText, link }: AuthHeaderProps) { | ||
return ( | ||
<div className={styles.authPageHeader}> | ||
<Link href={'/'} className={styles.logo}> | ||
<Image src={'/assets/images/logo.svg'} fill alt='Linkbrary' /> | ||
</Link> | ||
|
||
<div className={styles.membershipPromptBar}> | ||
<span className={styles.membershipPromptText}>{text}</span> | ||
<Link href={link} className={styles.membershipPromptLink}> | ||
{linkText} | ||
</Link> | ||
</div> | ||
</div> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
.btn { | ||
background-image: linear-gradient(to right, #6d6afe, #6de3fe); | ||
padding: 10px 16px; | ||
border-radius: 8px; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
font-size: 1.125em; | ||
font-weight: 600; | ||
color: #f5f5f5; | ||
text-decoration-line: none; | ||
flex-shrink: 0; | ||
font-family: Pretendard; | ||
} | ||
|
||
.btn:hover { | ||
cursor: pointer; | ||
} | ||
|
||
@media (max-width: 767px) { | ||
.btn { | ||
padding: 10px 16px; | ||
font-size: 14px; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import styles from './Button.module.css'; | ||
|
||
interface ButtonProps { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. button element가 기본적으로 받아올 수 있는 요소들이 존재할텐데요 |
||
children?: React.ReactNode; | ||
onClick?: () => void; | ||
className?: string; | ||
type?: 'button' | 'submit' | 'reset' | undefined; | ||
disabled?: boolean; | ||
} | ||
|
||
const Button = ({ | ||
children, | ||
onClick, | ||
className, | ||
type = 'button', | ||
disabled = false, | ||
}: ButtonProps) => { | ||
return ( | ||
<button | ||
onClick={onClick} | ||
className={`${className} ${styles.btn}`} | ||
type={type} | ||
disabled={disabled} | ||
> | ||
{disabled ? '처리중' : children} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그리고 여기서 처리중임을 꽂아주기보다 그렇다면 다음과 같은 형태로 동적으로 값들이 할당되도록 할 수 있겠죠 <Button disabled={isLoggingIn}>로그인 {isLoggingIn && <Icons.spinner />}</Button> |
||
</button> | ||
); | ||
}; | ||
|
||
export default Button; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
.folderToolBarContainer { | ||
display: flex; | ||
flex-direction: column; | ||
gap: 24px; | ||
width: 1060px; | ||
|
||
.folderToolButtons { | ||
display: flex; | ||
width: 100%; | ||
justify-content: space-between; | ||
align-items: center; | ||
|
||
.folderNameButtons { | ||
display: flex; | ||
flex-wrap: wrap; | ||
width: 80%; | ||
gap: 8px; | ||
} | ||
} | ||
|
||
.folderNameDisplay { | ||
font-size: 24px; | ||
letter-spacing: -0.2px; | ||
font-weight: 600; | ||
} | ||
|
||
.folderNameBar { | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
|
||
.utilButtons { | ||
display: flex; | ||
gap: 12px; | ||
} | ||
} | ||
|
||
@media (max-width: 1124px) { | ||
width: 706px; | ||
} | ||
|
||
@media (max-width: 767px) { | ||
width: 325px; | ||
|
||
.folderNameBar { | ||
flex-direction: column; | ||
align-items: flex-start; | ||
gap: 12px; | ||
} | ||
} | ||
} | ||
|
||
.folderNameButton { | ||
background-color: #fff; | ||
border: 1px solid #6d6afe; | ||
padding: 8px 12px; | ||
border-radius: 5px; | ||
height: 36px; | ||
|
||
&:hover { | ||
background-color: #e7effb; | ||
} | ||
} | ||
|
||
.focusedButton { | ||
background-color: #6d6afe; | ||
color: #fff; | ||
&:hover { | ||
background-color: #6d6afe; | ||
} | ||
} | ||
|
||
.utilButton { | ||
position: relative; | ||
display: flex; | ||
gap: 4px; | ||
color: #9fa6b2; | ||
font-size: 14px; | ||
font-weight: 600; | ||
} | ||
.utilButtonIcon { | ||
position: relative; | ||
width: 18px; | ||
height: 18px; | ||
} | ||
|
||
.folderAddButton { | ||
display: flex; | ||
font-weight: 500; | ||
gap: 4px; | ||
color: #6d6afe; | ||
|
||
.addIconWhite { | ||
display: none; | ||
} | ||
|
||
@media (max-width: 767px) { | ||
position: fixed; | ||
bottom: 101px; | ||
padding: 8px 24px; | ||
left: 50%; | ||
transform: translateX(-50%); | ||
border-radius: 20px; | ||
background-color: #6d6afe; | ||
color: #fff; | ||
z-index: 1; | ||
|
||
.addIcon { | ||
display: none; | ||
} | ||
|
||
.addIconWhite { | ||
display: block; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import FolderToolBarButton from './FolderToolBarButton'; | ||
import styles from './FolderToolBar.module.scss'; | ||
import UtilButton from './UtilButton'; | ||
import { UTIL_BUTTONS_PROPS } from './constants'; | ||
import { FolderObj } from '@/utils/interfaces'; | ||
|
||
const addIcon = '/assets/images/add_icon.svg'; | ||
const addIconWhite = '/assets/images/add_icon_white.svg'; | ||
interface FolderToolBarProps { | ||
folders?: FolderObj[]; | ||
currentFolderId?: number; | ||
folderNameOnClick: (id: number) => void; | ||
onFolderNameChangeClick: () => void; | ||
onFolderAddClick: () => void; | ||
onFolderDeleteClick: () => void; | ||
onShare: () => void; | ||
} | ||
|
||
export default function FolderToolBar({ | ||
folders, | ||
currentFolderId, | ||
folderNameOnClick, | ||
onFolderAddClick, | ||
onFolderNameChangeClick, | ||
onFolderDeleteClick, | ||
onShare, | ||
}: FolderToolBarProps) { | ||
const currentFolder = folders?.find( | ||
(folder) => folder.id === currentFolderId | ||
); | ||
const currentFolderName = currentFolder?.name; | ||
UTIL_BUTTONS_PROPS.share.onClick = onShare; | ||
UTIL_BUTTONS_PROPS.changeName.onClick = onFolderNameChangeClick; | ||
UTIL_BUTTONS_PROPS.delete.onClick = onFolderDeleteClick; | ||
|
||
return ( | ||
<div className={styles.folderToolBarContainer}> | ||
<div className={styles.folderToolButtons}> | ||
<ul className={styles.folderNameButtons}> | ||
{folders?.map((item) => ( | ||
<li key={item.id}> | ||
<FolderToolBarButton | ||
onClick={folderNameOnClick} | ||
id={item.id} | ||
isFocused={item.id === currentFolderId} | ||
> | ||
{item.name} | ||
</FolderToolBarButton> | ||
</li> | ||
))} | ||
</ul> | ||
|
||
<button className={styles.folderAddButton} onClick={onFolderAddClick}> | ||
<span>폴더 추가</span> | ||
<img | ||
src={addIcon} | ||
alt='폴더 추가 아이콘' | ||
className={styles.addIcon} | ||
/> | ||
<img | ||
src={addIconWhite} | ||
alt='폴더 추가 아이콘' | ||
className={styles.addIconWhite} | ||
/> | ||
</button> | ||
</div> | ||
<div className={styles.folderNameBar}> | ||
<span className={styles.folderNameDisplay}>{currentFolderName}</span> | ||
<ul className={styles.utilButtons}> | ||
{Object.entries(UTIL_BUTTONS_PROPS).map(([key, btn]) => ( | ||
<li key={btn.id}> | ||
{currentFolderId !== -1 && ( | ||
<UtilButton | ||
imgSrc={btn.imgSrc} | ||
alt={btn.alt} | ||
onClick={btn.onClick} | ||
> | ||
{btn.btnText} | ||
</UtilButton> | ||
)} | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
</div> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import styles from './FolderToolBar.module.scss'; | ||
|
||
interface FolderToolBarButtonProps { | ||
id: number; | ||
children: React.ReactNode; | ||
onClick: (id: number) => void; | ||
isFocused: boolean; | ||
} | ||
|
||
export default function FolderToolBarButton({ | ||
id, | ||
children, | ||
onClick, | ||
isFocused, | ||
}: FolderToolBarButtonProps) { | ||
const handleClick = () => { | ||
onClick(id); | ||
}; | ||
return ( | ||
<button | ||
onClick={handleClick} | ||
className={`${styles.folderNameButton} ${ | ||
isFocused && styles.focusedButton | ||
}`} | ||
> | ||
{children} | ||
</button> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bk-git-hub
이걸로 설정해보는건 어떤가요? 공식문서에서도 recommend 하고있는 strict 형태여서 제안드립니다
https://nextjs.org/docs/app/building-your-application/configuring/eslint