page.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. 'use client';
  2. import './style.scss';
  3. import Link from 'next/link';
  4. import { useState, useCallback, useRef } from 'react';
  5. import { useConfigContext } from '@/contexts/configProvider';
  6. import { useMemberContext } from '@/contexts/memberProvider';
  7. import useErrorAlert from '@/hooks/useErrorAlert';
  8. import { ChangeNameRequest } from '@/types/request/account';
  9. import { fetchApi, throwError } from '@/lib/utils/client';
  10. import Loading from '@/app/component/Loading';
  11. export default function ChangeName()
  12. {
  13. const config = useConfigContext();
  14. const { member, setMember } = useMemberContext();
  15. const { setError } = useErrorAlert();
  16. const [loading, setLoading] = useState<boolean>(false);
  17. const [newName, setNewName] = useState<string>('');
  18. const newNameRef = useRef<HTMLInputElement>(null);
  19. const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
  20. e.preventDefault();
  21. if (!member) {
  22. return;
  23. }
  24. if (!newName) {
  25. newNameRef.current?.focus();
  26. return setError('별명을 입력하세요.');
  27. }
  28. setLoading(true);
  29. fetchApi('/api/mypage/name', {
  30. method: 'POST',
  31. body: { Name: newName } as ChangeNameRequest
  32. }).then((res) => {
  33. throwError(res);
  34. member.name = newName;
  35. setMember(member);
  36. localStorage.setItem('member', JSON.stringify(member));
  37. alert("별명이 변경되었습니다.");
  38. }).catch(err => {
  39. setError(err.message);
  40. }).finally(() => {
  41. setLoading(false);
  42. setNewName('');
  43. });
  44. }
  45. const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
  46. setNewName(e.target.value.trim());
  47. }, []);
  48. const handleDelete = async () => {
  49. if (confirm("별명을 삭제하시겠습니까?")) {
  50. if (!member || !member.name) {
  51. return;
  52. }
  53. setLoading(true);
  54. fetchApi('/api/mypage/name', { method: 'DELETE' }).then((res) => {
  55. throwError(res);
  56. member.name = null;
  57. setMember(member);
  58. localStorage.setItem('member', JSON.stringify(member));
  59. alert("별명이 삭제되었습니다.");
  60. }).catch(err => {
  61. setError(err.message);
  62. }).finally(() => {
  63. setLoading(false);
  64. setNewName('');
  65. });
  66. }
  67. };
  68. return (
  69. <>
  70. <div id="changeName">
  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. <caption>
  76. 개성을 담아 별명을 지어보세요!<br />
  77. 일 간격으로 별명을 변경할 수 있습니다.
  78. </caption>
  79. <colgroup>
  80. <col width="30%"/>
  81. <col width="60%"/>
  82. <col width="10%"/>
  83. </colgroup>
  84. <tbody>
  85. <tr>
  86. <th>현재 별명</th>
  87. <td>{member?.name ?? '-'}</td>
  88. <td>&nbsp;</td>
  89. </tr>
  90. <tr>
  91. <th>새 별명</th>
  92. <td>
  93. <input type="text" name="new_name" id="newName" ref={newNameRef} value={newName} placeholder="변경할 별명" maxLength={20} autoFocus autoComplete="off" onChange={handleChange} />
  94. </td>
  95. <td>&nbsp;</td>
  96. </tr>
  97. </tbody>
  98. <tfoot>
  99. <tr>
  100. <td colSpan={3}>
  101. <div className="flex justify-center gap-2">
  102. <button type="submit" className="btn btn-submit">확인</button>
  103. { member?.name && (
  104. <button type="button" className="btn btn-delete" onClick={handleDelete}>삭제</button>
  105. )}
  106. <Link href="/profile" className="btn btn-default">취소</Link>
  107. </div>
  108. </td>
  109. </tr>
  110. </tfoot>
  111. </table>
  112. </form>
  113. <br />
  114. <dl className="max-xl:w-full lg:w-[600px]">
  115. <dt>등록할 수 없는 별명</dt>
  116. <dd>
  117. <ol>
  118. <li>별명은 최대 20자 이내로 입력 가능합니다.</li>
  119. <li>욕설 및 비속어는 별명으로 만들 수 없습니다.</li>
  120. <li>부적절한 별명은 별도의 고지 없이 변경될 수 있습니다.</li>
  121. {config.account.changeNameDay > 0 && <li>별명 변경 주기는 {config.account.changeNameDay}일입니다.</li>}
  122. </ol>
  123. </dd>
  124. </dl>
  125. </div>
  126. </>
  127. );
  128. }