-
Notifications
You must be signed in to change notification settings - Fork 9
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
Issue164 리뷰 이미지 업로드 기능 추가 #165
Merged
The head ref may contain hidden characters: "issue164-\uB9AC\uBDF0-\uC774\uBBF8\uC9C0-\uC5C5\uB85C\uB4DC-\uAE30\uB2A5-\uCD94\uAC00"
Merged
Changes from 24 commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
001df53
fix: Star 컴포넌트 사이즈 버그 수정
hafnium1923 4a9790b
feat: 리뷰이미지 타입추가 및 mock data변경
hafnium1923 626d982
feat: 리뷰이미지 API 추가
hafnium1923 a2ae69c
feat: 이미지 업로드 컴포넌트 UI 구현
hafnium1923 bab0593
feat: 리뷰이미지 업로드 msw handler 구현
hafnium1923 7f128d4
feat: 리뷰이미지 업로드 훅 분리
hafnium1923 4f10130
feat: 리뷰이미지 컴포넌트 연결
hafnium1923 be7755b
feat: 리뷰이미지 리뷰아이템에 적용
hafnium1923 b3caf5c
fix: useImageUpload에서 불필요한 옵셔널 체이닝 및 변수 할당 제거
ashleysyheo 66790c1
refactor: 리뷰 이미지에 border radius 추가
ashleysyheo 3a4c4ae
refactor: 함수명 수정
ashleysyheo 9c9058c
refactor: 이미지 업로드 한 후 ui 변경
ashleysyheo 13b822d
fix: 상세페이지 갔을 때 무조건 리뷰 입력창 열리는 버그 수정
ashleysyheo 00323ab
refactor: 이미지 삭제 버튼 ui 수정
ashleysyheo 54b1c28
refactor: 이미지 업로드 실패 메세지 수정
ashleysyheo 155b5a1
refactor: 불필요한 css property 제거
ashleysyheo 27af139
refactor: imageHandler 임포트 상대경로에서 절대경로로 변경
ashleysyheo 9613370
refactor: ImageUploadInput 컴포넌트에서 alt 텍스트를 props로 받도록 수정
ashleysyheo 08fbe37
style: 비슷한 css property끼리 묶기
ashleysyheo 77f41e5
refactor: ImageUploadInput 컴포넌트에서 input 태그 기본 attribute를 props로 사용할 수…
ashleysyheo a300b20
style: Textarea input max-width 추가
ashleysyheo d587de3
fix: 업로드한 이미지 삭제 후 같은 이미지 재업로드 안 되는 문제 해결
ashleysyheo 0cca335
refactor: textarea resize 못하게 하기
ashleysyheo c97d818
refactor: 스타일링 분기 처리할 때 클래그 네임 사용 대신 함수를 만들어서 css 리턴하도록 수정
ashleysyheo 9ca5c8e
Merge branch 'develop' into issue164-리뷰-이미지-업로드-기능-추가
ashleysyheo 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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains 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,35 @@ | ||
import { AxiosResponse } from "axios"; | ||
|
||
import { ACCESS_TOKEN, ENDPOINTS } from "constants/api"; | ||
|
||
import axiosInstance from "api/axiosInstance"; | ||
|
||
interface ImageUploadResponse { | ||
imageUrl: string; | ||
} | ||
|
||
const sendImageUploadPostRequest = async (imageFile: File) => { | ||
const accessToken = window.sessionStorage.getItem(ACCESS_TOKEN); | ||
|
||
if (!accessToken) { | ||
window.sessionStorage.removeItem(ACCESS_TOKEN); | ||
window.alert("다시 로그인 해주세요"); | ||
window.location.reload(); | ||
throw new Error("엑세스토큰이 유효하지 않습니다"); | ||
} | ||
ashleysyheo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
const response: AxiosResponse<ImageUploadResponse> = await axiosInstance.post( | ||
ashleysyheo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ENDPOINTS.IMAGE_UPLOAD, | ||
imageFile, | ||
{ | ||
headers: { | ||
Authorization: `Bearer ${accessToken}`, | ||
ashleysyheo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
"Content-Type": "multipart/form-data", | ||
}, | ||
} | ||
); | ||
|
||
return response.data; | ||
}; | ||
|
||
export default sendImageUploadPostRequest; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains 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
67 changes: 67 additions & 0 deletions
67
src/components/common/ImageUploadInput/ImageUploadInput.style.ts
This file contains 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,67 @@ | ||
import styled, { css } from "styled-components"; | ||
|
||
export const Container = styled.div` | ||
width: 100%; | ||
display: flex; | ||
flex-direction: column; | ||
gap: ${({ theme }) => theme.spacer.spacing2}; | ||
`; | ||
|
||
export const InputWrapper = styled.div` | ||
display: flex; | ||
align-items: flex-start; | ||
gap: ${({ theme }) => theme.spacer.spacing2}; | ||
`; | ||
|
||
export const Input = styled.input` | ||
display: none; | ||
`; | ||
|
||
export const UploadedImageWrapper = styled.div` | ||
position: relative; | ||
height: 10rem; | ||
`; | ||
|
||
export const UploadedImage = styled.img` | ||
width: 10rem; | ||
height: 10rem; | ||
object-fit: cover; | ||
border-radius: ${({ theme }) => theme.borderRadius.small}; | ||
`; | ||
|
||
export const DeleteButton = styled.button` | ||
position: absolute; | ||
right: 0; | ||
width: 3.6rem; | ||
height: 3.6rem; | ||
background-color: ${({ theme }) => theme.color.black}; | ||
|
||
border: none; | ||
border-radius: 0; | ||
border-top-right-radius: ${({ theme }) => theme.borderRadius.small}; | ||
outline: 0; | ||
|
||
transition: all 0.2s ease-in; | ||
|
||
&:hover { | ||
background-color: ${({ theme }) => theme.color.gray800}; | ||
} | ||
|
||
& svg { | ||
width: 12px; | ||
height: 12px; | ||
|
||
& > path { | ||
stroke: ${({ theme }) => theme.color.white}; | ||
} | ||
} | ||
`; | ||
|
||
export const getUploadButtonStyle = (isUploaded: boolean) => css` | ||
height: 10rem; | ||
display: ${isUploaded ? "none" : "flex"}; | ||
align-items: center; | ||
justify-content: center; | ||
gap: ${({ theme }) => theme.spacer.spacing2}; | ||
font-weight: normal; | ||
`; |
66 changes: 66 additions & 0 deletions
66
src/components/common/ImageUploadInput/ImageUploadInput.tsx
This file contains 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,66 @@ | ||
import { Button } from "../Button/Button.style"; | ||
import { Label } from "../Label/Label.style"; | ||
ashleysyheo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
import * as S from "./ImageUploadInput.style"; | ||
import { ComponentPropsWithoutRef, useRef } from "react"; | ||
|
||
import { CloseIcon, ImageIcon } from "asset"; | ||
|
||
interface ImageUploadInputProps extends ComponentPropsWithoutRef<"input"> { | ||
label?: string; | ||
imageUrl: string | null; | ||
ashleysyheo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
imageAltText: string; | ||
onRemove: () => void; | ||
} | ||
function ImageUploadInput({ | ||
id, | ||
label, | ||
imageUrl, | ||
imageAltText, | ||
onRemove, | ||
...attributes | ||
}: ImageUploadInputProps) { | ||
const inputRef = useRef<HTMLInputElement | null>(null); | ||
|
||
const handleUploadButton = () => { | ||
if (!inputRef.current) return; | ||
|
||
inputRef.current.click(); | ||
}; | ||
|
||
return ( | ||
<S.Container> | ||
{label && <Label id={id}>{label}</Label>} | ||
<S.InputWrapper> | ||
<Button | ||
css={S.getUploadButtonStyle(!!imageUrl)} | ||
type="button" | ||
className={imageUrl ? "uploaded" : ""} | ||
onClick={handleUploadButton} | ||
> | ||
<ImageIcon /> | ||
{!imageUrl && " 이미지를 업로드해 주세요"} | ||
</Button> | ||
<S.Input | ||
type="file" | ||
accept="image/*" | ||
id={id} | ||
ref={inputRef} | ||
{...attributes} | ||
/> | ||
{imageUrl && ( | ||
<S.UploadedImageWrapper> | ||
<S.UploadedImage src={imageUrl} alt={imageAltText} /> | ||
<S.DeleteButton | ||
type="button" | ||
aria-label="이미지 삭제" | ||
onClick={onRemove} | ||
> | ||
<CloseIcon /> | ||
</S.DeleteButton> | ||
</S.UploadedImageWrapper> | ||
)} | ||
</S.InputWrapper> | ||
</S.Container> | ||
); | ||
} | ||
export default ImageUploadInput; |
This file contains 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 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 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 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 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 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 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
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.
디렉토리명 > image보다 더 구체적으로 정하면 어떨까요?
review 디렉토리에 넣지 않고 image를 새로 만든 이유가 있을까요?
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.
이미지 api 자체를 재사용할 수 있게 만들기 위해서 리뷰를 보낼 때 이미지 파일 데이터를 보내서 imageUrl을 생성하는 것이 아닌 별도의 api를 만들었다고 백엔드한테 들었습니다. 그런 의미에서 추후에 이 api가 리뷰가 아닌 다른 상황에서 사용될 것을 생각하면 images를 만드는 것이 좀 더 어울리지 않나 싶어서 그렇게 했습니다!
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.
아하 그러면 한 api로 모든 종류의 이미지 업로드를 다루는건가요?? 아니면 나중에 /image/review 식으로 세부적으로 나뉘나요?
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.
제가 이해하기로는 이 images api로 모든 종류의 이미지 업로드를 다 다룬다고 알고 있습니다! 그래서 백엔드 쪽에서도 리뷰 폼을 제출할 때 이미지 파일 데이터를 보내는 것이 아니라, 일차적으로 이미지 url을 요청한 다음에 그 url을 리뷰 보낼 때 함께 보내도록 만든 것 같아요.