Skip to content
Merged
18 changes: 16 additions & 2 deletions src/apis/users/queries.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import { useQuery } from '@tanstack/react-query';
import { getUser } from '.';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { getUser, updateUser } from '.';
import { UpdateUserForm } from './types';

export const useGetUser = () => {
return useQuery({
queryKey: ['user'],
queryFn: () => getUser(),
});
};

export const useUpdateUser = () => {
const queryClient = useQueryClient();

return useMutation({
mutationFn: (params: UpdateUserForm) => {
return updateUser(params);
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['user'] });
},
});
};
19 changes: 9 additions & 10 deletions src/apis/users/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,19 @@ export type SignupFailResponse = FailResponse;

export type SignupResponse = Promise<SignupSuccessResponse | SignupFailResponse>;

type ProfileImageUrl = string | URL | null;
const profileImageUrlSchema = z
.instanceof(File)
.refine((file) => ['image/jpeg', 'image/jpg', 'image/png', 'image/ico'].includes(file.type), {
message: PROFILEEDIT_FORM_ERROR_MESSAGE.IMAGE.TYPE,
})
.refine((file) => file.size < 2 * 1024 * 1024, { message: `2${PROFILEEDIT_FORM_ERROR_MESSAGE.IMAGE.SIZE}` });

export const updateUserFormSchema = z.object({
nickname: z.string().max(PROFILEEDIT_FORM_VALID_LENGTH.NICKNAME.MAX, PROFILEEDIT_FORM_ERROR_MESSAGE.NICKNAME.MAX),
profileImageUrl: z.string(),
profileImageUrl: z.union([z.string().url(), profileImageUrlSchema]).optional().nullable(),
});

export type UpdateUserForm = Omit<z.infer<typeof updateUserFormSchema>, 'profileImageUrl'> & {
profileImageUrl: ProfileImageUrl;
};

const profileImageUrlSchema = z.instanceof(File).refine((file) => ['image/jpeg', 'image/jpg', 'image/png', 'image/svg+xml', 'image/ico'].includes(file.type), {
message: '지원되지 않는 이미지 파일입니다.',
});
export type UpdateUserForm = z.infer<typeof updateUserFormSchema>;

export const createProfileImageFormSchema = z.object({
image: profileImageUrlSchema,
Expand All @@ -66,7 +65,7 @@ export interface CreateProfileImageForm {
}

export const profileImageUrlResponseSchema = z.object({
profileImageUrl: z.union([z.string(), z.instanceof(URL)]),
profileImageUrl: z.string().url(),
});

export type ProfileImageUrlResponse = z.infer<typeof profileImageUrlResponseSchema>;
7 changes: 7 additions & 0 deletions src/app/(after-login)/mypage/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default function loading() {
return (
<div className='p-10'>
<div className='py-6 text-md text-gray-40'>내정보를 불러오는 중입니다.</div>
</div>
);
}
29 changes: 23 additions & 6 deletions src/app/(after-login)/mypage/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
import { redirect } from 'next/navigation';
import { User, userSchema } from '@/apis/users/types';
import PasswordEdit from '@/components/profile/PasswordEdit';
import ProfileEdit from '@/components/profile/ProfileEdit';
import GoBackLink from '@/components/ui/Link/GoBackLink';
import axiosServerHelper from '@/utils/network/axiosServerHelper';
import { safeResponse } from '@/utils/network/safeResponse';

export default function MyPage() {
return (
<div className='mx-10 flex max-w-[670px] flex-col'>
{/* TODO: 돌아가기 컴포넌트 연동 */}
export default async function MyPage() {
const response = await axiosServerHelper<User>('/users/me');
const userData = safeResponse(response.data, userSchema);

if (!userData) {
redirect('/login');
}

<ProfileEdit />
return (
<div className='p-10'>
<div className='mb-8'>
<GoBackLink href='/mydashboard' />
</div>
<div className='grid w-full max-w-[620px] gap-4'>
{/* 프로필 수정 */}
<ProfileEdit user={userData} />

<PasswordEdit />
{/* 비밀번호 수정 */}
<PasswordEdit />
</div>
</div>
);
}
11 changes: 8 additions & 3 deletions src/assets/images/logo_bi.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading