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

Feat: 이미지 첨부 기능 구현 및 리스트 생성 제출 API 연동 #17

Merged
merged 17 commits into from
Feb 5, 2024

Conversation

seoyoung-min
Copy link
Contributor

@seoyoung-min seoyoung-min commented Feb 4, 2024

개요

  • 이미지를 첨부하고, 프리뷰를 확인할 수 있는 기능을 추가했습니다.
  • 리스트 생성 제출 API 연결 했습니다.

작업 사항

  • 아이템 추가, 삭제, 입력 구현
  • input 에러 처리 (타이틀 미입력, url 형식, 코멘트 글자수 초과시 입력제한)
  • 드래그앤드랍구현
  • 링크 모달 구현, 앞에 http:// 없을시 추가 로직 구현
  • 아이템 파트 헤더 컴포넌트화 (@Eugene-A-01 헤더 복붙)
  • 이미지 첨부 - 미리보기 기능 구현
  • 완료시 리스트 생성 API 실행 및 이미지 업로드 구현 (axios, react-query)
    • 리스트생성 - presignedUrl 요청 - presignedUrl에 이미지 업로드 - 서버에 성공 신고
  • 코멘트 길이 에러 CSS 수정
  • 링크 첨부시 프리뷰에 도메인 노출 ⭐️
  • 아코디언 UI ⭐️
  • 함수, 컴포넌트에 설명 및 파라미터 설명 추가⭐️
  • 이미지 첨부 사이즈 제한(프론트)
  • 링크&이미지 첨부아이콘 클릭시 색 변경
  • 통신 에러 토스트 처리

참고 사항 (optional)

  • react-beautiful-dnd 라이브러리를 사용했습니다. 앞으로 관리에 집중하지 않을 것이라는 선언을 한 라이브러리라 고민이 됐지만, 사용자가 많아 자료를 찾기 쉽고, trello 회사인 atlassian에서 만들어 신뢰도가 높아 선택했습니다.
  • 이번에 제일 어렵다고 느낀 것은 타입스크립트였어요 🙈

스크린샷

  1. 아이템 추가-삭제
    리스트생성_아이템추가삭제

  2. 에러처리 (높이 달라지는 css 수정 예정)
    리스트생성_에러처리

  3. 이미지 첨부
    리스트생성_이미지첨부

  4. 드래그앤드랍
    리스트생성_드래그앤드랍

  5. api 요청
    리스트생성_api


리뷰어에게

  • 머지 충돌을 잡다보니 많은 파일들이 모두 새로운 커밋으로 들어갔습니다🥲 2/5까지 제가 작성한 코드들을 코드리뷰로 표시하겠습니다.
  • @Eugene-A-01 리스트생성 api 코드, 헤더 컴포넌트 코드 중 기능 구현을 위해 일부 수정한 부분이 있습니다🙏 코드리뷰로 표시하겠습니다!

@seoyoung-min seoyoung-min added Feat 구현 Refactor 리팩토링 labels Feb 4, 2024
@seoyoung-min seoyoung-min self-assigned this Feb 4, 2024
Copy link
Contributor

@Nahyun-Kang Nahyun-Kang left a comment

Choose a reason for hiding this comment

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

presigned url 구현 어려우셨을텐데 대박 이렇게하는 거군요👍 이미지 첨부를 제가 맡게된다면 서영님 PR 보면서 공부하겠습니다! 완성도가 정말 높군요.. 1차 mvp도 너무 고생하셨습니다! 회의 끝나고 더 자세하게 보겠습니당 🥰

@seoyoung-min seoyoung-min merged commit 88ced21 into 8-Sprinters:dev Feb 5, 2024
1 check passed

export const createList = async (data: ListCreateType) => {
const response = await axiosInstance.post<ListCreateType>('/lists', data);
const response = await axiosInstance.post<ListIdType>('/lists', data);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Eugene-A-01 🖊️ 제네릭으로 response로 받을 타입으로 넣어야 해서 수정했습니다!

Comment on lines +1 to +31
import axiosInstance from '@/lib/axios/axiosInstance';
import { ItemImagesType, PresignedUrlListType } from '@/lib/types/listType';
import axios from 'axios';

interface uploadItemImagesProps {
listId: number;
imageData: ItemImagesType;
imageFileList: File[];
}

export const uploadItemImages = async ({ listId, imageData, imageFileList }: uploadItemImagesProps) => {
imageData.listId = listId;

//PresignedUrl 생성 요청
const response = await axiosInstance.post<PresignedUrlListType>('/lists/upload-url', imageData);

//PresignedUrl에 이미지 업로드
for (let i = 0; i < response.data.length; i++) {
const result = await axios.put(response.data[i].presignedUrl, imageFileList[i], {
headers: {
'Content-Type': imageFileList[i]?.type,
},
});
if (result.status !== 200) return;
}

//서버에 성공 완료 알림
if (imageFileList.length !== 0) {
await axiosInstance.post('/lists/upload-complete', imageData);
}
};
Copy link
Contributor Author

Choose a reason for hiding this comment

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

👩‍💻리스트 생성 성공 후 리스트 아이템 이미지를 업로드하는 과정입니다!

queryFn, MutationFn 모두 파라미터 1개만 전달할 수 있는 것 같아요!
여러개를 받아야해서 객체 타입으로 받았습니다!

@@ -22,7 +22,7 @@ import { UserProfileType } from '@/lib/types/userProfileType';
import { getCategories } from '@/app/_api/category/getCategories';
import { getUsers } from '@/app/_api/user/getUsers';
import { listDescriptionRules, listLabelRules, listTitleRules } from '@/lib/constants/formInputValidationRules';
import { listDescription } from '@/app/[userNickname]/[listId]/_components/ListDetailOuter/ListInformation.css';
// import { listDescription } from '@/app/[userNickname]/[listId]/_components/ListDetailOuter/ListInformation.css';
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Eugene-A-01 🖊️ 배포시 미사용 코드로 워닝이 떠서 주석처리했습니다~!

@@ -75,7 +76,7 @@ function CreateList({ onNextClick }: CreateListProps) {
return (
<div>
{/* 헤더 */}
<Header isNextActive={isValid} onClickNext={onNextClick} />
<Header isNextActive={title && category} onClickNext={onNextClick} />
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Eugene-A-01 🖊️isValid가 아이템 페이지까지 채워져야 true가 돼서 title, category를 watch하여 값이 있을때 true가 되도록 코드를 수정했습니다! 급하게 수정한 것이라 옳은 방식인지는 확신이 없습니다ㅠㅠ!

<button className={isNextActive ? styles.headerNextButtonActive : styles.headerNextButton} onClick={onClickNext}>
<button
className={isNextActive ? styles.headerNextButtonActive : styles.headerNextButton}
disabled={!isNextActive}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Eugene-A-01 🖊️클릭 안되게 하기 위해 disabled 속성을 추가했습니다!

Comment on lines +91 to 107
const saveImageMutation = useMutation({ mutationFn: uploadItemImages });

const createListMutation = useMutation({
mutationFn: createList,
onSuccess: (data) => {
saveImageMutation.mutate({
listId: data.listId,
imageData: formatData().imageData,
imageFileList: formatData().imageFileList,
});
},
});

const handleSubmit = () => {
const { listData } = formatData();
createListMutation.mutate(listData);
};
Copy link
Contributor Author

Choose a reason for hiding this comment

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

👩‍💻 리액트 쿼리를 처음 써봅니다..! 잘 사용한 것인지 궁금합니다!

@seoyoung-min seoyoung-min deleted the feature/create-item-image branch October 28, 2024 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feat 구현 Refactor 리팩토링
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants