본문 바로가기
카테고리 없음

by 두잇건강 2025. 8. 19.
반응형

3) 컴포저블: 아이디 중복 검사 로직 (composables/useUsernameCheck.js)

// composables/useUsernameCheck.js
import { ref, watch, computed } from 'vue';
import { debounce } from '@/utils/debounce';
import { checkUsernameExists } from '@/api/auth';

const USERNAME_REGEX = /^[a-z0-9_]{4,16}$/;

export function useUsernameCheck() {
  const username = ref('');
  const isFormatValid = ref(null);   // true | false | null
  const isChecking = ref(false);
  const isDuplicate = ref(null);     // true | false | null
  const error = ref(null);

  const validateFormat = (v) => {
    if (!v) return null;
    return USERNAME_REGEX.test(v);
  };

  const doCheck = async (v) => {
    const valid = validateFormat(v);
    isFormatValid.value = valid;
    isDuplicate.value = null;
    error.value = null;

    if (!v || !valid) return;

    try {
      isChecking.value = true;
      const exists = await checkUsernameExists(v);
      isDuplicate.value = exists;
    } catch (e) {
      error.value = '아이디 중복 확인 중 오류가 발생했습니다. 잠시 후 다시 시도해주세요.';
      isDuplicate.value = null;
    } finally {
      isChecking.value = false;
    }
  };

  const debouncedCheck = debounce(doCheck, 400);

  watch(username, (v) => {
    if (!v) {
      isFormatValid.value = null;
      isDuplicate.value = null;
      error.value = null;
      return;
    }
    debouncedCheck(v);
  });

  const checkNow = () => doCheck(username.value);

  const canSubmit = computed(() => {
    return (
      isFormatValid.value === true &&
      isDuplicate.value === false &&
      !isChecking.value &&
      !error.value
    );
  });

  return {
    username,
    isFormatValid,
    isChecking,
    isDuplicate,
    error,
    checkNow,
    canSubmit,
  };
}
반응형