保誠-保戶業務員媒合平台
HelenHuang
2022-06-09 9bdb95c9e34cef640534e5e5a1e2225a80442000
PAMapp/pages/index.vue
@@ -41,46 +41,78 @@
    </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>
            <p class="smTxt">{{appointmentDetail.appointmentDate | formatDate}}</p>
            <div class="reserved-info">
                <p>姓名:{{appointmentDetail.name}}</p>
                <p>電話:{{appointmentDetail.phone}}</p>
                <p>Email:{{appointmentDetail.email}}</p>
                <p>性別:{{gender}}</p>
                <p>年齡:{{appointmentDetail.age | toAgeLabel }}</p>
                <p>職業:{{appointmentDetail.job}}</p>
                <p>需求:{{appointmentDetail.requirement.split(',').join('、')}}</p>
                <p
                    v-for="(item, index) in hopeContactTime"
                    :key="index"
                >連絡時段{{index + 1 | formatNumber}}:{{ item | formatHopeContactTime }}</p>
                <div v-if="appointmentDetail.satisfactionScore">
                    <div class="mdTxt mt-10 mb-10">滿意度</div>
                    <el-rate
                    :value="appointmentDetail.satisfactionScore"
                    class="pam-myDemand-dialog__rate"
                    disabled>
                    </el-rate>
                </div>
            </div>
          <div v-if="appointmentDetail">
              <h5 class="subTitle text--center mb-30">預約成功</h5>
              <p class="smTxt">{{appointmentDetail.appointmentDate | formatDate}}</p>
              <div class="reserved-info">
                  <p>姓名:{{appointmentDetail.name}}</p>
                  <p>電話:{{appointmentDetail.phone}}</p>
                  <p>Email:{{appointmentDetail.email}}</p>
                  <p>性別:{{gender}}</p>
                  <p>年齡:{{appointmentDetail.age | toAgeLabel }}</p>
                  <p>職業:{{appointmentDetail.job}}</p>
                  <p>需求:{{appointmentDetail.requirement.split(',').join('、')}}</p>
                  <p
                      v-for="(item, index) in hopeContactTime"
                      :key="index"
                  >連絡時段{{index + 1 | formatNumber}}:{{ item | formatHopeContactTime }}</p>
                  <div v-if="appointmentDetail.satisfactionScore">
                      <div class="mdTxt mt-10 mb-10">滿意度</div>
                      <el-rate
                      :value="appointmentDetail.satisfactionScore"
                      class="pam-myDemand-dialog__rate"
                      disabled>
                      </el-rate>
                  </div>
              </div>
            <div v-if="!appointmentDetail.satisfactionScore" class="reserved-btn">
                <el-button type="primary"
                    @click.native="reviewsBtn = true">給予滿意度評分</el-button>
            </div>
        </div>
              <div v-if="notScoreAppointmentYet" class="reserved-btn">
                  <el-button type="primary"
                      @click.native="reviewsBtn = true">給予滿意度評分</el-button>
              </div>
              <div v-if="appointmentDetail.communicateStatus === 'reserved'" class="text--center mt-10">
                  <el-button @click="isCancelPopup = true">取消預約</el-button>
                  <el-button @click="edit" type="primary">編輯</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,13 +142,21 @@
<script lang="ts">
  import { Vue, Component, State, Action, Watch, namespace } from 'nuxt-property-decorator';
  import { Consultant } from '~/shared/models/consultant.model';
import { UserReviewsConsultantsParams } from '~/shared/models/reviews.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 { Appointment, AppointmentClosedInfo } from '~/shared/models/appointment.model';
  import { Consultant } from '~/shared/models/consultant.model';
  import { UserReviewParams } from '~/shared/models/reviews.model';
  import { StrictQueryParams } from '~/shared/models/strict-query.model';
  import { AgentInfo } from '~/shared/models/agent-info.model';
  import { ContactStatus } from '~/shared/models/enum/contact-status';
