Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"use client";
import { useAuth } from "@/hooks/useAuth";
import { useLogin } from "@/hooks/queries/auth/useLogin";
import { type LoginSchema, loginSchema } from "@/schemas/authSchema";
import { zodResolver } from "@hookform/resolvers/zod";
import Image from "next/image";
import Link from "next/link";
import { useForm } from "react-hook-form";

export default function LoginPage() {
const { login, isLoginPending } = useAuth();
const { login, isPending } = useLogin();
const {
register,
handleSubmit,
Expand Down Expand Up @@ -57,10 +57,10 @@ export default function LoginPage() {
<div>
<button
type="submit"
disabled={isLoginPending}
disabled={isPending}
className="group relative flex w-full justify-center rounded-lg bg-lime-600 px-4 py-2 text-sm font-medium text-white hover:bg-lime-700 focus:outline-none focus:ring-2 focus:ring-lime-500 focus:ring-offset-2 disabled:bg-lime-300"
>
{isLoginPending ? "로그인 중..." : "로그인"}
{isPending ? "로그인 중..." : "로그인"}
</button>
</div>
<div className="flex justify-center space-x-6">
Expand Down
8 changes: 4 additions & 4 deletions src/app/(auth)/signup/applicant/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { useAuth } from "@/hooks/useAuth";
import { useSignup } from "@/hooks/queries/auth/useSignup";
import { type SignupSchema, signupSchema } from "@/schemas/authSchema";
import { userRoles } from "@/constants/userRoles";
import { zodResolver } from "@hookform/resolvers/zod";
Expand All @@ -9,7 +9,7 @@ import { useForm } from "react-hook-form";
import Image from "next/image";

export default function ApplicantSignupPage() {
const { signup, isSignupPending } = useAuth();
const { signup, isPending } = useSignup();
const {
register,
handleSubmit,
Expand Down Expand Up @@ -100,10 +100,10 @@ export default function ApplicantSignupPage() {
<div>
<button
type="submit"
disabled={isSignupPending}
disabled={isPending}
className="group relative flex w-full justify-center rounded-lg bg-lime-600 px-4 py-2 text-sm font-medium text-white hover:bg-lime-700 focus:outline-none focus:ring-2 focus:ring-lime-500 focus:ring-offset-2 disabled:bg-lime-300"
>
{isSignupPending ? "회원가입 중..." : "회원가입"}
{isPending ? "회원가입 중..." : "회원가입"}
</button>
</div>
<div className="flex justify-center space-x-4">
Expand Down
8 changes: 4 additions & 4 deletions src/app/(auth)/signup/owner/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { useAuth } from "@/hooks/useAuth";
import { useSignup } from "@/hooks/queries/auth/useSignup";
import { type SignupSchema, signupSchema } from "@/schemas/authSchema";
import { userRoles } from "@/constants/userRoles";
import { zodResolver } from "@hookform/resolvers/zod";
Expand All @@ -9,7 +9,7 @@ import { useForm } from "react-hook-form";
import Image from "next/image";

export default function OwnerSignupPage() {
const { signup, isSignupPending } = useAuth();
const { signup, isPending } = useSignup();
const {
register,
handleSubmit,
Expand Down Expand Up @@ -122,10 +122,10 @@ export default function OwnerSignupPage() {
<div>
<button
type="submit"
disabled={isSignupPending}
disabled={isPending}
className="group relative flex w-full justify-center rounded-lg bg-lime-600 px-4 py-2 text-sm font-medium text-white hover:bg-lime-700 focus:outline-none focus:ring-2 focus:ring-lime-500 focus:ring-offset-2 disabled:bg-lime-300"
>
{isSignupPending ? "회원가입 중..." : "회원가입"}
{isPending ? "회원가입 중..." : "회원가입"}
</button>
</div>
<div className="flex justify-center space-x-4">
Expand Down
4 changes: 2 additions & 2 deletions src/app/(pages)/mypage/components/FilterBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import Button from "@/app/components/button/default/Button";
import KebabDropdown from "@/app/components/button/dropdown/KebabDropdown";
import { userRoles } from "@/constants/userRoles";
import useModalStore from "@/store/modalStore";
import { useUser } from "@/hooks/useUser";
import { useUser } from "@/hooks/queries/user/me/useUser";

export default function FilterBar() {
const { user, isLoading } = useUser();
const { openModal } = useModalStore();

if (isLoading) {
return <div>Loading...</div>;
return null;
}

if (!user) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import React from "react";
import { useState } from "react";
import { useUser } from "@/hooks/useUser";
import { useMyComments } from "@/hooks/queries/user/me/useMyComments";
import Pagination from "@/app/components/pagination/Pagination";
import type { MyCommentType } from "@/types/response/user";

Expand All @@ -14,7 +14,6 @@ export default function CommentsSection() {
const [currentPage, setCurrentPage] = useState(1);

// 내가 작성한 댓글 목록 조회
const { useMyComments } = useUser();
const { data, isLoading, error } = useMyComments({
page: currentPage,
pageSize: COMMENTS_PER_PAGE,
Expand Down
3 changes: 1 addition & 2 deletions src/app/(pages)/mypage/components/sections/PostsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import React, { useEffect } from "react";
import { useInView } from "react-intersection-observer";
import { useUser } from "@/hooks/useUser";
import { useMyPosts } from "@/hooks/queries/user/me/useMyPosts";
import { useSortStore } from "@/store/sortStore";
import type { PostListType } from "@/types/response/post";

Expand All @@ -21,7 +21,6 @@ export default function PostsSection() {
});

// 내가 작성한 게시글 목록 조회
const { useMyPosts } = useUser();
const { data, isLoading, error, hasNextPage, fetchNextPage, isFetchingNextPage } = useMyPosts({
limit: POSTS_PER_PAGE,
orderBy: orderBy.posts,
Expand Down
3 changes: 1 addition & 2 deletions src/app/(pages)/mypage/components/sections/ScrapsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import React, { useEffect } from "react";
import { useInView } from "react-intersection-observer";
import { useUser } from "@/hooks/useUser";
import { useMyScraps } from "@/hooks/queries/user/me/useMyScraps";
import { useSortStore } from "@/store/sortStore";
import type { FormListType } from "@/types/response/form";

Expand All @@ -21,7 +21,6 @@ export default function ScrapsSection() {
});

// 내가 스크랩한 알바폼 목록 조회
const { useMyScraps } = useUser();
const { data, isLoading, error, hasNextPage, fetchNextPage, isFetchingNextPage } = useMyScraps({
limit: SCRAPS_PER_PAGE,
orderBy: orderBy.scrap,
Expand Down
6 changes: 3 additions & 3 deletions src/app/components/layout/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import Image from "next/image";
import Link from "next/link";
import { usePathname, useRouter } from "next/navigation";
import { cn } from "@/lib/tailwindUtil";
import { useAuth } from "@/hooks/useAuth";
import { useLogout } from "@/hooks/queries/auth/useLogout";
import { useState } from "react";
import { toast } from "react-hot-toast";
import { useUser } from "@/hooks/useUser";
import { useUser } from "@/hooks/queries/user/me/useUser";

export default function Header() {
const { logout } = useAuth();
const { logout } = useLogout();
const { user, isLoading } = useUser();
const pathname = usePathname();
const router = useRouter();
Expand Down
52 changes: 18 additions & 34 deletions src/app/components/modal/modals/form/ChangePasswordModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ import { passwordSchema } from "@/schemas/commonSchema";
import { z } from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import axios from "axios";
import toast from "react-hot-toast";
import { useState } from "react";
import { useAuth } from "@/hooks/useAuth";
import { useLogout } from "@/hooks/queries/auth/useLogout";
import { usePassword } from "@/hooks/queries/user/me/usePassword";

interface ChangePasswordModalProps {
isOpen: boolean;
Expand Down Expand Up @@ -54,8 +52,8 @@ const defaultFields = [
] as const;

const ChangePasswordModal = ({ isOpen, onClose, className }: ChangePasswordModalProps) => {
const [isSubmitting, setIsSubmitting] = useState(false);
const { logout } = useAuth();
const { mutate: changePassword, isPending } = usePassword();
const { logout } = useLogout();

const {
register,
Expand All @@ -75,35 +73,21 @@ const ChangePasswordModal = ({ isOpen, onClose, className }: ChangePasswordModal
if (!isOpen) return null;

const onSubmitHandler = async (data: ChangePasswordFormData) => {
if (isSubmitting) return;
if (isPending) return;

try {
setIsSubmitting(true);
await axios.patch("/api/users/me/password", {
changePassword(
{
currentPassword: data.currentPassword,
newPassword: data.newPassword,
});

reset();
onClose();
// 비밀번호 변경 후 로그아웃 처리
logout();
toast.success("비밀번호가 변경되었습니다!\n다시 로그인해주세요.", {
style: {
whiteSpace: "pre-line", // \n을 줄바꿈으로 처리
textAlign: "center", // 텍스트 중앙 정렬
},
{
onSuccess: () => {
reset();
onClose();
logout();
},
});
} catch (error) {
if (axios.isAxiosError(error)) {
const errormessage = error.response?.data?.message || "비밀번호 변경에 실패했습니다.";
toast.error(errormessage);
} else {
toast.error("비밀번호 변경 중 오류가 발생했습니다.");
}
} finally {
setIsSubmitting(false);
}
);
};

return (
Expand All @@ -124,7 +108,7 @@ const ChangePasswordModal = ({ isOpen, onClose, className }: ChangePasswordModal
type={field.type}
placeholder={field.placeholder}
variant="white"
disabled={isSubmitting}
disabled={isPending}
size="w-[327px] h-[54px] md:w-[640px] md:h-[64px]"
errormessage={errors[field.name]?.message}
/>
Expand All @@ -138,17 +122,17 @@ const ChangePasswordModal = ({ isOpen, onClose, className }: ChangePasswordModal
onClose();
reset();
}}
disabled={isSubmitting}
disabled={isPending}
className="text-grayscale-700 flex-1 rounded-md border border-grayscale-300 bg-white px-4 py-2 text-sm font-semibold transition-colors hover:bg-grayscale-50 md:text-base"
>
취소
</button>
<button
type="submit"
disabled={isSubmitting}
disabled={isPending}
className="flex-1 rounded-md bg-orange-500 px-4 py-2 text-sm font-semibold text-white transition-colors hover:bg-orange-600 md:text-base"
>
{isSubmitting ? "변경 중..." : "변경하기"}
{isPending ? "변경 중..." : "변경하기"}
</button>
</div>
</form>
Expand Down
72 changes: 15 additions & 57 deletions src/app/components/modal/modals/form/EditMyProfileModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import { useState, useRef, useEffect } from "react";
import Image from "next/image";
import { FiUser, FiEdit2 } from "react-icons/fi";
import BaseInput from "@/app/components/input/text/BaseInput";
import { useUser } from "@/hooks/useUser";
import axios from "axios";
import toast from "react-hot-toast";
import { useUser } from "@/hooks/queries/user/me/useUser";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
Expand All @@ -28,10 +26,9 @@ const editMyProfileSchema = z.object({
type EditMyProfileFormData = z.infer<typeof editMyProfileSchema>;

const EditMyProfileModal = ({ isOpen, onClose, className }: EditMyProfileModalProps) => {
const { user, refetch } = useUser();
const { user, updateProfile, isUpdating } = useUser();
const [selectedFile, setSelectedFile] = useState<File | null>(null);
const [previewUrl, setPreviewUrl] = useState<string>("");
const [isSubmitting, setIsSubmitting] = useState(false);
const fileInputRef = useRef<HTMLInputElement>(null);

const {
Expand Down Expand Up @@ -78,58 +75,19 @@ const EditMyProfileModal = ({ isOpen, onClose, className }: EditMyProfileModalPr
};

const onSubmitHandler = async (data: EditMyProfileFormData) => {
if (isSubmitting) return;
if (isUpdating) return;

try {
setIsSubmitting(true);

let imageUrl = user?.imageUrl || "";

if (selectedFile) {
const uploadFormData = new FormData();
uploadFormData.append("image", selectedFile);

const uploadResponse = await axios.post("/api/images/upload", uploadFormData, {
withCredentials: true,
});

if (uploadResponse.status === 201 && uploadResponse.data?.url) {
imageUrl = uploadResponse.data.url;
} else {
throw new Error("이미지 업로드에 실패했습니다.");
}
}

const updateData = {
const success = await updateProfile(
{
name: data.name,
nickname: data.nickname,
phoneNumber: data.phone,
imageUrl,
};

const updateResponse = await axios.patch("/api/users/me", updateData);

if (updateResponse.status === 200) {
await refetch(); // React Query 캐시 갱신
toast.success("프로필이 성공적으로 수정되었습니다.");
onClose();
} else {
throw new Error("프로필 업데이트에 실패했습니다.");
}
} catch (error) {
if (axios.isAxiosError(error)) {
const errorMessage = error.response?.data?.message || "프로필 수정에 실패했습니다.";
console.error("Profile update error:", {
status: error.response?.status,
data: error.response?.data,
});
toast.error(errorMessage);
} else {
console.error("Unexpected error:", error);
toast.error("프로필 수정 중 오류가 발생했습니다.");
}
} finally {
setIsSubmitting(false);
},
selectedFile
);

if (success) {
onClose();
}
};

Expand Down Expand Up @@ -201,7 +159,7 @@ const EditMyProfileModal = ({ isOpen, onClose, className }: EditMyProfileModalPr
variant="white"
size="w-[327px] h-[54px] md:w-[640px] md:h-[64px]"
wrapperClassName="px-[14px] md:px-[20px]"
disabled={isSubmitting}
disabled={isUpdating}
errormessage={errors[field.name]?.message}
/>
</div>
Expand All @@ -213,17 +171,17 @@ const EditMyProfileModal = ({ isOpen, onClose, className }: EditMyProfileModalPr
<button
type="button"
onClick={onClose}
disabled={isSubmitting}
disabled={isUpdating}
className="text-grayscale-700 w-[158px] rounded-md border border-grayscale-300 bg-white px-4 py-2 text-sm font-semibold transition-colors hover:bg-grayscale-100 md:w-[314px] md:text-base"
>
취소
</button>
<button
type="submit"
disabled={isSubmitting}
disabled={isUpdating}
className="w-[158px] rounded-md bg-primary-orange-300 px-4 py-2 text-sm font-semibold text-white transition-colors hover:bg-primary-orange-200 md:w-[314px] md:text-base"
>
{isSubmitting ? "수정 중..." : "수정하기"}
{isUpdating ? "수정 중..." : "수정하기"}
</button>
</div>
</form>
Expand Down
Loading
Loading