page.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. 'use client';
  2. import './style.scss';
  3. import Link from 'next/link';
  4. import { useState, useEffect, useCallback, useRef } from 'react';
  5. import { useMemberContext } from '@/contexts/memberProvider';
  6. import { useConfigContext } from '@/contexts/configProvider';
  7. import { ChangeEmailRequest } from '@/dtos/request/account';
  8. import { fetchApi, throwError } from '@/lib/utils/client';
  9. import Loading from '@/app/component/Loading';
  10. export default function ChangeEmail()
  11. {
  12. const config = useConfigContext();
  13. const { member } = useMemberContext();
  14. const [error, setError] = useState<string>('');
  15. const [isComplete, setComplete] = useState<boolean>(false);
  16. const [loading, setLoading] = useState<boolean>(false);
  17. const [newEmail, setNewEmail] = useState<string>('');
  18. const newEmailRef = useRef<HTMLInputElement>(null);
  19. useEffect(() => {
  20. if (error) {
  21. alert(error);
  22. setError('');
  23. }
  24. }, [error]);
  25. // 이메일 변경 요청
  26. const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
  27. e.preventDefault();
  28. if (!member) {
  29. return;
  30. }
  31. if (!newEmail) {
  32. newEmailRef.current?.focus();
  33. return setError('변경하실 이메일을 입력하세요.');
  34. }
  35. setLoading(true);
  36. fetchApi('/api/mypage/email', {
  37. method: 'POST',
  38. body: { NewEmail: newEmail } as ChangeEmailRequest
  39. }).then((res) => {
  40. throwError(res);
  41. setComplete(true);
  42. }).catch(err => {
  43. setError(err.message);
  44. }).finally(() => {
  45. setLoading(false);
  46. });
  47. }
  48. const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
  49. setNewEmail(e.target.value.trim());
  50. }, []);
  51. const refresh = () => location.reload();
  52. return (
  53. <>
  54. <div id="changeEmail">
  55. { loading && <Loading /> }
  56. {!isComplete ?
  57. <>
  58. <h1>이메일 변경</h1>
  59. <form method="post" acceptCharset="utf-8" autoComplete="off" onSubmit={handleSubmit}>
  60. <table className="table-auto max-xl:w-full lg:w-[600px]">
  61. <caption>
  62. 새 이메일 주소를 입력하고 &quot;확인&quot; 버튼을 누릅니다.<br />
  63. 인증 메일이 도착하시면 내용을 확인하신 후 본문에 있는 링크를 클릭해주세요.
  64. </caption>
  65. <colgroup>
  66. <col width="30%"/>
  67. <col width="60%"/>
  68. <col width="10%"/>
  69. </colgroup>
  70. <tbody>
  71. <tr>
  72. <th>현재 이메일</th>
  73. <td>{member?.email}</td>
  74. <td>&nbsp;</td>
  75. </tr>
  76. <tr>
  77. <th>새 이메일</th>
  78. <td>
  79. <input type="email" name="new_email" id="newEmail" ref={newEmailRef} value={newEmail} placeholder="변경할 이메일 주소" maxLength={60} autoFocus autoComplete="off" onChange={handleChange} />
  80. </td>
  81. <td>&nbsp;</td>
  82. </tr>
  83. </tbody>
  84. <tfoot>
  85. <tr>
  86. <td colSpan={3}>
  87. <div className="flex justify-center gap-2">
  88. <button type="submit" className="btn btn-submit">확인</button>
  89. <Link href="/profile" className="btn btn-default">취소</Link>
  90. </div>
  91. </td>
  92. </tr>
  93. </tfoot>
  94. </table>
  95. </form>
  96. <br />
  97. <dl className="max-xl:w-full lg:w-[600px]">
  98. <dt>등록할 수 없는 이메일 주소</dt>
  99. <dd>
  100. <ol>
  101. <li>전 세계 인터넷 통신 표준 RFC(Request for Comments)를 준수하지 않는 전자 메일 주소</li>
  102. <li>회사에서 지정한 사용할 수 없는 문자(공백 및 더블바이트 문자)</li>
  103. <li>전자 메일 계정 부분에서 반자 영숫자, 반자 기호 _(밑줄), . (점) 및 -(하이픈) 이외의 문자가 사용됩니다.</li>
  104. {config.account.changeEmailDay > 0 && <li>이메일 변경 주기는 {config.account.changeEmailDay}일입니다.</li>}
  105. </ol>
  106. </dd>
  107. </dl>
  108. </>
  109. :
  110. <>
  111. <h1>인증 이메일 발송</h1>
  112. <blockquote>
  113. <strong>{newEmail} 으로 인증 이메일이 발송되었습니다.</strong><br />
  114. 메일이 도착하면 내용을 확인하신 후 본문에 있는 링크를 클릭해 주세요.<br />
  115. 몇 분 이내에 메일이 도착하지 않는 경우 등록 된 메일 주소 및 수신 거부 설정을 확인한 후
  116. 처음부터 다시 시도해 주십시오.
  117. </blockquote>
  118. <br />
  119. <button className="btn btn-default" onClick={refresh}>다시 시도하기</button>
  120. </>
  121. }
  122. </div>
  123. </>
  124. );
  125. }