All files / src/hooks/use-auth/use-auth-login index.ts

21.35% Statements 22/103
100% Branches 0/0
0% Functions 0/4
21.35% Lines 22/103

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 1041x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                 1x 1x                     1x 1x 1x                     1x 1x                                                                                                            
'use client';
 
import { useRouter, useSearchParams } from 'next/navigation';
 
import { useCallback, useState } from 'react';
 
import axios, { AxiosError } from 'axios';
import Cookies from 'js-cookie';
 
import { API } from '@/api';
import { useAuth } from '@/providers';
import { LoginRequest } from '@/types/service/auth';
import { CommonErrorResponse } from '@/types/service/common';
 
const normalizePath = (raw: string | null) => {
  const value = (raw ?? '').trim();

  if (!value) return '/';

  if (value.startsWith('//') || value.includes('://')) return '/';

  return value.startsWith('/') ? value : `/${value}`;
};
 
const getLoginErrorMessage = (problem: CommonErrorResponse) => {
  if (
    problem.errorCode === 'USER_NOT_FOUND' ||
    problem.errorCode === 'INVALID_PASSWORD_VALUE' ||
    problem.errorCode === 'INVALID_INPUT_VALUE'
  ) {
    return '이메일 또는 비밀번호가 일치하지 않습니다.';
  }

  return '로그인에 실패했습니다.';
};
 
// 📜 proxy 설정 후 삭제
const isCommonErrorResponse = (e: unknown): e is CommonErrorResponse => {
  if (!e || typeof e !== 'object') return false;

  const obj = e as Record<string, unknown>;
  return (
    typeof obj.status === 'number' &&
    typeof obj.detail === 'string' &&
    typeof obj.errorCode === 'string' &&
    typeof obj.instance === 'string'
  );
};
 
export const useLogin = () => {
  const router = useRouter();
  const searchParams = useSearchParams();

  const [loginError, setLoginError] = useState<string | null>(null);
  const clearLoginError = useCallback(() => setLoginError(null), []);

  const { setIsAuthenticated } = useAuth();

  const handleLogin = async (payload: LoginRequest, formApi: { reset: () => void }) => {
    setLoginError(null);

    try {
      const result = await API.authService.login(payload);
      // 📜 추후 삭제
      console.log('login success:', result);

      Cookies.set('userId', String(result.user.userId), {
        path: '/',
        sameSite: 'lax',
        secure: process.env.NODE_ENV === 'production',
      });

      formApi.reset();

      setIsAuthenticated(true);

      const nextPath = normalizePath(searchParams.get('path'));
      router.replace(nextPath);
    } catch (error) {
      if (isCommonErrorResponse(error)) {
        console.error('[LOGIN ERROR]', error.errorCode, error.detail);
        setLoginError(getLoginErrorMessage(error));
        return;
      }

      if (axios.isAxiosError(error)) {
        const axiosError = error as AxiosError<CommonErrorResponse>;
        const problem = axiosError.response?.data;

        if (problem) {
          console.error('[LOGIN ERROR]', problem.errorCode, problem.detail);
          setLoginError(getLoginErrorMessage(problem));
        }
        return;
      }

      console.error(error);
      setLoginError('알 수 없는 오류가 발생했습니다.');
    }
  };

  return { handleLogin, loginError, clearLoginError };
};