"use client"; import Link from "next/link"; import { useEffect, useState, FormEvent } from "react"; import { useRouter } from "next/navigation"; import { useAppLocale } from "@/features/i18n/LocaleProvider"; import { getMyPageMessages } from "@/features/i18n/messages/mypage"; // 마이페이지(/mypage) 화면 컴포넌트 // - 현재 로그인 유저 정보를 /api/auth/me 에서 불러와 표시한다. // - 비로그인(401) 응답 시 /login 으로 리다이렉트한다. // - 비밀번호 변경 및 이메일 변경 폼을 통해 각각 /api/auth/change-password, /api/auth/change-email 를 호출한다. interface AuthUser { id: string; email: string; tokenVersion?: number; emailVerified?: boolean; } export default function MyPage() { const router = useRouter(); const locale = useAppLocale(); const m = getMyPageMessages(locale); // 현재 로그인된 유저 정보와 로딩/에러 상태를 관리한다. const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); // 비밀번호/이메일 변경 폼 상태 const [currentPassword, setCurrentPassword] = useState(""); const [newPassword, setNewPassword] = useState(""); const [newPasswordConfirm, setNewPasswordConfirm] = useState(""); const [changePasswordMessage, setChangePasswordMessage] = useState(null); const [newEmail, setNewEmail] = useState(""); const [emailChangePassword, setEmailChangePassword] = useState(""); const [changeEmailMessage, setChangeEmailMessage] = useState(null); // 이메일 인증 메일 재발송 상태 const [verificationMessage, setVerificationMessage] = useState(null); const [verificationLoading, setVerificationLoading] = useState(false); // 마운트 시 /api/auth/me 를 호출해 인증 상태와 유저 정보를 확인한다. useEffect(() => { let cancelled = false; const load = async () => { try { setLoading(true); setError(null); const res = await fetch("/api/auth/me"); if (cancelled) return; if (res.status === 401) { // 비로그인 상태이므로 로그인 페이지로 보낸다. router.push("/login"); return; } if (!res.ok) { setError(m.loadError); return; } const data = (await res.json()) as AuthUser; setUser(data); } catch { if (!cancelled) { setError(m.loadError); } } finally { if (!cancelled) { setLoading(false); } } }; void load(); return () => { cancelled = true; }; }, [router]); const handleSubmitChangePassword = async (event: FormEvent) => { event.preventDefault(); setChangePasswordMessage(null); if (!currentPassword || !newPassword || !newPasswordConfirm) { setChangePasswordMessage(m.changePasswordErrorRequired); return; } if (newPassword !== newPasswordConfirm) { setChangePasswordMessage(m.changePasswordErrorMismatch); return; } try { const res = await fetch("/api/auth/change-password", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ currentPassword, newPassword }), }); const data = await res.json().catch(() => null as any); if (!res.ok) { setChangePasswordMessage(data?.message || m.changePasswordErrorNetwork); return; } setChangePasswordMessage(data?.message || m.changePasswordSuccess); setCurrentPassword(""); setNewPassword(""); setNewPasswordConfirm(""); } catch { setChangePasswordMessage(m.changePasswordErrorNetwork); } }; const handleRequestEmailVerification = async () => { // 이메일 인증 메일 전송 요청 상태를 초기화한다. setVerificationMessage(null); setVerificationLoading(true); try { const res = await fetch("/api/auth/request-email-verification", { method: "POST", }); const data = await res.json().catch(() => null as any); if (!res.ok) { setVerificationMessage(data?.message || m.emailVerificationError); return; } setVerificationMessage(data?.message || m.emailVerificationSuccess); } catch { setVerificationMessage(m.emailVerificationError); } finally { setVerificationLoading(false); } }; const handleSubmitChangeEmail = async (event: FormEvent) => { event.preventDefault(); setChangeEmailMessage(null); if (!newEmail || !emailChangePassword) { setChangeEmailMessage(m.changeEmailErrorRequired); return; } try { const res = await fetch("/api/auth/change-email", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ newEmail, password: emailChangePassword }), }); const data = await res.json().catch(() => null as any); if (!res.ok) { setChangeEmailMessage(data?.message || m.changeEmailErrorNetwork); return; } setChangeEmailMessage(data?.message || m.changeEmailSuccess); setNewEmail(""); setEmailChangePassword(""); // 응답에 새로운 이메일이 있으면 프로필에도 반영한다. if (data?.email && user) { setUser({ ...user, email: data.email }); } } catch { setChangeEmailMessage(m.changeEmailErrorNetwork); } }; return (

{m.title}

{m.description}

{m.backToDashboardLabel}
{error && (

{error}

)} {loading && !user && !error && (

{m.loadingText}

)} {user && (

{m.profileSectionTitle}

{m.profileEmailLabel} {user.email}

{m.profileUserIdLabel} {user.id}

{user.emailVerified && (

{m.emailVerifiedBadge}

)} {!user.emailVerified && ( <>

{m.emailVerificationNotice}

{verificationMessage && (

{verificationMessage}

)} )}

{m.changePasswordTitle}

setCurrentPassword(e.target.value)} className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-xs text-slate-900 focus:outline-none focus:ring-1 focus:ring-sky-500 dark:border-slate-700 dark:bg-slate-950 dark:text-slate-50" />
setNewPassword(e.target.value)} className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-xs text-slate-900 focus:outline-none focus:ring-1 focus:ring-sky-500 dark:border-slate-700 dark:bg-slate-950 dark:text-slate-50" minLength={8} />
setNewPasswordConfirm(e.target.value)} className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-xs text-slate-900 focus:outline-none focus:ring-1 focus:ring-sky-500 dark:border-slate-700 dark:bg-slate-950 dark:text-slate-50" minLength={8} />
{changePasswordMessage && (

{changePasswordMessage}

)}

{m.changeEmailTitle}

setNewEmail(e.target.value)} className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-xs text-slate-900 focus:outline-none focus:ring-1 focus:ring-sky-500 dark:border-slate-700 dark:bg-slate-950 dark:text-slate-50" />
setEmailChangePassword(e.target.value)} className="w-full rounded border border-slate-300 bg-white px-2 py-1 text-xs text-slate-900 focus:outline-none focus:ring-1 focus:ring-sky-500 dark:border-slate-700 dark:bg-slate-950 dark:text-slate-50" minLength={8} />
{changeEmailMessage && (

{changeEmailMessage}

)}
)}
); }