21.03.21 lamplight서비스 프로젝트(요청수정페이지,회원정보페이지,회원수정페이지까지 DB연계 완료)
2021. 3. 21. 20:23ㆍVue.js/Spring & Vue APP 프로젝트(프론트엔드)
#NOTE
-요청 수정 페이지[ㅇ]
-회원정보 수정 페이지[ㅇ]
-평점/후기페이지[...]
#주요소스코드
<OrderModifyPage.vue>
<template>
<TitleBar>요청서 수정 페이지</TitleBar>
<section class="section section-article-write-form-box px-2">
<div class="container mx-auto">
<div class="px-6 py-6 bg-white rounded-lg shadow-md">
<form v-if="globalShare.isLogined" v-on:submit.prevent="checkAndModifyOrder">
<FormRow title="제목">
<input ref="modifiedOrderTitleElRef" class="form-row-input" type="text" :value="state.order.title">
</FormRow>
<FormRow title="장례식장">
<input ref="modifiedOrderFuneralHomeElRef" class="form-row-input" type="text" :value="state.order.funeralHome">
</FormRow>
<FormRow title="옵션1">
<input ref="modifiedOrderOption1ElRef" class="form-row-input" type="text" :value="state.order.option1">
<select ref="modifiedOrderOption1qtyElRef" name="option1qty" class="form-row-input w-full rounded-sm" :value="state.order.option1qty">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</FormRow>
<FormRow title="옵션2">
<input ref="modifiedOrderOption2ElRef" class="form-row-input" type="text" :value="state.order.option2">
<select ref="modifiedOrderOption2qtyElRef" name="option1qty" class="form-row-input w-full rounded-sm" :value="state.order.option2qty">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</FormRow>
<FormRow title="옵션3">
<input ref="modifiedOrderOption3ElRef" class="form-row-input" type="text" :value="state.order.option3">
<select ref="modifiedOrderOption3qtyElRef" name="option1qty" class="form-row-input w-full rounded-sm" :value="state.order.option3qty">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</FormRow>
<FormRow title="옵션4">
<input ref="modifiedOrderOption4ElRef" class="form-row-input" type="text" :value="state.order.option4">
<select ref="modifiedOrderOption4qtyElRef" name="option1qty" class="form-row-input w-full rounded-sm" :value="state.order.option4qty">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</FormRow>
<FormRow title="옵션5">
<input ref="modifiedOrderOption5ElRef" class="form-row-input" type="text" :value="state.order.option5">
<select ref="modifiedOrderOption5qtyElRef" name="option1qty" class="form-row-input w-full rounded-sm" :value="state.order.option5qty">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</FormRow>
<FormRow title="추가 요청 사항">
<textarea ref="modifiedOrderBodyElRef" class="form-row-input" :value="state.order.body"></textarea>
</FormRow>
<FormRow title="완료">
<div class="btns">
<input type="submit" value="완료" class="btn-primary" />
</div>
</FormRow>
</form>
<div v-else>
<router-link class="btn-link" to="/member/login">로그인</router-link> 후 이용해주세요.
</div>
</div>
</div>
</section>
</template>
<script lang="ts">
import { defineComponent, reactive, ref, getCurrentInstance, onMounted, watch } from 'vue'
import { MainApi } from '../apis'
import { Router } from 'vue-router'
import { IOrder } from '../types'
export default defineComponent({
name: 'AddOrderPage',
props: {
globalShare: {
type: Object,
required: true
},
id: {
type: Number,
required: true
}
},
setup(props){
const router:Router = getCurrentInstance()?.appContext.config.globalProperties.$router;
const mainApi:MainApi = getCurrentInstance()?.appContext.config.globalProperties.$mainApi;
const modifiedOrderTitleElRef = ref<HTMLInputElement>();
const modifiedOrderFuneralHomeElRef = ref<HTMLInputElement>();
const modifiedOrderOption1ElRef = ref<HTMLInputElement>();
const modifiedOrderOption1qtyElRef = ref<HTMLInputElement>();
const modifiedOrderOption2ElRef = ref<HTMLInputElement>();
const modifiedOrderOption2qtyElRef = ref<HTMLInputElement>();
const modifiedOrderOption3ElRef = ref<HTMLInputElement>();
const modifiedOrderOption3qtyElRef = ref<HTMLInputElement>();
const modifiedOrderOption4ElRef = ref<HTMLInputElement>();
const modifiedOrderOption4qtyElRef = ref<HTMLInputElement>();
const modifiedOrderOption5ElRef = ref<HTMLInputElement>();
const modifiedOrderOption5qtyElRef = ref<HTMLInputElement>();
const modifiedOrderBodyElRef = ref<HTMLInputElement>();
const state = reactive({
order: {} as IOrder
});
function loadOrder(id:number) {
mainApi.order_detail(id)
.then(axiosResponse => {
state.order = axiosResponse.data.body.order;
});
}
onMounted(() => {
loadOrder(props.id);
});
watch(() => props.id, (newValue, oldValue) => {
loadOrder(props.id);
})
/* 공백 체크 */
function checkAndModifyOrder(){
//일반적으로 안해도 되지만 typescript에서는 해야됨
//제목
if(modifiedOrderTitleElRef.value == null){
return;
}
const modifiedOrderTitleEl = modifiedOrderTitleElRef.value;
modifiedOrderTitleEl.value = modifiedOrderTitleEl.value.trim();
if(modifiedOrderTitleEl.value.length == 0){
alert('제목을 입력해 주세요.')
modifiedOrderTitleEl.focus();
return;
}
//장례식장
if(modifiedOrderFuneralHomeElRef.value == null){
return;
}
const modifiedOrderFuneralHomeEl = modifiedOrderFuneralHomeElRef.value;
modifiedOrderFuneralHomeEl.value = modifiedOrderFuneralHomeEl.value.trim();
if(modifiedOrderFuneralHomeEl.value.length == 0){
alert('장례식장명을 입력해 주세요.')
modifiedOrderFuneralHomeEl.focus();
return;
}
//옵션1
if(modifiedOrderOption1ElRef.value == null){
return;
}
const modifiedOrderOption1El = modifiedOrderOption1ElRef.value;
modifiedOrderOption1El.value = modifiedOrderOption1El.value.trim();
if(modifiedOrderOption1El.value.length == 0){
alert('옵션1을 입력해 주세요.')
modifiedOrderOption1El.focus();
return;
}
//옵션1qty
if(modifiedOrderOption1qtyElRef.value == null){
return;
}
const modifiedOrderOption1qtyEl = modifiedOrderOption1qtyElRef.value;
//옵션2
if(modifiedOrderOption2ElRef.value == null){
return;
}
const modifiedOrderOption2El = modifiedOrderOption2ElRef.value;
modifiedOrderOption2El.value = modifiedOrderOption2El.value.trim();
if(modifiedOrderOption1El.value.length == 0){
alert('옵션2를 입력해 주세요.')
modifiedOrderOption2El.focus();
return;
}
//옵션2qty
if(modifiedOrderOption2qtyElRef.value == null){
return;
}
const modifiedOrderOption2qtyEl = modifiedOrderOption2qtyElRef.value;
//옵션3
if(modifiedOrderOption3ElRef.value == null){
return;
}
const modifiedOrderOption3El = modifiedOrderOption3ElRef.value;
modifiedOrderOption3El.value = modifiedOrderOption3El.value.trim();
if(modifiedOrderOption3El.value.length == 0){
alert('옵션3을 입력해 주세요.')
modifiedOrderOption3El.focus();
return;
}
//옵션3qty
if(modifiedOrderOption3qtyElRef.value == null){
return;
}
const modifiedOrderOption3qtyEl = modifiedOrderOption3qtyElRef.value;
//옵션4
if(modifiedOrderOption4ElRef.value == null){
return;
}
const modifiedOrderOption4El = modifiedOrderOption4ElRef.value;
modifiedOrderOption4El.value = modifiedOrderOption4El.value.trim();
if(modifiedOrderOption4El.value.length == 0){
alert('옵션4를 입력해 주세요.')
modifiedOrderOption4El.focus();
return;
}
//옵션4qty
if(modifiedOrderOption4qtyElRef.value == null){
return;
}
const modifiedOrderOption4qtyEl = modifiedOrderOption4qtyElRef.value;
//옵션5
if(modifiedOrderOption5ElRef.value == null){
return;
}
const modifiedOrderOption5El = modifiedOrderOption5ElRef.value;
modifiedOrderOption5El.value = modifiedOrderOption5El.value.trim();
if(modifiedOrderOption5El.value.length == 0){
alert('옵션5를 입력해 주세요.')
modifiedOrderOption5El.focus();
return;
}
//옵션5qty
if(modifiedOrderOption5qtyElRef.value == null){
return;
}
const modifiedOrderOption5qtyEl = modifiedOrderOption5qtyElRef.value;
//body
if(modifiedOrderBodyElRef.value == null){
return;
}
const modifiedOrderBodyEl = modifiedOrderBodyElRef.value;
modifiedOrderBodyEl.value = modifiedOrderBodyEl.value.trim();
if(modifiedOrderBodyEl.value.length == 0){
alert('내용을 입력해 주세요.')
modifiedOrderBodyEl.focus();
return;
}
// 작성 함수로 보내기
modifyOrder(props.id, modifiedOrderTitleEl.value, modifiedOrderFuneralHomeEl.value, modifiedOrderOption1El.value, parseInt(modifiedOrderOption1qtyEl.value), modifiedOrderOption2El.value, parseInt(modifiedOrderOption2qtyEl.value), modifiedOrderOption3El.value, parseInt(modifiedOrderOption3qtyEl.value), modifiedOrderOption4El.value, parseInt(modifiedOrderOption4qtyEl.value), modifiedOrderOption5El.value, parseInt(modifiedOrderOption5qtyEl.value), modifiedOrderBodyEl.value, state.order.directorId, props.globalShare.loginedMember.id);
}
//typescript에서는 title:string, body:string 이런식으로 type을 적어주어야 한다
function modifyOrder(id:number, title:string, funeralHome:string, option1:string, option1qty:number, option2:string, option2qty:number, option3:string, option3qty:number, option4:string, option4qty:number, option5:string, option5qty:number, body:string, directorId:number, clientId:number){
mainApi.order_doModify(id, title, funeralHome, option1, option1qty, option2, option2qty, option3, option3qty, option4, option4qty, option5, option5qty, body, directorId, clientId)
.then(axiosResponse => {
alert(axiosResponse.data.msg);
// 로그인이 fail 상태이면 리턴
if ( axiosResponse.data.fail ) {
return;
}
//authKey가 있는 상태에서 가능
const modifiedOrderId = axiosResponse.data.body.id;
//alert(modifiedArticleId + "번 게시물 등록 완료!!");
router.replace("detail?id=" + modifiedOrderId);
});
}
return{
state,
modifiedOrderTitleElRef,
modifiedOrderFuneralHomeElRef,
modifiedOrderOption1ElRef,
modifiedOrderOption1qtyElRef,
modifiedOrderOption2ElRef,
modifiedOrderOption2qtyElRef,
modifiedOrderOption3ElRef,
modifiedOrderOption3qtyElRef,
modifiedOrderOption4ElRef,
modifiedOrderOption4qtyElRef,
modifiedOrderOption5ElRef,
modifiedOrderOption5qtyElRef,
modifiedOrderBodyElRef,
checkAndModifyOrder,
}
}
})
</script>
<style scoped>
</style>
<MemberMyPage.vue>
<template>
<TitleBar>My Page</TitleBar>
<section class="section section-member-join-form px-2">
<div class="container mx-auto">
<div class="px-6 py-6 bg-white rounded-lg shadow-md">
<div v-if="globalShare.isLogined" v-on:submit.prevent="checkAndJoin">
<div title="프로필 이미지">
<img class="h-96 rounded-lg object-cover object-center" :src="'http://localhost:8090' + state.member.extra__thumbImg">
</div>
<div title="회원유형">
<p>회원유형</p>
{{state.member.authLevel}}
</div>
<div title="아이디">
<p>아이디</p>
{{state.member.loginId}}
</div>
<div title="이름">
<p>이름</p>
{{state.member.name}}
</div>
<div title="닉네임">
<p>닉네임</p>
{{state.member.nickname}}
</div>
<div title="전화번호">
<p>전화번호</p>
{{state.member.cellphoneNo}}
</div>
<div title="이메일">
<p>이메일</p>
{{state.member.email}}
</div>
<div title="주소">
<p>주소</p>
{{state.member.address}}
</div>
<div>
<div class="btns">
<router-link class="btn-secondary" :to="'/member/doModify?id=' + state.member.id">회원정보수정</router-link>
<router-link class="btn-danger" to="member/doDelete">탈퇴</router-link>
</div>
</div>
</div>
<div v-else>
로그인 후 이용가능합니다.<router-link class="btn-link" to="/">홈</router-link> 으로 이동
</div>
</div>
</div>
</section>
</template>
<script lang="ts">
import { defineComponent, ref, reactive, watch, getCurrentInstance, onMounted } from 'vue'
import { MainApi } from '../apis'
import { IMember } from '../types'
export default defineComponent({
name: 'MemberMyPage',
props: {
globalShare: {
type: Object,
required: true
},
id: {
type: Number,
required: true
}
},
setup(props) {
const mainApi:MainApi = getCurrentInstance()?.appContext.config.globalProperties.$mainApi;
const state = reactive({
member: {} as IMember
});
function loadMember(id:number) {
mainApi.member_detail(id)
.then(axiosResponse => {
state.member = axiosResponse.data.body.member;
});
}
onMounted(() => {
loadMember(props.id);
});
watch(() => props.id, (newValue, oldValue) => {
loadMember(props.id);
})
return {
state,
}
}
})
</script>
<style scoped>
</style>
<MemberModifyPage.vue>
<template>
<TitleBar>회원정보수정</TitleBar>
<section class="section section-member-modify-form px-2">
<div class="container mx-auto">
<div class="px-6 py-6 bg-white rounded-lg shadow-md">
<form v-if="globalShare.isLogined" v-on:submit.prevent="checkAndModify">
<div title="프로필 이미지">
<img class="h-96 rounded-lg object-cover object-center" :src="'http://localhost:8090' + state.member.extra__thumbImg">
</div>
<FormRow title="프로필 이미지">
<input ref="profileImgElRef" class="form-row-input" type="file">
</FormRow>
<FormRow title="회원유형">
<select ref="authLevelElRef" :value="state.member.authLevel">
<option value="3">일반회원</option>
<option value="4">도우미</option>
<option value="5">지도사</option>
</select>
</FormRow>
<FormRow title="아이디">
<input ref="loginIdElRef" class="form-row-input" type="text" :value="state.member.loginId">
</FormRow>
<FormRow title="비밀번호">
<input ref="loginPwElRef" class="form-row-input" type="password" placeholder="비밀번호를 입력해주세요.">
</FormRow>
<FormRow title="비밀번호 확인">
<input ref="loginPwConfirmElRef" class="form-row-input" type="password" placeholder="비밀번호 확인을 해주세요.">
</FormRow>
<FormRow title="이름">
<input ref="nameElRef" class="form-row-input" type="text" :value="state.member.name">
</FormRow>
<FormRow title="닉네임">
<input ref="nicknameElRef" class="form-row-input" type="text" :value="state.member.nickname">
</FormRow>
<FormRow title="전화번호">
<input ref="cellphoneNoElRef" class="form-row-input" type="tel" maxlength="11" :value="state.member.cellphoneNo">
</FormRow>
<FormRow title="이메일">
<input ref="emailElRef" class="form-row-input" type="email" :value="state.member.email">
</FormRow>
<FormRow title="시/도">
<input ref="addressElRef" class="form-row-input" type="text" :value="state.member.address">
</FormRow>
<FormRow title="완료">
<div class="btns">
<input type="submit" value="완료" class="btn-primary" />
</div>
</FormRow>
</form>
<div v-else>
이미 로그인 상태입니다. <router-link class="btn-link" to="/">홈</router-link> 으로 이동
</div>
</div>
</div>
</section>
</template>
<script lang="ts">
import { defineComponent, ref, reactive, getCurrentInstance, onMounted, watch } from 'vue'
import { MainApi } from '../apis'
import { Router } from 'vue-router'
import { IMember } from '../types'
export default defineComponent({
name: 'MemberJoinPage',
props: {
globalShare: {
type: Object,
required: true
},
id: {
type: Number,
required: true
}
},
setup(props) {
const router:Router = getCurrentInstance()?.appContext.config.globalProperties.$router;
const mainApi:MainApi = getCurrentInstance()?.appContext.config.globalProperties.$mainApi;
const profileImgElRef = ref<HTMLInputElement>();
const authLevelElRef = ref<HTMLInputElement>();
const loginIdElRef = ref<HTMLInputElement>();
const loginPwElRef = ref<HTMLInputElement>();
const loginPwConfirmElRef = ref<HTMLInputElement>();
const nameElRef = ref<HTMLInputElement>();
const nicknameElRef = ref<HTMLInputElement>();
const cellphoneNoElRef = ref<HTMLInputElement>();
const emailElRef = ref<HTMLInputElement>();
const addressElRef = ref<HTMLInputElement>();
const state = reactive({
member: {} as IMember
});
function loadMember(id:number) {
mainApi.member_detail(id)
.then(axiosResponse => {
state.member = axiosResponse.data.body.member;
});
}
onMounted(() => {
loadMember(props.id);
});
watch(() => props.id, (newValue, oldValue) => {
loadMember(props.id);
})
function checkAndModify() {
// 아이디 체크
if ( loginIdElRef.value == null ) {
return;
}
const loginIdEl = loginIdElRef.value;
loginIdEl.value = loginIdEl.value.trim();
if ( loginIdEl.value.length == 0 ) {
alert('아이디를 입력해주세요.');
loginIdEl.focus();
return;
}
// 비번 체크
if ( loginPwElRef.value == null ) {
return;
}
const loginPwEl = loginPwElRef.value;
loginPwEl.value = loginPwEl.value.trim();
if ( loginPwEl.value.length == 0 ) {
alert('비밀번호를 입력해주세요.');
loginPwEl.focus();
return;
}
// 비번확인 체크
if ( loginPwConfirmElRef.value == null ) {
return;
}
const loginPwConfirmEl = loginPwConfirmElRef.value;
if ( loginPwEl.value != loginPwConfirmEl.value ) {
alert('로그인 비번이 일치하지 않습니다.');
loginPwConfirmEl.focus();
return;
}
// 이름 체크
if ( nameElRef.value == null ) {
return;
}
const nameEl = nameElRef.value;
nameEl.value = nameEl.value.trim();
if ( nameEl.value.length == 0 ) {
alert('이름을 입력해주세요.');
nameEl.focus();
return;
}
// 닉네임 체크
if ( nicknameElRef.value == null ) {
return;
}
const nicknameEl = nicknameElRef.value;
nicknameEl.value = nicknameEl.value.trim();
if ( nicknameEl.value.length == 0 ) {
alert('닉네임을 입력해주세요.');
nicknameEl.focus();
return;
}
// 전화번호 체크
if ( cellphoneNoElRef.value == null ) {
return;
}
const cellphoneNoEl = cellphoneNoElRef.value;
cellphoneNoEl.value = cellphoneNoEl.value.trim();
if ( cellphoneNoEl.value.length == 0 ) {
alert('전화번호를 입력해주세요.');
cellphoneNoEl.focus();
return;
}
// 이메일 체크
if ( emailElRef.value == null ) {
return;
}
const emailEl = emailElRef.value;
emailEl.value = emailEl.value.trim();
if ( emailEl.value.length == 0 ) {
alert('이메일을 입력해주세요.');
emailEl.focus();
return;
}
// 시/도 주소 체크
if ( addressElRef.value == null ) {
return;
}
const addressEl = addressElRef.value;
addressEl.value = addressEl.value.trim();
if ( addressEl.value.length == 0 ) {
alert('시/도를 입력해주세요.');
addressEl.focus();
return;
}
if(authLevelElRef.value == null){
return
}
const authLevelEl = authLevelElRef.value;
const startFileUpload = (onSuccess:Function) => {
// ! => 반전
// a = undefinded(or null) / !a = true / !!a = flase란 의미
// ? => 만약 profileImgElRef.value?까지가 null이면 여기까지만 실행하겠다라는 의미
// 즉, !!!profileImgElRef.value?.files의 의미는 해당 파일이 없는지 물어보는 것
// 없으면 true
if(!!!profileImgElRef.value?.files){
onSuccess(""); //파일이 없으면 다음 과정 생략하고 onSuccess() 즉시 실행
return;
}
mainApi.common_genFile_doUpload(profileImgElRef.value?.files[0])
.then(axiosResponse => {
if ( axiosResponse.data.fail ) {
alert(axiosResponse.data.msg);
return;
}
else{
onSuccess(axiosResponse.data.body.genFileIdsStr);
}
});
};
//회원가입 join함수 시작
//파일첨부기능 추가로 인해 로직 변경
//join(loginIdEl.value, loginPwEl.value, nameEl.value, nicknameEl.value, cellphoneNoEl.value, emailEl.value);
const startModify = (genFileIdsStr:string) =>{
modify(props.id, parseInt(authLevelEl.value), loginIdEl.value, loginPwEl.value, nameEl.value, nicknameEl.value, cellphoneNoEl.value, emailEl.value, addressEl.value, genFileIdsStr);
};
//startFileUpload 로직을 먼저 실행한 후
//onSuccess 즉, startJoin를 실행한다. onSuccess = startJoin
//실행 순서 : 1.첨부파일이 있는지 확인하고 업로드까지 진행하는 startFileUpload함수 종료 후 2.회원가입 join함수가 실행된다.
startFileUpload(startModify);
}
function modify(id:number, authLevel:number, loginId:string, loginPw:string, name:string, nickname:string, cellphoneNo:string, email:string, address:string, genFileIdsStr:string) {
mainApi.member_doModify(id, authLevel, loginId, loginPw, name, nickname, cellphoneNo, email, address, genFileIdsStr)
.then(axiosResponse => {
alert(axiosResponse.data.msg);
if ( axiosResponse.data.fail ) {
return;
}
router.replace('/member/detail?id=' + id)
});
}
return {
state,
checkAndModify,
profileImgElRef,
authLevelElRef,
loginIdElRef,
loginPwElRef,
loginPwConfirmElRef,
nameElRef,
nicknameElRef,
cellphoneNoElRef,
emailElRef,
addressElRef
}
}
})
</script>
<style scoped>
</style>