view.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. 'use client';
  2. import './style.scss';
  3. import Link from 'next/link';
  4. import { Checkbox } from '@/components/ui/checkbox';
  5. import { useState, useEffect, useRef } from 'react';
  6. import { fetchLogin } from '@/lib/api/auth';
  7. import { throwError } from '@/lib/utils/client';
  8. import { LoginRequest } from '@/dtos/request/auth';
  9. import useAuth from '@/hooks/useAuth';
  10. export default function View()
  11. {
  12. const { login } = useAuth();
  13. const [error, setError] = useState<string>('');
  14. const [loading, setLoading] = useState<boolean>(false);
  15. const [email, setEmail] = useState<string>('');
  16. const [password, setPassword] = useState<string>('');
  17. const [rememberMe, setRememberMe] = useState<boolean>(false);
  18. const emailRef = useRef<HTMLInputElement>(null);
  19. const passwordRef = useRef<HTMLInputElement>(null);
  20. useEffect(() => {
  21. if (error) {
  22. alert(error);
  23. setError('');
  24. }
  25. }, [error]);
  26. const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
  27. e.preventDefault();
  28. try {
  29. if (email.length < 1) {
  30. emailRef.current?.focus();
  31. throw new Error('이메일을 입력하세요.');
  32. }
  33. if (password.length < 1) {
  34. passwordRef.current?.focus();
  35. throw new Error('비밀번호를 입력하세요.');
  36. }
  37. const res = await fetchLogin({
  38. Email: email,
  39. Password: password
  40. } as LoginRequest);
  41. if (!res.ok) {
  42. throwError(res);
  43. }
  44. login(rememberMe);
  45. } catch (err) {
  46. if (err instanceof Error) {
  47. setError(err.message);
  48. }
  49. } finally {
  50. setLoading(false);
  51. }
  52. }
  53. return (
  54. <>
  55. <div id="loginForm" className="row-start-2 flex flex-row flex-wrap gap-2">
  56. <fieldset className="grow">
  57. <legend>로그인</legend>
  58. <form id="fLogin" method="post" acceptCharset="utf-8" autoComplete="off" className="grid p-4" onSubmit={handleSubmit}>
  59. <label htmlFor="email">이메일</label>
  60. <input type="email" name="email" id="email" ref={emailRef} maxLength={30} onChange={e => setEmail(e.target.value)} autoComplete="off" />
  61. <label htmlFor="password">비밀번호</label>
  62. <input type="password" name="password" id="password" ref={passwordRef} maxLength={20} onChange={e => setPassword(e.target.value)} />
  63. <button type="submit" className="btn btn-submit" disabled={loading}>
  64. {loading ? "로그인 중..." : "로그인"}
  65. </button>
  66. <section className="mt-3 text-center">
  67. <Checkbox name="remember_me" id="rememberMe" checked={rememberMe} onCheckedChange={(checked) => setRememberMe(checked === true)} />
  68. <label htmlFor="rememberMe">로그인 상태 유지</label>
  69. </section>
  70. </form>
  71. </fieldset>
  72. <fieldset className="grow basis-1/2">
  73. <dl>
  74. <dt>아직 회원이 아니신가요?</dt>
  75. <dd>회원가입 한번으로 커뮤니티에 참여하세요!</dd>
  76. <dd>
  77. <Link href="/register">
  78. <small>></small> 회원가입
  79. </Link>
  80. </dd>
  81. </dl>
  82. <hr />
  83. <dl>
  84. <dt>비밀번호를 잊으셨나요?</dt>
  85. <dd>비밀번호를 깜박했다면 다시 설정할 수 있어요!</dd>
  86. <dd>
  87. <Link href="/forgot-password">
  88. <small>></small> 비밀번호 재설정
  89. </Link>
  90. </dd>
  91. </dl>
  92. </fieldset>
  93. </div>
  94. </>
  95. );
  96. }