import { SatisfactionType } from '~/shared/models/enum/satisfaction-type';
  const localStorage = namespace('localStorage');
  const roleStorage = namespace('localStorage');
  @Component({
    layout: 'home'
@@ -129,10 +169,17 @@
    @State('myConsultantList')
    myConsultantList!: Consultant[];
    @roleStorage.Getter
    isAdminLogin!: boolean;
    @roleStorage.Getter
    isUserLogin!: boolean;
    @Action
    storeRecommendList!: any;
    @Action storeConsultantList!: any;
    @Action
    storeConsultantList!: any;
    @localStorage.Mutation
    storageClearQuickFilter!: () => void;
@@ -143,37 +190,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               : '',
@@ -192,17 +257,32 @@
    //////////////////////////////////////////////////////////////////////
    mounted() {
      if (!this.recommendList?.length) {
        this.storeRecommendList();
      if (this.isAdminLogin) {
        this.$router.push('/myAppointmentList/appointmentList');
      } else {
        if (!this.recommendList?.length) {
          this.storeRecommendList();
        }
        this.storeConsultantList();
        this.storageClearQuickFilter();
        this.storageClearRecommendConsultant();
        if (this.isUserLogin) {
          appointmentService.getNotContactAppointment().then((appointment) => {
            if (appointment) {
              this.$router.push({ query: { notContactAppointmentId: appointment.id + ''}});
              this.autoOpenAppointmentBy('askReAppointment', appointment.id);
            }
          });
        }
      }
      this.storeConsultantList();
      this.storageClearQuickFilter();
      this.storageClearRecommendConsultant();
    }
    destroyed() {
      this.clearSatisfactionId();
      this.removeUrlQueryParameter();
    }
    //////////////////////////////////////////////////////////////////////
@@ -210,34 +290,59 @@
    @Watch('myConsultantList')
    onMyConsultantListChange() {
      this.consultantList = (this.myConsultantList || [])
        .filter(item => item.contactStatus !== 'contacted')
        .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.appointmentDetail.satisfactionScore) {
              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;
          }
        });
    }
    //////////////////////////////////////////////////////////////////////
@@ -246,39 +351,84 @@
      this.$router.push(path);
    }
    edit() {
        this.isShowAppointmentDialog = false;
        this.$router.push({path: `/questionnaire/${this.agentInfo.agentNo}`, query: {'edit': 'true'}});
    }
    reAppointment(): void {
      appointmentService.cancelAppointment(this.appointmentDetail.id).then(() => {
        const requirements = this.appointmentDetail.requirement.split(',');
        this.storeConsultantList();
        this.storageStrickQueryItem({ requirements: requirements });
        this.storageClearNotContactAppointmentIdFromMsg();
        this.removeUrlQueryParameter('notContactAppointmentId');
        this.$router.push('/recommendConsultant');
      });
    }
    cancelAppointment(): void {
      appointmentService.cancelAppointment(this.appointmentDetail.id).then(() => {
        this.storeConsultantList();
        this.storageClearNotContactAppointmentIdFromMsg();
        this.removeUrlQueryParameter('notContactAppointmentId');
        this.isShowReAppointmentDialog = false;
        this.isShowAppointmentDialog = false;
        this.$router.push('/');
      });
    }
    userReviewsConsultants() {
      const reviewParams: UserReviewsConsultantsParams = {
      const reviewParams: UserReviewParams = {
            appointmentId: this.appointmentDetail.id,
            score: this.inputScore,
            type: SatisfactionType.APPOINTMENT
        }
        this.appointmentDetail.satisfactionScore = this.inputScore;
        reviewsService.userReviewsConsultants(reviewParams).then((res) => {
            this.reviewsBtn = false;
            this.isShowReviewDialog = false;
        });
    }
    clearSatisfactionId() {
        console.log('close');
        this.$router.push({query: {}});
    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 = {};
        if (targetKey) {
          Object.keys(this.$route.query).forEach((key) => {
            if (key !== targetKey) {
              newRouteQuery[key] = this.$route.query[key]
            }
          })
        }
        this.$router.push(newRouteQuery);
        this.storageClearSatisfactionIdFromMsg();
        this.storageClearNotContactAppointmentIdFromMsg();
    }
    ///////////////////////////////////////////////////////////////////////////////
    get gender() {
    get gender(): string {
        if (this.appointmentDetail.gender) {
            return this.appointmentDetail.gender === 'male' ? '男性' : '女性';
        }
        return ''
    }
    get hopeContactTime() {
    get hopeContactTime(): string[] {
        const contactList = this.appointmentDetail.hopeContactTime
            .split("'").map((item: any) => item.slice(0, item.length));
        return contactList.filter((item: any) => !!item && item !== ",")
    }
    get notScoreAppointmentYet(): boolean {
      if (this.appointmentDetail.communicateStatus === 'closed' || this.appointmentDetail.communicateStatus === 'done') {
        return !this.appointmentDetail.satisfactionScore;
      };
      return false;
    }
  }
</script>