| | |
| | | <template> |
| | | <div> |
| | | <div class="pam-myAppointment-banner"></div> |
| | | <div class="pam-myAppointment-banner"></div> |
| | | <div class="pam-container"> |
| | | <div class="pam-cus-tabs mb-30"> |
| | | <div class="pam-cus-tabs mb-10"> |
| | | <div |
| | | class="cus-tab-item" |
| | | :class="{'is-active': activeTabName === 'appointmentList'}" |
| | | @click="tabClick('appointmentList')" |
| | | >客戶預約 |
| | | <span class="p">({{appointmentList.length}})</span> |
| | | @click="clickTab('appointmentList')" |
| | | > |
| | | <span class="smTxt">未聯絡({{ appointmentItemSum }})</span> |
| | | </div> |
| | | <div |
| | | class="cus-tab-item" |
| | | :class="{'is-active': activeTabName === 'contactedList'}" |
| | | @click="tabClick('contactedList')" |
| | | >已聯絡 |
| | | <span class="p">({{contactedList.length}})</span> |
| | | @click="clickTab('contactedList')" |
| | | > |
| | | <span class="smTxt">約訪中({{ contactedItemSum }})</span> |
| | | </div> |
| | | <div |
| | | class="cus-tab-item" |
| | | :class="{'is-active': activeTabName === 'closedList'}" |
| | | @click="clickTab('closedList')" |
| | | > |
| | | <span class="smTxt">結案({{ closedItemSum }})</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <NuxtChild></NuxtChild> |
| | | <NuxtChild keep-alive></NuxtChild> |
| | | |
| | | </div> |
| | | |
| | | <!-- DIALOG --> |
| | | <PopUpFrame |
| | | :isOpen.sync="showNewAppointmentNumber" |
| | | :isOpen.sync="isShowNewAppointmentHint" |
| | | > |
| | | <div class="text--center mdTxt"> |
| | | <p class="mb-50">你有 <span class="text--primary">{{newAppointmentNumber}}</span> 則新的預約</p> |
| | | <p class="mb-50">您有 <span class="text--primary">{{ newAppointmentSum }}</span> 則新的預約</p> |
| | | <div class="text--center"> |
| | | <el-button |
| | | type="primary" |
| | | @click="showNewAppointmentNumber = false" |
| | | @click="isShowNewAppointmentHint = false" |
| | | >我知道了</el-button> |
| | | </div> |
| | | </div> |
| | | </PopUpFrame> |
| | | |
| | | <PopUpFrame |
| | | :isOpen.sync="isShowRemindAppointmentDialog" |
| | | > |
| | | <div class="text--center mdTxt"> |
| | | <p class="mb-50">您有 <span class="text--primary">{{ pendingAppointmentSum }}</span> 則預約單未進行聯繫,請盡速處理</p> |
| | | <div class="text--center"> |
| | | <el-button |
| | | type="primary" |
| | | @click="isShowRemindAppointmentDialog = false" |
| | | >我知道了</el-button> |
| | | </div> |
| | | </div> |
| | | </PopUpFrame> |
| | | </div> |
| | | </template> |
| | | |
| | | <script lang="ts"> |
| | | import { Vue, Component, State, Action, Watch } from 'nuxt-property-decorator'; |
| | | import { allAppointmentsView, ClientInfo } from '~/assets/ts/api/appointment'; |
| | | import * as _ from 'lodash'; |
| | | import { Vue, Component, Watch, namespace } from 'nuxt-property-decorator'; |
| | | |
| | | import appointmentService from '~/shared/services/appointment.service'; |
| | | import { Appointment } from '~/shared/models/appointment.model'; |
| | | import { ContactStatus } from '~/shared/models/enum/contact-status'; |
| | | |
| | | const localStorage = namespace('localStorage'); |
| | | const appointmentStore = namespace('appointment.store'); |
| | | |
| | | @Component({ |
| | | layout: 'home' |
| | | layout: 'home', |
| | | middleware: 'myAppointment' |
| | | }) |
| | | export default class ClientReservedList extends Vue { |
| | | activeTabName = 'appointmentList'; |
| | | appointmentList: ClientInfo[] = []; |
| | | contactedList: ClientInfo[] = []; |
| | | clients: ClientInfo[] = []; |
| | | newAppointmentNumber: number = 0; |
| | | showNewAppointmentNumber = false; |
| | | |
| | | @State('myAppointmentList') myAppointmentList!: ClientInfo[]; |
| | | @Action storeMyAppointmentList!: () => Promise<number>; |
| | | @appointmentStore.State('myAppointmentList') |
| | | myAppointmentList!: Appointment[]; |
| | | |
| | | @appointmentStore.Getter('newAppointmentSum') |
| | | newAppointmentSum!: number; |
| | | |
| | | @appointmentStore.Getter('appointmentItemSum') |
| | | appointmentItemSum!: number; |
| | | |
| | | @appointmentStore.Getter('contactedItemSum') |
| | | contactedItemSum!: number; |
| | | |
| | | @appointmentStore.Getter('closedItemSum') |
| | | closedItemSum!: number; |
| | | |
| | | @appointmentStore.Action |
| | | getMyAppointmentList!: () => Promise<Appointment[]>; |
| | | |
| | | @localStorage.Mutation |
| | | storageClearAppointmentIdFromMsg!: () => void; |
| | | |
| | | @localStorage.Getter |
| | | currentAppointmentIdFromMsg!: string; |
| | | |
| | | contactStatus = ContactStatus; |
| | | |
| | | activeTabName = 'appointmentList'; |
| | | isShowNewAppointmentHint = false; |
| | | isShowRemindAppointmentDialog = false; |
| | | pendingAppointmentSum = 0; |
| | | |
| | | ////////////////////////////////////////////////////////////////////// |
| | | |
| | | mounted() { |
| | | this.storeMyAppointmentList().then(newDataLength => { |
| | | this.newAppointmentNumber = newDataLength; |
| | | if (this.newAppointmentNumber > 0) { |
| | | this.showNewAppointmentNumber = true; |
| | | allAppointmentsView().then(res => res); |
| | | } |
| | | }); |
| | | |
| | | if (this.$route.name) { |
| | | this.activeTabName = this.$route.name.split('-')[1] |
| | | } |
| | | this.getMyAppointmentList(); |
| | | appointmentService.getPendingAppointmentSum().then((pendingAppointmentSum) => { |
| | | this.pendingAppointmentSum = pendingAppointmentSum; |
| | | if (this.pendingAppointmentSum) { |
| | | this.isShowRemindAppointmentDialog = true; |
| | | } |
| | | }); |
| | | } |
| | | |
| | | destroyed() { |
| | | this.storageClearAppointmentIdFromMsg(); |
| | | } |
| | | |
| | | ////////////////////////////////////////////////////////////////////// |
| | | |
| | | @Watch('myAppointmentList') |
| | | onMyAppointmentListChange() { |
| | | this.contactedList = this.myAppointmentList |
| | | .filter(item => item.communicateStatus === 'contacted'); |
| | | |
| | | this.appointmentList = this.myAppointmentList |
| | | .filter(item => item.communicateStatus !== 'contacted'); |
| | | onMyAppointmentListChange(): void { |
| | | if (this.currentAppointmentIdFromMsg) { |
| | | this.redirectAppointmentStatus(); |
| | | } |
| | | } |
| | | |
| | | tabClick(path: string) { |
| | | this.activeTabName = path; |
| | | this.$router.push('/myAppointmentList/' + this.activeTabName) |
| | | } |
| | | |
| | | get route(): string{ |
| | | const routeName = this.$route.name; |
| | | return routeName ? routeName:''; |
| | | private redirectAppointmentStatus() { |
| | | const currentAppointmentIndex = this.myAppointmentList |
| | | .findIndex(item => item.id === +this.currentAppointmentIdFromMsg); |
| | | if (currentAppointmentIndex > -1) { |
| | | const communicateStatus = this.myAppointmentList[currentAppointmentIndex].communicateStatus; |
| | | let pathName = 'closedList' |
| | | if (communicateStatus === this.contactStatus.RESERVED || communicateStatus === this.contactStatus.PICKED) { |
| | | pathName = 'contactedList'; |
| | | } |
| | | if (communicateStatus === this.contactStatus.CONTACTED) { |
| | | pathName = 'contactedList'; |
| | | } |
| | | this.$router.push( |
| | | { |
| | | path: '/myAppointmentList/' + pathName, |
| | | query: {appointmentId: this.currentAppointmentIdFromMsg} |
| | | } |
| | | ); |
| | | } |
| | | }; |
| | | |
| | | @Watch('newAppointmentSum') |
| | | newAppointmentSumChange(): void { |
| | | this.isShowNewAppointmentHint = this.newAppointmentSum > 0; |
| | | } |
| | | |
| | | @Watch('$route', {immediate: true}) |
| | | onRouteChange() { |
| | | const routeFullName = this.$route.name; |
| | | if (routeFullName) { |
| | | this.activeTabName = routeFullName.split('-')[1]; |
| | | } |
| | | } |
| | | |
| | | ////////////////////////////////////////////////////////////////////// |
| | | |
| | | clickTab(path: string): void { |
| | | this.activeTabName = path; |
| | | this.$router.push(`/myAppointmentList/${this.activeTabName}`); |
| | | } |
| | | |
| | | get bannerClassName() { |
| | | return this.routeFormatBannerClass(this.route); |
| | | const routeName = this.$route.name || ''; |
| | | return this.routeFormatBannerClass(routeName); |
| | | }; |
| | | |
| | | // format to {page}-banner or pam-no-banner tag |
| | | private routeFormatBannerClass(route: string): string { |
| | | const needBannerTags = ['myAppointmentList-appointmentList', 'myAppointmentList-contactedList']; |
| | | return _.includes(needBannerTags, route) ? route + '-banner' : 'pam-no-banner'; |
| | | const needBannerTags = ['myAppointmentList-appointmentList', 'myAppointmentList-closedList']; |
| | | return needBannerTags.includes(route) ? route + '-banner' : 'pam-no-banner'; |
| | | }; |
| | | |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .pam-myAppointment-banner { |
| | | width: 100%; |
| | | height: 120px; |
| | | background-size: cover; |
| | | background-repeat: no-repeat; |
| | | width : 100%; |
| | | height : 120px; |
| | | background-size : cover; |
| | | background-repeat : no-repeat; |
| | | background-position: center; |
| | | position: relative; |
| | | background-image: url('~/assets/images/myAppointmentList/agent_banner_mob.svg'); |
| | | position : relative; |
| | | background-image : url('~/assets/images/myAppointmentList/agent_banner_mob.svg'); |
| | | } |
| | | |
| | | @media (min-width: 768px) { |
| | |
| | | margin: 30px auto; |
| | | } |
| | | } |
| | | </style> |
| | | </style> |