page.tsx 3.8 KB

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