保誠-保戶業務員媒合平台
Mila
2021-12-13 544f91e63a01f37e7b79db99609eec99b1afafd9
PAMapp/pages/questionnaire/_agentNo.vue
@@ -1,8 +1,10 @@
<template>
  <div class="ques-page--reset">
  <div class="ques-page--reset" v-if="isUserLogin">
    <div class="ques-header">
        <div class="ques-header__mob-banner"></div>
        <div class="ques-header__info" v-if="myRequest.contactType==='phone'">
        <div
          class="ques-header__info"
          v-if="myRequest.contactType==='phone'">
          <div class="text--middle">
              <div class="mdTxt">你指定的聯繫方式</div>
              <div class="mt-10">
@@ -21,7 +23,7 @@
              <div class="mdTxt">其他備用聯繫方式</div>
              <div class="ques-header__input-block">
                  <span>Email:</span>
                  <input class="ques-header__input"
                  <input class="ques-header__input"
                    placeholder="請輸入"
                    v-model="myRequest.email">
              </div>
@@ -49,7 +51,7 @@
                <span v-show="!phoneValid">手機號碼格式有誤</span>
              </div>
          </div>
          <div class="mt-30" v-if="checkPhoneLength&&phoneValid">
          <div class="mt-30" v-if="myRequest.phone && phoneValid">
              <div class="datepicker">
                  <span class="mdTxt">手機連絡的方便時間</span>
                  <PhoneContactTimePicker
@@ -88,14 +90,14 @@
      </div>
      <div class="pam-paragraph ques-footer">
        <el-button type="primary"
          :disabled="isRequiredByInit || !phoneValid"
          :disabled="isDisabledSubmitBtn"
          @click.native="sentDemand">
          送出
          {{isEditBtn ? '更新' : '送出'}}
        </el-button>
      </div>
    </div>
    <PopUpFrame :isOpen.sync="showDrawer" :drawerSize=" '95%' ">
    <PopUpFrame :isOpen.sync="showDrawer">
      <div class="qaTextTitle mdTxt">
        <strong>想要詢問的問題</strong>
      </div>
@@ -122,18 +124,34 @@
          </el-button>
        </div>
    </PopUpFrame>
    <PopUpFrame :isOpen.sync="isEditPopup">
      <div class="text--middle mt-30 sendReserve-txt">是否繼續編輯預約單?</div>
      <div class="text--center mdTxt">
        <el-button @click="$router.go(-1)">返回</el-button>
        <el-button @click="isEditPopup = false" type="primary">編輯</el-button>
      </div>
    </PopUpFrame>
  </div>
</template>
<script lang="ts">
  import { Vue, Component } from 'vue-property-decorator';
  import { addFavoriteConsultant, appointmentDemand, AppointmentParams, AppointmentRequests ,RegisterInfo } from '~/assets/ts/api/consultant';
  import { getRequestsFromStorage, setRequestsToStorage } from '~/assets/ts/storageRequests';
  import { Gender } from '~/assets/ts/models/enum/Gender';
  import { ContactType } from '~/assets/ts/models/enum/ContactType';
  import _ from 'lodash';
