page.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. 'use client';
  2. import './style.scss';
  3. import Link from 'next/link';
  4. import { useState, useEffect, useRef } from 'react';
  5. import { fetchApi, throwError } from '@/lib/utils/client';
  6. import useAuth from '@/hooks/useAuth';
  7. import Loading from '@/app/component/Loading';
  8. import NavTabs from '../navTabs';
  9. export default function Withdraw()
  10. {
  11. const { member } = useAuth();
  12. const [error, setError] = useState<string>('');
  13. const [loading, setLoading] = useState<boolean>(false);
  14. const [isComplete, setComplete] = useState<boolean>(false);
  15. const [agree, setAgree] = useState<boolean>(false);
  16. const [password, setPassword] = useState<string|null>('');
  17. const passwordRef = useRef<HTMLInputElement>(null);
  18. useEffect(() => {
  19. if (error) {
  20. alert(error);
  21. setError('');
  22. }
  23. }, [error]);
  24. const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
  25. e.preventDefault();
  26. if (!member) {
  27. return;
  28. }
  29. if (!password) {
  30. alert('비밀번호를 입력해주세요.');
  31. passwordRef.current?.focus();
  32. return;
  33. }
  34. if (!agree) {
  35. alert('탈퇴에 동의해주세요.');
  36. return;
  37. }
  38. if (confirm('정말 탈퇴하시겠습니까?')) {
  39. setLoading(true);
  40. fetchApi('/api/mypage/withdraw', {
  41. method: 'POST',
  42. body: { password }
  43. }).then((res) => {
  44. throwError(res);
  45. setComplete(true);
  46. localStorage.removeItem('member');
  47. }).catch(err => {
  48. setError(err.message);
  49. }).finally(() => {
  50. setLoading(false);
  51. });
  52. }
  53. }
  54. const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  55. setAgree(e.target.checked);
  56. };
  57. useEffect(() => {
  58. if (isComplete) {
  59. alert('탈퇴가 완료되었습니다.');
  60. setComplete(false);
  61. location.replace('/');
  62. }
  63. }, [isComplete]);
  64. if (!member) {
  65. return null;
  66. }
  67. return (
  68. <>
  69. <NavTabs />
  70. <div id="withdraw">
  71. { loading && <Loading /> }
  72. <h1>회원탈퇴</h1>
  73. <form method="post" acceptCharset="utf-8" autoComplete="off" onSubmit={handleSubmit}>
  74. <table className="table-auto max-xl:w-full lg:w-[600px]">
  75. <tbody>
  76. <tr>
  77. <th>
  78. <blockquote>
  79. 사용하고 계신 계정({member.email})은 탈퇴할 경우 재사용 및 복구가 불가능합니다.
  80. <ins>탈퇴한 계정은 본인과 타인 모두 재사용 및 복구가 불가하오니 신중하게 선택하시기 바랍니다.</ins>
  81. <br/>
  82. <br/>
  83. 추가 회원가입은 탈퇴일로부터 90일 후에 가능합니다.
  84. 탈퇴 후 회원정보와 주요 서비스 이용기록은 모두 삭제되며, 삭제된 데이터는 복구되지 않습니다.
  85. <br/>
  86. <br/>
  87. 삭제되는 내용을 확인하시고 필요한 데이터는 미리 백업을 해주세요.
  88. 탈퇴 후 게시판, 댓글은은 등록한 게시물은 삭제되지 않고 유지됩니다.
  89. <br/>
  90. <br/>
  91. 탈퇴하기 전에 이메일 인증이 필요합니다.
  92. </blockquote>
  93. </th>
  94. </tr>
  95. <tr>
  96. <td>
  97. <div className='flex flex-col sm:flex-row gap-2 justify-self-center items-center'>
  98. <label htmlFor="password" className='pe-2 shrink-0'>비밀번호</label>
  99. <input type="password" name="password" id="password" className="form-control w-full" ref={passwordRef} onChange={(e) => setPassword(e.target.value)} autoFocus />
  100. </div>
  101. </td>
  102. </tr>
  103. <tr>
  104. <td>
  105. <label>
  106. <input type="checkbox" name="agree" onChange={handleChange} />
  107. 위 내용으로 탈퇴에 동의합니다.
  108. </label>
  109. </td>
  110. </tr>
  111. </tbody>
  112. <tfoot>
  113. <tr>
  114. <td>
  115. <div className="flex justify-center gap-2">
  116. <button type="submit" className="btn btn-submit">확인</button>
  117. <Link href="/profile" className="btn btn-default">취소</Link>
  118. </div>
  119. </td>
  120. </tr>
  121. </tfoot>
  122. </table>
  123. </form>
  124. </div>
  125. </>
  126. );
  127. }