From 510ea31ca45130dbc6be567c677d8b58e2ead9bf Mon Sep 17 00:00:00 2001
From: aken-you
Date: Fri, 18 Jul 2025 17:15:08 +0900
Subject: [PATCH 01/58] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=A6=84,=20?=
=?UTF-8?q?=EC=97=B0=EB=9D=BD=EC=B2=98=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20?=
=?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../my-page/ui/profile-edit-modal.tsx | 27 +++++++++++++------
src/shared/ui/form/form-field.tsx | 7 ++++-
2 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/src/features/my-page/ui/profile-edit-modal.tsx b/src/features/my-page/ui/profile-edit-modal.tsx
index 02cdb8a0..40cac8f0 100644
--- a/src/features/my-page/ui/profile-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-edit-modal.tsx
@@ -29,9 +29,15 @@ export default function ProfileEditModal({
const [name, setName] = useState(
memberProfile.memberName ?? '',
);
+ // 이름 유효성 검사: 2~10자, 한글 또는 영문만 허용
+ const isNameValid = /^[가-힣a-zA-Z]{2,10}$/.test(name);
+
const [tel, setTel] = useState(
memberProfile.tel ?? '',
);
+ // 연락처 유효성 검사: "(2~3자리 지역번호)-(3~4자리 번호)-(4자리 번호)" 형식
+ const isTelValid = /^\d{2,3}-\d{3,4}-\d{4}$/.test(tel);
+
const [githubLink, setGithubLink] = useState<
UpdateUserProfileRequest['githubLink']
>(memberProfile.githubLink?.url ?? '');
@@ -70,12 +76,6 @@ export default function ProfileEditModal({
};
const handleSubmit = async () => {
- if (!name || !tel) {
- alert('모든 필수 정보를 입력해주세요!');
-
- return;
- }
-
const file = fileInputRef.current?.files?.[0];
const hasImageFile = !!file;
@@ -158,7 +158,12 @@ export default function ProfileEditModal({
수정 완료
diff --git a/src/shared/ui/form/form-field.tsx b/src/shared/ui/form/form-field.tsx
index f617a5d6..737f3edf 100644
--- a/src/shared/ui/form/form-field.tsx
+++ b/src/shared/ui/form/form-field.tsx
@@ -21,10 +21,12 @@ interface FormFieldProps {
value: T;
direction?: 'horizontal' | 'vertical';
onChange: (value: T) => void;
+ error?: boolean;
}
export function FormField({
label,
+ error = false,
description,
type,
required = false,
@@ -42,10 +44,13 @@ export function FormField({
onChange(e.target.value as T)}
/>
{description && (
-
+
{description}
)}
From ff35c9007ddf9d5c7dc63230590796033f570307 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Fri, 18 Jul 2025 17:20:52 +0900
Subject: [PATCH 02/58] =?UTF-8?q?refactor:=20=EC=97=B0=EB=9D=BD=EC=B2=98?=
=?UTF-8?q?=20input=EC=97=90=20=EC=88=AB=EC=9E=90=EC=99=80=20-=EB=A7=8C=20?=
=?UTF-8?q?=EC=9E=85=EB=A0=A5=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=A0=9C?=
=?UTF-8?q?=ED=95=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/my-page/ui/profile-edit-modal.tsx | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/features/my-page/ui/profile-edit-modal.tsx b/src/features/my-page/ui/profile-edit-modal.tsx
index 40cac8f0..a8d81b0d 100644
--- a/src/features/my-page/ui/profile-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-edit-modal.tsx
@@ -178,7 +178,10 @@ export default function ProfileEditModal({
: '연락처는 숫자와 하이픈(-)을 포함한 형식으로 입력해주세요.'
}
value={tel}
- onChange={setTel}
+ onChange={(value) => {
+ const onlyNumberAndHyphen = value.replace(/[^\d-]/g, '');
+ setTel(onlyNumberAndHyphen);
+ }}
required
/>
Date: Fri, 18 Jul 2025 17:29:33 +0900
Subject: [PATCH 03/58] =?UTF-8?q?refactor:=20=EB=82=B4=20=ED=94=84?=
=?UTF-8?q?=EB=A1=9C=ED=95=84=20=EC=88=98=EC=A0=95=20=EB=AA=A8=EB=8B=AC?=
=?UTF-8?q?=EC=9D=98=20Footer=20=EB=94=94=EC=9E=90=EC=9D=B8=20=EB=B3=80?=
=?UTF-8?q?=EA=B2=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/my-page/ui/profile-edit-modal.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/features/my-page/ui/profile-edit-modal.tsx b/src/features/my-page/ui/profile-edit-modal.tsx
index a8d81b0d..47d537e5 100644
--- a/src/features/my-page/ui/profile-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-edit-modal.tsx
@@ -223,16 +223,16 @@ export default function ProfileEditModal({
-
+
);
From 6724fde5226ebca7e4b7b8cc737af558a0b189c2 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Fri, 18 Jul 2025 22:14:39 +0900
Subject: [PATCH 06/58] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=ED=95=84=20?=
=?UTF-8?q?=EA=B8=B0=EB=B3=B8=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EA=B2=BD?=
=?UTF-8?q?=EB=A1=9C=20=EC=83=81=EC=88=98=ED=99=94?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/my-page/consts/my-page-const.ts | 2 ++
src/features/my-page/ui/profile-edit-modal.tsx | 9 +++++++--
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/features/my-page/consts/my-page-const.ts b/src/features/my-page/consts/my-page-const.ts
index 15b20a72..5f909266 100644
--- a/src/features/my-page/consts/my-page-const.ts
+++ b/src/features/my-page/consts/my-page-const.ts
@@ -29,3 +29,5 @@ export const MBTI_OPTIONS = [
{ label: 'ENFJ', value: 'ENFJ' },
{ label: 'ENTJ', value: 'ENTJ' },
];
+
+export const DEFAULT_PROFILE_IMAGE_URL = '/profile-default.svg';
diff --git a/src/features/my-page/ui/profile-edit-modal.tsx b/src/features/my-page/ui/profile-edit-modal.tsx
index 5bb94386..48147397 100644
--- a/src/features/my-page/ui/profile-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-edit-modal.tsx
@@ -10,7 +10,11 @@ import Button from '@/shared/ui/button';
import { Modal } from '@/shared/ui/modal';
import { FormField } from '../../../shared/ui/form/form-field';
import { UpdateUserProfileRequest } from '../api/types';
-import { DEFAULT_OPTIONS, MBTI_OPTIONS } from '../consts/my-page-const';
+import {
+ DEFAULT_OPTIONS,
+ DEFAULT_PROFILE_IMAGE_URL,
+ MBTI_OPTIONS,
+} from '../consts/my-page-const';
import { useUpdateUserProfileMutation } from '../model/use-update-user-profile-mutation';
interface Props {
@@ -58,7 +62,7 @@ export default function ProfileEditModal({ memberProfile, memberId }: Props) {
const [image, setImage] = useState(
memberProfile.profileImage?.resizedImages?.[0]?.resizedImageUrl ??
- '/profile-default.svg',
+ DEFAULT_PROFILE_IMAGE_URL,
);
const queryClient = useQueryClient();
@@ -119,6 +123,7 @@ export default function ProfileEditModal({ memberProfile, memberId }: Props) {
alert('이미지 업로드에 실패했습니다.');
}
}
+ console.log('memberinfo 업데이트');
await queryClient.invalidateQueries({ queryKey: ['memberInfo'] });
};
From 6ec6122e68a04e35e52f2cb062000ece9b7a669d Mon Sep 17 00:00:00 2001
From: aken-you
Date: Fri, 18 Jul 2025 22:44:11 +0900
Subject: [PATCH 07/58] =?UTF-8?q?style:=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C?=
=?UTF-8?q?=EA=B1=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/auth/api/auth.ts | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/features/auth/api/auth.ts b/src/features/auth/api/auth.ts
index a055640c..26828943 100644
--- a/src/features/auth/api/auth.ts
+++ b/src/features/auth/api/auth.ts
@@ -19,13 +19,10 @@ export async function uploadProfileImage(
filename: string,
file: FormData,
) {
- console.log('uploadProfileImage 요청직전', file);
- // Bug : 여기서 에러발생중
const res = await axiosInstanceForMultipart.put(
`/files/members/${memberId}/profile/image/${filename}`,
file,
);
- console.log('auth.ts - uploadProfileImage 응답', res);
return res.data;
}
From 7e89030d06bf5f97b8cece4d7c9c67914f2f16fd Mon Sep 17 00:00:00 2001
From: aken-you
Date: Fri, 18 Jul 2025 22:48:49 +0900
Subject: [PATCH 08/58] =?UTF-8?q?style:=20--color-background-dimmer=20opac?=
=?UTF-8?q?ity=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/global.css | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/global.css b/app/global.css
index bcbecc55..74119091 100644
--- a/app/global.css
+++ b/app/global.css
@@ -185,7 +185,7 @@ https://velog.io/@oneook/tailwindcss-4.0-%EB%AC%B4%EC%97%87%EC%9D%B4-%EB%8B%AC%E
--color-background-alternative: var(--color-gray-50);
--color-background-default: var(--color-gray-0);
- --color-background-dimmer: rgba(24, 29, 39, 80);
+ --color-background-dimmer: rgba(24, 29, 39, 0.8);
--color-background-disabled: var(--color-gray-100);
--color-background-brand-subtle: var(--color-rose-300);
From 4153fd3d6e10040e3ebc8f04c54c4c5144203992 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Fri, 18 Jul 2025 23:23:01 +0900
Subject: [PATCH 09/58] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C=ED=95=84?=
=?UTF-8?q?=20=ED=8E=B8=EC=A7=91=20=EB=AA=A8=EB=8B=AC=EC=97=90=EC=84=9C=20?=
=?UTF-8?q?=ED=8F=BC=EA=B3=BC=20=EA=B4=80=EB=A0=A8=EB=90=9C=20=EC=83=81?=
=?UTF-8?q?=ED=83=9C=20=ED=86=B5=ED=95=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../my-page/ui/profile-edit-modal.tsx | 107 +++++++++---------
1 file changed, 54 insertions(+), 53 deletions(-)
diff --git a/src/features/my-page/ui/profile-edit-modal.tsx b/src/features/my-page/ui/profile-edit-modal.tsx
index 48147397..b9275896 100644
--- a/src/features/my-page/ui/profile-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-edit-modal.tsx
@@ -25,46 +25,29 @@ interface Props {
export type MbtiValue = (typeof MBTI_OPTIONS)[number]['value'];
export default function ProfileEditModal({ memberProfile, memberId }: Props) {
- const [isOpen, setIsOpen] = useState(false);
const fileInputRef = useRef(null);
+ const [isOpen, setIsOpen] = useState(false);
- const [name, setName] = useState(
- memberProfile.memberName ?? '',
- );
- // 이름 유효성 검사: 2~10자, 한글 또는 영문만 허용
- const isNameValid = /^[가-힣a-zA-Z]{2,10}$/.test(name);
-
- const [tel, setTel] = useState(
- memberProfile.tel ?? '',
- );
- // 연락처 유효성 검사: "(2~3자리 지역번호)-(3~4자리 번호)-(4자리 번호)" 형식
- const isTelValid = /^\d{2,3}-\d{3,4}-\d{4}$/.test(tel);
-
- const [githubLink, setGithubLink] = useState<
- UpdateUserProfileRequest['githubLink']
- >(memberProfile.githubLink?.url ?? '');
-
- const [blogOrSnsLink, setBlogOrSnsLink] = useState<
- UpdateUserProfileRequest['blogOrSnsLink']
- >(memberProfile.blogOrSnsLink?.url ?? '');
-
- const [mbti, setMbti] = useState(
- memberProfile.mbti ?? '',
- );
-
- const [simpleIntroduction, setSimpleIntroduction] = useState<
- UpdateUserProfileRequest['simpleIntroduction']
- >(memberProfile.simpleIntroduction ?? '');
-
- const [interests, setInterests] = useState<
- UpdateUserProfileRequest['interests']
- >(memberProfile.interests?.map((item) => item.name) ?? []);
+ const [profileForm, setProfileForm] = useState({
+ name: memberProfile.memberName ?? '',
+ tel: memberProfile.tel ?? '',
+ githubLink: memberProfile.githubLink?.url ?? '',
+ blogOrSnsLink: memberProfile.blogOrSnsLink?.url ?? '',
+ mbti: memberProfile.mbti ?? '',
+ simpleIntroduction: memberProfile.simpleIntroduction ?? '',
+ interests: memberProfile.interests?.map((item) => item.name) ?? [],
+ });
const [image, setImage] = useState(
memberProfile.profileImage?.resizedImages?.[0]?.resizedImageUrl ??
DEFAULT_PROFILE_IMAGE_URL,
);
+ // 이름 유효성 검사: 2~10자, 한글 또는 영문만 허용
+ const isNameValid = /^[가-힣a-zA-Z]{2,10}$/.test(profileForm.name);
+ // 연락처 유효성 검사: "(2~3자리 지역번호)-(3~4자리 번호)-(4자리 번호)" 형식
+ const isTelValid = /^\d{2,3}-\d{3,4}-\d{4}$/.test(profileForm.tel);
+
const queryClient = useQueryClient();
const { mutateAsync: updateProfile, data: updatedProfile } =
useUpdateUserProfileMutation(memberId);
@@ -86,13 +69,14 @@ export default function ProfileEditModal({ memberProfile, memberId }: Props) {
ext && ['JPG', 'PNG', 'GIF', 'WEBP'].includes(ext) ? ext : undefined;
const rawFormData: UpdateUserProfileRequest = {
- name,
- tel,
- githubLink: githubLink.trim() || undefined,
- blogOrSnsLink: blogOrSnsLink.trim() || undefined,
- simpleIntroduction: simpleIntroduction.trim() || undefined,
- mbti: mbti.trim() || undefined,
- interests: interests.length > 0 ? interests : undefined,
+ name: profileForm.name,
+ tel: profileForm.tel,
+ githubLink: profileForm.githubLink.trim() || undefined,
+ blogOrSnsLink: profileForm.blogOrSnsLink.trim() || undefined,
+ simpleIntroduction: profileForm.simpleIntroduction.trim() || undefined,
+ mbti: profileForm.mbti.trim() || undefined,
+ interests:
+ profileForm.interests.length > 0 ? profileForm.interests : undefined,
profileImageExtension: hasImageFile ? profileImageExtension : undefined,
};
@@ -168,8 +152,14 @@ export default function ProfileEditModal({ memberProfile, memberId }: Props) {
? '소셜 계정에서 불러온 닉네임 대신 이름을 입력해 주세요.'
: '이름은 2~10자의 한글 또는 영문만 허용됩니다.'
}
- value={name}
- onChange={setName}
+ value={profileForm.name}
+ onChange={(value) => {
+ // 공백 입력하지 못하도록 제한
+ setProfileForm({
+ ...profileForm,
+ name: value.replace(/\s/g, ''),
+ });
+ }}
required
/>
{
+ // 숫자와 하이픈(-)만 입력 허용
const onlyNumberAndHyphen = value.replace(/[^\d-]/g, '');
- setTel(onlyNumberAndHyphen);
+ setProfileForm({ ...profileForm, tel: onlyNumberAndHyphen });
}}
required
/>
@@ -192,37 +183,47 @@ export default function ProfileEditModal({ memberProfile, memberId }: Props) {
label="Github"
type="text"
description="스터디 진행을 위한 연락 가능한 정보를 입력해 주세요."
- value={githubLink}
- onChange={setGithubLink}
+ value={profileForm.githubLink}
+ onChange={(value) =>
+ setProfileForm({ ...profileForm, githubLink: value })
+ }
/>
+ setProfileForm({ ...profileForm, mbti: value })
+ }
options={MBTI_OPTIONS}
/>
+ setProfileForm({ ...profileForm, interests: value })
+ }
options={DEFAULT_OPTIONS}
/>
+ setProfileForm({ ...profileForm, simpleIntroduction: value })
+ }
/>
+ setProfileForm({ ...profileForm, blogOrSnsLink: value })
+ }
/>
From 71e0dcbd6db4d7cfc423ab34452117962a4a9a20 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 00:02:39 +0900
Subject: [PATCH 10/58] =?UTF-8?q?fix:=20=EB=AA=A8=EB=8B=AC=EC=9D=84=20?=
=?UTF-8?q?=EB=8B=A4=EC=8B=9C=20=EC=97=B4=EC=96=B4=EB=8F=84=20=EC=9D=B4?=
=?UTF-8?q?=EC=A0=84=EC=97=90=20=EC=88=98=EC=A0=95=ED=95=9C=20=ED=8F=BC=20?=
=?UTF-8?q?=EC=83=81=ED=83=9C=20=EC=9C=A0=EC=A7=80=EB=90=98=EB=8A=94=20?=
=?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/my-page/ui/profile-edit-modal.tsx | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/src/features/my-page/ui/profile-edit-modal.tsx b/src/features/my-page/ui/profile-edit-modal.tsx
index b9275896..37806d92 100644
--- a/src/features/my-page/ui/profile-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-edit-modal.tsx
@@ -60,6 +60,22 @@ export default function ProfileEditModal({ memberProfile, memberId }: Props) {
}
};
+ const resetForm = () => {
+ setProfileForm({
+ name: memberProfile.memberName ?? '',
+ tel: memberProfile.tel ?? '',
+ githubLink: memberProfile.githubLink?.url ?? '',
+ blogOrSnsLink: memberProfile.blogOrSnsLink?.url ?? '',
+ mbti: memberProfile.mbti ?? '',
+ simpleIntroduction: memberProfile.simpleIntroduction ?? '',
+ interests: memberProfile.interests?.map((item) => item.name) ?? [],
+ });
+ setImage(
+ memberProfile.profileImage?.resizedImages?.[0]?.resizedImageUrl ??
+ DEFAULT_PROFILE_IMAGE_URL,
+ );
+ };
+
const handleSubmit = async () => {
const file = fileInputRef.current?.files?.[0];
@@ -121,7 +137,7 @@ export default function ProfileEditModal({ memberProfile, memberId }: Props) {
-
+
내 프로필 수정
From d2e95181e1cadac13da49f9ed44da8922c4872d7 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 00:27:15 +0900
Subject: [PATCH 11/58] =?UTF-8?q?fix:=20github=20=EB=A7=81=ED=81=AC?=
=?UTF-8?q?=EC=99=80=20blog/sns=20=EB=A7=81=ED=81=AC=EA=B0=80=20=EC=97=86?=
=?UTF-8?q?=EC=9D=84=20=EA=B2=BD=EC=9A=B0,=20=EC=9E=85=EB=A0=A5=20?=
=?UTF-8?q?=EB=B6=80=ED=83=81=20=EB=A9=94=EC=84=B8=EC=A7=80=20=ED=91=9C?=
=?UTF-8?q?=EC=8B=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/my-page/ui/profile.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/features/my-page/ui/profile.tsx b/src/features/my-page/ui/profile.tsx
index 2b277bde..811cbc3f 100644
--- a/src/features/my-page/ui/profile.tsx
+++ b/src/features/my-page/ui/profile.tsx
@@ -65,7 +65,7 @@ export default function Profile({ memberId, memberProfile }: ProfileProps) {
width={16}
height={16}
/>
- {memberProfile.githubLink?.url ?? '깃허브 링크를 입력해주세요!'}
+ {memberProfile.githubLink?.url || '깃허브 링크를 입력해주세요!'}
- {memberProfile.blogOrSnsLink?.url ??
+ {memberProfile.blogOrSnsLink?.url ||
'블로그 링크를 입력해주세요!'}
From af97facddf5186917adff442511693e9c61ec63e Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 00:28:29 +0900
Subject: [PATCH 12/58] =?UTF-8?q?refactor:=20=EA=B3=B5=EB=B0=B1=20?=
=?UTF-8?q?=EC=A0=9C=EA=B1=B0=20=ED=9B=84=20github,=20=EB=B8=94=EB=A1=9C?=
=?UTF-8?q?=EA=B7=B8/SNS=20=EB=A7=81=ED=81=AC=20=EC=83=81=ED=83=9C=20?=
=?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/my-page/ui/profile-edit-modal.tsx | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/src/features/my-page/ui/profile-edit-modal.tsx b/src/features/my-page/ui/profile-edit-modal.tsx
index 37806d92..ee15d672 100644
--- a/src/features/my-page/ui/profile-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-edit-modal.tsx
@@ -87,10 +87,10 @@ export default function ProfileEditModal({ memberProfile, memberId }: Props) {
const rawFormData: UpdateUserProfileRequest = {
name: profileForm.name,
tel: profileForm.tel,
- githubLink: profileForm.githubLink.trim() || undefined,
- blogOrSnsLink: profileForm.blogOrSnsLink.trim() || undefined,
+ githubLink: profileForm.githubLink,
+ blogOrSnsLink: profileForm.blogOrSnsLink,
simpleIntroduction: profileForm.simpleIntroduction.trim() || undefined,
- mbti: profileForm.mbti.trim() || undefined,
+ mbti: profileForm.mbti || undefined,
interests:
profileForm.interests.length > 0 ? profileForm.interests : undefined,
profileImageExtension: hasImageFile ? profileImageExtension : undefined,
@@ -201,7 +201,10 @@ export default function ProfileEditModal({ memberProfile, memberId }: Props) {
description="스터디 진행을 위한 연락 가능한 정보를 입력해 주세요."
value={profileForm.githubLink}
onChange={(value) =>
- setProfileForm({ ...profileForm, githubLink: value })
+ setProfileForm({
+ ...profileForm,
+ githubLink: value.replace(/\s/g, ''),
+ })
}
/>
- setProfileForm({ ...profileForm, blogOrSnsLink: value })
+ setProfileForm({
+ ...profileForm,
+ blogOrSnsLink: value.replace(/\s/g, ''),
+ })
}
/>
From 8909fedf0a6a772a483d6b2cad200c882c63acec Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 09:05:28 +0900
Subject: [PATCH 13/58] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C=ED=95=84?=
=?UTF-8?q?=20=EC=88=98=EC=A0=95=20=ED=8F=BC=20=EC=BB=B4=ED=8F=AC=EB=84=8C?=
=?UTF-8?q?=ED=8A=B8=EB=A1=9C=20=EB=B6=84=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- ProfileEditModal에서 폼상태를 관리하면 memberProfile이 변경돼도, 폼 상태가 변경되지 않음
---
.../my-page/ui/profile-edit-modal.tsx | 318 +++++++++---------
1 file changed, 156 insertions(+), 162 deletions(-)
diff --git a/src/features/my-page/ui/profile-edit-modal.tsx b/src/features/my-page/ui/profile-edit-modal.tsx
index ee15d672..a9325855 100644
--- a/src/features/my-page/ui/profile-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-edit-modal.tsx
@@ -25,9 +25,44 @@ interface Props {
export type MbtiValue = (typeof MBTI_OPTIONS)[number]['value'];
export default function ProfileEditModal({ memberProfile, memberId }: Props) {
- const fileInputRef = useRef(null);
const [isOpen, setIsOpen] = useState(false);
+ return (
+
+ setIsOpen(true)}
+ className="rounded-100 bg-fill-brand-default-default font-designer-16b text-text-inverse w-full px-150 py-100"
+ >
+ 내 프로필 수정
+
+
+
+
+
+
+ 내 프로필 수정
+
+
+
+
+
+ setIsOpen(false)}
+ />
+
+
+
+ );
+}
+
+function ProfileEditForm({
+ memberProfile,
+ memberId,
+ onClose,
+}: Props & { onClose: () => void }) {
+ const fileInputRef = useRef(null);
const [profileForm, setProfileForm] = useState({
name: memberProfile.memberName ?? '',
tel: memberProfile.tel ?? '',
@@ -60,22 +95,6 @@ export default function ProfileEditModal({ memberProfile, memberId }: Props) {
}
};
- const resetForm = () => {
- setProfileForm({
- name: memberProfile.memberName ?? '',
- tel: memberProfile.tel ?? '',
- githubLink: memberProfile.githubLink?.url ?? '',
- blogOrSnsLink: memberProfile.blogOrSnsLink?.url ?? '',
- mbti: memberProfile.mbti ?? '',
- simpleIntroduction: memberProfile.simpleIntroduction ?? '',
- interests: memberProfile.interests?.map((item) => item.name) ?? [],
- });
- setImage(
- memberProfile.profileImage?.resizedImages?.[0]?.resizedImageUrl ??
- DEFAULT_PROFILE_IMAGE_URL,
- );
- };
-
const handleSubmit = async () => {
const file = fileInputRef.current?.files?.[0];
@@ -128,150 +147,125 @@ export default function ProfileEditModal({ memberProfile, memberId }: Props) {
};
return (
-
- setIsOpen(true)}
- className="rounded-100 bg-fill-brand-default-default font-designer-16b text-text-inverse w-full px-150 py-100"
- >
- 내 프로필 수정
-
-
-
-
-
-
- 내 프로필 수정
-
-
-
-
-
-
-
-
-
{
- // 공백 입력하지 못하도록 제한
- setProfileForm({
- ...profileForm,
- name: value.replace(/\s/g, ''),
- });
- }}
- required
- />
- {
- // 숫자와 하이픈(-)만 입력 허용
- const onlyNumberAndHyphen = value.replace(/[^\d-]/g, '');
- setProfileForm({ ...profileForm, tel: onlyNumberAndHyphen });
- }}
- required
- />
-
- setProfileForm({
- ...profileForm,
- githubLink: value.replace(/\s/g, ''),
- })
- }
- />
-
- setProfileForm({ ...profileForm, mbti: value })
- }
- options={MBTI_OPTIONS}
- />
-
- setProfileForm({ ...profileForm, interests: value })
- }
- options={DEFAULT_OPTIONS}
- />
-
- setProfileForm({ ...profileForm, simpleIntroduction: value })
- }
- />
-
- setProfileForm({
- ...profileForm,
- blogOrSnsLink: value.replace(/\s/g, ''),
- })
- }
- />
-
-
-
-
-
-
-
-
-
-
-
+ <>
+
+
+
+
{
+ // 공백 입력하지 못하도록 제한
+ setProfileForm({
+ ...profileForm,
+ name: value.replace(/\s/g, ''),
+ });
+ }}
+ required
+ />
+ {
+ // 숫자와 하이픈(-)만 입력 허용
+ const onlyNumberAndHyphen = value.replace(/[^\d-]/g, '');
+ setProfileForm({ ...profileForm, tel: onlyNumberAndHyphen });
+ }}
+ required
+ />
+
+ setProfileForm({
+ ...profileForm,
+ githubLink: value.replace(/\s/g, ''),
+ })
+ }
+ />
+
+ setProfileForm({ ...profileForm, mbti: value })
+ }
+ options={MBTI_OPTIONS}
+ />
+
+ setProfileForm({ ...profileForm, interests: value })
+ }
+ options={DEFAULT_OPTIONS}
+ />
+
+ setProfileForm({ ...profileForm, simpleIntroduction: value })
+ }
+ />
+
+ setProfileForm({
+ ...profileForm,
+ blogOrSnsLink: value.replace(/\s/g, ''),
+ })
+ }
+ />
+
+
+
+
+
+
+
+
+ >
);
}
From 81d58b024745d4e2c8e6e1b7925d43f67186b988 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 11:21:22 +0900
Subject: [PATCH 14/58] =?UTF-8?q?style:=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C?=
=?UTF-8?q?=EA=B1=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/my-page/ui/profile-edit-modal.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/features/my-page/ui/profile-edit-modal.tsx b/src/features/my-page/ui/profile-edit-modal.tsx
index a9325855..c4fea137 100644
--- a/src/features/my-page/ui/profile-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-edit-modal.tsx
@@ -142,7 +142,7 @@ function ProfileEditForm({
alert('이미지 업로드에 실패했습니다.');
}
}
- console.log('memberinfo 업데이트');
+
await queryClient.invalidateQueries({ queryKey: ['memberInfo'] });
};
From b910c3811ac778c98998f187404dffe9c476497e Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 11:24:01 +0900
Subject: [PATCH 15/58] =?UTF-8?q?refactor:=201024px=20=EA=B8=B0=EC=A4=80?=
=?UTF-8?q?=EC=9C=BC=EB=A1=9C=20layout=20=EC=8A=A4=ED=83=80=EC=9D=BC=20?=
=?UTF-8?q?=EB=8B=A4=EB=A5=B4=EA=B2=8C=20=EC=A0=81=EC=9A=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/(my)/layout.tsx | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/app/(my)/layout.tsx b/app/(my)/layout.tsx
index 76a6fae5..c4c054fd 100644
--- a/app/(my)/layout.tsx
+++ b/app/(my)/layout.tsx
@@ -14,7 +14,9 @@ export default function MyLayout({
return (
-
{children}
+
+ {children}
+
);
}
From a738ab45b99be58361fe8683e2b835fbc14f59f8 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 12:01:38 +0900
Subject: [PATCH 16/58] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C=ED=95=84?=
=?UTF-8?q?=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20input=EC=97=90=20=ED=8C=8C?=
=?UTF-8?q?=EC=9D=BC=20=ED=99=95=EC=9E=A5=EC=9E=90=EC=99=80=20=EC=84=A0?=
=?UTF-8?q?=ED=83=9D=20=EA=B0=9C=EC=88=98=20=EC=A0=9C=ED=95=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/auth/ui/sign-up-image-selector.tsx | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/features/auth/ui/sign-up-image-selector.tsx b/src/features/auth/ui/sign-up-image-selector.tsx
index 4e7fe757..4b0ffb78 100644
--- a/src/features/auth/ui/sign-up-image-selector.tsx
+++ b/src/features/auth/ui/sign-up-image-selector.tsx
@@ -20,7 +20,7 @@ export default function SignupImageSelector({
From dd6dd4996d63e9c7e3e5e88a251599b310818524 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 12:05:45 +0900
Subject: [PATCH 17/58] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C=ED=95=84?=
=?UTF-8?q?=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=97=85=EB=8D=B0=EC=9D=B4?=
=?UTF-8?q?=ED=8A=B8=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../my-page/ui/profile-edit-modal.tsx | 24 +++++++------------
1 file changed, 9 insertions(+), 15 deletions(-)
diff --git a/src/features/my-page/ui/profile-edit-modal.tsx b/src/features/my-page/ui/profile-edit-modal.tsx
index c4fea137..acac51f4 100644
--- a/src/features/my-page/ui/profile-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-edit-modal.tsx
@@ -84,8 +84,7 @@ function ProfileEditForm({
const isTelValid = /^\d{2,3}-\d{3,4}-\d{4}$/.test(profileForm.tel);
const queryClient = useQueryClient();
- const { mutateAsync: updateProfile, data: updatedProfile } =
- useUpdateUserProfileMutation(memberId);
+ const { mutateAsync: updateProfile } = useUpdateUserProfileMutation(memberId);
const { mutateAsync: uploadProfileImage } = useUploadProfileImageMutation();
const handleImageChange = (e: React.ChangeEvent) => {
@@ -97,11 +96,7 @@ function ProfileEditForm({
const handleSubmit = async () => {
const file = fileInputRef.current?.files?.[0];
-
- const hasImageFile = !!file;
- const ext = file?.name.split('.').pop()?.toUpperCase();
- const profileImageExtension =
- ext && ['JPG', 'PNG', 'GIF', 'WEBP'].includes(ext) ? ext : undefined;
+ const profileImageExtension = file?.name.split('.').pop();
const rawFormData: UpdateUserProfileRequest = {
name: profileForm.name,
@@ -112,21 +107,18 @@ function ProfileEditForm({
mbti: profileForm.mbti || undefined,
interests:
profileForm.interests.length > 0 ? profileForm.interests : undefined,
- profileImageExtension: hasImageFile ? profileImageExtension : undefined,
+ profileImageExtension: profileImageExtension,
};
const formData = Object.fromEntries(
Object.entries(rawFormData).filter(([_, v]) => v !== undefined),
) as UpdateUserProfileRequest;
- await updateProfile(formData);
+ const updatedProfile = await updateProfile(formData);
- if (
- fileInputRef.current?.files?.[0] &&
- updatedProfile.profileImageUploadUrl
- ) {
+ if (file && updatedProfile.profileImageUploadUrl) {
const imageFormData = new FormData();
- imageFormData.append('file', fileInputRef.current.files[0]);
+ imageFormData.append('file', file);
const filename = updatedProfile.profileImageUploadUrl.split('/').pop();
if (!filename) return;
@@ -143,7 +135,9 @@ function ProfileEditForm({
}
}
- await queryClient.invalidateQueries({ queryKey: ['memberInfo'] });
+ await queryClient.invalidateQueries({
+ queryKey: ['userProfile', memberId],
+ });
};
return (
From d48ef193780adb49cc47ffbf038e0fa66ffa5dd0 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 12:15:31 +0900
Subject: [PATCH 18/58] =?UTF-8?q?style:=20=ED=8C=8C=EC=9D=BC=20=ED=8F=B4?=
=?UTF-8?q?=EB=8D=94=EB=A5=BC=20=EC=97=AC=EB=8A=94=20=ED=95=B8=EB=93=A4?=
=?UTF-8?q?=EB=9F=AC=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/auth/ui/sign-up-image-selector.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/features/auth/ui/sign-up-image-selector.tsx b/src/features/auth/ui/sign-up-image-selector.tsx
index 4b0ffb78..8a8f9ce0 100644
--- a/src/features/auth/ui/sign-up-image-selector.tsx
+++ b/src/features/auth/ui/sign-up-image-selector.tsx
@@ -14,7 +14,7 @@ export default function SignupImageSelector({
handleImageChange: (event: React.ChangeEvent) => void;
}) {
const setDefaultImage = () => setImage('/profile-default.svg');
- const openFileDialog = () => fileInputRef.current?.click();
+ const openFileFolder = () => fileInputRef.current?.click();
return (
@@ -44,7 +44,7 @@ export default function SignupImageSelector({
앨범에서 선택
From d773b55eca1e62d92729d1db420151463eda695a Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 12:38:03 +0900
Subject: [PATCH 19/58] =?UTF-8?q?feat:=20=ED=94=84=EB=A1=9C=ED=95=84=20?=
=?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=EB=A5=BC=20=EA=B8=B0=EB=B3=B8=20?=
=?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=EB=A1=9C=20=EC=84=A0=ED=83=9D?=
=?UTF-8?q?=ED=95=98=EB=A9=B4,=20=EC=84=9C=EB=B2=84=EC=97=90=EA=B2=8C=20?=
=?UTF-8?q?=EA=B8=B0=EB=B3=B8=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=A0=84?=
=?UTF-8?q?=EC=86=A1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
public/profile-default.jpg | Bin 0 -> 7003 bytes
.../my-page/ui/profile-edit-modal.tsx | 27 ++++++++++++++++++
2 files changed, 27 insertions(+)
create mode 100644 public/profile-default.jpg
diff --git a/public/profile-default.jpg b/public/profile-default.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..46ce5400c3215ec3c00d42dc7cb915d22c50a664
GIT binary patch
literal 7003
zcmbuEXH-*Nm&b#E6cwZwDN2;n4DT%T3%WGv9`W}C+z*&KR7%h9{>KsMFJrGx6A$o_CL5Toj`Jh
zjEt0w;tv}R`9G2U8|=ThrU2JTNiJU=DIGu+aDILl@bStkk(t@)DS?w{W66FJg%@28
z57X@TIs7|h$|$6LmW=r@2olZP+LGNWOTgRWHC7D{nrg=nI@2LI0R@*jlPQ5c%@I1+
z?`zFI^8z^^V%$VAM~K9hIX~6j5rA2tO@nCc`DUDI;>T-)_}_7YtM!RpUa|rdgk&FD
z;x*D~dF1n}v*po7i|z~46Wv!qXHQ)H0ZNM#zr~#`3ly~kBYsGV(u+pHqV*oFe_be{
z!GEQjF?tOIFan;EJRk==!`Ba+{kRrdX?X#lQ${G9AFBNNE#RqGcg_s8q!ET9b03Kg
z%OuGe+b3^QJfm=61$Y9O?07GssR4hpi&|LeL2su~QA>1c?$)0FEZ4BHA1S)MFi7E3
z=saXo)_FxKl`Y`cUhOvF`AT_lcBNxd+YgD+2p5Ato|CA?7;ZvW9>9j5v)vo-jw3Xj
z9j?FqgymkmK3vNo$(N-4=Uhn&sIV~19t|m??YH2oGAc#rjJoYf1Xte7$2-Yc&}ruy4ZB%
zgRB~GwcWF-w1EG1d{%Gn1BJasZElXO4oji_f~q@0E!%}#_(SW`{k`5SV82VKjWD(%
zFdX6@u;^q|j7H_BLOZ&IldL^@-O(F96BhMGj$91Pv)kbcUVOW}(zvDyXv4uHdKMH8xu~
zmd$r!aT^BJIrP}qqc(rscme3@F9EjE<awDxgsR#AO=<}R{rYPCt*7v@|LdoPZLtLQjd|@_#koJ=JTeZai~p|W5l+V
zp~;Z1mADsa-dsxZLTVXH-KT)L*7CBTOuRz(~U_cVI7MX05+mc2PI87#>__hOR#xq
z#H|%;@8=b@bXNIs+<)a!dwpnsHqHcMg2L$OV|H9RersEW39cTGQxj-uwM*xPIu;g?
z-z#XS%jms_dsutK3fbLegDZ+xF`2sS8$Ws1uzqqL4n7q_xfb|E7TeF(T+*l9L1XKcSX0`g^Tz;kjrF2`KE*Ts@)E?hEs*B
z@rDH&IiS(vewhseB$W}`05KJJNB5?#VKxG1&x#U~O#;Iu0#26KQhq_LDNR>I>J@xX
zqK>+1pUWLOl*ZOPK;3fRPA%}r!q&W;R0^sMX+F#eRV;S70JvXvZ5z44^VbUlSDO$*
zFO<#K$i>WtyNd?WLdyC=VRYcR8<^b*KNRPEWPrAA(s8Ul?ts%8uQO}#`{&b!l+|r<
z!K5VvDXph_(oE|8^uX5Jt@+^q6Eth*wKO_?9fX0-uIfh#g)j=ywl=DCTZsu#AkgV)
z>rgnmi;jZp8>EdZIxHUPa$K{7^N|B(Id`RbEL@4Ez0)
zuPt1_oI6XO2)0=kBT_};Ukyvl%EA3>&v5qKf#GeTMSJSlMZ0n(y7X56)LVw|y|c&*
z!1vRtJ$#sW$2rYvV79QmyqjT<&oz(-d7$VQhI_}h;A7{K|1MjUK|VFpo~fgS?5(Lq+L8VcZNF7muU@iLD`sek)k#
z!%gq8oxKadxR8`l@M7B;iN4wQ1%)PS8#(=Y_in+I`;8xYRf&7a#1RY1zCu#IBzgNl
zhnF#T6A@`Z041%Z%r)Xz#xk8(@MW}H3av>RWRW4jI0xrk*z^O6;VdYT37`ZPAeHe+?{MRcW@Acxds31F-S
za};Hf6;6NbWpOg0%#)w0jlfs$y$NMGYG_Fs-nsyo2Y4-ZaIqEW$@W1B72?G^u&AZZ{gZ-K_|jBV`cP+suJ}k@hu^F97uD$Z7`)R9eXa(k?!O&amZ@>xpl|{4ffJDS1Gs`pG9dI1Ge3ZaG
z#kZ@Gu3+YFpp+A))lHMu%d7*I^IQo<*x}c&ls;o7&<|PmMvh`X9fi%gJf13qhgBZC
zHf|qjoxj?3d|P0RsQn_5kJNp)_DBFFlkFH4>)F0sdi1-YnVV(`YV3>WXHO9VhvZn-
zo$>tR(*L}W?92l~V5;G#x|zUf9kJMA%uFE=o27IT%(iM#WH`KZ7hK&cHhTf6O@YtY
z)=Cn6jp53!#cDklfIjBo&-?B_*Je%=I^NS34jnORlFA{5q*LOQg@
zq3gJkt@VDB)w2Vcme7E+3coC|vZn_+(dp;MiIMx|l;|i0ih8
zBoDOXuGRN*D59SdN+#|c#7$KvY&lPNipf0*us7S{!(ruPq$4aux>)G^K;$;
z`QkgX9mI_0`7G-Sw-AONkHef@%&X@bN}Lrtex*0y%6>FttlfE1W@e|Sl?SeP{1K3t
z&+`hvba3+xin3Knov+y{)Ox4)e7~o1MpiFv!Ml+oP-21uC<^3vQ4sdh#=(P99r_Fq
zIWxt&25vQze;EZ)EOwo;L>}^-m9)64PNFVF={3wD-u%{?W-FX7tKC|WXcoA9&4%3U
zRC7pRSm5(8QZWq^h$4EQAGIphOrKbBxBDNmhYUHh1jRSaAC{$}rmP6|MUZlkB;vrJ
zv7iszi&-m7D1e4+hB+)H+;D6JC)-NYajFXqb_Tl|Up0+dEQmvF)Q*H4@KZ~taiN;n
zeUYp{1+Y%;&A8^V3&5KfAyUf9%F>jGJa!$yDG~lSihUU~|v4t#P5L~W(ocUeqJ5f+;D3YThJ_Z;IO<_@(|fhB=mN}5X^?WtZP%EbgYO7;;HW=#!S
zmx@mAE-uEJmSdKh8U;R6d|xT(1_6c85YKW|_u~yD>2KF^t+S7R=iB#H7sir)&$q*9
zp+yaigp$wRM#61*c!Sjpd#9P0k4YpiAo#Cbu9n9V2mI5?glrRhh+~xe`sxgCmfgzM
z<{ZgA1~**qC(p`QVh&=qo^SrqzKKO-H_mZkE8P{FdxCRU)sv7v75OpNMWFh1nK(9C
zRn3!Np|_Zl&2gnw%kT5aegUc8dxjaG&_DiqQ!AY#zO`YG=wruluGM2Bw_ScFd;#D+
zfL-1DzD(@Q6@bb+$a5Gg*f^S750Gn{|1>>whS+TmzZ@Bwgx?r%gjtaT7)f?b;#6Jw
z92d(^8E-A_Y@!Inpv|q2u-)?a?)w)2ju2k3?wXO+
z_1WowD@SeCflFn!npZcC?}W(tAc(QLZ=Vb=B>gn}HU=||XGM(jp&$nlGqJ&f
zf}vbBpUt`NSwsoz#7bByyhc5u(`ECM=FWvQu9}FO6kM-?%REQ7778GKtZ5(|jE$@m
z2cN$2hR+?;9o)IB=q>{}1&+J2@ZI>F!l-W-c+g3aFRDClvw5`8BG@Z;dUF96iSAT<
z(Kyo|QpHR2Ir9SW)voLUz`{U)-TK8JvDips!De3O_?L#R9P!fxyLXAncsiX4#nJrB
zgj!`yr{@t$2sR1MB>VETwN+L1Fx7?UhvhV)=O!v*XGnK8H|0CdRFlBYYR|Sf=9+{j
z@l-n>#O66a=?0sWr(#@Gdamtw!%m=Qqzm^bu?+1KY3cWc*&vin?gdfk1TiTLTYGfXpw)u}M?@-w{vfCxwL1R5fZKE20V^vPN5&NVqF
z@h3zp^DkNP{OGdYZHaOvtGri($;UJMTR-`1t~)YmIWrB;0X;3@GEX$HID{U7o#C0v
zrOSL+=~IqR3T5=HrAkTJjM;g{@uu@>HC)wl>{TKf+oMALQlGv2V^eItaqr?i=)YYf
zdgxrn(Mzv=1Ixf8R@y%VsEr@K85A7bbhUrbGRe$M?@Jpwo~u|rJnC=pjUHdPJ%z>A
zygzzL_oOxyvRNUY$~8A+Gm@2_IWN6>St4`?vwES}M!v15aVb;_8cW*jZOeBr^2fv}
z@(=VDIH8^XI&9gjJK+i&fLCU{4#cB=Qwy0O(R-XtuuUWo1-9|QjsQrSx$
zJe)CSiH%Z*
z@nJ?JA}ltrrR6e>_@cLb0bu@hkmF_LdXEilD+Pj0R?V1ur3py+bQujFCY7C+
z9*o-N@4Myx;)9BMFuwKHDvi4jiJ)B%xL-d`bsV@`zNLu*UlzrbiO-&R4wOAE|4Q>k
z2&oJ{5OG~t4tH=+9{-$r-$e|cbyBx;T=1Lrt9eCym|z|(2q~IhY!&Dz_uC<_dpKA@xHc^t#1wH(jH8_&qYbDKIU>Z5Re5q0rL^2=>B
zre8|{aYLzB6l5MH#VebKT&y-BX9Yr4Pscm%#Q_*r=64o>vxKW
zk8Ge{8!Zgq{;IW~6|^CbLLEHmeCM{sACaS_H#O*8dAKh~i9@l;cjg-w2t719{BZhp
zY#(gcR*(DX)^6DGj9@eh0-_txf(3EORe1*Vx|hkb22wFGMUb`U
zo@jkR)!%yf&oWd@pdhMR68h_0J~}ZM2G{i;7lvY8Y@JKPl@j)
z-)AhNUXJ;v0t$nIN(-^dP+q3d7NS_UY(U*PENyqr!a}A`MA%43%v4R*w*r{yo_p&C
zxOz*(=yPR#91qd}kq2VPhUuSk6Irx~fs0r$srG}-JV#vlq~8Dwa7i|L^9q&2!PET!AivwTF#Nmv-m9dQ)X7f7IJ=
zo!+UU$}*OHJ_-=@bNpxu9>|EZpEefk|09w=xapf2i7rdlxjeXKS;dYj*LwFRCeiQoo6%dm`pVb*4sUy(h6a18S|Z&)orT@jWhIO+UimGY3ypXqV%b
z-x4f|3TKYu7@+72Gi&ePO&;MOq(J$Bs|k;O1P`5m6_c|sy2DUaSvhpKypx+|`!8S2
z{nZh64IQvww|S`8sy|agNRPCG*XH_*YI>%PsiSdy2uwymeCoRuU(QjX#m1*;@Q4>}OhHBm
zmd%7#jrBQ=7l`G6Qk>N=?8!*u?34{0N=OYM$P&=c5Ni;Ze_#*`zHg`!M)24i**$63
z1CFJnhcPyPXjs!063BS&zJs(RYj3UF9<+RbGTMhM-v4!4?OT<%*(F6`Yr%LgEl8Vr*wN}@b`h7tUU_Gkc?$~NfDMwnDx3+C?Ar_?x*&>
z83&Clzv|KB^ucD@v)pqIqJDl|mM)AQFBz`tLLiCRCi~!RenZm!{WpzG*52J&F!QL0
z%I0TJNY|3^I&yP)Dre-lXWP04s?xQpZ~=&Ew8#}2LdCw&PD1}P*v
XljZOBrNj+CJz9aIyo|Gei^=~0tTkT@
literal 0
HcmV?d00001
diff --git a/src/features/my-page/ui/profile-edit-modal.tsx b/src/features/my-page/ui/profile-edit-modal.tsx
index acac51f4..9c26e4a8 100644
--- a/src/features/my-page/ui/profile-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-edit-modal.tsx
@@ -116,6 +116,33 @@ function ProfileEditForm({
const updatedProfile = await updateProfile(formData);
+ // todo: 서버 측에서 api 수정되면, 리팩토링
+ // 기본 프로필 이미지를 선택할 경우, 기본 프로필 이미지 전송 -> 서버 측에서 나중에 리팩토링 예정
+ // public 폴더의 profile-default.jpg 파일을 fetch해서 FormData에 추가
+ // profile-default.jpg를 추가한 이유는 서버에서 프로필 이미지 확장자에 svg 파일을 고려하지 못함 -> 서버 측에서 리팩토링 예정
+ if (image === DEFAULT_PROFILE_IMAGE_URL) {
+ try {
+ const defaultProfileImage = 'profile-default.jpg';
+ const response = await fetch(defaultProfileImage);
+ const blob = await response.blob();
+ const defaultFile = new File([blob], defaultProfileImage, {
+ type: 'image/jpeg',
+ });
+ const imageFormData = new FormData();
+ imageFormData.append('file', defaultFile);
+
+ await uploadProfileImage({
+ memberId,
+ filename: defaultProfileImage,
+ file: imageFormData,
+ });
+ } catch (error) {
+ console.error('기본 프로필 이미지 업로드 실패:', error);
+ alert('기본 프로필 이미지 업로드에 실패했습니다.');
+ }
+ }
+
+ // 폴더에서 이미지를 선택한 경우
if (file && updatedProfile.profileImageUploadUrl) {
const imageFormData = new FormData();
imageFormData.append('file', file);
From f690b4d91d6726ed05252243bad6ecd1b726afb0 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 13:23:32 +0900
Subject: [PATCH 20/58] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C=ED=95=84?=
=?UTF-8?q?=20=EC=88=98=EC=A0=95=20=ED=8F=BC=20=EC=95=88=EB=82=B4=20?=
=?UTF-8?q?=EB=AC=B8=EA=B5=AC=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/my-page/ui/profile-edit-modal.tsx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/features/my-page/ui/profile-edit-modal.tsx b/src/features/my-page/ui/profile-edit-modal.tsx
index 9c26e4a8..9c9028f6 100644
--- a/src/features/my-page/ui/profile-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-edit-modal.tsx
@@ -219,7 +219,7 @@ function ProfileEditForm({
setProfileForm({
@@ -250,7 +250,7 @@ function ProfileEditForm({
setProfileForm({ ...profileForm, simpleIntroduction: value })
From 2e4b595919cd86e847b176688f7eb93cd0b80dd7 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 17:49:08 +0900
Subject: [PATCH 21/58] =?UTF-8?q?refactor:=20=EB=A9=B4=EC=A0=91=20?=
=?UTF-8?q?=EC=A4=80=EB=B9=84/=EC=99=84=EB=A3=8C=20=EB=AA=A8=EB=8B=AC=20Fo?=
=?UTF-8?q?oter=20=EB=94=94=EC=9E=90=EC=9D=B8=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/ui/today-study-modal.tsx | 136 +++++++++++---------
1 file changed, 78 insertions(+), 58 deletions(-)
diff --git a/src/features/study/ui/today-study-modal.tsx b/src/features/study/ui/today-study-modal.tsx
index f21c3127..372f3a17 100644
--- a/src/features/study/ui/today-study-modal.tsx
+++ b/src/features/study/ui/today-study-modal.tsx
@@ -62,13 +62,11 @@ export default function TodayStudyModal({
-
- {isInterviewee ? (
-
- ) : (
-
- )}
-
+ {isInterviewee ? (
+
+ ) : (
+
+ )}
@@ -113,34 +111,44 @@ function ReadyForm({
return (
<>
-
-
-
- 이번 스터디에서 다룰 면접 주제를 입력하세요
-
- setInterviewTopic(e.target.value)}
- />
-
+
+
+
+
+
+ 이번 스터디에서 다룰 면접 주제를 입력하세요
+
+
-
-
-
- 참고할 링크나 자료가 있다면 입력해 주세요
-
- setReferenceLink(e.target.value)}
- />
-
+
setInterviewTopic(e.target.value)}
+ />
+
+
+
+
+
+
+ 참고할 링크나 자료가 있다면 입력해 주세요
+
+
+
+
setReferenceLink(e.target.value)}
+ />
+
+
@@ -202,37 +210,49 @@ function DoneForm({
return (
<>
-
-
-
- 면접 완료 후 해당 지원자의 상태를 업데이트해 주세요.
-
- setProgressStatus(e as StudyProgressStatus)}
- />
-
+
+
+
+
+
+ 면접 완료 후 해당 지원자의 상태를 업데이트해 주세요.
+
+
+
+
setProgressStatus(e as StudyProgressStatus)}
+ />
+
+
+
+
+
+
+ 면접 결과에 대한 간단한 피드백을 입력해 주세요.
+
+
+
-
-
-
- 면접 결과에 대한 간단한 피드백을 입력해 주세요.
-
setFeedback(e)}
/>
-
+
From b17c97df7ddbd2651b7745a3dce63e4a32496a4f Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 18:05:25 +0900
Subject: [PATCH 22/58] =?UTF-8?q?refactor:=20=EB=A9=B4=EC=A0=91=20?=
=?UTF-8?q?=EB=AA=A8=EB=8B=AC=20trigger=20text=20=EB=B3=80=EA=B2=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/ui/today-study-modal.tsx | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/src/features/study/ui/today-study-modal.tsx b/src/features/study/ui/today-study-modal.tsx
index 372f3a17..e6eae9de 100644
--- a/src/features/study/ui/today-study-modal.tsx
+++ b/src/features/study/ui/today-study-modal.tsx
@@ -44,11 +44,8 @@ export default function TodayStudyModal({
return (
-
-
-
- 작성하기
-
+
+
From 2fdee7542ca4a55c7c199801839f4ce137c793a8 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 18:06:18 +0900
Subject: [PATCH 23/58] =?UTF-8?q?refactor:=20DoneForm=EC=9D=98=20TextAreaI?=
=?UTF-8?q?nput=20=EC=9C=84=EC=B9=98=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/ui/today-study-modal.tsx | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/features/study/ui/today-study-modal.tsx b/src/features/study/ui/today-study-modal.tsx
index e6eae9de..93fd5d80 100644
--- a/src/features/study/ui/today-study-modal.tsx
+++ b/src/features/study/ui/today-study-modal.tsx
@@ -241,14 +241,14 @@ function DoneForm({
면접 결과에 대한 간단한 피드백을 입력해 주세요.
-
- setFeedback(e)}
- />
+ setFeedback(e)}
+ />
+
From 64c828fe44aefd485b225c53f3779732c9b4ab86 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 20:04:35 +0900
Subject: [PATCH 24/58] =?UTF-8?q?refactor:=20=ED=94=84=EB=A1=9C=ED=95=84?=
=?UTF-8?q?=EC=9D=84=20=EA=B8=B0=EB=B3=B8=20=ED=94=84=EB=A1=9C=ED=95=84?=
=?UTF-8?q?=EB=A1=9C=20=EC=88=98=EC=A0=95=ED=96=88=EC=9D=84=20=EB=95=8C?=
=?UTF-8?q?=EC=9D=98=20=EC=9A=94=EC=B2=AD=20=EB=A1=9C=EC=A7=81=20=EC=88=98?=
=?UTF-8?q?=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../my-page/ui/profile-edit-modal.tsx | 39 +++++++------------
1 file changed, 13 insertions(+), 26 deletions(-)
diff --git a/src/features/my-page/ui/profile-edit-modal.tsx b/src/features/my-page/ui/profile-edit-modal.tsx
index 9c9028f6..08cedf1a 100644
--- a/src/features/my-page/ui/profile-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-edit-modal.tsx
@@ -96,7 +96,8 @@ function ProfileEditForm({
const handleSubmit = async () => {
const file = fileInputRef.current?.files?.[0];
- const profileImageExtension = file?.name.split('.').pop();
+ const profileImageExtension =
+ image === DEFAULT_PROFILE_IMAGE_URL ? 'jpg' : file?.name.split('.').pop();
const rawFormData: UpdateUserProfileRequest = {
name: profileForm.name,
@@ -116,36 +117,22 @@ function ProfileEditForm({
const updatedProfile = await updateProfile(formData);
- // todo: 서버 측에서 api 수정되면, 리팩토링
- // 기본 프로필 이미지를 선택할 경우, 기본 프로필 이미지 전송 -> 서버 측에서 나중에 리팩토링 예정
- // public 폴더의 profile-default.jpg 파일을 fetch해서 FormData에 추가
- // profile-default.jpg를 추가한 이유는 서버에서 프로필 이미지 확장자에 svg 파일을 고려하지 못함 -> 서버 측에서 리팩토링 예정
- if (image === DEFAULT_PROFILE_IMAGE_URL) {
- try {
+ if (updatedProfile.profileImageUploadUrl) {
+ const imageFormData = new FormData();
+
+ if (file) imageFormData.append('file', file);
+
+ // 기본 프로필 이미지를 선택할 경우, public 폴더의 profile-default.jpg로 서버 api에게 기본 프로필 이미지 전송 -> 서버 측에서 나중에 리팩토링 예정
+ // profile-default.jpg를 추가한 이유는 서버에서 프로필 이미지 확장자에 svg 파일을 고려하지 못함 -> 서버 측에서 리팩토링 예정
+ if (!file && image === DEFAULT_PROFILE_IMAGE_URL) {
const defaultProfileImage = 'profile-default.jpg';
const response = await fetch(defaultProfileImage);
const blob = await response.blob();
- const defaultFile = new File([blob], defaultProfileImage, {
- type: 'image/jpeg',
+ const defaultProfileFile = new File([blob], defaultProfileImage, {
+ type: 'image/jpg',
});
- const imageFormData = new FormData();
- imageFormData.append('file', defaultFile);
-
- await uploadProfileImage({
- memberId,
- filename: defaultProfileImage,
- file: imageFormData,
- });
- } catch (error) {
- console.error('기본 프로필 이미지 업로드 실패:', error);
- alert('기본 프로필 이미지 업로드에 실패했습니다.');
+ imageFormData.append('file', defaultProfileFile);
}
- }
-
- // 폴더에서 이미지를 선택한 경우
- if (file && updatedProfile.profileImageUploadUrl) {
- const imageFormData = new FormData();
- imageFormData.append('file', file);
const filename = updatedProfile.profileImageUploadUrl.split('/').pop();
if (!filename) return;
From 1ebd8fd158515536b1a994a30c8dd492508d43dd Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 19 Jul 2025 21:59:28 +0900
Subject: [PATCH 25/58] =?UTF-8?q?fix:=201=EC=9D=BC=20=EC=A0=84=EC=9D=98=20?=
=?UTF-8?q?=EB=82=A0=EC=A7=9C=EB=A1=9C=20=ED=8A=B9=EC=A0=95=20=EB=82=A0?=
=?UTF-8?q?=EC=A7=9C=EC=9D=98=20=EB=82=B4=20=EC=8A=A4=ED=84=B0=EB=94=94=20?=
=?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=20?=
=?UTF-8?q?=ED=95=B4=EA=B2=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/ui/study-card.tsx | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/features/study/ui/study-card.tsx b/src/features/study/ui/study-card.tsx
index 4ce50232..f56729bd 100644
--- a/src/features/study/ui/study-card.tsx
+++ b/src/features/study/ui/study-card.tsx
@@ -62,7 +62,10 @@ export default function StudyCard() {
day: selectedDate.getDate(),
};
- const studyParams = { studyDate: selectedDate.toISOString().split('T')[0] };
+ const offset = selectedDate.getTimezoneOffset() * 60000; // ms단위라 60000곱해줌
+ const dateOffset = new Date(selectedDate.getTime() - offset);
+
+ const studyParams = { studyDate: dateOffset.toISOString().split('T')[0] };
const { data: participationData } = useWeeklyParticipation(params);
const isParticipate = participationData?.isParticipate ?? false;
From d626510e5e1d2e75f884e99cb3b42cefb9cfb8da Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sun, 20 Jul 2025 23:31:19 +0900
Subject: [PATCH 26/58] =?UTF-8?q?refactor:=20ProfileInfoEditModal=EC=97=90?=
=?UTF-8?q?=EC=84=9C=20=ED=8F=BC=20UI=EB=A5=BC=20=EC=BB=B4=ED=8F=AC?=
=?UTF-8?q?=EB=84=8C=ED=8A=B8=EB=A1=9C=20=EB=B6=84=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../my-page/ui/profile-info-edit-modal.tsx | 310 ++++++++++--------
1 file changed, 178 insertions(+), 132 deletions(-)
diff --git a/src/features/my-page/ui/profile-info-edit-modal.tsx b/src/features/my-page/ui/profile-info-edit-modal.tsx
index 29b6247a..a50dd1f6 100644
--- a/src/features/my-page/ui/profile-info-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-info-edit-modal.tsx
@@ -22,42 +22,11 @@ interface Props {
}
export default function ProfileInfoEditModal({ memberInfo, onSubmit }: Props) {
- const [selfIntroduction, setSelfIntroduction] = useState<
- UpdateUserProfileInfoRequest['selfIntroduction']
- >(memberInfo.selfIntroduction ?? '');
- const [studyPlan, setStudyPlan] = useState<
- UpdateUserProfileInfoRequest['studyPlan']
- >(memberInfo.studyPlan ?? '');
- const [preferredStudySubjectId, setPreferredStudySubjectId] = useState<
- UpdateUserProfileInfoRequest['preferredStudySubjectId']
- >(memberInfo.preferredStudySubject?.studySubjectId ?? undefined);
- const [availableTimeSlots, setAvailableTimeSlots] = useState<
- UpdateUserProfileInfoRequest['availableStudyTimeIds']
- >((memberInfo.availableStudyTimes ?? []).map((time) => time?.id ?? 0));
- const [selectedSkills, setSelectedSkills] = useState<
- UpdateUserProfileInfoRequest['techStackIds']
- >((memberInfo.techStacks ?? []).map((tech) => tech?.techStackId ?? 0));
-
- const handleSubmit = () => {
- const formData: UpdateUserProfileInfoRequest = {
- selfIntroduction,
- studyPlan,
- preferredStudySubjectId: preferredStudySubjectId,
- availableStudyTimeIds: availableTimeSlots
- .filter((id) => id)
- .map((id) => Number(id)),
- techStackIds: selectedSkills.filter((id) => id).map((id) => Number(id)),
- };
- onSubmit(formData);
- };
-
- const { data: availableStudyTimes } = useAvailableStudyTimesQuery();
- const { data: studySubjects } = useStudySubjectsQuery();
- const { data: techStacks } = useTechStacksQuery();
+ const [isOpen, setIsOpen] = useState(false);
return (
-
-
+
+ setIsOpen(true)}>
편집
@@ -73,106 +42,183 @@ export default function ProfileInfoEditModal({ memberInfo, onSubmit }: Props) {
-
-
-
-
- ({
- value: studySubjectId,
- label: name,
- })) ?? []
- }
- />
- ({
- value: availableTimeId.toString(),
- label: display,
- })) ?? []
- }
- onChange={(availableStudyTimeIds) =>
- setAvailableTimeSlots(availableStudyTimeIds.map(Number))
- }
- required
- />
- ({
- value: techStackId,
- label: techStackName,
- }),
- )}
- />
-
-
-
-
-
-
-
-
-
-
+ setIsOpen(false)}
+ />
);
}
+
+function ProfileInfoEditForm({
+ memberInfo,
+ onSubmit,
+ onClose,
+}: {
+ memberInfo: MemberInfo;
+ onSubmit: (formData: UpdateUserProfileInfoRequest) => void;
+ onClose: () => void;
+}) {
+ const [infoForm, setInfoForm] = useState({
+ selfIntroduction: memberInfo.selfIntroduction ?? '',
+ studyPlan: memberInfo.studyPlan ?? '',
+ preferredStudySubjectId: memberInfo.preferredStudySubject?.studySubjectId,
+ availableStudyTimeIds: (memberInfo.availableStudyTimes ?? []).map(
+ (time) => time?.id ?? 0,
+ ),
+ techStackIds: (memberInfo.techStacks ?? []).map(
+ (tech) => tech?.techStackId ?? 0,
+ ),
+ });
+
+ const handleSubmit = () => {
+ const formData: UpdateUserProfileInfoRequest = {
+ selfIntroduction: infoForm.selfIntroduction,
+ studyPlan: infoForm.studyPlan,
+ preferredStudySubjectId: infoForm.preferredStudySubjectId,
+ availableStudyTimeIds: infoForm.availableStudyTimeIds
+ .filter((id) => id)
+ .map((id) => Number(id)),
+ techStackIds: infoForm.techStackIds
+ .filter((id) => id)
+ .map((id) => Number(id)),
+ };
+
+ onSubmit(formData);
+ };
+
+ const { data: availableStudyTimes } = useAvailableStudyTimesQuery();
+ const { data: studySubjects } = useStudySubjectsQuery();
+ const { data: techStacks } = useTechStacksQuery();
+
+ return (
+ <>
+
+
+
+ setInfoForm((prev) => ({
+ ...prev,
+ selfIntroduction: value,
+ }))
+ }
+ direction="vertical"
+ maxLength={500}
+ />
+
+ setInfoForm((prev) => ({
+ ...prev,
+ studyPlan: value,
+ }))
+ }
+ direction="vertical"
+ maxLength={500}
+ required
+ />
+
+ setInfoForm((prev) => ({
+ ...prev,
+ preferredStudySubjectId: value,
+ }))
+ }
+ direction="vertical"
+ required
+ options={
+ studySubjects?.map(({ studySubjectId, name }) => ({
+ value: studySubjectId,
+ label: name,
+ })) ?? []
+ }
+ />
+ ({
+ value: availableTimeId.toString(),
+ label: display,
+ })) ?? []
+ }
+ onChange={(availableStudyTimeIds) =>
+ setInfoForm((prev) => ({
+ ...prev,
+ availableStudyTimeIds: availableStudyTimeIds.map(Number),
+ }))
+ }
+ required
+ />
+
+ setInfoForm((prev) => ({
+ ...prev,
+ techStackIds: value,
+ }))
+ }
+ direction="vertical"
+ required
+ options={(techStacks ?? []).map(
+ ({ techStackId, techStackName }) => ({
+ value: techStackId,
+ label: techStackName,
+ }),
+ )}
+ />
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
From 24dc7af222c903c558bb975faf031312b27d2ced Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sun, 20 Jul 2025 23:37:59 +0900
Subject: [PATCH 27/58] =?UTF-8?q?refactor:=20=EB=82=B4=20=EC=A0=95?=
=?UTF-8?q?=EB=B3=B4=20=EC=88=98=EC=A0=95=20mutation=20=ED=9B=85=20?=
=?UTF-8?q?=EC=9C=84=EC=B9=98=20=EC=9D=B4=EB=8F=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../my-page/ui/profile-info-edit-modal.tsx | 22 ++++++++++---------
src/features/my-page/ui/profile-info.tsx | 13 +----------
2 files changed, 13 insertions(+), 22 deletions(-)
diff --git a/src/features/my-page/ui/profile-info-edit-modal.tsx b/src/features/my-page/ui/profile-info-edit-modal.tsx
index a50dd1f6..2ae158dc 100644
--- a/src/features/my-page/ui/profile-info-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-info-edit-modal.tsx
@@ -5,7 +5,6 @@ import { XIcon } from 'lucide-react';
import { useState } from 'react';
import { MemberInfo } from '@/entities/user/api/types';
import { hashValue } from '@/shared/lib/hash';
-import { getCookie } from '@/shared/tanstack-query/cookie';
import Button from '@/shared/ui/button';
import { FormField } from '@/shared/ui/form/form-field';
import { Modal } from '@/shared/ui/modal';
@@ -14,14 +13,15 @@ import {
useAvailableStudyTimesQuery,
useStudySubjectsQuery,
useTechStacksQuery,
+ useUpdateUserProfileInfoMutation,
} from '../model/use-update-user-profile-mutation';
interface Props {
+ memberId: number;
memberInfo: MemberInfo;
- onSubmit: (formData: UpdateUserProfileInfoRequest) => void;
}
-export default function ProfileInfoEditModal({ memberInfo, onSubmit }: Props) {
+export default function ProfileInfoEditModal({ memberId, memberInfo }: Props) {
const [isOpen, setIsOpen] = useState(false);
return (
@@ -43,8 +43,8 @@ export default function ProfileInfoEditModal({ memberInfo, onSubmit }: Props) {
setIsOpen(false)}
/>
@@ -54,12 +54,12 @@ export default function ProfileInfoEditModal({ memberInfo, onSubmit }: Props) {
}
function ProfileInfoEditForm({
+ memberId,
memberInfo,
- onSubmit,
onClose,
}: {
+ memberId: number;
memberInfo: MemberInfo;
- onSubmit: (formData: UpdateUserProfileInfoRequest) => void;
onClose: () => void;
}) {
const [infoForm, setInfoForm] = useState({
@@ -74,6 +74,9 @@ function ProfileInfoEditForm({
),
});
+ const { mutate: updateProfileInfo } =
+ useUpdateUserProfileInfoMutation(memberId);
+
const handleSubmit = () => {
const formData: UpdateUserProfileInfoRequest = {
selfIntroduction: infoForm.selfIntroduction,
@@ -87,7 +90,7 @@ function ProfileInfoEditForm({
.map((id) => Number(id)),
};
- onSubmit(formData);
+ updateProfileInfo(formData);
};
const { data: availableStudyTimes } = useAvailableStudyTimesQuery();
@@ -189,7 +192,7 @@ function ProfileInfoEditForm({
-
+
@@ -200,7 +203,6 @@ function ProfileInfoEditForm({
onClick={() => {
handleSubmit();
- const memberId = getCookie('memberId');
const selectedSkillNames = techStacks.filter((techStack) =>
infoForm.techStackIds.includes(techStack.techStackId),
);
@@ -208,7 +210,7 @@ function ProfileInfoEditForm({
sendGTMEvent({
event: 'custom_member_card',
dl_timestamp: new Date().toISOString(),
- dl_member_id: hashValue(memberId),
+ dl_member_id: hashValue(String(memberId)),
dl_tags: selectedSkillNames,
});
diff --git a/src/features/my-page/ui/profile-info.tsx b/src/features/my-page/ui/profile-info.tsx
index 4ba127ac..93e87afe 100644
--- a/src/features/my-page/ui/profile-info.tsx
+++ b/src/features/my-page/ui/profile-info.tsx
@@ -3,8 +3,6 @@
import { MemberInfo } from '@/entities/user/api/types';
import ProfileInfoEditModal from '@/features/my-page/ui/profile-info-edit-modal';
import ProfileInfoCard from '@/widgets/my-page/profileinfo-card';
-import { UpdateUserProfileInfoRequest } from '../api/types';
-import { useUpdateUserProfileInfoMutation } from '../model/use-update-user-profile-mutation';
interface ProfileInfoProps {
memberId: number;
@@ -15,21 +13,12 @@ export default function ProfileInfo({
memberId,
memberInfo,
}: ProfileInfoProps) {
- const { mutate } = useUpdateUserProfileInfoMutation(memberId);
-
- const handleSubmit = (formData: UpdateUserProfileInfoRequest) => {
- mutate(formData);
- };
-
return (
Date: Sun, 20 Jul 2025 23:53:53 +0900
Subject: [PATCH 28/58] =?UTF-8?q?refactor:=20=EB=82=B4=20=EC=A0=95?=
=?UTF-8?q?=EB=B3=B4=20=EC=88=98=EC=A0=95=EC=9D=B4=20=EC=84=B1=EA=B3=B5?=
=?UTF-8?q?=ED=96=88=EC=9D=84=20=EA=B2=BD=EC=9A=B0=20=ED=98=B8=EC=B6=9C?=
=?UTF-8?q?=ED=95=A0=20onSuccess=20=EC=84=A4=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../my-page/ui/profile-info-edit-modal.tsx | 45 +++++++++----------
1 file changed, 20 insertions(+), 25 deletions(-)
diff --git a/src/features/my-page/ui/profile-info-edit-modal.tsx b/src/features/my-page/ui/profile-info-edit-modal.tsx
index 2ae158dc..1d9840af 100644
--- a/src/features/my-page/ui/profile-info-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-info-edit-modal.tsx
@@ -74,6 +74,9 @@ function ProfileInfoEditForm({
),
});
+ const { data: availableStudyTimes } = useAvailableStudyTimesQuery();
+ const { data: studySubjects } = useStudySubjectsQuery();
+ const { data: techStacks } = useTechStacksQuery();
const { mutate: updateProfileInfo } =
useUpdateUserProfileInfoMutation(memberId);
@@ -90,12 +93,23 @@ function ProfileInfoEditForm({
.map((id) => Number(id)),
};
- updateProfileInfo(formData);
- };
+ updateProfileInfo(formData, {
+ onSuccess: () => {
+ const selectedSkillNames = techStacks.filter((techStack) =>
+ infoForm.techStackIds.includes(techStack.techStackId),
+ );
- const { data: availableStudyTimes } = useAvailableStudyTimesQuery();
- const { data: studySubjects } = useStudySubjectsQuery();
- const { data: techStacks } = useTechStacksQuery();
+ sendGTMEvent({
+ event: 'custom_member_card',
+ dl_timestamp: new Date().toISOString(),
+ dl_member_id: hashValue(String(memberId)),
+ dl_tags: selectedSkillNames,
+ });
+
+ onClose();
+ },
+ });
+ };
return (
<>
@@ -197,26 +211,7 @@ function ProfileInfoEditForm({
취소
-
From 6ebf8c403cdb721551d3f08caa86ed4738debf5c Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sun, 20 Jul 2025 23:56:09 +0900
Subject: [PATCH 29/58] =?UTF-8?q?refactor:=20=EB=82=B4=20=EC=A0=95?=
=?UTF-8?q?=EB=B3=B4=20=EC=88=98=EC=A0=95=20=EB=AA=A8=EB=8B=AC=EC=9D=98=20?=
=?UTF-8?q?"=EC=88=98=EC=A0=95=20=EC=99=84=EB=A3=8C"=20=EB=B2=84=ED=8A=BC?=
=?UTF-8?q?=20disabled=20=EC=84=A4=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/my-page/ui/profile-info-edit-modal.tsx | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/features/my-page/ui/profile-info-edit-modal.tsx b/src/features/my-page/ui/profile-info-edit-modal.tsx
index 1d9840af..f1ed5a2b 100644
--- a/src/features/my-page/ui/profile-info-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-info-edit-modal.tsx
@@ -211,7 +211,17 @@ function ProfileInfoEditForm({
취소
-
+
수정 완료
From 51541549b4c27777657cbfa0d63d1cf0d83fe1ef Mon Sep 17 00:00:00 2001
From: aken-you
Date: Tue, 22 Jul 2025 01:06:50 +0900
Subject: [PATCH 30/58] =?UTF-8?q?refactor:=20=EC=97=B0=EB=9D=BD=EC=B2=98?=
=?UTF-8?q?=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EC=A1=B0=EA=B1=B4=20=EC=88=98?=
=?UTF-8?q?=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/my-page/ui/profile-edit-modal.tsx | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/features/my-page/ui/profile-edit-modal.tsx b/src/features/my-page/ui/profile-edit-modal.tsx
index 08cedf1a..dd6a4500 100644
--- a/src/features/my-page/ui/profile-edit-modal.tsx
+++ b/src/features/my-page/ui/profile-edit-modal.tsx
@@ -81,7 +81,9 @@ function ProfileEditForm({
// 이름 유효성 검사: 2~10자, 한글 또는 영문만 허용
const isNameValid = /^[가-힣a-zA-Z]{2,10}$/.test(profileForm.name);
// 연락처 유효성 검사: "(2~3자리 지역번호)-(3~4자리 번호)-(4자리 번호)" 형식
- const isTelValid = /^\d{2,3}-\d{3,4}-\d{4}$/.test(profileForm.tel);
+ const isTelValid =
+ profileForm.tel.length === 0 ||
+ /^\d{2,3}-\d{3,4}-\d{4}$/.test(profileForm.tel);
const queryClient = useQueryClient();
const { mutateAsync: updateProfile } = useUpdateUserProfileMutation(memberId);
From bb21d01109bb369b4c0b077a8fd11f389c316797 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Tue, 22 Jul 2025 01:50:15 +0900
Subject: [PATCH 31/58] =?UTF-8?q?fix:=20=EC=8A=A4=ED=84=B0=EB=94=94=20?=
=?UTF-8?q?=EC=A0=84=EC=B2=B4=20=EC=A1=B0=ED=9A=8C=20studyDate=EB=A1=9C=20?=
=?UTF-8?q?=EB=B3=80=EA=B2=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/api/types.ts | 4 +---
src/features/study/model/use-study-query.ts | 5 +++++
src/widgets/home/study-list-table.tsx | 11 +++++------
3 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/src/features/study/api/types.ts b/src/features/study/api/types.ts
index 978f3503..f43c039b 100644
--- a/src/features/study/api/types.ts
+++ b/src/features/study/api/types.ts
@@ -47,9 +47,7 @@ export interface GetDailyStudyDetailParams2 {
export interface GetDailyStudiesParams {
cursor?: number;
pageSize?: number;
- year?: number;
- month?: number;
- day?: number;
+ studyDate?: string;
}
export interface GetDailyStudiesResponse {
diff --git a/src/features/study/model/use-study-query.ts b/src/features/study/model/use-study-query.ts
index 091764ca..b8f4cf99 100644
--- a/src/features/study/model/use-study-query.ts
+++ b/src/features/study/model/use-study-query.ts
@@ -15,6 +15,7 @@ import {
MonthlyCalendarResponse,
} from '../api/types';
+// 스터디 주간 참여 유무 확인 query
export const useWeeklyParticipation = (params: GetDailyStudyDetailParams2) => {
return useQuery({
queryKey: ['weeklyParticipation', params],
@@ -23,6 +24,7 @@ export const useWeeklyParticipation = (params: GetDailyStudyDetailParams2) => {
});
};
+// 스터디 상세 조회 query
export const useDailyStudyDetailQuery = (
params: GetDailyStudyDetailParams,
enabled: boolean = true,
@@ -35,6 +37,7 @@ export const useDailyStudyDetailQuery = (
});
};
+// 스터디 전체 조회 query
export const useDailyStudiesQuery = (params?: GetDailyStudiesParams) => {
return useQuery({
queryKey: ['dailyStudies', params],
@@ -43,6 +46,7 @@ export const useDailyStudiesQuery = (params?: GetDailyStudiesParams) => {
});
};
+// 스터디 캘린더 조회 query
export const useMonthlyStudyCalendarQuery = (
params: GetMonthlyCalendarParams,
) => {
@@ -54,6 +58,7 @@ export const useMonthlyStudyCalendarQuery = (
});
};
+// 스터디 신청 mutation
export const useJoinStudyMutation = () => {
return useMutation({
mutationFn: (payload: JoinStudyRequest) => postJoinStudy(payload),
diff --git a/src/widgets/home/study-list-table.tsx b/src/widgets/home/study-list-table.tsx
index 1ad06baa..80778e99 100644
--- a/src/widgets/home/study-list-table.tsx
+++ b/src/widgets/home/study-list-table.tsx
@@ -68,16 +68,15 @@ function mapDailyStudyToDisplayData(
}
export default function StudyListSection({ date }: Props) {
- const year = date.getFullYear();
- const month = date.getMonth() + 1;
- const day = date.getDate();
+ const offset = date.getTimezoneOffset() * 60000;
+ const dateOffset = new Date(date.getTime() - offset);
+
+ const studyDate = dateOffset.toISOString().split('T')[0];
const { data, isLoading, error } = useDailyStudiesQuery({
cursor: 0,
pageSize: 10,
- year,
- month,
- day,
+ studyDate,
});
if (isLoading) return 로딩 중...
;
From d7d91423c0cfdb06035932d74f0899e8ee70008c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Tue, 22 Jul 2025 02:12:40 +0900
Subject: [PATCH 32/58] =?UTF-8?q?fix:=20=EB=A9=B4=EC=A0=91=20=EC=99=84?=
=?UTF-8?q?=EB=A3=8C=20api=20=EB=B3=80=EA=B2=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/api/get-study-data.ts | 29 +++--------
src/features/study/api/types.ts | 3 +-
src/features/study/ui/today-study-modal.tsx | 58 ++++++++++-----------
3 files changed, 36 insertions(+), 54 deletions(-)
diff --git a/src/features/study/api/get-study-data.ts b/src/features/study/api/get-study-data.ts
index 07cc4932..72354c27 100644
--- a/src/features/study/api/get-study-data.ts
+++ b/src/features/study/api/get-study-data.ts
@@ -1,4 +1,5 @@
import type {
+ CompleteStudyRequest,
DailyStudyDetail,
GetDailyStudiesParams,
GetDailyStudiesResponse,
@@ -8,9 +9,7 @@ import type {
JoinStudyRequest,
MonthlyCalendarResponse,
PostDailyRetrospectRequest,
- PutRetrospectRequest,
PutStudyDailyRequest,
- StudyProgressStatus,
WeeklyParticipationResponse,
} from '@/features/study/api/types';
import { axiosInstance } from '@/shared/tanstack-query/axios';
@@ -60,29 +59,13 @@ export const putStudyDaily = async (
return res.data;
};
-// 면접자 스터디 업데이트 [스터디 진행 상태]
-export const patchStudyStatus = async (
+// 면접 완료 및 회고 작성
+export const completeStudy = async (
dailyStudyId: number,
- progressStatus: StudyProgressStatus,
+ body: CompleteStudyRequest,
) => {
- const res = await axiosInstance.patch(
- `/study/daily/${dailyStudyId}/status`,
- null,
- {
- params: { progressStatus },
- },
- );
-
- return res.data;
-};
-
-// 면접자 스터디 업데이트 [피드백]
-export const putRetrospect = async (
- retrospectId: number,
- body: PutRetrospectRequest,
-) => {
- const res = await axiosInstance.put(
- `/study/daily/retrospect/${retrospectId}`,
+ const res = await axiosInstance.post(
+ `/study/daily/${dailyStudyId}/complete`,
body,
);
diff --git a/src/features/study/api/types.ts b/src/features/study/api/types.ts
index f43c039b..45ea1e9c 100644
--- a/src/features/study/api/types.ts
+++ b/src/features/study/api/types.ts
@@ -101,6 +101,7 @@ export interface WeeklyParticipationResponse {
isParticipate: boolean;
}
-export interface PutRetrospectRequest {
+export interface CompleteStudyRequest {
description: string;
+ progressStatus: StudyProgressStatus;
}
diff --git a/src/features/study/ui/today-study-modal.tsx b/src/features/study/ui/today-study-modal.tsx
index 93fd5d80..fc8e9f96 100644
--- a/src/features/study/ui/today-study-modal.tsx
+++ b/src/features/study/ui/today-study-modal.tsx
@@ -8,15 +8,10 @@ import Button from '@/shared/ui/button';
import { SingleDropdown } from '@/shared/ui/dropdown';
import { BaseInput, TextAreaInput } from '@/shared/ui/input';
import { Modal } from '@/shared/ui/modal';
-import CreateIcon from 'public/icons/create.svg';
-import {
- patchStudyStatus,
- putRetrospect,
- putStudyDaily,
-} from '../api/get-study-data';
+import { completeStudy, putStudyDaily } from '../api/get-study-data';
import {
+ CompleteStudyRequest,
DailyStudyDetail,
- PutRetrospectRequest,
PutStudyDailyRequest,
StudyProgressStatus,
} from '../api/types';
@@ -60,9 +55,9 @@ export default function TodayStudyModal({
{isInterviewee ? (
-
+
) : (
-
+
)}
@@ -70,7 +65,7 @@ export default function TodayStudyModal({
);
}
-function ReadyForm({
+function StudyReadyForm({
refetch,
data,
}: {
@@ -168,34 +163,27 @@ function ReadyForm({
);
}
-function DoneForm({
+function StudyDoneForm({
data,
refetch,
}: {
data: DailyStudyDetail;
refetch: () => void;
}) {
- const [feedback, setFeedback] = useState(
- data.description ?? '',
- );
-
- const [progressStatus, setProgressStatus] = useState(
- data.progressStatus ?? 'PENDING',
- );
+ const [form, setForm] = useState({
+ description: data.description ?? '',
+ progressStatus: data.progressStatus ?? 'PENDING',
+ });
const handleSubmit = async (e: React.MouseEvent) => {
- if (!feedback || !progressStatus) {
+ if (!form.description || !form.progressStatus) {
e.preventDefault();
return;
}
try {
- await patchStudyStatus(data.dailyStudyId, progressStatus);
-
- await putRetrospect(data.dailyStudyId, {
- description: feedback,
- });
+ await completeStudy(data.dailyStudyId, form);
await refetch();
} catch (err) {
@@ -223,9 +211,14 @@ function DoneForm({
setProgressStatus(e as StudyProgressStatus)}
+ onChange={(e) =>
+ setForm((prev) => ({
+ ...prev,
+ progressStatus: e as StudyProgressStatus,
+ }))
+ }
/>
@@ -244,9 +237,11 @@ function DoneForm({
setFeedback(e)}
+ onChange={(value) =>
+ setForm((prev) => ({ ...prev, description: value }))
+ }
/>
@@ -260,9 +255,12 @@ function DoneForm({
From 999187206cf09eef7cdbcbbbe67e00085e74b7f1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Tue, 22 Jul 2025 22:16:28 +0900
Subject: [PATCH 33/58] =?UTF-8?q?refactor:=20=EB=AA=A8=EB=8B=AC=20?=
=?UTF-8?q?=EB=B6=84=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/ui/study-done-modal.tsx | 163 ++++++++++++
src/features/study/ui/today-study-card.tsx | 21 +-
src/features/study/ui/today-study-modal.tsx | 273 --------------------
3 files changed, 182 insertions(+), 275 deletions(-)
create mode 100644 src/features/study/ui/study-done-modal.tsx
delete mode 100644 src/features/study/ui/today-study-modal.tsx
diff --git a/src/features/study/ui/study-done-modal.tsx b/src/features/study/ui/study-done-modal.tsx
new file mode 100644
index 00000000..f5a6f438
--- /dev/null
+++ b/src/features/study/ui/study-done-modal.tsx
@@ -0,0 +1,163 @@
+'use client';
+
+import { XIcon } from 'lucide-react';
+import { useState } from 'react';
+import { cn } from '@/shared/shadcn/lib/utils';
+import Button from '@/shared/ui/button';
+import { SingleDropdown } from '@/shared/ui/dropdown';
+import { TextAreaInput } from '@/shared/ui/input';
+import { Modal } from '@/shared/ui/modal';
+import { completeStudy } from '../api/get-study-data';
+import {
+ CompleteStudyRequest,
+ DailyStudyDetail,
+ StudyProgressStatus,
+} from '../api/types';
+import { STUDY_PROGRESS_OPTIONS } from '../consts/study-const';
+
+interface Props {
+ data: DailyStudyDetail;
+ refetch: () => void;
+}
+
+export default function StudyDoneModal({ data, refetch }: Props) {
+ const [isOpen, setIsOpen] = useState(false);
+
+ return (
+
+ setIsOpen(true)}>
+
+ 완료하기
+
+
+
+
+
+
+
+ 면접 완료하기
+
+
+
+
+
+
+ setIsOpen(false)}
+ />
+
+
+
+ );
+}
+
+function StudyDoneForm({
+ data,
+ refetch,
+ onClose,
+}: {
+ data: DailyStudyDetail;
+ refetch: () => void;
+ onClose: () => void;
+}) {
+ const [form, setForm] = useState({
+ description: data.description ?? '',
+ progressStatus: data.progressStatus ?? 'PENDING',
+ });
+
+ const handleSubmit = async (e: React.MouseEvent) => {
+ if (!form.description || !form.progressStatus) {
+ e.preventDefault();
+
+ return;
+ }
+
+ try {
+ await completeStudy(data.dailyStudyId, form);
+ await refetch();
+ onClose();
+ } catch (err) {
+ e.preventDefault();
+ console.error(err);
+ alert('요청 처리에 실패했습니다. 다시 시도해주세요.');
+ }
+ };
+
+ return (
+ <>
+
+
+
+
+
+ 면접 완료 후 해당 지원자의 상태를 업데이트해 주세요.
+
+
+
+
+ setForm((prev) => ({
+ ...prev,
+ progressStatus: e as StudyProgressStatus,
+ }))
+ }
+ />
+
+
+
+
+
+
+ 면접 결과에 대한 간단한 피드백을 입력해 주세요.
+
+
+
+
+ setForm((prev) => ({ ...prev, description: value }))
+ }
+ />
+
+
+
+
+
+
+ 취소
+
+
+ 작성 완료
+
+
+
+ >
+ );
+}
diff --git a/src/features/study/ui/today-study-card.tsx b/src/features/study/ui/today-study-card.tsx
index 6ad64340..80356be2 100644
--- a/src/features/study/ui/today-study-card.tsx
+++ b/src/features/study/ui/today-study-card.tsx
@@ -1,8 +1,11 @@
'use client';
+import { useEffect, useState } from 'react';
+import { getCookie } from '@/shared/tanstack-query/cookie';
import UserAvatar from '@/shared/ui/avatar';
import Badge from '@/shared/ui/badge';
-import TodayStudyModal from './today-study-modal';
+import StudyDoneModal from './study-done-modal';
+import StudyReadyModal from './study-ready-modal';
import { DailyStudyDetail, StudyProgressStatus } from '../api/types';
interface Props {
@@ -18,11 +21,25 @@ const statusBadgeMap: Partial> = {
};
export default function TodayStudyCard({ data, refetch }: Props) {
+ const [memberId, setMemberId] = useState(null);
+
+ useEffect(() => {
+ const id = getCookie('memberId');
+ setMemberId(id ? Number(id) : null);
+ }, []);
+
+ const isInterviewee = memberId === data.intervieweeId;
+
return (
오늘의 스터디
-
+ {memberId !== null &&
+ (isInterviewee ? (
+
+ ) : (
+
+ ))}
diff --git a/src/features/study/ui/today-study-modal.tsx b/src/features/study/ui/today-study-modal.tsx
deleted file mode 100644
index fc8e9f96..00000000
--- a/src/features/study/ui/today-study-modal.tsx
+++ /dev/null
@@ -1,273 +0,0 @@
-'use client';
-
-import { XIcon } from 'lucide-react';
-import { useEffect, useState } from 'react';
-import { cn } from '@/shared/shadcn/lib/utils';
-import { getCookie } from '@/shared/tanstack-query/cookie';
-import Button from '@/shared/ui/button';
-import { SingleDropdown } from '@/shared/ui/dropdown';
-import { BaseInput, TextAreaInput } from '@/shared/ui/input';
-import { Modal } from '@/shared/ui/modal';
-import { completeStudy, putStudyDaily } from '../api/get-study-data';
-import {
- CompleteStudyRequest,
- DailyStudyDetail,
- PutStudyDailyRequest,
- StudyProgressStatus,
-} from '../api/types';
-import { STUDY_PROGRESS_OPTIONS } from '../consts/study-const';
-
-interface TodayStudyModalProps {
- data: DailyStudyDetail;
- refetch: () => void;
-}
-
-export default function TodayStudyModal({
- data,
- refetch,
-}: TodayStudyModalProps) {
- const [memberId, setMemberId] = useState
(null);
-
- useEffect(() => {
- const id = getCookie('memberId');
- setMemberId(id ? Number(id) : null);
- }, []);
-
- if (memberId === null) return null;
-
- const isInterviewee = memberId === data.intervieweeId;
-
- return (
-
-
- {isInterviewee ? '준비하기' : '완료하기'}
-
-
-
-
-
-
- {isInterviewee ? '면접 준비하기' : '면접 완료하기'}
-
-
-
-
-
-
- {isInterviewee ? (
-
- ) : (
-
- )}
-
-
-
- );
-}
-
-function StudyReadyForm({
- refetch,
- data,
-}: {
- refetch: () => void;
- data: DailyStudyDetail;
-}) {
- const [interviewTopic, setInterviewTopic] = useState<
- PutStudyDailyRequest['subject']
- >(data.subject ?? '');
-
- const [referenceLink, setReferenceLink] = useState<
- PutStudyDailyRequest['link']
- >(data.link ?? '');
-
- const handleSubmit = async (e: React.MouseEvent) => {
- if (!interviewTopic) {
- e.preventDefault();
-
- return;
- }
-
- try {
- await putStudyDaily(data.dailyStudyId, {
- subject: interviewTopic,
- description: '',
- link: referenceLink,
- });
- await refetch();
- } catch (err) {
- e.preventDefault();
- console.error(err);
- alert('요청 처리에 실패했습니다. 다시 시도해주세요.');
- }
- };
-
- return (
- <>
-
-
-
-
-
- 이번 스터디에서 다룰 면접 주제를 입력하세요
-
-
-
-
setInterviewTopic(e.target.value)}
- />
-
-
-
-
-
-
- 참고할 링크나 자료가 있다면 입력해 주세요
-
-
-
-
setReferenceLink(e.target.value)}
- />
-
-
-
-
-
-
- 취소
-
-
-
-
- 작성 완료
-
-
-
- >
- );
-}
-
-function StudyDoneForm({
- data,
- refetch,
-}: {
- data: DailyStudyDetail;
- refetch: () => void;
-}) {
- const [form, setForm] = useState({
- description: data.description ?? '',
- progressStatus: data.progressStatus ?? 'PENDING',
- });
-
- const handleSubmit = async (e: React.MouseEvent) => {
- if (!form.description || !form.progressStatus) {
- e.preventDefault();
-
- return;
- }
-
- try {
- await completeStudy(data.dailyStudyId, form);
-
- await refetch();
- } catch (err) {
- e.preventDefault();
- console.error(err);
- alert('요청 처리에 실패했습니다. 다시 시도해주세요.');
- }
- };
-
- return (
- <>
-
-
-
-
-
- 면접 완료 후 해당 지원자의 상태를 업데이트해 주세요.
-
-
-
-
- setForm((prev) => ({
- ...prev,
- progressStatus: e as StudyProgressStatus,
- }))
- }
- />
-
-
-
-
-
-
- 면접 결과에 대한 간단한 피드백을 입력해 주세요.
-
-
-
-
- setForm((prev) => ({ ...prev, description: value }))
- }
- />
-
-
-
-
-
-
- 취소
-
-
-
-
- 작성 완료
-
-
-
- >
- );
-}
From 4268bb9d79732c5d1bfd9c46f952c1eff0633481 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Tue, 22 Jul 2025 22:16:48 +0900
Subject: [PATCH 34/58] =?UTF-8?q?fix:=20=EB=A9=B4=EC=A0=91=20=EC=A4=80?=
=?UTF-8?q?=EB=B9=84=20api?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/api/get-study-data.ts | 8 +-
src/features/study/api/types.ts | 3 +-
src/features/study/ui/study-ready-modal.tsx | 145 ++++++++++++++++++++
3 files changed, 150 insertions(+), 6 deletions(-)
create mode 100644 src/features/study/ui/study-ready-modal.tsx
diff --git a/src/features/study/api/get-study-data.ts b/src/features/study/api/get-study-data.ts
index 72354c27..7dbcd6b6 100644
--- a/src/features/study/api/get-study-data.ts
+++ b/src/features/study/api/get-study-data.ts
@@ -9,7 +9,7 @@ import type {
JoinStudyRequest,
MonthlyCalendarResponse,
PostDailyRetrospectRequest,
- PutStudyDailyRequest,
+ PrepareStudyRequest,
WeeklyParticipationResponse,
} from '@/features/study/api/types';
import { axiosInstance } from '@/shared/tanstack-query/axios';
@@ -49,12 +49,12 @@ export const postDailyRetrospect = async (body: PostDailyRetrospectRequest) => {
return res.data;
};
-// 피면접자 스터디 업데이트
+// 면접 준비 시작
export const putStudyDaily = async (
dailyId: number,
- body: PutStudyDailyRequest,
+ body: PrepareStudyRequest,
) => {
- const res = await axiosInstance.put(`/study/daily/${dailyId}`, body);
+ const res = await axiosInstance.put(`/study/daily/${dailyId}/prepare`, body);
return res.data;
};
diff --git a/src/features/study/api/types.ts b/src/features/study/api/types.ts
index 45ea1e9c..557ddcb6 100644
--- a/src/features/study/api/types.ts
+++ b/src/features/study/api/types.ts
@@ -78,9 +78,8 @@ export interface PostDailyRetrospectRequest {
parentId: number;
}
-export interface PutStudyDailyRequest {
+export interface PrepareStudyRequest {
subject: string;
- description: string;
link: string;
}
diff --git a/src/features/study/ui/study-ready-modal.tsx b/src/features/study/ui/study-ready-modal.tsx
new file mode 100644
index 00000000..c5e498bc
--- /dev/null
+++ b/src/features/study/ui/study-ready-modal.tsx
@@ -0,0 +1,145 @@
+'use client';
+
+import { XIcon } from 'lucide-react';
+import { useState } from 'react';
+import { cn } from '@/shared/shadcn/lib/utils';
+import Button from '@/shared/ui/button';
+import { BaseInput } from '@/shared/ui/input';
+import { Modal } from '@/shared/ui/modal';
+import { putStudyDaily } from '../api/get-study-data';
+import { DailyStudyDetail, PrepareStudyRequest } from '../api/types';
+
+interface Props {
+ data: DailyStudyDetail;
+ refetch: () => void;
+}
+
+export default function StudyReadyModal({ data, refetch }: Props) {
+ const [isOpen, setIsOpen] = useState(false);
+
+ return (
+
+ setIsOpen(true)}>
+
+ 준비하기
+
+
+
+
+
+
+
+
+ 면접 준비하기
+
+
+
+
+
+
+ setIsOpen(false)}
+ />
+
+
+
+ );
+}
+
+function StudyReadyForm({
+ data,
+ refetch,
+ onClose,
+}: {
+ data: DailyStudyDetail;
+ refetch: () => void;
+ onClose: () => void;
+}) {
+ const [form, setForm] = useState({
+ subject: data.subject ?? '',
+ link: data.link ?? '',
+ });
+
+ const handleSubmit = async (e: React.MouseEvent) => {
+ if (!form.subject.trim()) {
+ e.preventDefault();
+
+ return;
+ }
+
+ try {
+ await putStudyDaily(data.dailyStudyId, form);
+ await refetch();
+ onClose();
+ } catch (err) {
+ e.preventDefault();
+ console.error(err);
+ alert('요청 처리에 실패했습니다. 다시 시도해주세요.');
+ }
+ };
+
+ return (
+ <>
+
+
+
+
+
+ 이번 스터디에서 다룰 면접 주제를 입력하세요
+
+
+
+
+ setForm((prev) => ({ ...prev, subject: e.target.value }))
+ }
+ />
+
+
+
+
+
+
+ 참고할 링크나 자료가 있다면 입력해 주세요
+
+
+
+
+ setForm((prev) => ({ ...prev, link: e.target.value }))
+ }
+ />
+
+
+
+
+
+
+ 취소
+
+
+ 작성 완료
+
+
+
+ >
+ );
+}
From 54da5e5f5287ca293069f07d070f080b80b4c36e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Tue, 22 Jul 2025 22:57:59 +0900
Subject: [PATCH 35/58] =?UTF-8?q?refactor:=20=EB=B1=83=EC=A7=80=EB=A7=B5?=
=?UTF-8?q?=20=ED=95=A8=EC=88=98=20=EB=B6=84=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/lib/ui/status-badge-map.tsx | 18 ++++++++++++++++++
src/features/study/ui/today-study-card.tsx | 15 ++-------------
src/shared/ui/badge/index.tsx | 13 ++++++++-----
src/widgets/home/study-list-table.tsx | 16 +++-------------
4 files changed, 31 insertions(+), 31 deletions(-)
create mode 100644 src/features/study/lib/ui/status-badge-map.tsx
diff --git a/src/features/study/lib/ui/status-badge-map.tsx b/src/features/study/lib/ui/status-badge-map.tsx
new file mode 100644
index 00000000..290721c9
--- /dev/null
+++ b/src/features/study/lib/ui/status-badge-map.tsx
@@ -0,0 +1,18 @@
+import type { ReactNode } from 'react';
+import Badge from '@/shared/ui/badge';
+import { StudyProgressStatus } from '../../api/types';
+
+export function getStatusBadge(status: StudyProgressStatus): ReactNode {
+ switch (status) {
+ case 'PENDING':
+ return 시작 전;
+ case 'IN_PROGRESS':
+ return 진행중;
+ case 'COMPLETE':
+ return 완료;
+ case 'ABSENT':
+ return 불참;
+ default:
+ return null;
+ }
+}
diff --git a/src/features/study/ui/today-study-card.tsx b/src/features/study/ui/today-study-card.tsx
index 80356be2..c5997f3e 100644
--- a/src/features/study/ui/today-study-card.tsx
+++ b/src/features/study/ui/today-study-card.tsx
@@ -1,25 +1,18 @@
'use client';
import { useEffect, useState } from 'react';
+import { getStatusBadge } from '@/features/study/lib/ui/status-badge-map';
import { getCookie } from '@/shared/tanstack-query/cookie';
import UserAvatar from '@/shared/ui/avatar';
-import Badge from '@/shared/ui/badge';
import StudyDoneModal from './study-done-modal';
import StudyReadyModal from './study-ready-modal';
-import { DailyStudyDetail, StudyProgressStatus } from '../api/types';
+import { DailyStudyDetail } from '../api/types';
interface Props {
data: DailyStudyDetail;
refetch: () => void;
}
-const statusBadgeMap: Partial> = {
- PENDING: 시작 전,
- IN_PROGRESS: 진행중,
- COMPLETE: 완료,
- ABSENT: 불참,
-};
-
export default function TodayStudyCard({ data, refetch }: Props) {
const [memberId, setMemberId] = useState(null);
@@ -81,8 +74,4 @@ export default function TodayStudyCard({ data, refetch }: Props) {
);
}
-
- function getStatusBadge(status: StudyProgressStatus) {
- return statusBadgeMap[status] ?? null;
- }
}
diff --git a/src/shared/ui/badge/index.tsx b/src/shared/ui/badge/index.tsx
index d8663c74..121e3802 100644
--- a/src/shared/ui/badge/index.tsx
+++ b/src/shared/ui/badge/index.tsx
@@ -6,14 +6,17 @@ import * as React from 'react';
import { cn } from '@/shared/shadcn/lib/utils';
const badgeVariants = cva(
- 'inline-flex min-w-[24px] px-100 py-50 justify-center items-center gap-[2px] text-xs font-medium whitespace-nowrap',
+ 'inline-flex min-w-[24px] px-100 py-50 justify-center items-center border gap-[2px] text-xs font-medium whitespace-nowrap',
{
variants: {
color: {
- default:
- 'bg-background-accent-blue-subtle text-text-subtlest border-border-default',
- completed: 'bg-fill-success-subtle-default text-text-success',
- incomplete: 'bg-fill-danger-subtle-default text-text-error',
+ default: 'text-text-subtlest border-border-default',
+ completed:
+ 'bg-fill-success-subtle-default text-text-success border-fill-success-subtle-default',
+ incomplete:
+ 'bg-fill-danger-subtle-default text-text-error border-fill-danger-subtle-default',
+ progress:
+ 'bg-background-accent-blue-default text-text-information border-background-accent-blue-default',
orange:
'bg-background-accent-orange-subtle text-background-accent-orange-strong',
gray: 'bg-background-accent-gray-subtle text-background-accent-gray-strong',
diff --git a/src/widgets/home/study-list-table.tsx b/src/widgets/home/study-list-table.tsx
index 80778e99..2640c64e 100644
--- a/src/widgets/home/study-list-table.tsx
+++ b/src/widgets/home/study-list-table.tsx
@@ -1,12 +1,9 @@
+import { getStatusBadge } from '@/features/study/lib/ui/status-badge-map';
import { useDailyStudiesQuery } from '@/features/study/model/use-study-query';
import UserAvatar from '@/shared/ui/avatar';
-import Badge from '@/shared/ui/badge/index';
import TableList from '@/shared/ui/table';
import LinkIcon from 'public/icons/Link.svg';
-import {
- DailyStudy,
- StudyProgressStatus,
-} from '../../features/study/api/types';
+import { DailyStudy } from '../../features/study/api/types';
const headers = [
'조',
@@ -23,13 +20,6 @@ interface Props {
date: Date;
}
-const statusBadgeMap: Partial> = {
- PENDING: 시작 전,
- IN_PROGRESS: 진행중,
- COMPLETE: 완료,
- ABSENT: 불참,
-};
-
function mapDailyStudyToDisplayData(
row: DailyStudy,
index: number,
@@ -58,7 +48,7 @@ function mapDailyStudyToDisplayData(
{row.feedback ?? '-'}
),
- '진행 상태': statusBadgeMap[row.progressStatus],
+ '진행 상태': getStatusBadge(row.progressStatus),
'참고 자료': row.link ? (
From 52f730718082c3ddd30cd2eabbb93af7240112e2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Tue, 22 Jul 2025 23:29:41 +0900
Subject: [PATCH 36/58] =?UTF-8?q?style:=20link=20=EB=B2=84=ED=8A=BC=20?=
=?UTF-8?q?=EB=B3=80=EA=B2=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
public/icons/Link.svg | 2 +-
src/widgets/home/study-list-table.tsx | 6 ++++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/public/icons/Link.svg b/public/icons/Link.svg
index 1b6bd7da..90694b76 100644
--- a/public/icons/Link.svg
+++ b/public/icons/Link.svg
@@ -1,5 +1,5 @@
diff --git a/src/widgets/home/study-list-table.tsx b/src/widgets/home/study-list-table.tsx
index 2640c64e..0e1caca5 100644
--- a/src/widgets/home/study-list-table.tsx
+++ b/src/widgets/home/study-list-table.tsx
@@ -51,9 +51,11 @@ function mapDailyStudyToDisplayData(
'진행 상태': getStatusBadge(row.progressStatus),
'참고 자료': row.link ? (
-
+
- ) : null,
+ ) : (
+
+ ),
};
}
From be689c645f0fbc5eff7801b18eaccd4c2ab6d4b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Wed, 23 Jul 2025 23:21:06 +0900
Subject: [PATCH 37/58] =?UTF-8?q?style:=20badge=20=EC=9D=B4=EB=A6=84=20?=
=?UTF-8?q?=EB=B3=80=EA=B2=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/lib/ui/status-badge-map.tsx | 6 +++---
src/shared/ui/badge/index.tsx | 8 +++-----
2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/src/features/study/lib/ui/status-badge-map.tsx b/src/features/study/lib/ui/status-badge-map.tsx
index 290721c9..30dfd1cc 100644
--- a/src/features/study/lib/ui/status-badge-map.tsx
+++ b/src/features/study/lib/ui/status-badge-map.tsx
@@ -7,11 +7,11 @@ export function getStatusBadge(status: StudyProgressStatus): ReactNode {
case 'PENDING':
return 시작 전;
case 'IN_PROGRESS':
- return 진행중;
+ return 진행중;
case 'COMPLETE':
- return 완료;
+ return 완료;
case 'ABSENT':
- return 불참;
+ return 불참;
default:
return null;
}
diff --git a/src/shared/ui/badge/index.tsx b/src/shared/ui/badge/index.tsx
index 121e3802..9dd0978e 100644
--- a/src/shared/ui/badge/index.tsx
+++ b/src/shared/ui/badge/index.tsx
@@ -11,12 +11,10 @@ const badgeVariants = cva(
variants: {
color: {
default: 'text-text-subtlest border-border-default',
- completed:
+ green:
'bg-fill-success-subtle-default text-text-success border-fill-success-subtle-default',
- incomplete:
- 'bg-fill-danger-subtle-default text-text-error border-fill-danger-subtle-default',
- progress:
- 'bg-background-accent-blue-default text-text-information border-background-accent-blue-default',
+ red: 'bg-fill-danger-subtle-default text-text-error border-fill-danger-subtle-default',
+ blue: 'bg-background-accent-blue-subtle text-text-information border-background-accent-blue-subtle',
orange:
'bg-background-accent-orange-subtle text-background-accent-orange-strong',
gray: 'bg-background-accent-gray-subtle text-background-accent-gray-strong',
From be1c023fa85175bff62c3218f7805e9ab4c16e4e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Wed, 23 Jul 2025 23:21:15 +0900
Subject: [PATCH 38/58] =?UTF-8?q?fix:=20=EB=A9=B4=EC=A0=91=20=EC=99=84?=
=?UTF-8?q?=EB=A3=8C=20api=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/api/types.ts | 2 +-
src/features/study/ui/study-done-modal.tsx | 13 ++++++-------
2 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/src/features/study/api/types.ts b/src/features/study/api/types.ts
index 557ddcb6..a5eb1c54 100644
--- a/src/features/study/api/types.ts
+++ b/src/features/study/api/types.ts
@@ -101,6 +101,6 @@ export interface WeeklyParticipationResponse {
}
export interface CompleteStudyRequest {
- description: string;
+ feedback: string;
progressStatus: StudyProgressStatus;
}
diff --git a/src/features/study/ui/study-done-modal.tsx b/src/features/study/ui/study-done-modal.tsx
index f5a6f438..a8e5bcdb 100644
--- a/src/features/study/ui/study-done-modal.tsx
+++ b/src/features/study/ui/study-done-modal.tsx
@@ -63,12 +63,12 @@ function StudyDoneForm({
onClose: () => void;
}) {
const [form, setForm] = useState({
- description: data.description ?? '',
+ feedback: data.feedback ?? '',
progressStatus: data.progressStatus ?? 'PENDING',
});
const handleSubmit = async (e: React.MouseEvent) => {
- if (!form.description || !form.progressStatus) {
+ if (!form.feedback || !form.progressStatus) {
e.preventDefault();
return;
@@ -129,10 +129,10 @@ function StudyDoneForm({
- setForm((prev) => ({ ...prev, description: value }))
+ setForm((prev) => ({ ...prev, feedback: value }))
}
/>
@@ -146,11 +146,10 @@ function StudyDoneForm({
From c5e31beaa96beaa44cd7f3ceff80f521b17be2fd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Thu, 24 Jul 2025 02:31:01 +0900
Subject: [PATCH 39/58] =?UTF-8?q?refactor:=20icon=20=ED=8F=B4=EB=8D=94=20?=
=?UTF-8?q?=EC=9D=B4=EB=8F=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
public/icons/Cake.svg => src/features/my-page/ui/icon/cake.svg | 0
.../features/my-page/ui/icon/github-logo.svg | 0
.../features/my-page/ui/icon/globe-simple.svg | 0
public/icons/Phone.svg => src/features/my-page/ui/icon/phone.svg | 0
4 files changed, 0 insertions(+), 0 deletions(-)
rename public/icons/Cake.svg => src/features/my-page/ui/icon/cake.svg (100%)
rename public/icons/GithubLogo.svg => src/features/my-page/ui/icon/github-logo.svg (100%)
rename public/icons/GlobeSimple.svg => src/features/my-page/ui/icon/globe-simple.svg (100%)
rename public/icons/Phone.svg => src/features/my-page/ui/icon/phone.svg (100%)
diff --git a/public/icons/Cake.svg b/src/features/my-page/ui/icon/cake.svg
similarity index 100%
rename from public/icons/Cake.svg
rename to src/features/my-page/ui/icon/cake.svg
diff --git a/public/icons/GithubLogo.svg b/src/features/my-page/ui/icon/github-logo.svg
similarity index 100%
rename from public/icons/GithubLogo.svg
rename to src/features/my-page/ui/icon/github-logo.svg
diff --git a/public/icons/GlobeSimple.svg b/src/features/my-page/ui/icon/globe-simple.svg
similarity index 100%
rename from public/icons/GlobeSimple.svg
rename to src/features/my-page/ui/icon/globe-simple.svg
diff --git a/public/icons/Phone.svg b/src/features/my-page/ui/icon/phone.svg
similarity index 100%
rename from public/icons/Phone.svg
rename to src/features/my-page/ui/icon/phone.svg
From 19f38a481b8cc8a2bea8f57241b76fbe34ac1123 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Thu, 24 Jul 2025 02:31:14 +0900
Subject: [PATCH 40/58] =?UTF-8?q?refactor:=20=ED=8F=B4=EB=8D=94=20?=
=?UTF-8?q?=EC=9C=84=EC=B9=98=20=EC=9D=B4=EB=8F=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/{lib => }/ui/status-badge-map.tsx | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename src/features/study/{lib => }/ui/status-badge-map.tsx (100%)
diff --git a/src/features/study/lib/ui/status-badge-map.tsx b/src/features/study/ui/status-badge-map.tsx
similarity index 100%
rename from src/features/study/lib/ui/status-badge-map.tsx
rename to src/features/study/ui/status-badge-map.tsx
From 35cbb62ee1808a38afd3348b5ff49a2a1380915b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Thu, 24 Jul 2025 02:32:12 +0900
Subject: [PATCH 41/58] =?UTF-8?q?refactor:=20image=20->=20svgr=20=EC=BB=B4?=
=?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A1=9C=20=EB=B3=80=EA=B2=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/my-page/ui/profile.tsx | 41 ++++++-------------
.../my-page/ui/user-profile-modal.tsx | 41 ++++++-------------
2 files changed, 24 insertions(+), 58 deletions(-)
diff --git a/src/features/my-page/ui/profile.tsx b/src/features/my-page/ui/profile.tsx
index 811cbc3f..aa685de4 100644
--- a/src/features/my-page/ui/profile.tsx
+++ b/src/features/my-page/ui/profile.tsx
@@ -1,5 +1,8 @@
-import Image from 'next/image';
import { MemberProfile } from '@/entities/user/api/types';
+import CakeIcon from '@/features/my-page/ui/icon/cake.svg';
+import GithubIcon from '@/features/my-page/ui/icon/github-logo.svg';
+import GlobeIcon from '@/features/my-page/ui/icon/globe-simple.svg';
+import PhoneIcon from '@/features/my-page/ui/icon/phone.svg';
import ProfileEditModal from '@/features/my-page/ui/profile-edit-modal';
import UserAvatar from '@/shared/ui/avatar';
import Badge from '@/shared/ui/badge';
@@ -37,43 +40,23 @@ export default function Profile({ memberId, memberProfile }: ProfileProps) {
-
-
+
+
{memberProfile.birthDate ?? '생일을 입력해주세요!'}
-
-
+
+
{memberProfile.tel ?? '번호를 입력해주세요!'}
-
-
+
+
{memberProfile.githubLink?.url || '깃허브 링크를 입력해주세요!'}
-
-
+
+
{memberProfile.blogOrSnsLink?.url ||
'블로그 링크를 입력해주세요!'}
diff --git a/src/features/my-page/ui/user-profile-modal.tsx b/src/features/my-page/ui/user-profile-modal.tsx
index 9ecdb593..0cd0f824 100644
--- a/src/features/my-page/ui/user-profile-modal.tsx
+++ b/src/features/my-page/ui/user-profile-modal.tsx
@@ -1,8 +1,11 @@
'use client';
import { XIcon } from 'lucide-react';
-import Image from 'next/image';
import { useUserProfileQuery } from '@/entities/user/model/use-user-profile-query';
+import CakeIcon from '@/features/my-page/ui/icon/cake.svg';
+import GithubIcon from '@/features/my-page/ui/icon/github-logo.svg';
+import GlobeIcon from '@/features/my-page/ui/icon/globe-simple.svg';
+import PhoneIcon from '@/features/my-page/ui/icon/phone.svg';
import UserAvatar from '@/shared/ui/avatar';
import Badge from '@/shared/ui/badge';
import { Modal } from '@/shared/ui/modal';
@@ -66,45 +69,25 @@ export default function UserProfileModal({
-
-
+
+
{profile.memberProfile.birthDate ??
'생일을 입력해주세요!'}
-
-
+
+
{profile.memberProfile.tel ?? '번호를 입력해주세요!'}
-
-
+
+
{profile.memberProfile.githubLink?.url ??
'깃허브 링크를 입력해주세요!'}
-
-
+
+
{profile.memberProfile.blogOrSnsLink?.url ??
'블로그 링크를 입력해주세요!'}
From 44dde990d91dd11852b19ace404c560a10fb976a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Thu, 24 Jul 2025 02:33:56 +0900
Subject: [PATCH 42/58] =?UTF-8?q?refactor:=20props=20=EB=B0=8F=20param=20?=
=?UTF-8?q?=ED=98=95=ED=83=9C=20=EB=B3=80=EA=B2=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/api/get-study-data.ts | 7 ++--
src/features/study/api/types.ts | 4 ---
src/features/study/ui/study-card.tsx | 12 ++-----
src/features/study/ui/today-study-card.tsx | 38 ++++++++++++----------
src/widgets/home/study-list-table.tsx | 13 ++------
5 files changed, 28 insertions(+), 46 deletions(-)
diff --git a/src/features/study/api/get-study-data.ts b/src/features/study/api/get-study-data.ts
index 7dbcd6b6..570e7b4e 100644
--- a/src/features/study/api/get-study-data.ts
+++ b/src/features/study/api/get-study-data.ts
@@ -3,7 +3,6 @@ import type {
DailyStudyDetail,
GetDailyStudiesParams,
GetDailyStudiesResponse,
- GetDailyStudyDetailParams,
GetDailyStudyDetailParams2,
GetMonthlyCalendarParams,
JoinStudyRequest,
@@ -16,11 +15,9 @@ import { axiosInstance } from '@/shared/tanstack-query/axios';
// 스터디 상세 조회
export const getDailyStudyDetail = async (
- params: GetDailyStudyDetailParams,
+ params: string,
): Promise => {
- const { studyDate } = params;
-
- const res = await axiosInstance.get(`/study/daily/mine/${studyDate}`);
+ const res = await axiosInstance.get(`/study/daily/mine/${params}`);
return res.data.content;
};
diff --git a/src/features/study/api/types.ts b/src/features/study/api/types.ts
index a5eb1c54..7dbf0b62 100644
--- a/src/features/study/api/types.ts
+++ b/src/features/study/api/types.ts
@@ -34,10 +34,6 @@ export interface DailyStudyDetail {
feedback: string;
}
-export interface GetDailyStudyDetailParams {
- studyDate: string;
-}
-
export interface GetDailyStudyDetailParams2 {
year: number;
month: number;
diff --git a/src/features/study/ui/study-card.tsx b/src/features/study/ui/study-card.tsx
index f56729bd..a54adc3e 100644
--- a/src/features/study/ui/study-card.tsx
+++ b/src/features/study/ui/study-card.tsx
@@ -65,15 +65,11 @@ export default function StudyCard() {
const offset = selectedDate.getTimezoneOffset() * 60000; // ms단위라 60000곱해줌
const dateOffset = new Date(selectedDate.getTime() - offset);
- const studyParams = { studyDate: dateOffset.toISOString().split('T')[0] };
+ const studyDate = dateOffset.toISOString().split('T')[0];
const { data: participationData } = useWeeklyParticipation(params);
const isParticipate = participationData?.isParticipate ?? false;
- const { data: todayStudyData, refetch } = useDailyStudyDetailQuery(
- studyParams,
- isParticipate,
- );
const { month, week } = getWeekly(selectedDate);
return (
@@ -83,10 +79,8 @@ export default function StudyCard() {
- {isParticipate && todayStudyData && (
-
- )}
-
+ {isParticipate && }
+
>
);
diff --git a/src/features/study/ui/today-study-card.tsx b/src/features/study/ui/today-study-card.tsx
index c5997f3e..109f265e 100644
--- a/src/features/study/ui/today-study-card.tsx
+++ b/src/features/study/ui/today-study-card.tsx
@@ -1,19 +1,14 @@
'use client';
import { useEffect, useState } from 'react';
-import { getStatusBadge } from '@/features/study/lib/ui/status-badge-map';
+import { getStatusBadge } from '@/features/study/ui/status-badge-map';
import { getCookie } from '@/shared/tanstack-query/cookie';
import UserAvatar from '@/shared/ui/avatar';
import StudyDoneModal from './study-done-modal';
import StudyReadyModal from './study-ready-modal';
-import { DailyStudyDetail } from '../api/types';
+import { useDailyStudyDetailQuery } from '../model/use-study-query';
-interface Props {
- data: DailyStudyDetail;
- refetch: () => void;
-}
-
-export default function TodayStudyCard({ data, refetch }: Props) {
+export default function TodayStudyCard({ studyDate }: { studyDate: string }) {
const [memberId, setMemberId] = useState
(null);
useEffect(() => {
@@ -21,7 +16,11 @@ export default function TodayStudyCard({ data, refetch }: Props) {
setMemberId(id ? Number(id) : null);
}, []);
- const isInterviewee = memberId === data.intervieweeId;
+ const { data: todayStudyData } = useDailyStudyDetailQuery(studyDate);
+
+ if (!todayStudyData) return null;
+
+ const isInterviewee = memberId === todayStudyData.intervieweeId;
return (
@@ -29,33 +28,38 @@ export default function TodayStudyCard({ data, refetch }: Props) {
오늘의 스터디
{memberId !== null &&
(isInterviewee ? (
-
+
) : (
-
+
))}
-
+
-
- {data.interviewerName}
+
+
+ {todayStudyData.interviewerName}
+
}
/>
-
+
피드백
-
{data.feedback ?? '-'}
+
{todayStudyData.feedback ?? '-'}
);
diff --git a/src/widgets/home/study-list-table.tsx b/src/widgets/home/study-list-table.tsx
index 0e1caca5..7dcd14d9 100644
--- a/src/widgets/home/study-list-table.tsx
+++ b/src/widgets/home/study-list-table.tsx
@@ -1,5 +1,5 @@
-import { getStatusBadge } from '@/features/study/lib/ui/status-badge-map';
import { useDailyStudiesQuery } from '@/features/study/model/use-study-query';
+import { getStatusBadge } from '@/features/study/ui/status-badge-map';
import UserAvatar from '@/shared/ui/avatar';
import TableList from '@/shared/ui/table';
import LinkIcon from 'public/icons/Link.svg';
@@ -16,10 +16,6 @@ const headers = [
] as const;
type Header = (typeof headers)[number];
-interface Props {
- date: Date;
-}
-
function mapDailyStudyToDisplayData(
row: DailyStudy,
index: number,
@@ -59,12 +55,7 @@ function mapDailyStudyToDisplayData(
};
}
-export default function StudyListSection({ date }: Props) {
- const offset = date.getTimezoneOffset() * 60000;
- const dateOffset = new Date(date.getTime() - offset);
-
- const studyDate = dateOffset.toISOString().split('T')[0];
-
+export default function StudyListSection({ studyDate }: { studyDate: string }) {
const { data, isLoading, error } = useDailyStudiesQuery({
cursor: 0,
pageSize: 10,
From f89b41195d41aa8230d6220cca9e62c5340763e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Thu, 24 Jul 2025 02:36:22 +0900
Subject: [PATCH 43/58] =?UTF-8?q?fix:=20=EC=97=85=EB=8D=B0=EC=9D=B4?=
=?UTF-8?q?=ED=8A=B8=20=EC=BF=BC=EB=A6=AC=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/model/use-study-query.ts | 31 ++++++--
src/features/study/ui/study-done-modal.tsx | 81 ++++++++++-----------
src/features/study/ui/study-ready-modal.tsx | 78 ++++++++++----------
3 files changed, 105 insertions(+), 85 deletions(-)
diff --git a/src/features/study/model/use-study-query.ts b/src/features/study/model/use-study-query.ts
index b8f4cf99..4926aefb 100644
--- a/src/features/study/model/use-study-query.ts
+++ b/src/features/study/model/use-study-query.ts
@@ -1,4 +1,4 @@
-import { useMutation, useQuery } from '@tanstack/react-query';
+import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
getDailyStudies,
getDailyStudyDetail,
@@ -8,7 +8,6 @@ import {
} from '@/features/study/api/get-study-data';
import {
GetDailyStudiesParams,
- GetDailyStudyDetailParams,
GetDailyStudyDetailParams2,
GetMonthlyCalendarParams,
JoinStudyRequest,
@@ -25,15 +24,12 @@ export const useWeeklyParticipation = (params: GetDailyStudyDetailParams2) => {
};
// 스터디 상세 조회 query
-export const useDailyStudyDetailQuery = (
- params: GetDailyStudyDetailParams,
- enabled: boolean = true,
-) => {
+export const useDailyStudyDetailQuery = (params: string) => {
return useQuery({
queryKey: ['dailyStudyDetail', params],
queryFn: () => getDailyStudyDetail(params),
staleTime: 60 * 1000,
- enabled: enabled && !!params,
+ enabled: !!params,
});
};
@@ -64,3 +60,24 @@ export const useJoinStudyMutation = () => {
mutationFn: (payload: JoinStudyRequest) => postJoinStudy(payload),
});
};
+
+// 스터디 상세 & 리스트 업데이트
+export const useInvalidateStudyQueries = () => {
+ const queryClient = useQueryClient();
+
+ const invalidateDailyStudyDetail = async (params: string) => {
+ await queryClient.invalidateQueries({
+ queryKey: ['dailyStudyDetail', params],
+ exact: true,
+ });
+ };
+
+ const invalidateDailyStudies = async (params: GetDailyStudiesParams) => {
+ await queryClient.invalidateQueries({
+ queryKey: ['dailyStudies', params],
+ exact: true,
+ });
+ };
+
+ return { invalidateDailyStudyDetail, invalidateDailyStudies };
+};
diff --git a/src/features/study/ui/study-done-modal.tsx b/src/features/study/ui/study-done-modal.tsx
index a8e5bcdb..ca2703f3 100644
--- a/src/features/study/ui/study-done-modal.tsx
+++ b/src/features/study/ui/study-done-modal.tsx
@@ -14,37 +14,40 @@ import {
StudyProgressStatus,
} from '../api/types';
import { STUDY_PROGRESS_OPTIONS } from '../consts/study-const';
+import { useInvalidateStudyQueries } from '../model/use-study-query';
-interface Props {
+interface StudyDoneModalProps {
data: DailyStudyDetail;
- refetch: () => void;
+ studyDate: string;
}
-export default function StudyDoneModal({ data, refetch }: Props) {
+export default function StudyDoneModal({
+ data,
+ studyDate,
+}: StudyDoneModalProps) {
const [isOpen, setIsOpen] = useState(false);
return (
- setIsOpen(true)}>
+
완료하기
+
-
- 면접 완료하기
-
-
-
-
+ 면접 완료하기
+
+
+
setIsOpen(false)}
/>
@@ -53,33 +56,35 @@ export default function StudyDoneModal({ data, refetch }: Props) {
);
}
-function StudyDoneForm({
- data,
- refetch,
- onClose,
-}: {
+interface StudyDoneFormProps {
data: DailyStudyDetail;
- refetch: () => void;
+ studyDate: string;
onClose: () => void;
-}) {
+}
+
+function StudyDoneForm({ data, studyDate, onClose }: StudyDoneFormProps) {
const [form, setForm] = useState({
feedback: data.feedback ?? '',
progressStatus: data.progressStatus ?? 'PENDING',
});
- const handleSubmit = async (e: React.MouseEvent) => {
- if (!form.feedback || !form.progressStatus) {
- e.preventDefault();
+ const { feedback, progressStatus } = form;
+ const { invalidateDailyStudyDetail, invalidateDailyStudies } =
+ useInvalidateStudyQueries();
- return;
- }
+ const handleChange = (key: keyof CompleteStudyRequest) => (value: string) => {
+ setForm((prev) => ({ ...prev, [key]: value }));
+ };
+
+ const handleSubmit = async () => {
+ if (!feedback.trim() || !progressStatus) return;
try {
await completeStudy(data.dailyStudyId, form);
- await refetch();
+ await invalidateDailyStudyDetail(studyDate);
+ await invalidateDailyStudies({ studyDate, cursor: 0, pageSize: 10 });
onClose();
} catch (err) {
- e.preventDefault();
console.error(err);
alert('요청 처리에 실패했습니다. 다시 시도해주세요.');
}
@@ -90,7 +95,7 @@ function StudyDoneForm({
-
+ {/* 피드백 */}
-
+
피드백
필수
@@ -129,11 +132,9 @@ function StudyDoneForm({
- setForm((prev) => ({ ...prev, feedback: value }))
- }
+ onChange={(value) => handleChange('feedback')(value)}
/>
@@ -145,11 +146,9 @@ function StudyDoneForm({
diff --git a/src/features/study/ui/study-ready-modal.tsx b/src/features/study/ui/study-ready-modal.tsx
index c5e498bc..49d4b182 100644
--- a/src/features/study/ui/study-ready-modal.tsx
+++ b/src/features/study/ui/study-ready-modal.tsx
@@ -8,18 +8,22 @@ import { BaseInput } from '@/shared/ui/input';
import { Modal } from '@/shared/ui/modal';
import { putStudyDaily } from '../api/get-study-data';
import { DailyStudyDetail, PrepareStudyRequest } from '../api/types';
+import { useInvalidateStudyQueries } from '../model/use-study-query';
-interface Props {
+interface StudyReadyModalProps {
data: DailyStudyDetail;
- refetch: () => void;
+ studyDate: string;
}
-export default function StudyReadyModal({ data, refetch }: Props) {
+export default function StudyReadyModal({
+ data,
+ studyDate,
+}: StudyReadyModalProps) {
const [isOpen, setIsOpen] = useState(false);
return (
- setIsOpen(true)}>
+
준비하기
@@ -29,17 +33,15 @@ export default function StudyReadyModal({ data, refetch }: Props) {
-
- 면접 준비하기
-
-
-
-
+ 면접 준비하기
+
+
+
setIsOpen(false)}
/>
@@ -48,33 +50,39 @@ export default function StudyReadyModal({ data, refetch }: Props) {
);
}
-function StudyReadyForm({
- data,
- refetch,
- onClose,
-}: {
+interface StudyReadyFormProps {
data: DailyStudyDetail;
- refetch: () => void;
+ studyDate: string;
onClose: () => void;
-}) {
+}
+
+function StudyReadyForm({ data, studyDate, onClose }: StudyReadyFormProps) {
const [form, setForm] = useState({
subject: data.subject ?? '',
link: data.link ?? '',
});
+ const { invalidateDailyStudyDetail, invalidateDailyStudies } =
+ useInvalidateStudyQueries();
+ const { subject, link } = form;
+
+ const handleChange =
+ (key: keyof PrepareStudyRequest) =>
+ (e: React.ChangeEvent) => {
+ setForm((prev) => ({ ...prev, [key]: e.target.value }));
+ };
+
const handleSubmit = async (e: React.MouseEvent) => {
- if (!form.subject.trim()) {
- e.preventDefault();
+ e.preventDefault();
- return;
- }
+ if (!subject.trim()) return;
try {
- await putStudyDaily(data.dailyStudyId, form);
- await refetch();
+ await putStudyDaily(data.dailyStudyId, { subject, link });
+ await invalidateDailyStudyDetail(studyDate);
+ await invalidateDailyStudies({ studyDate, cursor: 0, pageSize: 10 });
onClose();
} catch (err) {
- e.preventDefault();
console.error(err);
alert('요청 처리에 실패했습니다. 다시 시도해주세요.');
}
@@ -85,7 +93,7 @@ function StudyReadyForm({
-
+
면접 주제
필수
@@ -98,16 +106,14 @@ function StudyReadyForm({
- setForm((prev) => ({ ...prev, subject: e.target.value }))
- }
+ value={subject}
+ onChange={handleChange('subject')}
/>
-
+
참고 자료
@@ -117,10 +123,8 @@ function StudyReadyForm({
- setForm((prev) => ({ ...prev, link: e.target.value }))
- }
+ value={link}
+ onChange={handleChange('link')}
/>
@@ -132,8 +136,8 @@ function StudyReadyForm({
작성 완료
From 6dd1c8142a5967c29f4470cd9970619397b04ae7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Thu, 24 Jul 2025 02:48:10 +0900
Subject: [PATCH 44/58] =?UTF-8?q?fix:=20=EB=B9=88=20=EA=B0=92=20=EC=84=A4?=
=?UTF-8?q?=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/widgets/home/study-list-table.tsx | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/src/widgets/home/study-list-table.tsx b/src/widgets/home/study-list-table.tsx
index 7dcd14d9..12ec3d98 100644
--- a/src/widgets/home/study-list-table.tsx
+++ b/src/widgets/home/study-list-table.tsx
@@ -38,12 +38,8 @@ function mapDailyStudyToDisplayData(
),
- '면접 주제': row.subject,
- 피드백: (
-
- {row.feedback ?? '-'}
-
- ),
+ '면접 주제': row.subject || '-',
+ 피드백: row.feedback || '-',
'진행 상태': getStatusBadge(row.progressStatus),
'참고 자료': row.link ? (
From e8a2755750a9d3b7155241dd825b98e5257f5f57 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Thu, 24 Jul 2025 02:58:38 +0900
Subject: [PATCH 45/58] =?UTF-8?q?delete:=20=EC=82=AC=EC=9A=A9=ED=95=98?=
=?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=20=EC=A0=9C=EA=B1=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/ui/status-badge-map.tsx | 2 +-
src/features/study/ui/study-card.tsx | 5 +----
src/features/study/ui/study-done-modal.tsx | 6 +-----
src/features/study/ui/study-ready-modal.tsx | 3 +--
4 files changed, 4 insertions(+), 12 deletions(-)
diff --git a/src/features/study/ui/status-badge-map.tsx b/src/features/study/ui/status-badge-map.tsx
index 30dfd1cc..19cbaa63 100644
--- a/src/features/study/ui/status-badge-map.tsx
+++ b/src/features/study/ui/status-badge-map.tsx
@@ -1,6 +1,6 @@
import type { ReactNode } from 'react';
import Badge from '@/shared/ui/badge';
-import { StudyProgressStatus } from '../../api/types';
+import { StudyProgressStatus } from '../api/types';
export function getStatusBadge(status: StudyProgressStatus): ReactNode {
switch (status) {
diff --git a/src/features/study/ui/study-card.tsx b/src/features/study/ui/study-card.tsx
index a54adc3e..6cb4faa4 100644
--- a/src/features/study/ui/study-card.tsx
+++ b/src/features/study/ui/study-card.tsx
@@ -5,10 +5,7 @@ import { useState } from 'react';
import DateSelector from './data-selector';
import TodayStudyCard from './today-study-card';
import StudyListSection from '../../../widgets/home/study-list-table';
-import {
- useDailyStudyDetailQuery,
- useWeeklyParticipation,
-} from '../model/use-study-query';
+import { useWeeklyParticipation } from '../model/use-study-query';
// 스터디 주차 구하는 함수
function getWeekly(date: Date): { month: number; week: number } {
diff --git a/src/features/study/ui/study-done-modal.tsx b/src/features/study/ui/study-done-modal.tsx
index ca2703f3..6ca7f462 100644
--- a/src/features/study/ui/study-done-modal.tsx
+++ b/src/features/study/ui/study-done-modal.tsx
@@ -2,7 +2,6 @@
import { XIcon } from 'lucide-react';
import { useState } from 'react';
-import { cn } from '@/shared/shadcn/lib/utils';
import Button from '@/shared/ui/button';
import { SingleDropdown } from '@/shared/ui/dropdown';
import { TextAreaInput } from '@/shared/ui/input';
@@ -116,7 +115,6 @@ function StudyDoneForm({ data, studyDate, onClose }: StudyDoneFormProps) {
/>
- {/* 피드백 */}
@@ -147,9 +145,7 @@ function StudyDoneForm({ data, studyDate, onClose }: StudyDoneFormProps) {
작성 완료
diff --git a/src/features/study/ui/study-ready-modal.tsx b/src/features/study/ui/study-ready-modal.tsx
index 49d4b182..c4665d1a 100644
--- a/src/features/study/ui/study-ready-modal.tsx
+++ b/src/features/study/ui/study-ready-modal.tsx
@@ -2,7 +2,6 @@
import { XIcon } from 'lucide-react';
import { useState } from 'react';
-import { cn } from '@/shared/shadcn/lib/utils';
import Button from '@/shared/ui/button';
import { BaseInput } from '@/shared/ui/input';
import { Modal } from '@/shared/ui/modal';
@@ -137,7 +136,7 @@ function StudyReadyForm({ data, studyDate, onClose }: StudyReadyFormProps) {
작성 완료
From ffd7dff710ac82b08314fdfeffade7946d5a4c92 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Thu, 24 Jul 2025 02:58:59 +0900
Subject: [PATCH 46/58] =?UTF-8?q?fix:=20warning=20=EC=A0=9C=EA=B1=B0=20(im?=
=?UTF-8?q?g=20->=20Next/Image)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/not-found.tsx | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/app/not-found.tsx b/app/not-found.tsx
index 805eb852..48151d31 100644
--- a/app/not-found.tsx
+++ b/app/not-found.tsx
@@ -1,10 +1,11 @@
+import Image from 'next/image';
import Link from 'next/link';
import Button from '@/shared/ui/button';
export default function NotFound() {
return (
-

+
홈으로 이동
From a59a26e3a0b2f73cee7e09068f2715e076f5e77e Mon Sep 17 00:00:00 2001
From: SEONG JIN JO <123255935+seong-jin-jo@users.noreply.github.com>
Date: Thu, 24 Jul 2025 20:22:54 +0900
Subject: [PATCH 47/58] =?UTF-8?q?fix=20:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?=
=?UTF-8?q?=EB=A6=AC=EB=94=94=EB=A0=89=EC=85=98=EC=8B=9C=20=EC=BF=A0?=
=?UTF-8?q?=ED=82=A4=EC=97=90=20=EC=86=8C=EC=85=9C=EC=9D=B4=EB=AF=B8?=
=?UTF-8?q?=EC=A7=80=20=EB=94=94=EC=BD=94=EB=94=A9=ED=95=B4=EC=84=9C=20?=
=?UTF-8?q?=EB=84=A3=EA=B8=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app/redirection/page.tsx | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/app/redirection/page.tsx b/app/redirection/page.tsx
index a7caa192..279307b3 100644
--- a/app/redirection/page.tsx
+++ b/app/redirection/page.tsx
@@ -21,13 +21,13 @@ function RedirectionContent() {
const isGuest = searchParams.get('is-guest');
const memberId = searchParams.get('member-id');
const authVendor = searchParams.get('auth-vendor');
+ const socialImageURL = decodeURIComponent(
+ searchParams.get('profile-image-url') || '',
+ );
setCookie('accessToken', accessToken);
setCookie('memberId', memberId);
- setCookie(
- 'socialImageURL',
- searchParams.get('profile-image-url') || '',
- );
+ setCookie('socialImageURL', socialImageURL);
if (isGuest === 'true') {
router.push('/sign-up');
From ac24bad72d21970d9d4fbfc6fee439c27afad113 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=AF=BC=EC=A3=BC?=
Date: Thu, 24 Jul 2025 21:27:09 +0900
Subject: [PATCH 48/58] =?UTF-8?q?fix:=20mutation=20=EB=B0=A9=EC=8B=9D=20?=
=?UTF-8?q?=EB=B3=80=EA=B2=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/model/use-study-query.ts | 46 ++++++++++++++-------
src/features/study/ui/study-done-modal.tsx | 30 ++++++++------
src/features/study/ui/study-ready-modal.tsx | 46 ++++++++++-----------
3 files changed, 71 insertions(+), 51 deletions(-)
diff --git a/src/features/study/model/use-study-query.ts b/src/features/study/model/use-study-query.ts
index 4926aefb..72afc479 100644
--- a/src/features/study/model/use-study-query.ts
+++ b/src/features/study/model/use-study-query.ts
@@ -1,17 +1,21 @@
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import {
+ completeStudy,
getDailyStudies,
getDailyStudyDetail,
getMonthlyStudyCalendar,
getWeeklyParticipation,
postJoinStudy,
+ putStudyDaily,
} from '@/features/study/api/get-study-data';
import {
+ CompleteStudyRequest,
GetDailyStudiesParams,
GetDailyStudyDetailParams2,
GetMonthlyCalendarParams,
JoinStudyRequest,
MonthlyCalendarResponse,
+ PrepareStudyRequest,
} from '../api/types';
// 스터디 주간 참여 유무 확인 query
@@ -62,22 +66,34 @@ export const useJoinStudyMutation = () => {
};
// 스터디 상세 & 리스트 업데이트
-export const useInvalidateStudyQueries = () => {
- const queryClient = useQueryClient();
+interface UpdateDailyStudyVariables {
+ dailyStudyId: number;
+ studyDate: string;
+ form: PrepareStudyRequest | CompleteStudyRequest;
+ requestType: 'prepare' | 'complete';
+}
- const invalidateDailyStudyDetail = async (params: string) => {
- await queryClient.invalidateQueries({
- queryKey: ['dailyStudyDetail', params],
- exact: true,
- });
- };
+export const useUpdateDailyStudyMutation = () => {
+ const queryClient = useQueryClient();
- const invalidateDailyStudies = async (params: GetDailyStudiesParams) => {
- await queryClient.invalidateQueries({
- queryKey: ['dailyStudies', params],
- exact: true,
- });
- };
+ return useMutation({
+ mutationFn: async ({ dailyStudyId, form, requestType }) => {
+ if (requestType === 'prepare') {
+ await putStudyDaily(dailyStudyId, form as PrepareStudyRequest);
+ } else {
+ await completeStudy(dailyStudyId, form as CompleteStudyRequest);
+ }
+ },
+ onSuccess: async (_data, { studyDate }) => {
+ await queryClient.invalidateQueries({
+ queryKey: ['dailyStudyDetail', studyDate],
+ exact: true,
+ });
- return { invalidateDailyStudyDetail, invalidateDailyStudies };
+ await queryClient.invalidateQueries({
+ queryKey: ['dailyStudies', { studyDate }],
+ exact: false,
+ });
+ },
+ });
};
diff --git a/src/features/study/ui/study-done-modal.tsx b/src/features/study/ui/study-done-modal.tsx
index 6ca7f462..8d3698e4 100644
--- a/src/features/study/ui/study-done-modal.tsx
+++ b/src/features/study/ui/study-done-modal.tsx
@@ -6,14 +6,13 @@ import Button from '@/shared/ui/button';
import { SingleDropdown } from '@/shared/ui/dropdown';
import { TextAreaInput } from '@/shared/ui/input';
import { Modal } from '@/shared/ui/modal';
-import { completeStudy } from '../api/get-study-data';
import {
CompleteStudyRequest,
DailyStudyDetail,
StudyProgressStatus,
} from '../api/types';
import { STUDY_PROGRESS_OPTIONS } from '../consts/study-const';
-import { useInvalidateStudyQueries } from '../model/use-study-query';
+import { useUpdateDailyStudyMutation } from '../model/use-study-query';
interface StudyDoneModalProps {
data: DailyStudyDetail;
@@ -67,9 +66,8 @@ function StudyDoneForm({ data, studyDate, onClose }: StudyDoneFormProps) {
progressStatus: data.progressStatus ?? 'PENDING',
});
+ const { mutate, isPending } = useUpdateDailyStudyMutation();
const { feedback, progressStatus } = form;
- const { invalidateDailyStudyDetail, invalidateDailyStudies } =
- useInvalidateStudyQueries();
const handleChange = (key: keyof CompleteStudyRequest) => (value: string) => {
setForm((prev) => ({ ...prev, [key]: value }));
@@ -78,15 +76,21 @@ function StudyDoneForm({ data, studyDate, onClose }: StudyDoneFormProps) {
const handleSubmit = async () => {
if (!feedback.trim() || !progressStatus) return;
- try {
- await completeStudy(data.dailyStudyId, form);
- await invalidateDailyStudyDetail(studyDate);
- await invalidateDailyStudies({ studyDate, cursor: 0, pageSize: 10 });
- onClose();
- } catch (err) {
- console.error(err);
- alert('요청 처리에 실패했습니다. 다시 시도해주세요.');
- }
+ mutate(
+ {
+ dailyStudyId: data.dailyStudyId,
+ studyDate,
+ form,
+ requestType: 'complete',
+ },
+ {
+ onSuccess: onClose,
+ onError: (err) => {
+ console.error(err);
+ alert('요청 처리에 실패했습니다. 다시 시도해주세요.');
+ },
+ },
+ );
};
return (
diff --git a/src/features/study/ui/study-ready-modal.tsx b/src/features/study/ui/study-ready-modal.tsx
index c4665d1a..48bb1d72 100644
--- a/src/features/study/ui/study-ready-modal.tsx
+++ b/src/features/study/ui/study-ready-modal.tsx
@@ -5,9 +5,8 @@ import { useState } from 'react';
import Button from '@/shared/ui/button';
import { BaseInput } from '@/shared/ui/input';
import { Modal } from '@/shared/ui/modal';
-import { putStudyDaily } from '../api/get-study-data';
import { DailyStudyDetail, PrepareStudyRequest } from '../api/types';
-import { useInvalidateStudyQueries } from '../model/use-study-query';
+import { useUpdateDailyStudyMutation } from '../model/use-study-query';
interface StudyReadyModalProps {
data: DailyStudyDetail;
@@ -61,30 +60,31 @@ function StudyReadyForm({ data, studyDate, onClose }: StudyReadyFormProps) {
link: data.link ?? '',
});
- const { invalidateDailyStudyDetail, invalidateDailyStudies } =
- useInvalidateStudyQueries();
+ const { mutate, isPending } = useUpdateDailyStudyMutation();
const { subject, link } = form;
- const handleChange =
- (key: keyof PrepareStudyRequest) =>
- (e: React.ChangeEvent) => {
- setForm((prev) => ({ ...prev, [key]: e.target.value }));
- };
-
- const handleSubmit = async (e: React.MouseEvent) => {
- e.preventDefault();
+ const handleChange = (key: keyof PrepareStudyRequest) => (value: string) => {
+ setForm((prev) => ({ ...prev, [key]: value }));
+ };
+ const handleSubmit = async () => {
if (!subject.trim()) return;
- try {
- await putStudyDaily(data.dailyStudyId, { subject, link });
- await invalidateDailyStudyDetail(studyDate);
- await invalidateDailyStudies({ studyDate, cursor: 0, pageSize: 10 });
- onClose();
- } catch (err) {
- console.error(err);
- alert('요청 처리에 실패했습니다. 다시 시도해주세요.');
- }
+ mutate(
+ {
+ dailyStudyId: data.dailyStudyId,
+ studyDate,
+ form,
+ requestType: 'prepare',
+ },
+ {
+ onSuccess: onClose,
+ onError: (err) => {
+ console.error(err);
+ alert('요청 처리에 실패했습니다. 다시 시도해주세요.');
+ },
+ },
+ );
};
return (
@@ -106,7 +106,7 @@ function StudyReadyForm({ data, studyDate, onClose }: StudyReadyFormProps) {
handleChange('subject')(e.target.value)}
/>
@@ -123,7 +123,7 @@ function StudyReadyForm({ data, studyDate, onClose }: StudyReadyFormProps) {
handleChange('link')(e.target.value)}
/>
From 9662ba9250c0fe351ae2f7624c1d0735a69e17b8 Mon Sep 17 00:00:00 2001
From: SEONG JIN JO <123255935+seong-jin-jo@users.noreply.github.com>
Date: Fri, 25 Jul 2025 01:03:48 +0900
Subject: [PATCH 49/58] =?UTF-8?q?fix=20:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20?=
=?UTF-8?q?=EB=A6=AC=EB=94=94=EB=A0=89=EC=85=98=EC=8B=9C=20=EC=BF=A0?=
=?UTF-8?q?=ED=82=A4=EC=97=90=20=EC=86=8C=EC=85=9C=EC=9D=B4=EB=AF=B8?=
=?UTF-8?q?=EC=A7=80=20=EB=94=94=EC=BD=94=EB=94=A9=ED=95=B4=EC=84=9C=20?=
=?UTF-8?q?=EB=84=A3=EA=B8=B02?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/auth/ui/sign-up-modal.tsx | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/features/auth/ui/sign-up-modal.tsx b/src/features/auth/ui/sign-up-modal.tsx
index ebf64fae..56630242 100644
--- a/src/features/auth/ui/sign-up-modal.tsx
+++ b/src/features/auth/ui/sign-up-modal.tsx
@@ -29,6 +29,9 @@ export default function SignupModal({
const signUp = useSignUpMutation();
const uploadProfileImage = useUploadProfileImageMutation();
+ // 디버깅
+ console.log('Decoded 소셜이미지 cookie', getCookie('socialImageURL'));
+
// 이름 유효성 검사
const validateName = (value: string) => {
if (!/^[가-힣a-zA-Z]{2,10}$/.test(value)) {
From 8f9d035c6af3c2c5dbad105e94d4fd90917c1f11 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Fri, 25 Jul 2025 01:21:26 +0900
Subject: [PATCH 50/58] =?UTF-8?q?feat:=20=EC=8A=A4=ED=84=B0=EB=94=94=20?=
=?UTF-8?q?=EC=8B=A0=EC=B2=AD=20=EC=99=84=EB=A3=8C=20=EC=95=88=EB=82=B4=20?=
=?UTF-8?q?=EB=AC=B8=EA=B5=AC=20alert=EB=A1=9C=20=ED=91=9C=EC=8B=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/ui/start-study-modal.tsx | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/features/study/ui/start-study-modal.tsx b/src/features/study/ui/start-study-modal.tsx
index bbf66317..e411b252 100644
--- a/src/features/study/ui/start-study-modal.tsx
+++ b/src/features/study/ui/start-study-modal.tsx
@@ -321,6 +321,7 @@ export default function StartStudyModal({ memberId }: StartStudyModalProps) {
},
{
onSuccess: () => {
+ alert('스터디 신청이 완료되었습니다!');
router.refresh();
},
onError: () => {
From e945d9184681b33e50a901f8be2379e666732db2 Mon Sep 17 00:00:00 2001
From: SEONG JIN JO <123255935+seong-jin-jo@users.noreply.github.com>
Date: Fri, 25 Jul 2025 02:50:39 +0900
Subject: [PATCH 51/58] =?UTF-8?q?chore=20:=20=EC=A3=BC=EC=84=9D=EC=82=AD?=
=?UTF-8?q?=EC=A0=9C=20(=EB=B0=B0=ED=8F=AC=ED=99=98=EA=B2=BD=ED=85=8C?=
=?UTF-8?q?=EC=8A=A4=ED=8A=B8=EB=8A=94=20=EC=9D=B8=ED=94=84=EB=9D=BC?=
=?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=A7=84=ED=96=89)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/auth/ui/sign-up-modal.tsx | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/features/auth/ui/sign-up-modal.tsx b/src/features/auth/ui/sign-up-modal.tsx
index 56630242..ebf64fae 100644
--- a/src/features/auth/ui/sign-up-modal.tsx
+++ b/src/features/auth/ui/sign-up-modal.tsx
@@ -29,9 +29,6 @@ export default function SignupModal({
const signUp = useSignUpMutation();
const uploadProfileImage = useUploadProfileImageMutation();
- // 디버깅
- console.log('Decoded 소셜이미지 cookie', getCookie('socialImageURL'));
-
// 이름 유효성 검사
const validateName = (value: string) => {
if (!/^[가-힣a-zA-Z]{2,10}$/.test(value)) {
From 6dcce3a01363ef085a2d0e480024fc8e5acd7dfb Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 26 Jul 2025 01:12:37 +0900
Subject: [PATCH 52/58] =?UTF-8?q?refactor:=20=EC=95=BD=EA=B4=80=EB=8F=99?=
=?UTF-8?q?=EC=9D=98=20checkbox=20=EC=9D=B4=EB=8F=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/auth/ui/login-modal.tsx | 6 ---
src/features/auth/ui/sign-up-modal.tsx | 57 +++++++++++++--------
src/features/auth/ui/sign-up-name-input.tsx | 31 -----------
3 files changed, 35 insertions(+), 59 deletions(-)
delete mode 100644 src/features/auth/ui/sign-up-name-input.tsx
diff --git a/src/features/auth/ui/login-modal.tsx b/src/features/auth/ui/login-modal.tsx
index 260dfccd..0a53946d 100644
--- a/src/features/auth/ui/login-modal.tsx
+++ b/src/features/auth/ui/login-modal.tsx
@@ -112,12 +112,6 @@ export default function LoginModal({
-
-
-
- ZERO-ONE의 이용 약관과 개인정보 처리방침에 동의할게요.
-
-
diff --git a/src/features/auth/ui/sign-up-modal.tsx b/src/features/auth/ui/sign-up-modal.tsx
index ebf64fae..0a43171e 100644
--- a/src/features/auth/ui/sign-up-modal.tsx
+++ b/src/features/auth/ui/sign-up-modal.tsx
@@ -1,3 +1,4 @@
+import { sendGTMEvent } from '@next/third-parties/google';
import { XIcon } from 'lucide-react';
import { useState, useRef } from 'react';
import {
@@ -5,12 +6,11 @@ import {
useUploadProfileImageMutation,
} from '@/features/auth/model/use-auth-mutation';
import SignupImageSelector from '@/features/auth/ui/sign-up-image-selector';
-import SignupNameInput from '@/features/auth/ui/sign-up-name-input';
+import { hashValue } from '@/shared/lib/hash';
import { getCookie, setCookie } from '@/shared/tanstack-query/cookie';
import Button from '@/shared/ui/button';
+import { BaseInput } from '@/shared/ui/input';
import { Modal } from '@/shared/ui/modal';
-import { sendGTMEvent } from '@next/third-parties/google';
-import { hashValue } from '@/shared/lib/hash';
export default function SignupModal({
open,
@@ -20,7 +20,6 @@ export default function SignupModal({
onClose: () => void;
}) {
const [name, setName] = useState('');
- const [error, setError] = useState('');
const [image, setImage] = useState(
getCookie('socialImageURL') || 'profile-default.svg',
);
@@ -29,15 +28,7 @@ export default function SignupModal({
const signUp = useSignUpMutation();
const uploadProfileImage = useUploadProfileImageMutation();
- // 이름 유효성 검사
- const validateName = (value: string) => {
- if (!/^[가-힣a-zA-Z]{2,10}$/.test(value)) {
- setError('이름에는 숫자나 특수문자를 사용할 수 없습니다.');
- } else {
- setError('');
- }
- setName(value);
- };
+ const isValidName = /^[가-힣a-zA-Z]{2,10}$/.test(name);
// 이미지 업로드
const handleImageChange = (e: React.ChangeEvent) => {
@@ -60,12 +51,11 @@ export default function SignupModal({
{
// 회원가입 성공 시 프로필 이미지 업로드
onSuccess: (data) => {
-
const memberId = data.content.generatedMemberId;
if (data && memberId) {
- setCookie('memberId', memberId)
-
+ setCookie('memberId', memberId);
+
// 회원가입 GA 이벤트 전송
sendGTMEvent({
event: 'custom_member_join',
@@ -85,7 +75,6 @@ export default function SignupModal({
file: formData,
});
}
-
// 성공 후 홈페이지로 이동
window.location.href = '/';
@@ -124,17 +113,41 @@ export default function SignupModal({
서비스 이용을 위해 이름을 입력해주세요.
-
+
+
+
setName(e.target.value)}
+ placeholder="홍길동"
+ className={`w-full`}
+ color={isValidName ? 'default' : 'error'}
+ />
+
+ {isValidName
+ ? '신뢰 있는 매칭을 위해 실명을 사용해주세요. (예: 홍길동 )'
+ : '이름에는 숫자나 특수문자를 사용할 수 없습니다. 두 글자 이상 입력해주세요.'}
+
+
+
+
+
+ ZERO-ONE의 이용 약관과 개인정보 처리방침에 동의할게요.
+
+
+
가입 완료
diff --git a/src/features/auth/ui/sign-up-name-input.tsx b/src/features/auth/ui/sign-up-name-input.tsx
deleted file mode 100644
index 96e1ae6d..00000000
--- a/src/features/auth/ui/sign-up-name-input.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import { BaseInput } from '@/shared/ui/input';
-
-export default function SignupNameInput({
- name,
- setName,
- error,
-}: {
- name: string;
- setName: (name: string) => void;
- error: string;
-}) {
- return (
-
-
setName(e.target.value)}
- placeholder="최예림"
- className={`w-full`}
- color={error ? 'error' : 'default'}
- />
-
- {error
- ? '이름에는 숫자나 특수문자를 사용할 수 없습니다. 두 글자 이상 입력해주세요.'
- : '신뢰 있는 매칭을 위해 실명을 사용해주세요. (예: 홍길동 )'}
-
-
- );
-}
From e4d6e3840bee3fb4cfe37617ef0d37125755b1ae Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 26 Jul 2025 10:30:03 +0900
Subject: [PATCH 53/58] =?UTF-8?q?fix:=20=EC=9D=B4=EB=A6=84=20=EC=9C=A0?=
=?UTF-8?q?=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20=EC=8A=A4=ED=83=80?=
=?UTF-8?q?=EC=9D=BC=20=EA=B0=9C=EC=84=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 아무것도 입력하지 않았을 경우, 기본 input 스타일 적용
---
src/features/auth/ui/sign-up-modal.tsx | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/features/auth/ui/sign-up-modal.tsx b/src/features/auth/ui/sign-up-modal.tsx
index 0a43171e..aa12b59a 100644
--- a/src/features/auth/ui/sign-up-modal.tsx
+++ b/src/features/auth/ui/sign-up-modal.tsx
@@ -121,10 +121,12 @@ export default function SignupModal({
onChange={(e) => setName(e.target.value)}
placeholder="홍길동"
className={`w-full`}
- color={isValidName ? 'default' : 'error'}
+ color={
+ isValidName || name.length === 0 ? 'default' : 'error'
+ }
/>
{isValidName
? '신뢰 있는 매칭을 위해 실명을 사용해주세요. (예: 홍길동 )'
From 70df1e3142bc00eea4bc07aec5b9aad7e1c4d43a Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 26 Jul 2025 10:42:05 +0900
Subject: [PATCH 54/58] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=A6=84=20Input?=
=?UTF-8?q?=EC=9D=98=20=EC=9E=85=EB=A0=A5=EA=B0=92=20=EC=A0=9C=ED=95=9C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/auth/ui/sign-up-modal.tsx | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/features/auth/ui/sign-up-modal.tsx b/src/features/auth/ui/sign-up-modal.tsx
index aa12b59a..cd7a358f 100644
--- a/src/features/auth/ui/sign-up-modal.tsx
+++ b/src/features/auth/ui/sign-up-modal.tsx
@@ -118,17 +118,25 @@ export default function SignupModal({
setName(e.target.value)}
+ onChange={(e) => {
+ const value = e.target.value;
+ const filteredValue = value
+ .replace(/[^a-zA-Zㄱ-힣]/g, '')
+ .slice(0, 10)
+ .trim();
+ setName(filteredValue);
+ }}
placeholder="홍길동"
className={`w-full`}
color={
isValidName || name.length === 0 ? 'default' : 'error'
}
+ maxLength={10}
/>
- {isValidName
+ {isValidName || name.length === 0
? '신뢰 있는 매칭을 위해 실명을 사용해주세요. (예: 홍길동 )'
: '이름에는 숫자나 특수문자를 사용할 수 없습니다. 두 글자 이상 입력해주세요.'}
From b44c6c38ca8974070edf749155c64492ddc9fc23 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 26 Jul 2025 10:48:05 +0900
Subject: [PATCH 55/58] =?UTF-8?q?feat:=20=EA=B0=9C=EC=9D=B8=20=EC=95=BD?=
=?UTF-8?q?=EA=B4=80=20=EB=8F=99=EC=9D=98=ED=95=98=EC=A7=80=20=EC=95=8A?=
=?UTF-8?q?=EC=9C=BC=EB=A9=B4=20=EA=B0=80=EC=9E=85=20=EC=99=84=EB=A3=8C=20?=
=?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EB=B9=84=ED=99=9C=EC=84=B1=ED=99=94?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/auth/ui/sign-up-modal.tsx | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/features/auth/ui/sign-up-modal.tsx b/src/features/auth/ui/sign-up-modal.tsx
index cd7a358f..e2b8e15b 100644
--- a/src/features/auth/ui/sign-up-modal.tsx
+++ b/src/features/auth/ui/sign-up-modal.tsx
@@ -20,6 +20,7 @@ export default function SignupModal({
onClose: () => void;
}) {
const [name, setName] = useState('');
+ const [checked, setChecked] = useState(false);
const [image, setImage] = useState(
getCookie('socialImageURL') || 'profile-default.svg',
);
@@ -142,7 +143,12 @@ export default function SignupModal({
-
+
setChecked(e.target.checked)}
+ />
가입 완료
From 4619524fb251aa51470991e3d573ce2c85f4f1e8 Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 26 Jul 2025 14:31:22 +0900
Subject: [PATCH 56/58] =?UTF-8?q?refactor:=20=EC=8A=A4=ED=84=B0=EB=94=94?=
=?UTF-8?q?=20=EC=8B=9C=EC=9E=91=20=EC=A0=84=EC=97=90=EB=8A=94=20=EC=99=84?=
=?UTF-8?q?=EB=A3=8C=ED=95=98=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20=EB=B9=84?=
=?UTF-8?q?=ED=99=9C=EC=84=B1=ED=99=94?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/ui/study-done-modal.tsx | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/src/features/study/ui/study-done-modal.tsx b/src/features/study/ui/study-done-modal.tsx
index 8d3698e4..6224f2d3 100644
--- a/src/features/study/ui/study-done-modal.tsx
+++ b/src/features/study/ui/study-done-modal.tsx
@@ -27,11 +27,13 @@ export default function StudyDoneModal({
return (
-
-
- 완료하기
-
-
+ setIsOpen(true)}
+ >
+ 완료하기
+
@@ -149,7 +151,7 @@ function StudyDoneForm({ data, studyDate, onClose }: StudyDoneFormProps) {
작성 완료
From 9362b1ae460aa357f76802098131a73a9c2f0c0d Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 26 Jul 2025 14:33:11 +0900
Subject: [PATCH 57/58] =?UTF-8?q?refactor:=20=EC=A4=80=EB=B9=84=ED=95=98?=
=?UTF-8?q?=EA=B8=B0=20=EB=B2=84=ED=8A=BC=EC=97=90=20Button=20=EC=BB=B4?=
=?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=A0=81=EC=9A=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/ui/study-ready-modal.tsx | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/features/study/ui/study-ready-modal.tsx b/src/features/study/ui/study-ready-modal.tsx
index 48bb1d72..dd6a96e3 100644
--- a/src/features/study/ui/study-ready-modal.tsx
+++ b/src/features/study/ui/study-ready-modal.tsx
@@ -21,10 +21,8 @@ export default function StudyReadyModal({
return (
-
-
- 준비하기
-
+
+ 준비하기
From b56ecae15489842dad8a53870d2cace5be81b82e Mon Sep 17 00:00:00 2001
From: aken-you
Date: Sat, 26 Jul 2025 14:34:02 +0900
Subject: [PATCH 58/58] =?UTF-8?q?refactor:=20=EC=8A=A4=ED=84=B0=EB=94=94?=
=?UTF-8?q?=20=EC=A4=80=EB=B9=84=20mutate=EA=B0=80=20=EC=9D=91=EB=8B=B5?=
=?UTF-8?q?=EC=98=A4=EA=B8=B0=20=EC=A0=84=EC=97=90=20=EC=9E=91=EC=84=B1=20?=
=?UTF-8?q?=EC=99=84=EB=A3=8C=20=EB=B2=84=ED=8A=BC=20=EB=B9=84=ED=99=9C?=
=?UTF-8?q?=EC=84=B1=ED=99=94?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/features/study/ui/study-ready-modal.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/features/study/ui/study-ready-modal.tsx b/src/features/study/ui/study-ready-modal.tsx
index dd6a96e3..2926eb22 100644
--- a/src/features/study/ui/study-ready-modal.tsx
+++ b/src/features/study/ui/study-ready-modal.tsx
@@ -134,7 +134,7 @@ function StudyReadyForm({ data, studyDate, onClose }: StudyReadyFormProps) {
작성 완료