반응형
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,
};
}
반응형