From b1b1fa9058a8e7df07c25cf6d5be1678a042ab7e Mon Sep 17 00:00:00 2001 From: Mila <Mila@pollex.com.tw> Date: 星期二, 18 一月 2022 14:27:07 +0800 Subject: [PATCH] update: TODO#134382 [顧問管理流程] 刪除/編輯約訪紀錄 --- PAMapp/components/Interview/InterviewAdd.vue | 246 ++++++++++++++++++++++++++++------ PAMapp/assets/scss/vendors/elementUI/_dateTimePicker.scss | 3 PAMapp/store/index.ts | 33 ++++ PAMapp/shared/services/appointment.service.ts | 2 PAMapp/components/Ui/UiTimePicker.vue | 15 ++ PAMapp/components/Appointment/AppointmentInterviewList.vue | 85 ++++++++++- PAMapp/components/Ui/UiDatePicker.vue | 13 + PAMapp/shared/models/appointment.model.ts | 2 PAMapp/pages/appointment/_appointmentId/index.vue | 2 PAMapp/components/DateTimePicker.vue | 15 + 10 files changed, 348 insertions(+), 68 deletions(-) diff --git a/PAMapp/assets/scss/vendors/elementUI/_dateTimePicker.scss b/PAMapp/assets/scss/vendors/elementUI/_dateTimePicker.scss index 37aa67a..b75fa43 100644 --- a/PAMapp/assets/scss/vendors/elementUI/_dateTimePicker.scss +++ b/PAMapp/assets/scss/vendors/elementUI/_dateTimePicker.scss @@ -52,6 +52,9 @@ td.available:hover { color: $CORAL; } + td.today.current span { + color: $PRIMARY_WHITE; + } } } .el-year-table { diff --git a/PAMapp/components/Appointment/AppointmentInterviewList.vue b/PAMapp/components/Appointment/AppointmentInterviewList.vue index 14e66b3..e7a3325 100644 --- a/PAMapp/components/Appointment/AppointmentInterviewList.vue +++ b/PAMapp/components/Appointment/AppointmentInterviewList.vue @@ -13,27 +13,57 @@ </template> <template v-if="interviewList.length"> - <div class="interview--future"> + <div + v-for="(item, index) in futureList" + :key="index + 'feature'" + class="interview--future" + @click="editInterview(item)" + > <div class="record-card"> <div class="record-card-date"> - <span class="bold">01/10</span> - <span class="mt-5 line-space">09:00</span> + <div> + <UiDateFormat + class="date bold" + :date="item.interviewDate" + onlyShowSection="DAY" /> + </div> + <div> + <UiDateFormat + class="time mt-5 line-space" + :date="item.interviewDate" + onlyShowSection="TIME" /> + </div> </div> <div class="record-card-content"> - <span>�����恥�蝝��璅��撱喉�����������靽</span> + <span>{{item.content}}</span> </div> </div> </div> - <section class="interview--past"> + <section + class="interview--past" + v-for="(item, index) in pastList" + :key="index + 'past'" + @click="editInterview(item)" + > <div class="record-card"> <div class="record-card-date"> - <span class="bold">01/08</span> - <span class="mt-5 line-space">09:00</span> + <div> + <UiDateFormat + class="date bold" + :date="item.interviewDate" + onlyShowSection="DAY" /> + </div> + <div> + <UiDateFormat + class="time mt-5 line-space" + :date="item.interviewDate" + onlyShowSection="TIME" /> + </div> </div> <div class="record-card-content"> - <span>�����縑���閰梯�Ⅳ嚗���������</span> + <span>{{item.content}}</span> </div> </div> </section> @@ -46,18 +76,49 @@ </template> <script lang="ts"> -import { Vue, Component } from 'nuxt-property-decorator'; +import { Vue, Component, Prop, Watch, Mutation } from 'nuxt-property-decorator'; +import { InterviewRecord } from '~/shared/models/appointment.model'; @Component export default class AppointmentInterviewList extends Vue { + @Prop() + interviewList!: InterviewRecord[]; - interviewList = []; + @Mutation + updateInterviewRecord!: (data: InterviewRecord) => void; + + appointmentId!: string; + + futureList: InterviewRecord[] = []; + pastList: InterviewRecord[] = []; + + ////////////////////////////////////////////////////////////////////// + + mounted() { + this.appointmentId = this.$route.params.appointmentId; + } + + ////////////////////////////////////////////////////////////////////// + + @Watch('interviewList', {immediate: true}) + updateInterviewList() { + if (this.interviewList && this.interviewList.length > 0) { + this.futureList = this.interviewList + .filter(item => new Date(item.interviewDate).getTime() >= new Date().getTime()) + this.pastList = this.interviewList + .filter(item => new Date(item.interviewDate).getTime() < new Date().getTime()); + } + } ////////////////////////////////////////////////////////////////////// addInterview(): void { - const appointmentId = this.$route.params.appointmentId; - this.$router.push(`/appointment/${appointmentId}/interview/new`); + this.$router.push(`/appointment/${this.appointmentId}/interview/new`); + } + + editInterview(interviewRecord) { + this.updateInterviewRecord(interviewRecord); + this.$router.push(`/appointment/${this.appointmentId}/interview/${interviewRecord.id}`); } } diff --git a/PAMapp/components/DateTimePicker.vue b/PAMapp/components/DateTimePicker.vue index 99f4448..7916c77 100644 --- a/PAMapp/components/DateTimePicker.vue +++ b/PAMapp/components/DateTimePicker.vue @@ -2,19 +2,28 @@ <template> <div class="dateTime"> - <UiDatePicker @changeDate="changeDateTime($event, 'date')"></UiDatePicker> - <UiTimePicker @changeTime="changeDateTime($event, 'time')"></UiTimePicker> + <UiDatePicker + @changeDate="changeDateTime($event, 'date')" + :defaultValue="defaultValue" + ></UiDatePicker> + <UiTimePicker + @changeTime="changeDateTime($event, 'time')" + :defaultValue="defaultValue" + ></UiTimePicker> </div> </template> <script lang="ts"> -import { Component, Emit, Vue } from "nuxt-property-decorator"; +import { Component, Emit, Prop, Vue } from "nuxt-property-decorator"; @Component export default class DateTimePicker extends Vue { changeDate!: Date; changeTime!: string; + @Prop() + defaultValue!: string; + @Emit('changeDateTime') changeDateTime(event, type) { if (type === 'date') { diff --git a/PAMapp/components/Interview/InterviewAdd.vue b/PAMapp/components/Interview/InterviewAdd.vue index f88210e..e1227bc 100644 --- a/PAMapp/components/Interview/InterviewAdd.vue +++ b/PAMapp/components/Interview/InterviewAdd.vue @@ -1,76 +1,228 @@ <template> <div class="edit-appointment-record"> - <div class="edit-appointment-record-date"> - <span>隞予 11:00 撱箇��</span> - <span>隞予 11:00 ��</span> + <div class="edit-appointment-record-date" v-if="interviewId"> + <span>{{interviewRecord.createdDate | formatDate}} 撱箇��</span> + <span>{{interviewRecord.lastModifiedDate | formatDate}} ��</span> + </div> + <el-row class="mdTxt mb-10"> + <el-col :xs="16" :sm="20">蝝赤����</el-col> + <el-col :xs="8" :sm="4" class="text--right" v-if="interviewId"> + <span + v-if="!isEdit" + class="mr-10 text--primary text--underline cursor--pointer" + @click="showCancelPopUp = true" + >��</span> + <span + v-if="!isEdit" + class="text--primary text--underline cursor--pointer" + @click="isEdit = !isEdit" + >蝺刻摩</span> + </el-col> + </el-row> + <template v-if="!interviewId || isEdit"> + <DateTimePicker + @changeDateTime="interviewTime = $event" + :defaultValue="defaultValue" + ></DateTimePicker> + </template> + <template v-else> + <div class="mdTxt lighter mt-20"> + {{formatInterviewDate}} + </div> + </template> + + <div class="mdTxt mb-10 mt-30">蝝赤蝝����</div> + <template v-if="!interviewId || isEdit"> + <el-input + type="textarea" + :rows="5" + placeholder="隢撓�蝝赤蝝����" + resize="none" + v-model="content" + > + </el-input> + </template> + <template v-else> + <div class="mdTxt lighter mt-20"> + {{content}} + </div> + </template> + <div class="edit-appointment-record-btn" v-if="!interviewId || isEdit"> + <el-button @click="cancel">����</el-button> + <el-button + :disabled="!interviewTime || !content" + @click="saveInterviewRecord" + >蝣箏��</el-button> </div> - <div class="mdTxt mb-10">蝝赤����</div> - <DateTimePicker - @changeDateTime="interviewTime = $event" - ></DateTimePicker> - - <div class="mdTxt mb-10 mt-10">蝝赤蝝����</div> - <el-input - type="textarea" - :rows="5" - placeholder="隢撓�蝝赤蝝����" - resize="none" - v-model="content" + <PopUpFrame :isOpen.sync="showCancelPopUp" + @closePopUp="showCancelPopUp = false" > - </el-input> - - <div class="edit-appointment-record-btn"> - <el-button>����</el-button> - <el-button :disabled="!interviewTime || !content" @click="createInterviewRecord">蝣箏��</el-button> - </div> - - <PopUpFrame :isOpen.sync="isConfirmPopup" - @closePopUp="closeConfirmPopup"> - <div class="text--center mdTxt">�憓���</div> + <div class="text--center mdTxt">����甇斤��赤閮���</div> <div class="text--center mt-30"> - <el-button @click="closeConfirmPopup" type="primary">蝣箏��</el-button> + <el-button @click="showCancelPopUp = false">�</el-button> + <el-button @click="deleteInterviewRecord" type="primary">�</el-button> </div> - </PopUpFrame> + </PopUpFrame> + + <PopUpFrame :isOpen.sync="showConfirmPopup" + @closePopUp="closePopup"> + <div class="text--center mdTxt">{{confirmTxt}}嚗�</div> + <div class="text--center mt-30"> + <el-button @click="closePopup" type="primary">蝣箏��</el-button> + </div> + </PopUpFrame> + + <PopUpFrame :isOpen.sync="showFutureDateConfirmPopup" + @closePopUp="closePopup"> + <div class="text--center mdTxt">{{confirmTxt}}嚗�</div> + <div class="text--center mdTxt">蝡���赤�嚗�</div> + <div class="text--center mt-30"> + <el-button @click="closePopup">�����</el-button> + <el-button @click="showInterviewMsgPopup = true" type="primary">���赤�</el-button> + </div> + </PopUpFrame> + + <InterviewMsg + :isVisible.sync="showInterviewMsgPopup" + @closeDialog="closePopup" + ></InterviewMsg> </div> </template> <script lang="ts"> -import { AppointmentLog, InterviewRecordInfo } from '~/shared/models/appointment.model'; -import { Vue, Component, Prop } from 'nuxt-property-decorator'; -import authService from '~/shared/services/auth.service'; +import { InterviewRecord, InterviewRecordInfo } from '~/shared/models/appointment.model'; +import { Vue, Component, Prop, State, Mutation, Watch, Action } from 'nuxt-property-decorator'; import appointmentService from '~/shared/services/appointment.service'; @Component export default class InterviewAdd extends Vue { + @State + interviewRecord!: InterviewRecord; + + @Mutation + updateInterviewRecord!: (data: InterviewRecord) => void; + + @Mutation + clearInterviewRecord!: () => void; + interviewTime = ''; content = ''; - isConfirmPopup = false; - // @Prop() - // myAppointmentReviewLogList!: AppointmentLog[]; + interviewId = ''; + appointmentId = ''; + confirmTxt: '�憓���' | '蝺刻摩����' | '������' = '�憓���'; - // isUserLogin = false; + isEdit = false; - ////////////////////////////////////////////////////////////////////// - // mounted() { - // this.isUserLogin = authService.isUserLogin(); - // } + showConfirmPopup = false; + showCancelPopUp = false; + showInterviewMsgPopup = false; + showFutureDateConfirmPopup = false; - createInterviewRecord() { + defaultValue!: Date; + + //////////////////////////////////////////////////////////////////// + + mounted() { + this.interviewId = this.$route.params.interviewId; + this.appointmentId = this.$route.params.appointmentId; + const isEditPage = this.interviewId && this.interviewRecord; + if (isEditPage) { + this.checkInterviewRecord(); + } + } + + private checkInterviewRecord() { + if (this.interviewRecord.appointmentId !== +this.appointmentId + || this.interviewRecord.id !== +this.interviewId) { + appointmentService.getAppointmentDetail(+this.appointmentId).then((data) => { + const currentInterviewRecord = data.interviewRecordDTOs.filter(item => item.id === +this.interviewId)[0]; + this.updateInterviewRecord(currentInterviewRecord); + }) + } + } + + destroyed() { + this.clearInterviewRecord(); + } + + //////////////////////////////////////////////////////////////////// + + @Watch('interviewRecord', {immediate: true}) + watchInterviewRecord() { + if (this.interviewRecord && this.interviewRecord.content) { + this.content = this.interviewRecord.content; + this.defaultValue = new Date(this.interviewRecord.interviewDate); + } + } + + //////////////////////////////////////////////////////////////////// + + saveInterviewRecord() { const interviewRecordInfo: InterviewRecordInfo = { content: this.content, interviewDate: this.interviewTime, - appointmentId: +this.$route.params.appointmentId + appointmentId: +this.appointmentId + }; + if (!this.interviewId) { + this.createdRecord(interviewRecordInfo); + } else { + const updateInterviewRecord = { + ...interviewRecordInfo, + id: +this.interviewId + } + this.updateRecord(updateInterviewRecord); } - appointmentService.createInterviewRecord(interviewRecordInfo).then(res => { - this.isConfirmPopup = true; - }); - } - closeConfirmPopup() { - this.isConfirmPopup = false; - this.$router.go(-1); + private createdRecord(interviewRecordInfo) { + appointmentService.createInterviewRecord(interviewRecordInfo).then(res => { + this.confirmTxt = '�憓���' + this.showPopUp(); + }); + } + + private updateRecord(updateInterviewRecord) { + appointmentService.updateInterviewRecord(updateInterviewRecord).then(res => { + this.confirmTxt = '蝺刻摩����'; + this.showPopUp(); + }); + } + + private showPopUp() { + if (new Date(this.interviewTime).getTime() >= new Date().getTime()) { + this.showFutureDateConfirmPopup = true; + } else { + this.showConfirmPopup = true; + } + } + + closePopup() { + this.$router.push(`/appointment/${this.appointmentId}`); + } + + deleteInterviewRecord() { + appointmentService.deleteInterviewRecord(this.interviewId).then(res => { + this.confirmTxt = '������'; + this.showConfirmPopup = true; + }); + } + + cancel() { + if (this.interviewId) { + this.content = this.interviewRecord.content; + this.defaultValue = new Date(this.interviewRecord.interviewDate); + this.isEdit = false; + } else { + this.$router.push(`/appointment/${this.appointmentId}`); + } + } + + //////////////////////////////////////////////////////////////////// + + get formatInterviewDate() { + const interviewDate = new Date(this.interviewRecord.interviewDate); + return `${interviewDate.getFullYear()}/${interviewDate.getMonth() + 1}/${interviewDate.getDate()} ${interviewDate.getHours()}:${interviewDate.getMinutes()}`; } } diff --git a/PAMapp/components/Ui/UiDatePicker.vue b/PAMapp/components/Ui/UiDatePicker.vue index 56bdc58..184f2e4 100644 --- a/PAMapp/components/Ui/UiDatePicker.vue +++ b/PAMapp/components/Ui/UiDatePicker.vue @@ -14,15 +14,26 @@ </template> <script lang="ts"> -import { Component, Emit, Vue } from "nuxt-property-decorator"; +import { Component, Emit, Prop, Vue, Watch } from "nuxt-property-decorator"; @Component export default class UiDatePicker extends Vue { dateValue = ''; + @Prop() + defaultValue!: string; + @Emit('changeDate') changeDate() { return this.dateValue; } + + @Watch('defaultValue', {immediate: true}) + updateDefault() { + if (this.defaultValue) { + this.dateValue = this.defaultValue; + this.changeDate(); + } + } } </script> \ No newline at end of file diff --git a/PAMapp/components/Ui/UiTimePicker.vue b/PAMapp/components/Ui/UiTimePicker.vue index 3a13512..1fd0de1 100644 --- a/PAMapp/components/Ui/UiTimePicker.vue +++ b/PAMapp/components/Ui/UiTimePicker.vue @@ -14,7 +14,7 @@ </template> <script lang="ts"> -import { Component, Emit, Vue } from "nuxt-property-decorator"; +import { Component, Emit, Prop, Vue, Watch } from "nuxt-property-decorator"; @Component export default class UiTimePicker extends Vue { @@ -25,9 +25,22 @@ end: '21:00' } + @Prop() + defaultValue!: string; + @Emit('changeTime') changeTime() { return this.timeValue; } + + @Watch('defaultValue', {immediate: true}) + updateDefault() { + if (this.defaultValue) { + const hours = new Date(this.defaultValue).getHours(); + const minutes = new Date(this.defaultValue).getMinutes(); + this.timeValue = `${hours < 10 ? '0' + hours : hours}:${minutes < 10 ? '0' + minutes : minutes}`; + this.changeTime(); + } + } } </script> \ No newline at end of file diff --git a/PAMapp/pages/appointment/_appointmentId/index.vue b/PAMapp/pages/appointment/_appointmentId/index.vue index 8e8495b..2957175 100644 --- a/PAMapp/pages/appointment/_appointmentId/index.vue +++ b/PAMapp/pages/appointment/_appointmentId/index.vue @@ -80,7 +80,7 @@ <section class="mt-30"> - <AppointmentInterviewList /> + <AppointmentInterviewList :interviewList="appointmentDetail.interviewRecordDTOs" /> </section> <section class="mt-30"> diff --git a/PAMapp/shared/models/appointment.model.ts b/PAMapp/shared/models/appointment.model.ts index 22e4e25..172112d 100644 --- a/PAMapp/shared/models/appointment.model.ts +++ b/PAMapp/shared/models/appointment.model.ts @@ -74,7 +74,7 @@ gender : string; hopeContactTime : string; id : number; - interviewRecordDTOs : string[]; + interviewRecordDTOs : InterviewRecord[]; job : string; lastModifiedDate : string; name : string; diff --git a/PAMapp/shared/services/appointment.service.ts b/PAMapp/shared/services/appointment.service.ts index 083712a..a15e298 100644 --- a/PAMapp/shared/services/appointment.service.ts +++ b/PAMapp/shared/services/appointment.service.ts @@ -77,7 +77,7 @@ // ��蝝赤閮�� async deleteInterviewRecord(interviewRecordId) { - return http.delete(`/interview_record/'${interviewRecordId}`); + return http.delete(`/interview_record/${interviewRecordId}`); } } diff --git a/PAMapp/store/index.ts b/PAMapp/store/index.ts index 1aabd10..6d112fe 100644 --- a/PAMapp/store/index.ts +++ b/PAMapp/store/index.ts @@ -9,8 +9,10 @@ import reviewsService from '~/shared/services/reviews.service'; import { Consultant } from '~/shared/models/consultant.model'; -import { Appointment, AppointmentLog } from '~/shared/models/appointment.model'; +import { Appointment, AppointmentLog, InterviewRecord } from '~/shared/models/appointment.model'; import { AgentOfStrictQuery } from '~/shared/models/strict-query.model'; +import { AgentInfo } from '~/shared/models/agent-info.model'; +import { agentCommunicationStyleList } from '~/shared/const/agent-communication-style-list'; @Module export default class Store extends VuexModule { recommendList: Consultant[] = []; @@ -21,6 +23,16 @@ myNewAppointmentSum: number = 0; myAppointmentReviewLogList: AppointmentLog[] = []; + interviewRecord: InterviewRecord = { + appointmentId : 0, + content : '', + createdBy : '', + createdDate : '', + id : 0, + interviewDate : '', + lastModifiedBy : '', + lastModifiedDate: '' + } get isUserLogin() { return this.context.getters['localStorage/isUserLogin']; @@ -56,6 +68,25 @@ this.myAppointmentReviewLogList = data; } + @Mutation + updateInterviewRecord(data: InterviewRecord) { + this.interviewRecord = data; + } + + @Mutation + clearInterviewRecord() { + this.interviewRecord = { + appointmentId : 0, + content : '', + createdBy : '', + createdDate : '', + id : 0, + interviewDate : '', + lastModifiedBy : '', + lastModifiedDate: '' + } + } + @Action storeRecommendList() { queryConsultantService.getRecommendConsultantList().then(data => { -- Gitblit v1.8.0