page.tsx 3.8 KB

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