From 0806c3ab46e49711e64e4bc793c12753fb5fb000 Mon Sep 17 00:00:00 2001 From: Tomas <tomasysh@gmail.com> Date: 星期一, 24 一月 2022 16:24:43 +0800 Subject: [PATCH] add#134746: 客戶收到簡訊通知"有過久無回應的顧問",點擊簡訊/email url 後,進入此流程(belong to TODO#134717: [客戶] 取消預約再改選其他顧問(前端)) --- PAMapp/pages/index.vue | 225 ++++++++++++++++++++++++++++++++------------ PAMapp/components/Client/ClientCard.vue | 6 - PAMapp/store/localStorage.ts | 21 ++++ PAMapp/shared/models/strict-query.model.ts | 18 +- PAMapp/middleware/getUrlQuery.ts | 12 ++ PAMapp/assets/scss/utilities/_utilities.scss | 5 + 6 files changed, 207 insertions(+), 80 deletions(-) diff --git a/PAMapp/assets/scss/utilities/_utilities.scss b/PAMapp/assets/scss/utilities/_utilities.scss index 04b3932..ebf13d7 100644 --- a/PAMapp/assets/scss/utilities/_utilities.scss +++ b/PAMapp/assets/scss/utilities/_utilities.scss @@ -5,6 +5,10 @@ margin-bottom: 50px; } +.mt-50 { + margin-top: 50px; +} + .mt-30 { margin-top: 30px; } @@ -21,6 +25,7 @@ margin-bottom: 20px; } + .mt-10 { margin-top: 10px; } diff --git a/PAMapp/components/Client/ClientCard.vue b/PAMapp/components/Client/ClientCard.vue index e010af8..0ff9748 100644 --- a/PAMapp/components/Client/ClientCard.vue +++ b/PAMapp/components/Client/ClientCard.vue @@ -261,12 +261,6 @@ viewAppointmentDetail(): void { this.getAppointmentDetail(this.client.id).then((_) => { - // setTimeout(() => { - // const unread = !this.client.consultantReadTime; - // if (unread) { - // this.readAppointment(); - // } - // }, 0); const unread = !this.client.consultantReadTime; if (unread) { this.readAppointment(); diff --git a/PAMapp/middleware/getUrlQuery.ts b/PAMapp/middleware/getUrlQuery.ts index 0a6c0ec..5fb2841 100644 --- a/PAMapp/middleware/getUrlQuery.ts +++ b/PAMapp/middleware/getUrlQuery.ts @@ -3,7 +3,15 @@ const getUrlQuery: Middleware = (context) => { const currentRouteName = context.route.name; const satisfactionIdFromMsg = context.route.query.appointmentId; + const queryNotContactAppointmentId = context.route.query.notContactAppointmentId; const isUserLogin = context.store.getters['localStorage/isUserLogin']; + + if (currentRouteName === 'index' && queryNotContactAppointmentId) { + context.store.commit('localStorage/storageNotContactAppointmentIdFromMsg', queryNotContactAppointmentId); + if (!isUserLogin) { + context.redirect('/login'); + } + } if (currentRouteName === 'index' && satisfactionIdFromMsg) { context.store.commit('localStorage/storageSatisfactionIdFromMsg', satisfactionIdFromMsg); @@ -11,6 +19,8 @@ context.redirect('/login'); } } + + } -export default getUrlQuery \ No newline at end of file +export default getUrlQuery diff --git a/PAMapp/pages/index.vue b/PAMapp/pages/index.vue index c237e5e..286c1ff 100644 --- a/PAMapp/pages/index.vue +++ b/PAMapp/pages/index.vue @@ -41,10 +41,9 @@ </div> <Ui-Dialog - :isVisible.sync="isVisibleDialog" - :width="width" + :isVisible.sync="isShowAppointmentDialog" + :width="appointmentDialogWidth" class="pam-myDemand-dialog pam-dialog-reserved" - @closeDialog="clearSatisfactionId" > <div v-if="appointmentDetail"> <h5 class="subTitle text--center mb-30">������</h5> @@ -73,14 +72,42 @@ <div v-if="notScoreAppointmentYet" class="reserved-btn"> <el-button type="primary" - @click.native="reviewsBtn = true">蝯虫�遛��漲閰��</el-button> + @click.native="isShowReviewDialog = true">蝯虫�遛��漲閰��</el-button> </div> </div> </Ui-Dialog> <PopUpFrame - :isOpen.sync="reviewsBtn" - @closePopUp="clearSatisfactionId" + :isOpen.sync="isShowReAppointmentDialog" + @closePopUp="removeUrlQueryParameter('notContactAppointmentId')" + > + <div class="pam-dialog-review"> + <div class="mt-30 text--middle" v-if="agentInfo"> + 敺甇������<span class="text--bold">{{ consultantName }}</span>憿批�迤敹�葉嚗������蒂���隞“��� + </div> + + <el-row + type="flex" + class="mt-50" + justify="center"> + <el-button + type="primary" + @click="reAppointment">��������隞“���</el-button> + </el-row> + <el-row + type="flex" + class="mt-20" + justify="center"> + <el-button + class="outline_btn" + @click="cancelAppointment">������</el-button> + </el-row> + </div> + </PopUpFrame> + + <PopUpFrame + :isOpen.sync="isShowReviewDialog" + @closePopUp="removeUrlQueryParameter('appointmentId')" > <div class="mdTxt pam-dialog-review"> 靽憿批�遛��漲 @@ -110,11 +137,16 @@ <script lang="ts"> import { Vue, Component, State, Action, Watch, namespace } from 'nuxt-property-decorator'; + import { Appointment, AppointmentClosedInfo } from '~/shared/models/appointment.model'; import { Consultant } from '~/shared/models/consultant.model'; -import { UserReviewsConsultantsParams } from '~/shared/models/reviews.model'; + import { ContactStatus } from '~/shared/models/enum/contact-status'; + import { UserReviewsConsultantsParams } from '~/shared/models/reviews.model'; + import { StrictQueryParams } from '~/shared/models/strict-query.model'; import appointmentService from '~/shared/services/appointment.service'; -import reviewsService from '~/shared/services/reviews.service'; + import reviewsService from '~/shared/services/reviews.service'; import UtilsService from '~/shared/services/utils.service'; + import myConsultantService from '~/shared/services/my-consultant.service'; +import { AgentInfo } from '~/shared/models/agent-info.model'; const localStorage = namespace('localStorage'); const roleStorage = namespace('localStorage'); @@ -136,7 +168,8 @@ @Action storeRecommendList!: any; - @Action storeConsultantList!: any; + @Action + storeConsultantList!: any; @localStorage.Mutation storageClearQuickFilter!: () => void; @@ -147,37 +180,55 @@ @localStorage.Getter currentSatisfactionIdFromMsg!: string; + @localStorage.Getter + currentNotContactAppointmentIdFromMsg!: string; + @localStorage.Mutation storageClearSatisfactionIdFromMsg!: () => void; + @localStorage.Mutation + storageClearNotContactAppointmentIdFromMsg!: () => void; + + @localStorage.Mutation + storageStrickQueryItem!: (strictQueryDto: StrictQueryParams) => void; + consultantList: Consultant[] = []; - appointmentDetail: any = { - age : '', - agentNo : '', - appointmentDate : '', - communicateStatus : '', - consultantReadTime: null, - consultantViewTime: null, - contactTime : '', - contactType : '', - customerId : 0, - email : '', - gender : '', - hopeContactTime : "", - id : 0, - job : "", - lastModifiedDate : '', - name : '', - otherRequirement : null, - phone : "", - requirement : '', - satisfactionScore : 0, + appointmentDialogWidth = ''; + inputScore = 0; + isShowAppointmentDialog = false; + isShowReAppointmentDialog = false; + isShowReviewDialog = false; + consultantName = ''; + contactStatus = ContactStatus; + + appointmentDetail: Appointment = { + age : '', + agentNo : '', + appointmentClosedInfo: {} as AppointmentClosedInfo, + appointmentDate : '', + appointmentMemoList: [], + appointmentNoticeLogs: [], + communicateStatus : this.contactStatus.PICKED, + consultantReadTime: '', + consultantViewTime: '', + contactTime : '', + contactType : '', + customerId : 0, + email : '', + gender : '', + hopeContactTime : '', + interviewRecordDTOs: [], + id : 0, + job : '', + lastModifiedDate : '', + name : '', + otherRequirement : '', + phone : '', + requirement : '', + satisfactionScore : 0, }; - isVisibleDialog = false; - width = ''; - reviewsBtn = false; - inputScore = 0; + agentInfo: Consultant = { agentNo : '', name : '', @@ -211,7 +262,7 @@ } destroyed() { - this.clearSatisfactionId(); + this.removeUrlQueryParameter(); } ////////////////////////////////////////////////////////////////////// @@ -223,36 +274,81 @@ .map((item) => ({ ...item, formatDate: new Date(item.updateTime || item.createTime)})) .sort((preItem, nextItem) => +nextItem.formatDate - +preItem.formatDate); - if (this.currentSatisfactionIdFromMsg) { - this.agentInfo = this.myConsultantList.filter(item => { - const satisfactionIdIndex = item.appointments?.findIndex(i => i.id === +this.currentSatisfactionIdFromMsg); - return satisfactionIdIndex !== undefined && satisfactionIdIndex > -1; - })[0]; - if (this.agentInfo) { - this.openAppointmentInfo(); - } + if (this.currentNotContactAppointmentIdFromMsg) { + this.autoOpenAppointmentBy('askReAppointment', +this.currentNotContactAppointmentIdFromMsg); + return; + } + if (this.currentSatisfactionIdFromMsg) { + this.autoOpenAppointmentBy('inviteReviewConsultant',+this.currentSatisfactionIdFromMsg); + this.storageClearSatisfactionIdFromMsg(); + return; } } - private openAppointmentInfo() { - appointmentService.getAppointmentDetail(+this.currentSatisfactionIdFromMsg).then(res => { - this.appointmentDetail = res; - this.width = UtilsService.isMobileDevice() ? '80%' : ''; - this.isVisibleDialog = true; - - if (this.notScoreAppointmentYet) { - setTimeout(() => { - this.reviewsBtn = true; - }, 500) - } + private autoOpenAppointmentBy(reason: string, targetAppointmentId: number): void { + const setAgentInfo = new Promise((resolve, reject) => { + this.agentInfo = this.myConsultantList.filter(item => { + const appointmentIndex = item.appointments?.findIndex(i => i.id === targetAppointmentId); + return appointmentIndex !== undefined && appointmentIndex > -1; + })[0]; + if (this.agentInfo) { + myConsultantService.getConsultantDetail(this.agentInfo.agentNo).then((res) => resolve(res)); + } }); + + const setAppointment = new Promise((resolve, reject) => { + appointmentService.getAppointmentDetail(targetAppointmentId).then((res) => resolve(res)); + }); + + Promise.all([setAgentInfo, setAppointment]).then((values) => { + const agentInfo = values[0] as AgentInfo; + const appointmentInfo = values[1] as Appointment; + this.consultantName = agentInfo.name; + this.appointmentDetail = appointmentInfo; + this.appointmentDialogWidth = UtilsService.isMobileDevice() ? '80%' : ''; + this.isShowAppointmentDialog = true; + switch (reason) { + case 'inviteReviewConsultant': + if (this.notScoreAppointmentYet) { + setTimeout(() => { + this.isShowReviewDialog = true; + }, 500); + } + break; + case 'askReAppointment': + setTimeout(() => { + this.isShowReAppointmentDialog = true; + }, 500); + break; + } + }); + } ////////////////////////////////////////////////////////////////////// navigateToRoute(path: string): void { this.$router.push(path); + } + + reAppointment(): void { + appointmentService.cancelAppointment(this.appointmentDetail.id).then(() => { + const requirements = this.appointmentDetail.requirement.split(','); + console.log('requirements', requirements) + this.storeConsultantList(); + this.storageStrickQueryItem({ requirements: requirements }); + this.storageClearNotContactAppointmentIdFromMsg(); + this.$router.push('/recommendConsultant'); + }); + } + + cancelAppointment(): void { + appointmentService.cancelAppointment(this.appointmentDetail.id).then(() => { + this.storeConsultantList(); + this.storageClearNotContactAppointmentIdFromMsg(); + this.$router.push(''); + }); } userReviewsConsultants() { @@ -263,21 +359,22 @@ this.appointmentDetail.satisfactionScore = this.inputScore; reviewsService.userReviewsConsultants(reviewParams).then((res) => { - this.reviewsBtn = false; + this.isShowReviewDialog = false; }); } - clearSatisfactionId() { - // NOTE: ���摰�� query parameter [Tomas, 2022/1/24 11:36] - // [REF] How to remove a parameter from this.$router.query Nuxt.js? https://reurl.cc/X45aMD + removeUrlQueryParameter(targetKey?: string): void { + // NOTE: ���摰�� query parameter [Tomas, 2022/1/24 11:36] + // [REF] How to remove a parameter from this.$router.query Nuxt.js? https://reurl.cc/X45aMD let newRouteQuery = {}; - Object.keys(this.$route.query).forEach((key) => { - if (key !== 'appointmentId') { - newRouteQuery[key] = this.$route.query[key] - } - }) + if (targetKey) { + Object.keys(this.$route.query).forEach((key) => { + if (key !== targetKey) { + newRouteQuery[key] = this.$route.query[key] + } + }) + } this.$router.push(newRouteQuery); - this.storageClearSatisfactionIdFromMsg(); } /////////////////////////////////////////////////////////////////////////////// diff --git a/PAMapp/shared/models/strict-query.model.ts b/PAMapp/shared/models/strict-query.model.ts index 59892c1..45a5f31 100644 --- a/PAMapp/shared/models/strict-query.model.ts +++ b/PAMapp/shared/models/strict-query.model.ts @@ -1,14 +1,14 @@ export interface StrictQueryParams { - gender : string; - avgScore : number; - status : string; //phase 1 disable - area : string; - requirements : string[]; - otherRequirement: string; - seniority : string; - popularTags : string[]; - otherPopularTags: string; + gender? : string; + avgScore? : number; + status? : string; //phase 1 disable + area? : string; + requirements? : string[]; + otherRequirement?: string; + seniority? : string; + popularTags? : string[]; + otherPopularTags?: string; } export interface AgentOfStrictQuery { diff --git a/PAMapp/store/localStorage.ts b/PAMapp/store/localStorage.ts index 9ad38e9..a08b69a 100644 --- a/PAMapp/store/localStorage.ts +++ b/PAMapp/store/localStorage.ts @@ -1,6 +1,7 @@ import { Module, Mutation, VuexModule ,Action } from 'vuex-module-decorators'; import { Role } from '~/shared/models/enum/Role'; import { Selected } from '~/shared/models/quick-filter.model'; +import { StrictQueryParams } from '~/shared/models/strict-query.model'; @Module export default class LocalStorage extends VuexModule { id_token = localStorage.getItem('id_token'); @@ -10,6 +11,7 @@ recommendConsultantItem = localStorage.getItem('recommendConsultantItem'); appointmentIdFromMsg = localStorage.getItem('appointmentIdFromMsg'); satisfactionIdFromMsg = localStorage.getItem('satisfactionIdFromMsg'); + notContactAppointmentIdFromMsg = localStorage.getItem('notContactAppointmentIdFromMsg'); get idToken(): string|null { return this.id_token; @@ -41,6 +43,10 @@ get currentSatisfactionIdFromMsg(): string|null { return this.satisfactionIdFromMsg; + } + + get currentNotContactAppointmentIdFromMsg(): string|null { + return this.notContactAppointmentIdFromMsg; } @Mutation storageIdToken(token: string): void { @@ -78,6 +84,11 @@ this.satisfactionIdFromMsg = localStorage.getItem('satisfactionIdFromMsg'); } + @Mutation storageNotContactAppointmentIdFromMsg(id: string) { + localStorage.setItem('notContactAppointmentIdFromMsg', id); + this.notContactAppointmentIdFromMsg = id; + } + @Mutation storageClear(): void { localStorage.removeItem('myRequests'); localStorage.removeItem('userInfo'); @@ -112,6 +123,16 @@ this.appointmentIdFromMsg = localStorage.getItem('satisfactionIdFromMsg'); } + @Mutation storageClearNotContactAppointmentIdFromMsg() { + localStorage.removeItem('notContactAppointmentIdFromMsg'); + this.appointmentIdFromMsg = localStorage.getItem('notContactAppointmentIdFromMsg'); + } + + @Mutation storageStrickQueryItem(queryItem: StrictQueryParams): void { + localStorage.setItem('recommendConsultantItem', JSON.stringify(queryItem)); + this.recommendConsultantItem = localStorage.getItem('recommendConsultantItem'); + } + @Action actionStorageClear(): void { this.context.commit("storageClear"); } -- Gitblit v1.8.0