330 lines
11 KiB
Vue
330 lines
11 KiB
Vue
<template>
|
|
<form @submit.prevent="handleSubmit">
|
|
<div class="text-center">
|
|
<label
|
|
for="profilePic"
|
|
class="rounded-circle m-auto ui-bg-cover position-relative cursor-pointer"
|
|
id="profileLabel"
|
|
style="width: 100px; height: 100px; background-image: url(public/img/avatars/default-Profile.jpg); background-repeat: no-repeat;"
|
|
>
|
|
</label>
|
|
|
|
<span class="link-danger position-absolute">*</span>
|
|
<input type="file" id="profilePic" class="d-none" @change="profileUpload" />
|
|
<span v-if="profilerr" class="invalid-feedback d-block">{{ profilerr }}</span>
|
|
</div>
|
|
|
|
<div class="col-xl-12">
|
|
<UserFormInput
|
|
title="아이디"
|
|
name="id"
|
|
:isEssential="true"
|
|
:is-alert="idAlert"
|
|
:useInputGroup="true"
|
|
@update:data="id = $event"
|
|
@update:alert="idAlert = $event"
|
|
@blur="checkIdDuplicate"
|
|
:value="id"
|
|
/>
|
|
<span v-if="idError" class="invalid-feedback d-block">{{ idError }}</span>
|
|
|
|
<UserFormInput
|
|
title="비밀번호"
|
|
name="pw"
|
|
type="password"
|
|
:isEssential="true"
|
|
:is-alert="passwordAlert"
|
|
@update:data="password = $event"
|
|
@update:alert="passwordAlert = $event"
|
|
:value="password"
|
|
/>
|
|
|
|
<UserFormInput
|
|
title="비밀번호 확인"
|
|
name="pwch"
|
|
type="password"
|
|
:isEssential="true"
|
|
:is-alert="passwordcheckAlert"
|
|
@update:data="passwordcheck = $event"
|
|
@update:alert="passwordcheckAlert = $event"
|
|
@blur="checkPw"
|
|
:value="passwordcheck"
|
|
/>
|
|
<span v-if="passwordcheckError" class="invalid-feedback d-block">{{ passwordcheckError }}</span>
|
|
|
|
<FormSelect
|
|
title="비밀번호 힌트"
|
|
name="pwhint"
|
|
:is-essential="true"
|
|
:is-row="false"
|
|
:is-label="true"
|
|
:is-common="true"
|
|
:data="pwhintList"
|
|
@update:data="pwhint = $event"
|
|
/>
|
|
|
|
<UserFormInput
|
|
title="답변"
|
|
name="pwhintRes"
|
|
:is-essential="true"
|
|
:is-alert="pwhintResAlert"
|
|
@update:data="pwhintRes = $event"
|
|
@update:alert="pwhintResAlert = $event"
|
|
:value="pwhintRes"
|
|
/>
|
|
|
|
<div class="d-flex">
|
|
<UserFormInput
|
|
title="이름"
|
|
name="name"
|
|
:is-essential="true"
|
|
:is-alert="nameAlert"
|
|
@update:data="name = $event"
|
|
@update:alert="nameAlert = $event"
|
|
:value="name"
|
|
class="me-2 w-50"
|
|
/>
|
|
|
|
<FormSelect
|
|
title="컬러"
|
|
name="color"
|
|
:is-essential="true"
|
|
:is-row="false"
|
|
:is-label="true"
|
|
:is-common="true"
|
|
:data="colorList"
|
|
@update:data="color = $event"
|
|
class="w-50"
|
|
/>
|
|
</div>
|
|
|
|
<div class="d-flex">
|
|
<UserFormInput
|
|
title="생년월일"
|
|
name="birth"
|
|
:type="'date'"
|
|
:is-essential="true"
|
|
:is-alert="birthAlert"
|
|
@update:data="birth = $event"
|
|
@update:alert="birthAlert = $event"
|
|
:value="birth"
|
|
class="me-2 w-50"
|
|
/>
|
|
|
|
<FormSelect
|
|
title="MBTI"
|
|
name="mbti"
|
|
:is-essential="true"
|
|
:is-row="false"
|
|
:is-label="true"
|
|
:is-common="true"
|
|
:data="mbtiList"
|
|
@update:data="mbti = $event"
|
|
class="w-50"
|
|
/>
|
|
</div>
|
|
|
|
<ArrInput
|
|
title="주소"
|
|
name="address"
|
|
:isEssential="true"
|
|
:is-alert="addressAlert"
|
|
@update:data="handleAddressUpdate"
|
|
@update:alert="addressAlert = $event"
|
|
:value="address"
|
|
/>
|
|
|
|
<UserFormInput
|
|
title="휴대전화"
|
|
name="phone"
|
|
:isEssential="true"
|
|
:is-alert="phoneAlert"
|
|
@update:data="phone = $event"
|
|
@update:alert="phoneAlert = $event"
|
|
:maxlength="11"
|
|
:value="phone"
|
|
/>
|
|
|
|
<div class="d-flex mt-5">
|
|
<RouterLink type="button" class="btn btn-secondary me-2 w-50" to="/login">취소</RouterLink>
|
|
<button type="submit" class="btn btn-primary w-50">등록신청</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref } from 'vue';
|
|
import $api from '@api';
|
|
import commonApi from '@/common/commonApi'
|
|
import UserFormInput from '@c/input/UserFormInput.vue';
|
|
import FormSelect from '@c/input/FormSelect.vue';
|
|
import ArrInput from '@c/input/ArrInput.vue';
|
|
import { fileMsg } from '@/common/msgEnum';
|
|
import { useRouter } from 'vue-router';
|
|
import { useToastStore } from '@s/toastStore';
|
|
|
|
const router = useRouter();
|
|
|
|
const profile = ref(null);
|
|
const profilerr = ref('');
|
|
|
|
const id = ref('');
|
|
const idError = ref('');
|
|
const password = ref('');
|
|
const passwordcheck = ref('');
|
|
const passwordcheckError = ref('');
|
|
const pwhintRes = ref('');
|
|
const name = ref('');
|
|
const birth = ref('');
|
|
const address = ref('');
|
|
const detailAddress = ref('');
|
|
const postcode = ref(''); // 우편번호
|
|
const phone = ref('');
|
|
const color = ref(''); // 선택된 color
|
|
const mbti = ref(''); // 선택된 MBTI
|
|
const pwhint = ref(''); // 선택된 pwhint
|
|
|
|
const profilAlert = ref(false);
|
|
const idAlert = ref(false);
|
|
const idErrorAlert = ref(false);
|
|
const passwordAlert = ref(false);
|
|
const passwordcheckAlert = ref(false);
|
|
const passwordcheckErrorAlert = ref(false); // 비밀번호 확인 오류 메시지
|
|
const pwhintResAlert = ref(false);
|
|
const nameAlert = ref(false);
|
|
const birthAlert = ref(false);
|
|
const addressAlert = ref(false);
|
|
const phoneAlert = ref(false);
|
|
|
|
const toastStore = useToastStore();
|
|
|
|
|
|
// 프로필 체크
|
|
const profileValid = (size, type) => {
|
|
const maxSize = 5 * 1024 * 1024;
|
|
const validTypes = ['image/jpeg', 'image/png'];
|
|
|
|
// 용량
|
|
if (size > maxSize) {
|
|
profilerr.value = fileMsg.FileMaxSizeMsg;
|
|
return false;
|
|
}
|
|
|
|
// 파일 타입
|
|
if (!validTypes.includes(type)) {
|
|
profilerr.value = fileMsg.FileNotTypeMsg;
|
|
return false;
|
|
}
|
|
profilerr.value = '';
|
|
return true;
|
|
};
|
|
|
|
// 파일 업로드 시 미리보기
|
|
const profileUpload = e => {
|
|
const file = e.target.files[0];
|
|
const profileLabel = document.getElementById('profileLabel');
|
|
|
|
// 사이즈, 파일 타입 안 맞으면 기본 이미지
|
|
if (!profileValid(file.size, file.type)) {
|
|
e.target.value = '';
|
|
profileLabel.style.backgroundImage = 'url("public/img/avatars/default-Profile.jpg")';
|
|
return false;
|
|
}
|
|
|
|
const profilePic = e.target;
|
|
const url = URL.createObjectURL(profilePic.files[0]);
|
|
profileLabel.style.backgroundImage = `url(${url})`;
|
|
profile.value = file;
|
|
};
|
|
|
|
// 아이디 중복체크
|
|
const checkIdDuplicate = async () => {
|
|
const response = await $api.get(`/user/checkId?memberIds=${id.value}`);
|
|
|
|
if (!response.data.data) {
|
|
idErrorAlert.value = true;
|
|
idError.value = '이미 사용 중인 아이디입니다.';
|
|
} else {
|
|
idErrorAlert.value = false;
|
|
idError.value = '';
|
|
}
|
|
};
|
|
|
|
// 컬러, mbti, 비밀번호 힌트 목록 불러오기
|
|
const { colorList, mbtiList, pwhintList } = commonApi({
|
|
loadColor: true, colorType: 'YON',
|
|
loadMbti: true,
|
|
loadPwhint: true,
|
|
});
|
|
|
|
// 주소 업데이트 핸들러
|
|
const handleAddressUpdate = (addressData) => {
|
|
address.value = addressData.address;
|
|
detailAddress.value = addressData.detailAddress;
|
|
postcode.value = addressData.postcode; // 우편번호
|
|
};
|
|
|
|
// 비밀번호 확인 체크
|
|
const checkPw = async () => {
|
|
if (password.value !== passwordcheck.value) {
|
|
passwordcheckError.value = '비밀번호가 일치하지 않습니다.';
|
|
passwordcheckErrorAlert.value = true;
|
|
} else {
|
|
passwordcheckError.value = '';
|
|
passwordcheckErrorAlert.value = false;
|
|
}
|
|
};
|
|
|
|
// 회원가입
|
|
const handleSubmit = async () => {
|
|
|
|
idAlert.value = id.value.trim() === '';
|
|
passwordAlert.value = password.value.trim() === '';
|
|
passwordcheckAlert.value = passwordcheck.value.trim() === '';
|
|
pwhintResAlert.value = pwhintRes.value.trim() === '';
|
|
nameAlert.value = name.value.trim() === '';
|
|
birthAlert.value = birth.value.trim() === '';
|
|
addressAlert.value = address.value.trim() === '';
|
|
phoneAlert.value = phone.value.trim() === '';
|
|
|
|
// 프로필 이미지 체크
|
|
if (!profile.value) {
|
|
profilerr.value = '프로필 이미지를 선택해주세요.';
|
|
profilAlert.value = true;
|
|
} else {
|
|
profilerr.value = '';
|
|
profilAlert.value = false;
|
|
}
|
|
|
|
if (profilAlert.value || idAlert.value || idErrorAlert.value || passwordAlert.value || passwordcheckAlert.value ||
|
|
passwordcheckErrorAlert.value || pwhintResAlert.value || nameAlert.value || birthAlert.value || addressAlert.value || phoneAlert.value) {
|
|
return;
|
|
}
|
|
|
|
const formData = new FormData();
|
|
formData.append('memberIds', id.value);
|
|
formData.append('memberPwd', password.value);
|
|
formData.append('memberPwh', pwhint.value);
|
|
formData.append('memberPwr', pwhintRes.value);
|
|
formData.append('memberNam', name.value);
|
|
formData.append('memberArr', address.value);
|
|
formData.append('memberDtl', detailAddress.value);
|
|
formData.append('memberZip', postcode.value);
|
|
formData.append('memberBth', birth.value);
|
|
formData.append('memberTel', phone.value);
|
|
formData.append('memberCol', color.value);
|
|
formData.append('memberMbt', mbti.value);
|
|
formData.append('memberPrf', profile.value);
|
|
|
|
const response = await $api.post('/user/join', formData, { isFormData : true });
|
|
|
|
if (response.status === 200) {
|
|
toastStore.onToast('등록신청이 완료되었습니다. 관리자 승인 후 이용가능합니다.', 's');
|
|
router.push('/login');
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style></style>
|