-
Notifications
You must be signed in to change notification settings - Fork 0
Qnrr 463 조민주 스터디 신청 회원 불러오기 UI 및 api 적용 #122
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
The head ref may contain hidden characters: "QNRR-463-\uC870\uBBFC\uC8FC-\uC2A4\uD130\uB514-\uC2E0\uCCAD-\uD68C\uC6D0-\uBD88\uB7EC\uC624\uAE30-ui-\uBC0F-api-\uC801\uC6A9"
Changes from all commits
748b9ce
a1c6893
e0ebd29
3bf79a7
afc9ef6
ce1a661
c51493a
6938ee7
077821e
7d248ca
7c52987
5b19852
845e74b
074c827
be1ee08
904a825
06f0613
ac40b4f
9331b00
9d4277a
97cdf8b
e839c1d
80da665
7e64701
f7cb212
b5d708e
3a043f7
597b35f
969344f
f979d6e
074af24
de4bde2
dac6f53
952a9bc
33e3985
97e6c5b
d6db644
7e82581
2f38734
f3dda4a
be287e5
b5a36df
4e5e13f
b03ca1b
eeeec22
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 |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| nodeLinker: node-modules | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| import { FieldNamesMarkedBoolean } from 'react-hook-form'; | ||
| import { z } from 'zod'; | ||
| import type { MemberProfile } from '@/entities/user/api/types'; | ||
| import { UrlSchema } from '@/shared/util/zod-schema'; | ||
| import { UpdateUserProfileRequest } from '../api/types'; | ||
|
|
||
| const nameRegex = /^[가-힣a-zA-Z]{2,10}$/; | ||
| const telRegex = /^\d{2,3}-\d{3,4}-\d{4}$/; | ||
| const birthRegex = /^\d{4}\.(0[1-9]|1[0-2])\.(0[1-9]|[12]\d|3[01])$/; | ||
|
|
||
| export const ProfileFormSchema = z.object({ | ||
| name: z | ||
| .string() | ||
| .trim() | ||
| .min(1, '이름은 필수입니다.') | ||
| .regex(nameRegex, '이름은 2~10자의 한글 또는 영문만 허용됩니다.'), | ||
|
|
||
| tel: z | ||
| .string() | ||
| .trim() | ||
| .min(1, '연락처는 필수입니다.') | ||
| .regex(telRegex, '연락처는 숫자와 하이픈(-) 형식으로 입력해주세요.'), | ||
|
|
||
| birthDate: z | ||
| .string() | ||
| .trim() | ||
| .optional() | ||
| .transform((v) => (v === '' || v === undefined ? undefined : v)) | ||
| .refine((v) => v === undefined || birthRegex.test(v), { | ||
| message: '잘못된 형식입니다.', | ||
| }) | ||
| .refine( | ||
| (v) => { | ||
| if (!v) return true; | ||
| const d = new Date(v.replace(/\./g, '-')); | ||
| const year = d.getFullYear(); | ||
| const now = new Date().getFullYear(); | ||
|
|
||
| return !Number.isNaN(d.getTime()) && year >= 1900 && year <= now; | ||
| }, | ||
| { message: '잘못된 형식입니다.' }, | ||
| ) | ||
| .transform((v) => (v ? v.replace(/\./g, '-') : undefined)), | ||
|
|
||
| githubLink: UrlSchema, | ||
| blogOrSnsLink: UrlSchema, | ||
|
|
||
| simpleIntroduction: z | ||
| .string() | ||
| .trim() | ||
| .max(200, '최대 200자까지 입력할 수 있어요.') | ||
| .optional() | ||
| .transform((v) => (v === '' || v === undefined ? undefined : v)), | ||
|
|
||
| mbti: z | ||
| .string() | ||
| .optional() | ||
| .transform((v) => (v === '' || v === undefined ? undefined : v)), | ||
|
|
||
| interests: z | ||
| .array(z.string()) | ||
| .optional() | ||
| .transform((arr) => (!arr || arr.length === 0 ? undefined : arr)), | ||
| }); | ||
|
|
||
| export type ProfileFormInput = z.input<typeof ProfileFormSchema>; | ||
| export type ProfileFormValues = z.output<typeof ProfileFormSchema>; | ||
|
|
||
| export function buildProfileDefaultValues( | ||
| member: MemberProfile, | ||
| ): ProfileFormInput { | ||
| return { | ||
| name: member.memberName ?? '', | ||
| tel: member.tel ?? '', | ||
| // 화면에서는 점(.)으로 보여주기, 스키마 제출 시 하이픈(-) 변환 | ||
| birthDate: member.birthDate ? member.birthDate.replace(/-/g, '.') : '', | ||
| githubLink: member.githubLink?.url ?? '', | ||
| blogOrSnsLink: member.blogOrSnsLink?.url ?? '', | ||
| mbti: (member.mbti as string) ?? '', | ||
| simpleIntroduction: member.simpleIntroduction ?? '', | ||
| interests: member.interests?.map((i) => i.name) ?? [], | ||
| }; | ||
| } | ||
|
|
||
| // 서버 전송 payload | ||
| export function toUpdateProfilePayload( | ||
| v: ProfileFormValues, | ||
| extra?: Partial<Pick<UpdateUserProfileRequest, 'profileImageExtension'>>, | ||
| ): UpdateUserProfileRequest { | ||
| const payload: UpdateUserProfileRequest = { | ||
| name: v.name, | ||
| tel: v.tel, | ||
| birthDate: v.birthDate, | ||
| githubLink: v.githubLink, | ||
| blogOrSnsLink: v.blogOrSnsLink, | ||
| simpleIntroduction: v.simpleIntroduction, | ||
| mbti: v.mbti, | ||
| interests: v.interests, | ||
| }; | ||
|
|
||
| if (extra?.profileImageExtension) { | ||
| payload.profileImageExtension = extra.profileImageExtension; | ||
| } | ||
|
|
||
| return payload; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| import { z } from 'zod'; | ||
| import type { MemberInfo } from '@/entities/user/api/types'; | ||
| import type { UpdateUserProfileInfoRequest } from '../api/types'; | ||
|
|
||
| export const ProfileInfoFormSchema = z.object({ | ||
| selfIntroduction: z | ||
| .string() | ||
| .trim() | ||
| .max(500, '최대 500자까지 입력 가능합니다.'), | ||
|
|
||
| studyPlan: z | ||
| .string() | ||
| .trim() | ||
| .min(1, '공부 계획을 입력해 주세요.') | ||
| .max(500, '최대 500자까지 입력 가능합니다.'), | ||
|
|
||
| preferredStudySubjectId: z.string().optional(), | ||
|
|
||
| availableStudyTimeIds: z | ||
| .array(z.string()) | ||
| .min(1, '가능 시간대를 1개 이상 선택해 주세요.'), | ||
|
|
||
| techStackIds: z | ||
| .array(z.string()) | ||
| .min(1, '기술 스택을 1개 이상 선택해 주세요.'), | ||
| }); | ||
|
|
||
| export type ProfileInfoFormValues = z.infer<typeof ProfileInfoFormSchema>; | ||
|
|
||
| export function buildProfileInfoDefaultValues( | ||
| member: MemberInfo, | ||
| ): ProfileInfoFormValues { | ||
| return { | ||
| selfIntroduction: member.selfIntroduction ?? '', | ||
| studyPlan: member.studyPlan ?? '', | ||
| preferredStudySubjectId: member.preferredStudySubject | ||
| ? String(member.preferredStudySubject.studySubjectId) | ||
| : undefined, | ||
| availableStudyTimeIds: (member.availableStudyTimes ?? []) | ||
| .map((t) => t?.id) | ||
| .filter((x): x is number => typeof x === 'number') | ||
| .map(String), | ||
| techStackIds: (member.techStacks ?? []) | ||
| .map((t) => t?.techStackId) | ||
| .filter((x): x is number => typeof x === 'number') | ||
| .map(String), | ||
| }; | ||
| } | ||
|
|
||
| export function toUpdateUserProfileInfoRequest( | ||
| v: ProfileInfoFormValues, | ||
| ): UpdateUserProfileInfoRequest { | ||
| return { | ||
| selfIntroduction: v.selfIntroduction, | ||
| studyPlan: v.studyPlan, | ||
| preferredStudySubjectId: v.preferredStudySubjectId!, | ||
| availableStudyTimeIds: v.availableStudyTimeIds.map(Number), | ||
| techStackIds: v.techStackIds.map(Number), | ||
| }; | ||
| } | ||
|
Comment on lines
+30
to
+60
Contributor
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. 폼과 관련된 코드들은 위 파일과 같이 비슷한 형식이더라구요!
Contributor
Author
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. 넵 컨벤션이라기엔 좀 민망하지만 |
||
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.
저도 yarn으로 설치했을 때, 이 파일이 생기더라고요. 흠 왜생기는지는 저도 잘 모르겠네요 🤔
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.
헉 이 파일이 추가됐군요. 혹시 모를 부분이라 추가하지 않으려 했는데 추가되었나봅니다..
저도 이 파일에 대해서 알아봤는데, 그냥 프로젝트에서 node-modules를 사용하는 방식이라고 명시해주는 거라고 하더라구요.
원래도 저희는 node-modules를 사용하고는 있었지만, 따로 명시되어 있지 않아 node-module인지, pnp인지 방식을 확실히 알 수 없다고 합니다.
그래서 저 파일을 이용해 이 프로젝트는 node-modules을 사용하는 파일이다! 라고 명시해주는 거라고 하더라구요.
문제가 되는 파일인 것 같지 않아 그냥 제 로컬에만 놔두려했는데...ㅜㅜ 커밋을 수정하는 과정에서 추가되었나봅니다.
수아님도 괜찮으시다면 이 파일은 그냥 추가해둘까 합니닷.