'use client'; import './style.scss'; import Link from 'next/link'; import { useState, useEffect, useRef } from 'react'; import { fetchApi } from '@/lib/utils/client'; import useAuth from '@/hooks/useAuth'; import useErrorAlert from '@/hooks/useErrorAlert'; import Loading from '@/app/component/Loading'; import NavTabs from '../navTabs'; const CODE_EXPIRATION_SECONDS = 600; // 10분 export default function Withdraw() { const { member, logout } = useAuth(); const { setError } = useErrorAlert(); const [loading, setLoading] = useState(false); const [isComplete, setComplete] = useState(false); const [agree, setAgree] = useState(false); const [step, setStep] = useState<1|2>(1); const [code, setCode] = useState(''); const [remaining, setRemaining] = useState(0); const codeRef = useRef(null); // 카운트다운 useEffect(() => { if (step !== 2 || remaining <= 0) { return; } const timer = setInterval(() => { setRemaining(prev => Math.max(0, prev - 1)); }, 1000); return () => clearInterval(timer); }, [step, remaining]); const handleRequestCode = async () => { if (!member) { return; } if (!agree) { alert('탈퇴에 동의해주세요.'); return; } setLoading(true); try { await fetchApi('/api/mypage/withdraw/request-code', { method: 'POST' }); setStep(2); setRemaining(CODE_EXPIRATION_SECONDS); setCode(''); setTimeout(() => codeRef.current?.focus(), 100); } catch (err) { if (err instanceof Error) { setError(err.message); } } finally { setLoading(false); } }; const handleResendCode = async () => { setLoading(true); try { await fetchApi('/api/mypage/withdraw/request-code', { method: 'POST' }); setRemaining(CODE_EXPIRATION_SECONDS); setCode(''); alert('인증번호를 재발송했습니다. 메일함을 확인해주세요.'); } catch (err) { if (err instanceof Error) { setError(err.message); } } finally { setLoading(false); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!member) { return; } if (!code) { alert('인증번호를 입력해주세요.'); codeRef.current?.focus(); return; } if (!confirm('정말 탈퇴하시겠습니까?')) { return; } setLoading(true); try { await fetchApi('/api/mypage/withdraw', { method: 'POST', body: { code } }); setComplete(true); } catch (err) { if (err instanceof Error) { setError(err.message); } } finally { setLoading(false); } }; useEffect(() => { if (isComplete) { alert('탈퇴가 완료되었습니다.'); setComplete(false); // 탈퇴 후 자동 로그아웃: httpOnly 쿠키(accessToken/refreshToken) 클리어 + AuthContext 리셋 + 홈 이동 logout(); } }, [isComplete]); const formatRemaining = (sec: number) => { const m = Math.floor(sec / 60).toString().padStart(2, '0'); const s = (sec % 60).toString().padStart(2, '0'); return `${m}:${s}`; }; if (!member) { return null; } return ( <>
{ loading && }

회원탈퇴

{step === 1 && (
사용하고 계신 계정({member.email})은 탈퇴할 경우 재사용 및 복구가 불가능합니다. 탈퇴한 계정은 본인과 타인 모두 재사용 및 복구가 불가하오니 신중하게 선택하시기 바랍니다.

추가 회원가입은 탈퇴일로부터 90일 후에 가능합니다. 탈퇴 후 회원정보와 주요 서비스 이용기록은 모두 삭제되며, 삭제된 데이터는 복구되지 않습니다.

삭제되는 내용을 확인하시고 필요한 데이터는 미리 백업을 해주세요. 탈퇴 후 게시판, 댓글에 등록한 게시물은 삭제되지 않고 유지됩니다.

본인 확인을 위해 가입하신 이메일({member.email})로 인증번호를 발송합니다.
취소
)} {step === 2 && (
{member.email} 으로 인증번호를 발송했습니다. 메일함을 확인하시고 아래에 6자리 코드를 입력해주세요.

이 코드는 10분간 유효하며, 만료되면 재발송 버튼을 눌러주세요.
setCode(e.target.value.replace(/[^0-9]/g, '').slice(0, 6))} maxLength={6} inputMode="numeric" pattern="[0-9]{6}" placeholder="6자리 숫자" autoFocus /> {remaining > 0 ? formatRemaining(remaining) : '만료됨'}
)}
); }