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 구현 #68

Merged
merged 10 commits into from
Feb 7, 2024

Conversation

easyhyun00
Copy link
Collaborator

@easyhyun00 easyhyun00 commented Feb 6, 2024

🧩 이슈 번호

✅ 작업 사항

API 문서에 맞게 데이터를 수정하였고 API 구현을 하였습니다.

  const onSubmit = async (data: Inputs) => {
    const letterData: Letter = {
      content: data.content,
      equalGender: EQUAL_GENDER_DICT[data.gender],
      ageRangeStart: data.age[0],
      ageRangeEnd: data.age[1],
      worryType: data.worryType,
      image: data.image, // 아직 백엔드 미구현이지만 넣음
    };
    await postLetter(letterData);
  };

[결과]

e0cf2f52-85d7-42a9-a12f-1e09e4dfbd56.mp4

👩‍💻 공유 포인트 및 논의 사항

상훈님이 만든 @/constants/user.ts 를 보고 letter.ts 를 만들었습니다.
근데 여기서도 고민종류가 필요한데 user.ts 에서 가져오면 직관적으로 보이지 않아 import 하고 export 하였습니다...괜찮나요?

import { WORRY_DICT, type Worry } from './users';

export const EQUAL_GENDER_DICT: Record<string, boolean> = {
  '나와 같은 성별에게 보내기': true,
  '모두에게 보내기': false,
} as const;

export type EQUAL_GENDER = keyof typeof EQUAL_GENDER_DICT;

export { WORRY_DICT, type Worry };

@easyhyun00 easyhyun00 added the ✨ Feature 기능 개발 label Feb 6, 2024
@easyhyun00 easyhyun00 self-assigned this Feb 6, 2024
Copy link

github-actions bot commented Feb 6, 2024

🚀 Storybook Preview 보러가기: https://65a6c73d536a3c43b7c5c9bb-yhovclbdcp.chromatic.com/
🚀 React Preview 보러가기: https://dnd-10th-4-frontend-gvz4gatnw-bbearcookie.vercel.app

Copy link
Member

@bbearcookie bbearcookie left a comment

Choose a reason for hiding this comment

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

고생하셨어요~!! 😁
msw도 빠르게 적용하셨군요!! 👍👍