import { Vue, Component, State, Action, Watch, namespace } from 'nuxt-property-decorator';
import { addFavoriteConsultant, appointmentDemand, AppointmentParams, AppointmentRequests ,editAppointment,RegisterInfo } from '~/assets/ts/api/consultant';
import { getRequestQuestionFromStorage, getRequestsFromStorage, removeRequestQuestionFromStorage, setRequestsToStorage } from '~/assets/ts/storageRequests';
import _ from 'lodash';
import { Consultant } from '~/assets/ts/models/consultant.model';
import { ContactType } from '~/assets/ts/models/enum/ContactType';
import { Gender } from '~/assets/ts/models/enum/Gender';
import { Role } from '~/assets/ts/models/enum/Role';
  const roleStorage = namespace('localStorage');
  @Component
  export default class Questionnaire extends Vue {
    @State('myConsultantList') myConsultantList!: Consultant[];
    @Action storeConsultantList!: () => Promise<number>;
    @roleStorage.Getter isUserLogin!:boolean;
    genderOptions=[
      {
        title:'男性',
@@ -144,6 +162,7 @@
        label:Gender.FEMALE,
      }
    ];
    requirementOptions=[
      {
        title:'健康與保障',
@@ -166,10 +185,11 @@
        label:'保單健檢/規劃',
      },
      {
        title:'分紅保單相關',
        label:'分紅保單相關',
        title:'分紅保單',
        label:'分紅保單',
      },
    ];
    ageRangeOptions=[
      {
        title:'20歲以下',
@@ -188,10 +208,6 @@
        label:'41-50'
      },
      {
        title:'46-55 歲',
        label:'46-55',
      },
      {
        title:'51-60 歲',
        label:'51-60',
      },
@@ -204,102 +220,169 @@
        label:'over_71',
      }
    ];
    quesAboutList = [
      {
        title:'健康與保障',
        content:'突發的意外或疾病,往往造成個人或家庭沉重的經濟負擔,周全的保險才能擁有一個無憂的未來。'
      },
      {
        title:'子女教育',
        content:'利用分紅保單,規劃教育基金 提早為子女作準備,讓生活更有保障!'
      },
      {
        title:'資產規劃',
        content:'當財務責任加重時,規劃充足的保障、提供經濟上的庇護,是人生最堅強的後盾。'
      },
      {
        title:'樂活退休',
        content:'兼具保險與投資雙重功能,可靈活搭配各種附約,順應人生不同階段的靈活需要。'
      },
      {
        title:'保單健檢/規劃',
        content:'全面檢視自己的保障結構是否符合現在或未來的風險移轉需求,透過「斷、捨、離」把錢花在刀口上。'
      },
      {
        title:'防疫保單',
        content:'匹配度是透過嚴選配對或快速篩選後,將每一位保險顧問資料進行比對後排序推薦給您的媒合數值,您可以作為選擇適合顧問的參考值。'
      }
                  {
                      title:'健康與保障',
                      content:'唯有把身體照顧好,才是保障幸福之本,不做盲目燃燒的蠟燭,只做綻開的陽光,陪孩子多走一哩路,人生的美正要開展。'
                  },
                  {
                      title:'子女教育',
                      content:'孩子,我們是雙方的導師也是學生,面對未來要並肩作戰,學會勇敢無畏、克服挫折、善於理財,這條路上我們一起學。'
                  },
                  {
                      title:'資產規劃',
                      content:'真正的財富來自嚴謹規劃資產傳承,為人生蓋一堵抵禦財務風險的牆,確保資產穩健成長,替全家族的未來做好萬全準備。'
                  },
                  {
                      title:'樂活退休',
                      content:'拼一輩子,退休後的日子要輕鬆快活,就得提早透過保險商品規劃退休財務,替自己創造穩定收入,為精彩的熟年人生揭開序幕。'
                  },
                  {
                      title:'保單健檢/規劃',
                      content:'全面檢視自己的保障結構是否符合現在或未來的風險移轉需求。'
                  },
                  {
                      title:'分紅保單',
                      content:'分紅保單 分紅保單是兼具「分攤風險」與「紅利共享」特色的保單,具有一定穩定度,讓你可以同時享有壽險保障及紅利!'
                  }
    ];
    myRequest= {
      phone:this.userInfo?.phone ? this.userInfo.phone :'',
      email:this.userInfo?.email ? this.userInfo.email :'',
      contactType:_.includes(this.userInfo.contactType,ContactType.SMS) ? ContactType.PHONE : ContactType.EMAIL  ,
      gender: '',
      age: '',
      job: '',
      requirement: [],
    myRequest: AppointmentRequests = {
      phone          : this.userInfo?.phone ? this.userInfo.phone                               : '',
      email          : this.userInfo?.email ? this.userInfo.email                               : '',
      contactType    : _.isEqual(this.userInfo?.contactType,ContactType.SMS) ? ContactType.PHONE: ContactType.EMAIL,
      gender         : '',
      age            : '',
      job            : '',
      requirement    : [],
      hopeContactTime: [{
        selectWeekOptions:[],
        selectTimesOptions:[],
        selectWeekOptions : [],
        selectTimesOptions: [],
      }],
      agentNo:this.$route.params.agentNo,
      agentNo: '',
    };
    showDrawer= false;
    sendReserve = false;
    isEditPopup = false;
    isEditBtn = false;
    mounted() {
    appointmentId = 0;
    beforeRouteEnter(to: any, from: any, next: any) {
      next(vm => {
        const isUserLogin = vm.$store.getters['localStorage/isUserLogin'];
        if (from.name === 'login' && !isUserLogin) {
          vm.$router.go(-1);
          return;
        }
        if (!isUserLogin) {
          vm.$router.push('/login');
        }
      })
    }
    async fetch() {
      if (this.isUserLogin) {
        await this.storeConsultantList();
      };
    }
    mounted(): void {
      this.setMyRequest();
    }
    private setMyRequest(): void {
      const storageMyRequest = getRequestsFromStorage();
      const storageMyQuestion = getRequestQuestionFromStorage();
      if (storageMyRequest) {
        this.myRequest = storageMyRequest;
        this.myRequest = {
          ...storageMyRequest,
          hopeContactTime: storageMyRequest.hopeContactTime?.length
                            ? storageMyRequest.hopeContactTime
                            : [{
                                selectWeekOptions: [],
                                selectTimesOptions: [],
                              }],
        };
      }
      if (storageMyQuestion) {
        this.myRequest = {
          ...this.myRequest,
          requirement: storageMyQuestion
        }
        removeRequestQuestionFromStorage();
      }
    }
    get phoneValid():boolean{
    get phoneValid(): boolean {
      const rule = /^09[0-9]{8}$/;
      return this.myRequest.phone ? rule.test(this.myRequest.phone) : true;
      return this.myRequest.phone
            ? rule.test(this.myRequest.phone) && _.isEqual(this.myRequest.phone.length,10)
            : true;
    }
    get userInfo():RegisterInfo{
      const initUserInfo = JSON.parse(localStorage.getItem('userInfo'));
    get userInfo(): RegisterInfo {
      const initUserInfo = JSON.parse(localStorage.getItem('userInfo')!);
      return initUserInfo;
    }
    get isMainContractPhoneByLocalStorage():boolean{
      return true;
    get isDisabledSubmitBtn(): boolean {
           return _.includes(this.myRequest.contactType,ContactType.PHONE)
      ? !this.isHopeContactTimeDone()
      : !this.phoneValid;
    }
    get isRequiredByInit():boolean{
     return _.includes(this.myRequest.contactType,ContactType.PHONE)
      ? !this.isHopeContactTimeDone()
      :false;
    }
    get checkPhoneLength():boolean{
      return _.isEqual(this.myRequest.phone.length,10);
    }
    private isHopeContactTimeDone():boolean{
      return this.myRequest.hopeContactTime[0].selectWeekOptions.length >0 && this.myRequest.hopeContactTime[0].selectTimesOptions.length >0;
      return this.myRequest.hopeContactTime[0]?.selectWeekOptions.length >0 && this.myRequest.hopeContactTime[0]?.selectTimesOptions.length >0;
    }
    sentDemand() {
      addFavoriteConsultant([this.myRequest.agentNo]).then(res => this.sentAppointmentDemand());
      if (this.isEditBtn) {
        this.sentEditAppointmentDemand();
      } else {
        addFavoriteConsultant([this.$route.params.agentNo]).then(res => this.sentAppointmentDemand());
      }
    }
    private sentAppointmentDemand() {
        const data: AppointmentParams = {
          ...this.myRequest,
          requirement: _.map(this.myRequest.requirement,o=>o).toString(),
          hopeContactTime:this.phoneValid&&this.checkPhoneLength ? this.getHopeContactTime() :'',
          hopeContactTime: this.myRequest.phone && this.phoneValid ? this.getHopeContactTime() :'',
          agentNo: this.$route.params.agentNo
        };
        appointmentDemand(data).then(res => {
            this.sendReserve = true;
            this.myRequest.hopeContactTime = [];
            setRequestsToStorage(this.myRequest);
        });
    }
    private sentEditAppointmentDemand() {
      const info = {
          ...this.myRequest,
          requirement: _.map(this.myRequest.requirement,o=>o).toString(),
          hopeContactTime: this.myRequest.phone && this.phoneValid ? this.getHopeContactTime() :'',
          id: this.appointmentId,
          otherRequirement: null
        }
        editAppointment(info).then(res => {
          this.sendReserve = true;
          this.myRequest.hopeContactTime = [];
          setRequestsToStorage(this.myRequest);
        });
    }
    getHopeContactTime() {
        return this.myRequest.hopeContactTime.map(i => {
        const selectedHopeContactTime = this.myRequest.hopeContactTime.filter((i) => i.selectWeekOptions?.length && i.selectTimesOptions?.length);
        return selectedHopeContactTime.map(i => {
            return `'${i.selectWeekOptions}、${i.selectTimesOptions}'`}
        ).toString();
    }
@@ -309,37 +392,102 @@
        this.$router.push('/')
    }
  }
    private getLatestReserved(agentNo) {
      const agentInfo = this.myConsultantList.filter(item => item.agentNo === agentNo);
  export interface SelectedQuestion {
      name: string;
      selected: boolean;
      const appointmentInfo = agentInfo.length > 0 && agentInfo[0].appointments
        ? agentInfo[0].appointments!
              .filter((appointment) => appointment.communicateStatus !== 'contacted')
              .map((reversedAppointment) => {
                return {
                  ...reversedAppointment,
                  sortDate: new Date(reversedAppointment.appointmentDate)
                }
              })
              .sort((preAppointment, nextAppointment) => +nextAppointment.sortDate - +preAppointment.sortDate)[0]
        : null;
      return this.getReservedData(appointmentInfo);
    }
    private getReservedData(appointmentInfo) {
      if (appointmentInfo) {
        const hopeContactTime = appointmentInfo!.hopeContactTime.split("'")
              .filter(item => item && item !== ',');
        this.appointmentId = appointmentInfo.id;
        return {
            age: appointmentInfo.age,
            agentNo: appointmentInfo.agentNo,
            contactType: appointmentInfo.contactType,
            email: appointmentInfo.email || '',
            gender: appointmentInfo.gender,
            hopeContactTime: hopeContactTime.map(item => {
                const info = item.split('、');
                return {
                    selectWeekOptions: info[0].split(','),
                    selectTimesOptions: info[1].split(',')
                }
            }),
            job: appointmentInfo.job,
            phone: appointmentInfo.phone || '',
            requirement: appointmentInfo.requirement.split(',')
          }
      } else {
        return {
          age: '',
          agentNo: '',
          contactType: '',
          email: '',
          gender: '',
          hopeContactTime: [],
          job: '',
          phone: '',
          requirement: []
        }
      }
    }
    @Watch('myConsultantList') onMyConsultantListChange() {
      if (this.isUserLogin && this.myConsultantList.length > 0) {
          const editAppointment = this.getLatestReserved(this.$route.params.agentNo);
          if (editAppointment.agentNo) {
            this.myRequest = JSON.parse(JSON.stringify(editAppointment));
            if (!this.$route.query || this.$route.query.edit !== 'true') {
              this.isEditPopup = true;
            }
            this.isEditBtn = true;
            return;
          }
      }
    }
  }
</script>
<style lang="scss" scoped>
.sendReserve-txt{
    display: flex;
    justify-content: center;
    margin-top: 10px;
    margin-bottom: 26px;
  display: flex;
  justify-content: center;
  margin-top: 10px;
  margin-bottom: 26px;
}
//drawer最底下文字樣式
.qa-dialog-footer{
    display: flex;
    justify-content: center;
    margin-bottom: 81px;
    color: #ED1B2E;
    cursor: pointer;
}//drawer最底下文字樣式
  display: flex;
  justify-content: center;
  margin-bottom: 81px;
  color: #ED1B2E;
  cursor: pointer;
}
//送出按鈕樣式與排版
.ques-footer{
    justify-content: center;
    margin: 30px 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    .el-button {
  justify-content: center;
  margin: 30px 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  .el-button {
    width: 120px;
    height:50px;
    background-color: #ED1B2E;
@@ -362,47 +510,47 @@
    border-style: solid;
    pointer-events: none;
    }
    }
}//送出按鈕樣式與排版
  }
}
//詳細問題drawer中間內容空間大小設置
.qa-dialog{
    overflow-y:auto;
    height: 500px;
    margin-top: 20px;
}//詳細問題drawer中間內容空間大小設置
  overflow-y:auto;
  height: 60vh;
  margin-top: 20px;
}
//詳細問題drawer主要標題
.qaTextTitle{
    margin-top:30px;
    display: flex;
    justify-content: center;
}//詳細問題drawer主要標題
.el-button+.el-button{
    margin-left: 0;
  margin-top:30px;
  display: flex;
  justify-content: center;
}
.datepicker{
    display: flex;
    flex-direction: column;
  display: flex;
  flex-direction: column;
}
.required {
    position: relative;
    &::before {
        content: '*';
        position: absolute;
        color: #FF0000;
        transform: translate(-12px, 0);
    }
  position: relative;
  &::before {
      content: '*';
      position: absolute;
      color: #FF0000;
      transform: translate(-12px, 0);
  }
}
.ques-page--reset.pam-page-container{
    margin: 0px auto;
.ques-page--reset.pam-page-container {
  margin: 0px auto;
}
.ques-header{
    position: relative;
.ques-header {
  position: relative;
}
.ques-header__mob-banner{
.ques-header__mob-banner {
  width: 100%;
  min-height: 80px;
  background-color: #F8F9FA;
@@ -411,40 +559,42 @@
  background-size: cover;
  background-position: center;
}
.ques-header__info{
  position: relative;
  padding:30px 20px;
  margin: 0px 20px;
  background-color: #B3E7E3;
  border-radius: 10px;
}
.ques-header__input-block{
  display: flex;
  align-items: center;
  @extend .text--middle,.mt-10 ;
  .ques-header__input{
    &.is-invalid{
      border: 2px solid $PRIMARY_RED !important;
    }
    flex: 1;
    height: 50px;
  .ques-header__info {
    position: relative;
    padding:30px 20px;
    margin: 0px 20px;
    background-color: #B3E7E3;
    border-radius: 10px;
    border: 1px #CCCCCC solid;
    background-color: $PRIMARY_WHITE;
    padding: 15px 10px;
    box-sizing: border-box;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
  }
}
.ques-container{
  position: relative;
  margin: 0px 20px;
}
  .ques-header__input-block {
    display: flex;
    align-items: center;
    @extend .text--middle,.mt-10 ;
    .ques-header__input{
      &.is-invalid{
        border: 2px solid $PRIMARY_RED !important;
      }
      flex: 1;
      height: 50px;
      border-radius: 10px;
      border: 1px #CCCCCC solid;
      background-color: $PRIMARY_WHITE;
      padding: 15px 10px;
      box-sizing: border-box;
      -webkit-box-sizing: border-box;
      -moz-box-sizing: border-box;
    }
  }
  .ques-container {
    position: relative;
    margin: 0px 20px;
  }
@include desktop{
  @include desktop{
  .ques-header{
    display: flex;
    justify-content: flex-end;
@@ -471,3 +621,4 @@
}
</style>