-
Notifications
You must be signed in to change notification settings - Fork 26
[김참솔] Sprint 7 #103
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
kiJu2
merged 31 commits into
codeit-bootcamp-frontend:React-김참솔
from
cskime:React-김참솔-sprint7
Aug 7, 2025
The head ref may contain hidden characters: "React-\uAE40\uCC38\uC194-sprint7"
Merged
[김참솔] Sprint 7 #103
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
1fdc791
chore(Sprint6): 환경 변수 파일 git 추적 제거
cskime 01597ba
refactor(Sprint6): Button component의 disabled style을 CSS 코드만 사용해서 적용
cskime c92aa1f
refactor(Sprint6): <p> -> <span> tag 변경
cskime 1735fa3
feat(Sprint7) 상품 클릭 시 상세 페이지 이동
cskime 4716e30
fix(Sprint6): 상품 이미지 추가할 때 image input과 image preview 크기가 맞지 않는 문제 수정
cskime 9fe818f
feat(Sprint7): Product detail page로 이동했을 때 서버에서 product 상세 정보 가져오기
cskime 94f5653
feat(Sprint7): 상품 상세 - image, title, price 구현
cskime 5696e74
refactor(Sprint7): TagList component에서 margin 제거
cskime 5cb1e3a
feat(Sprint7): Tag 및 TagList component에 삭제 기능 on/off 구현
cskime 3bcc639
feat(Sprint7): 상품 상세 - description, tags 구현
cskime 9cc8034
feat(Sprint7): User profile 사진을 Avatar component로 분리
cskime e9c28ad
feat(Sprint7): 상품 상세 - profile, favorite button구현
cskime 104fe67
refactor(Sprint7): Component 외부와 접점이 없는 styled-components 이름을 단순하게 변경
cskime 9c59b12
feat(Sprint7): 상품 상세 - 상품 정보와 comment를 구분하는 Separator component 구현
cskime cb8a160
feat(Sprint7): TextInput component의 multiline height 설정을 `rows` 기반으로 변경
cskime ff0fc7b
feat(Sprint7): 상품 상세 - comment form 구현
cskime 9bbfb33
refactor(Sprint7): User profile component를 재사용 가능하도록 추출
cskime 4545044
feat(Sprint7): 아이콘 버튼을 component로 추출
cskime 754b92a
feat(Sprint7): 상품 상세 - comment 목록 UI 구현
cskime 5bb3815
feat(Sprint7): Button에 medium/small size 및 round/pill type에 따라 다른 sty…
cskime da3f3b5
feat(Sprint7): 상품 상세 - '목록으로 돌아가기' 버튼 구현
cskime d973617
feat(Sprint7): Comments API 연동, comments 없을 때 empty UI 표시
cskime cfc9d17
feat(Sprint7): '목록으로 돌아가기' 버튼 클릭 시 '/items' path로 이동
cskime 3c447c9
feat(Sprint7): Comment more button 클릭할 때 dropdown 표시
cskime e3d97ff
feat(Sprint7): Comment 수정 UI 구현
cskime 5bd5689
feat(Sprint7): 상품 상세 - comments list를 mock data를 사용해서 구현
cskime ec223d8
feat(Sprint7): Button component에 hover 효과 적용
cskime 481f0d9
fix(Sprint7): SectionHeaderActions에서 child element의 세로 정렬 수정
cskime 177c0b7
fix(Sprint7): Input component에 `value` prop 전달 시 `onChange` 설정 error 해결
cskime 46ac20a
fix(Sprint7): useEffect missing dependencies warning 제거
cskime 29eb44b
refactor(Sprint7): SearchInput을 styled-components로 구현, input 폴더로 묶음
cskime File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,3 +22,5 @@ dist-ssr | |
| *.njsproj | ||
| *.sln | ||
| *.sw? | ||
|
|
||
| .env.* | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| function trimPath(str) { | ||
| let trimmed = str.trim(); | ||
| while (trimmed.startsWith("/")) { | ||
| trimmed = trimmed.slice(1); | ||
| } | ||
| return trimmed; | ||
| } | ||
|
|
||
| export function createUrl(path, params) { | ||
| const trimmed = trimPath(path); | ||
| const url = new URL(`${import.meta.env.VITE_API_BASE_URL}/${trimmed}`); | ||
|
|
||
| if (!params) { | ||
| return url; | ||
| } | ||
|
|
||
| Object.keys(params).forEach((key) => | ||
| url.searchParams.append(key, params[key]) | ||
| ); | ||
|
|
||
| return url; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| { | ||
| "nextCursor": 0, | ||
| "list": [ | ||
| { | ||
| "writer": { | ||
| "image": "", | ||
| "nickname": "똑똑한 판다", | ||
| "id": 1 | ||
| }, | ||
| "updatedAt": "2024-08-06T02:57:22.000Z", | ||
| "createdAt": "2024-08-06T02:57:22.000Z", | ||
| "content": "혹시 사용 기간이 어떻게 되실까요?", | ||
| "id": 1 | ||
| }, | ||
| { | ||
| "writer": { | ||
| "image": "", | ||
| "nickname": "똑똑한 고양이", | ||
| "id": 2 | ||
| }, | ||
| "updatedAt": "2025-07-06T02:57:22.000Z", | ||
| "createdAt": "2025-07-06T02:57:22.000Z", | ||
| "content": "잘 작동하나요??", | ||
| "id": 2 | ||
| }, | ||
| { | ||
| "writer": { | ||
| "image": "", | ||
| "nickname": "똑똑한 강아지", | ||
| "id": 3 | ||
| }, | ||
| "updatedAt": "2025-08-03T02:57:22.000Z", | ||
| "createdAt": "2025-08-03T02:57:22.000Z", | ||
| "content": "저도 사고싶어요!", | ||
| "id": 3 | ||
| }, | ||
| { | ||
| "writer": { | ||
| "image": "", | ||
| "nickname": "똑똑한 고양이", | ||
| "id": 2 | ||
| }, | ||
| "updatedAt": "2025-08-06T02:57:22.000Z", | ||
| "createdAt": "2025-08-06T02:57:22.000Z", | ||
| "content": "제가 샀습니다.", | ||
| "id": 4 | ||
| }, | ||
| { | ||
| "writer": { | ||
| "image": "", | ||
| "nickname": "똑똑한 토끼", | ||
| "id": 4 | ||
| }, | ||
| "updatedAt": "2025-08-06T07:10:22.000Z", | ||
| "createdAt": "2025-08-06T07:10:22.000Z", | ||
| "content": "까비...", | ||
| "id": 5 | ||
| } | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import mock from "./comments-mock.json"; | ||
|
|
||
| export async function fetchComments(productId) { | ||
| // const url = createUrl(`products/${productId}/comments`, { limit }); | ||
| // const response = await fetch(url); | ||
| // if (!response.ok) { | ||
| // throw new Error("Failed to fetch comments"); | ||
| // } | ||
|
|
||
| // const json = await response.json(); | ||
| // return json.list; | ||
|
|
||
| if (!productId) return; | ||
| return mock.list; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import styled from "styled-components"; | ||
| import defaultImg from "../assets/profile-default.svg"; | ||
|
|
||
| const StyledAvatar = styled.div` | ||
| width: ${({ $size }) => $size}px; | ||
| height: ${({ $size }) => $size}px; | ||
|
|
||
| img { | ||
| width: 100%; | ||
| height: 100%; | ||
| object-fit: cover; | ||
| border-radius: 20; | ||
| } | ||
| `; | ||
|
|
||
| const DEFAULT_SIZE = 40; | ||
|
|
||
| function Avatar({ imageUrl, size = DEFAULT_SIZE }) { | ||
| return ( | ||
| <StyledAvatar $size={size}> | ||
| <img src={imageUrl || defaultImg} alt="프로필 사진" /> | ||
| </StyledAvatar> | ||
| ); | ||
| } | ||
|
|
||
| export default Avatar; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| export const BUTTON_SIZE = { | ||
| medium: "medium", | ||
| small: "small", | ||
| }; | ||
|
|
||
| export const BUTTON_TYPE = { | ||
| round: "round", | ||
| pill: "pill", | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| import styled from "styled-components"; | ||
| import { BUTTON_SIZE, BUTTON_TYPE } from "./button-styles"; | ||
|
|
||
| function padding(buttonSize) { | ||
| return buttonSize === BUTTON_SIZE.medium ? "11px 40px" : "8px 23px"; | ||
| } | ||
|
|
||
| function fontSize(buttonSize) { | ||
| return buttonSize === BUTTON_SIZE.medium ? 18 : 16; | ||
| } | ||
|
|
||
| function borderRadius(buttonType) { | ||
| return buttonType === BUTTON_TYPE.round ? 8 : 24; | ||
| } | ||
|
|
||
| const StyledButton = styled.button` | ||
| display: flex; | ||
| gap: 8px; | ||
| background-color: var(--color-primary-100); | ||
| padding: ${({ $size }) => padding($size)}; | ||
| color: var(--color-cool-gray-100); | ||
| font-size: ${({ $size }) => fontSize($size)}px; | ||
| font-weight: 600; | ||
| line-height: 26px; | ||
| border-radius: ${({ $type }) => borderRadius($type)}px; | ||
| border: none; | ||
| cursor: pointer; | ||
|
|
||
| &:disabled { | ||
| background-color: var(--color-cool-gray-400); | ||
| cursor: default; | ||
| } | ||
|
|
||
| &:hover:not(:disabled) { | ||
| opacity: 0.5; | ||
| } | ||
| `; | ||
|
|
||
| function Button({ | ||
| children, | ||
| size = BUTTON_SIZE.small, | ||
| type = BUTTON_TYPE.round, | ||
| ...props | ||
| }) { | ||
| return ( | ||
| <StyledButton $size={size} $type={type} {...props}> | ||
| {children} | ||
| </StyledButton> | ||
| ); | ||
| } | ||
|
|
||
| export default Button; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
(심화/응용) 해당 함수는 Base URL을 만드는 유틸 함수로 보이는군요 !
다음과 같이
fetch를 간단히 사용할 수 있으면 얼마나 좋을까요?:그 외에도 여러 상황들을 고려해볼 수 있어요.
예를 들어서
method를 고려해야 하며, 그 중post일 경우body를 고려해볼 수 있고,get일 경우에는 쿼리(?query=1)를 고려하게 될겁니다 !더 나아가면 공통적인 예외 처리, 응답 실패 시의 예외 처리, 특정
path에 대한 예외 처리 등등도 고려될 수 있겠네요.이러한 모듈을 만들어 보는 것도 좋은 경험이 될 수 있을거예요.
다음은
GPT로 만들어낸 예시입니다:그리고 사용 예시:
참솔님이라면 이러한 학습 욕심도 있으실 것 같아서 제안드려봅니다 ~!
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.
혹은 편하게
axios를 사용하는 방법도 있어요 !fetch모듈을 잘 만든다는 것은 어렵습니다. 다음 사항들을 고려해볼 수 있어요:get이 아닌 메써드(post,patch,delete등)일 경우는 어떻게 처리할 수 있을까요?query와body가 필요할 때는 어떻게 처리 할 수 있을까요?이 모든 요구사항들을 '잘 만든다는 것'은 어려워요. 따라서 이 모든걸 만들어진
fetch모듈을 사용해보고 후에fetch모듈을 만들어 보는 것도 좋은 학습 방법이 될 수 있어요.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.
어떻게 세팅하면 될까? 🤔
instance를 만들어서export를 하고 사용해보는 것 정도로 시도해보면 좋을 것 같아요.axios-instance파일을 만들어서instance를 생성하고export한 후 사용해보는건 어떨까요?다음과 같이 만들어볼 수 있어요:
인가에 필요한
accessToken을localStorage가 있다면 axios의 인터셉터를 활용할 수 있습니다 !사용 방법 🚀
사용 방법은 정말 간단해요. 다음과 같이 사용할 수 있습니다:
딱 보니. 마이그레이션도 정말 쉽게 할 수 있겠죠? 😊