@@ -0,0 +1,23 @@
export const WORRY_DICT: Record<string, string> = {
Copy link
Member

Choose a reason for hiding this comment

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

p1;
Record<string, string> 형태로 타입 선언이 되어 있다 보니.. 아래처럼 key-value가 상수가 아닌 string 형으로 되어버리네요!! 😅

image

as const 키워드로 자연스럽게 리터럴 타입으로 만드는 게 좋을 것 같아요!!

Suggested change
export const WORRY_DICT: Record<string, string> = {
export const WORRY_DICT = {

Copy link
Member

Choose a reason for hiding this comment

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

image

혹시 타입 문제때문에 Record<string, string> 타입 선언을 하셨다면.. 아래처럼 worryType 자체를 스키마에서 enum 타입으로 만들어주는 방법도 있을 것 같아요 😊
(Object.keys(WORRY_DICT)로 바로 만들어서 z.enum에 인자로 넣는 건 불가능한 문제가 있더라구요..)
참고자료: colinhacks/zod#839 (comment)

const [firstWorry, ...otherWorries] = Object.keys(WORRY_DICT) as Worry[];

const schema = z.object({
  worryType: z.literal('').or(z.enum([firstWorry, ...otherWorries])),
});

아니면.. 가장 간단하게 zod 스키마에는 모든 string을 허용하고, 가져와서 사용할 때에만 타입 단언을 주는 방법도 있겠네요!

const worryType = watch('worryType') as Worry;

Copy link
Collaborator Author

@easyhyun00 easyhyun00 Feb 7, 2024

Choose a reason for hiding this comment

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

아하 그렇군요!
제가 빈문자열 '' 때문에 이렇게 바꾼건데

export const WORRY_DICT: Record<string, string> = {

Worry | '' 이렇게 하는게 더 괜찮을 것 같네요!

const worryType = watch('worryType') as Worry | '';

가장 간단하게 zod 스키마에는 모든 string을 허용하고, 가져와서 사용할 때에만 타입 단언을 주는 방법도 있겠네요!

네! zod 스키마에서는 string 으로 하고 입력 받거나 사용할 때만 타입 단언 해줘도 괜찮을 것 같아요!

const [age, setAge] = useState([15, 40]);
const [gender, setGender] = useState('');
const [concern, setConcern] = useState('');
const [age, setAge] = useState<number[]>([
Copy link
Member

Choose a reason for hiding this comment

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

p5;
현재 원소가 number라면 배열의 길이에 상관 없이 모두 들어가기 때문에 반드시 원소 2개만 들어갈 수 있는 튜플 형태로 타입을 잡아주는 것도 좋겠다는 생각이 들었어요 😁

image

Suggested change
const [age, setAge] = useState<number[]>([
const [age, setAge] = useState<[number, number]>([

@@ -0,0 +1,10 @@
import { type Worry } from '@/constants/letters';

export type Letter = {
Copy link
Member

Choose a reason for hiding this comment

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

자주 사용될만한 타입을 빼주신 부분 좋네요! 👍👍

concern: z.string().min(L.concern.value, { message: L.concern.message }),
worryType: z
.string()
.min(L.worryType.value, { message: L.worryType.message }),
image: z.any(),
Copy link
Member

Choose a reason for hiding this comment

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

p5;
any보다 이미지 파일 형식에 맞춘 타입이면 보다 안정적일 듯 한데.. 저도 해보진 않은 작업이라서 링크만 살포시 올려놓을게요!!

colinhacks/zod#387 (comment)

Copy link
Collaborator Author

@easyhyun00 easyhyun00 Feb 7, 2024

Choose a reason for hiding this comment

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

오 감사합니다!
제가 zod 로 이미지 파일을 어떻게 타입을 지정해야 될지 잘 몰라서
accept="image/*" 가 있어도 PC 에서는 바꿀 수 있기 때문에 이미지를 입력받을 때부터 아예 등록하지 못하게 했었는데

  const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0] as File;
    const isImage = file.type.startsWith('image/');
    if (isImage) {
      setValue('image', file);
      event.target.value = '';
    }
  };

이런식으로 하면 폼을 제출할 때, 일관된 에러를 보여줄 수 있겠네요.

  image: z
    .any()
    .optional()
    .refine(
      (files) => !files || files?.[0]?.size <= MAX_FILE_SIZE,
      `사진은 5MB 이하여야 합니다.`,
    )
    .refine(
      (files) => !files || ACCEPTED_IMAGE_TYPES.includes(files?.[0]?.type),
      '사진은 이미지 파일만 가능합니다.',
    ),

Comment on lines 3 to 6
export const EQUAL_GENDER_DICT: Record<string, boolean> = {
'모두에게 보내기': false,
'나와 같은 성별에게 보내기': true,
} as const;
Copy link
Member

Choose a reason for hiding this comment

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

p3;
편지와 관련한 내용을 상수로 빼신 부분이 좋은 시도라고 생각해요 😊👍
다만.. 요 데이터가 나타내려고 하는 값이 특정 리터럴 값이 아니라 boolean 이다 보니 상수로 관리하지 않아도 충분하지 않을까 싶은 생각이 있어요! (true or false 이기에 스키마를 다룰 때에도 간단하게 boolean만 사용 가능..)

모두에게 보내기, 나와 같은 성별에게 보내기 와 같은 텍스트의 경우 전역적인 도메인 차원에서 활용 된다기 보다는 일부 컴포넌트에서 화면에 보여줘야 하는 데이터이기에 JSX 트리에 직접 텍스트를 넣어도 충분하다고 생각해요!
지현님은 어떻게 생각하시나요!?

Copy link
Collaborator Author

@easyhyun00 easyhyun00 Feb 7, 2024

Choose a reason for hiding this comment

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

리뷰 감사합니다!

상수로 관리하지 않아도 충분

배열로 관리하는게 좋을 것 같네요!

export const EQUAL_GENDER_DICT = [
  '모두에게 보내기',
  '나와 같은 성별에게 보내기',
] as const;

export type EqualGender = (typeof EQUAL_GENDER_DICT)[number];

모두에게 보내기, 나와 같은 성별에게 보내기 와 같은 텍스트의 경우 전역적인 도메인 차원에서 활용 된다기 보다는 일부 컴포넌트에서 화면에 보여줘야 하는 데이터이기에 JSX 트리에 직접 텍스트를 넣어도 충분하다고 생각해요!
지현님은 어떻게 생각하시나요!?

좋은 의견 감사합니다! 이게 편지 쓰기 페이지 에만 사용되지만 파일 3곳에서 사용이 하더라구요. 그래서 letter.ts 에서 관리하는게 더 좋을 것 같습니다. 데이터를 따로 다른 파일에 두어 관리하는게 더 좋지 않을까요..?

@easyhyun00 easyhyun00 merged commit 1e66aa0 into feat/#55/write-page Feb 7, 2024
7 checks passed
@easyhyun00 easyhyun00 deleted the feat/#55/write-page-api branch February 7, 2024 09:47
easyhyun00 added a commit that referenced this pull request Feb 7, 2024
* ✨ feat: 편지쓰기 페이지 UI 구현 (#60)

* ✨ feat: Tooltip 컴포넌트, useTimeout 훅 작성 (#57)

* 📦 chore: @radix-ui/react-tooltip 설치

* ✨ feat: useTimeout 훅 작성

* ✨ feat: Tooltip 컴포넌트 작성

* 🔨 refactor: IconButton에 forwardRef 추가

* 💄 design: Tooltip 스토리북 작성

* 📝 style: isOpen 초기 값 delay > 0 로 변경

* 💄 design: 배경 이미지 변경

* ✨ feat: LetterWrite 페이지 편지지 UI 구현

* ✨ feat: LetterWrite 페이지 경로 추가

* ✨ feat: LetterWrite 페이지 바텀시트 UI 구현

* 🔨 refactor: LetterWrite 페이지 컴포넌트 분리

* 🔨 refactor: html 태그 변경 및 인터페이스 분리

* 💄 design: AgeSlider 툴팁 변경

* 🚑 fix: 빌드 오류 수정

* 🚑 fix: 빌드 오류 수정-버튼 스타일 인자

* 🔨 refactor: Button 컴포넌트 사용 및 함수명 변경

---------

Co-authored-by: SangHoon Lee <50488780+bbearcookie@users.noreply.github.com>

* ✨ feat: 편지쓰기 페이지 form 구현 (#62)

* ✨ feat: 편지 내용 글자수 제한 기능 구현

* ✨ feat: 편지 받는이 BottomSheet 클릭 이벤트 구현

* ✨ feat: react-hook-form 에 제출할 폼 내용 등록

* ✨ feat: 사진 form 등록 및 사진 삭제 기능 구현

* ✨ feat: 선택된 편지 받는 사람 표시 구현

* ✨ feat: Zod 를 사용하여 form 유효성 검사

* ✨ feat: 폴라로이드 모달 구현 및 폴라로이드 컴포넌트 수정

* 🔨 refactor: LetterWrite 페이지 컴포넌트 및 스타일 분리

* 🚑 fix: 이미지 삭제 후 같은 이미지 재선택 시 등록 안되는 오류 수정

* 📝 style: px 을 rem 단위로 변경 및 console.log 제거

* ✨ feat: textarea 의 maxLength 속성 사용

* ✨ feat: 스키마의 숫자 값 상수화 및 useForm 에 스키마 타입 추가

* ✨ feat: 이미지 유효성 검사 추가

* 📝 style: 하단 버튼 문구 '보내기'로 변경

* ✨ feat: 편지 쓰기 모킹 API 구현 (#68)

* ✨ feat: 편지 작성 모킹 및 API 구현

* ✨ feat: 타입 수정 및 폼 데이터 API 문서에 맞게 값 변환 완료

* ✨ feat: 편지 작성 API 처리

* 📝 style: postLetter API 매개변수명 변경

* 💄 design: Letter Write 페이지 디자인 수정

* 💄 design: 편지 받는 사람 설정 컨테이너 디자인 변경 및 아이콘 변경

* 🔨 refactor: 타입 변경

* 💄 design: 보낸 사람 선택창 필터링 Chip으로 변경 및 UI 수정

* 📝 style: 뷰포트 메타 태그에 user-scalable 비활성화

* 💄 design: AgeSlider padding 추가

* 🚑 fix: build 에러 수정

* 💄 design: 닉네임 온보딩 아이콘 위치 상대적으로 변경

---------

Co-authored-by: SangHoon Lee <50488780+bbearcookie@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨ Feature 기능 개발
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants