| | |
| | | <template> |
| | | <div> |
| | | <el-row type="flex" class="rowStyle"> |
| | | <el-col :xs="5" :sm="3"> |
| | | <el-row |
| | | type="flex" |
| | | class="rowStyle cursor--pointer" |
| | | justify="space-between" |
| | | :class="{'new': !isView && isReserved}" |
| | | @click.native="openDetail" |
| | | > |
| | | <el-col :xs="1" :sm="1" class="unread" align="middle" v-if="isReserved"> |
| | | <div class="circle" v-if="!isRead"></div> |
| | | </el-col> |
| | | <el-col :xs="5" :sm="3" align="middle"> |
| | | <el-avatar |
| | | :size="50" |
| | | src="" |
| | | class="cursor--pointer" |
| | | ></el-avatar> |
| | | <!-- <div class="satisfaction"> |
| | | <i class="icon-star pam-icon icon--yellow satisfaction"></i> |
| | | <span>{{'1'}}</span> |
| | | </div> --> |
| | | <div class="satisfaction"> |
| | | <template v-if="client.satisfactionScore"> |
| | | <i class="icon-star pam-icon icon--yellow satisfaction"></i> |
| | | <span>{{client.satisfactionScore}}</span> |
| | | </template> |
| | | <template v-else> |
| | | <div class="unfilled">未填滿意度</div> |
| | | </template> |
| | | </div> |
| | | </el-col> |
| | | <el-col :xs="14" :sm="15"> |
| | | <el-col :xs="14" :sm="14" class="pl-10"> |
| | | <div class="smTxt_bold name">{{client.name}}</div> |
| | | <div class="message">預約成功</div> |
| | | <div class="professionals"> |
| | |
| | | </template> |
| | | </div> |
| | | </el-col> |
| | | <el-col class="flex-column contactInfo" :xs="5" :sm="6"> |
| | | <div class="smTxt_bold cursor--pointer" |
| | | :class="client.communicateStatus" |
| | | @click="openDetail" |
| | | >{{isReserved ? '已預約' : '已聯絡'}} |
| | | </div> |
| | | <div class="date xsTxt text--mid_grey">{{date}}</div> |
| | | <div class="xsTxt text--mid_grey">{{time}}</div> |
| | | <el-col class="flex-column contactInfo" :xs="4" :sm="6"> |
| | | <div |
| | | class="smTxt_bold fix-chrome-click--issue" |
| | | :class="{'unread-txt': reservedTxt === '未讀', 'read-txt': reservedTxt !== '未讀'}" |
| | | >{{reservedTxt}}</div> |
| | | <div |
| | | class="date xsTxt text--mid_grey" |
| | | >{{date}}</div> |
| | | <div |
| | | class="xsTxt text--mid_grey" |
| | | >{{time}}</div> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <Ui-Dialog |
| | | :isVisible.sync="isVisibleDialog" |
| | | :width="width" |
| | | @closeDialog="close" |
| | | class="pam-myDemand-dialog" |
| | | > |
| | | <h5 class="subTitle text--center mb-30" |
| | | >{{isReserved ? '預約成功' : '已聯絡資訊'}}</h5> |
| | | <p class="smTxt text-right">{{client.appointmentDate | formatDate}}</p> |
| | | >{{isReserved ? '預約資訊' : '已聯絡資訊'}}</h5> |
| | | |
| | | <p v-if='isReserved' |
| | | class="smTxt text-right" |
| | | ><span v-if="isRead">{{client.consultantReadTime | formatDate}}</span> 已讀</p> |
| | | <p |
| | | v-if="!isReserved" |
| | | class="smTxt text-right" |
| | | >{{client.contactTime | formatDate}} 聯絡</p> |
| | | <p class="smTxt">{{client.appointmentDate | formatDate}} 預約</p> |
| | | |
| | | <div class="dialogTxt"> |
| | | <p>姓名:{{client.name}}</p> |
| | | <p>電話:{{client.phone}}</p> |
| | | <p>Email:{{client.email}}</p> |
| | | <p>性別:{{gender}}</p> |
| | | <p>年齡:{{client.age}}</p> |
| | | <p>職業:{{client.job}}</p> |
| | | <p>需求:{{client.requirement.replace(',', '、')}}</p> |
| | | <p v-for="(item, index) in hopeContactTime" :key="index">連絡時段{{index + 1 | formatNumber}}:{{item}}</p> |
| | | <p>姓名:<span>{{client.name}}</span></p> |
| | | <p>電話:<span>{{client.phone}}</span></p> |
| | | <p>Email:<span>{{client.email}}</span></p> |
| | | <p>性別:<span>{{gender}}</span></p> |
| | | <p>年齡:<span>{{client.age | toAgeLabel }}</span></p> |
| | | <p>職業:<span>{{client.job}}</span></p> |
| | | <p>需求:<span>{{client.requirement.split(',').join('、')}}</span></p> |
| | | <p v-for="(item, index) in hopeContactTime" |
| | | :key="index" |
| | | >連絡時段{{index + 1 | formatNumber}}:<span>{{ item | formatHopeContactTime}}</span></p> |
| | | </div> |
| | | <div class="mt-30 text--center" v-if="isReserved"> |
| | | <el-button @click="markAppointment">標註為已連絡</el-button> |
| | | </div> |
| | | |
| | | </div> |
| | | </Ui-Dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script lang="ts"> |
| | | import { Vue, Component, Prop } from 'nuxt-property-decorator'; |
| | | import { Vue, Component, Prop, Action } from 'nuxt-property-decorator'; |
| | | import { isMobileDevice } from '~/assets/ts/device'; |
| | | import { ClientInfo, markAsContact } from '~/assets/ts/api/appointment'; |
| | | import { ClientInfo, markAsContact, recordRead } from '~/assets/ts/api/appointment'; |
| | | |
| | | @Component({ |
| | | filters: { |
| | |
| | | const upperNumber = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十'] |
| | | return upperNumber[index]; |
| | | } |
| | | }, |
| | | formatHopeContactTime(item: string): string { |
| | | if (item) { |
| | | const [hopeDay, hopeTime] = item.split('、'); |
| | | const day = hopeDay.split(',').length > 6 ? '不限日期' : hopeDay; |
| | | const time = hopeTime.split(',').length > 3 ? '不限時間' : hopeTime; |
| | | return `${day}、${time}`; |
| | | } |
| | | return ''; |
| | | } |
| | | } |
| | | }) |
| | | export default class ClientList extends Vue { |
| | | @Action updateMyAppointment!: (data: ClientInfo) => void |
| | | @Action storeConsultantList!: () => void; |
| | | |
| | | @Prop() client!: ClientInfo; |
| | | isVisibleDialog = false; |
| | | width = ''; |
| | |
| | | } |
| | | |
| | | get hopeContactTime() { |
| | | const contactList = this.client.hopeContactTime.split("'").map(item => item.slice(0, item.length - 1)); |
| | | return contactList.filter(item => !!item) |
| | | } |
| | | |
| | | get time() { |
| | | const formatDate = (this.$options.filters as any).formatDate(this.client.appointmentDate); |
| | | return formatDate.split(' ')[1] |
| | | } |
| | | |
| | | get date() { |
| | | const formatDate = (this.$options.filters as any).formatDate(this.client.appointmentDate); |
| | | return formatDate.split(' ')[0] |
| | | const contactList = this.client.hopeContactTime.split("'").map(item => item.slice(0, item.length)); |
| | | return contactList.filter(item => !!item && item !== ",") |
| | | } |
| | | |
| | | get isReserved() { |
| | | return this.client.communicateStatus === 'reserved'; |
| | | } |
| | | |
| | | get isRead() { |
| | | return !!this.client.consultantReadTime; |
| | | } |
| | | |
| | | get isView() { |
| | | return !!this.client.consultantViewTime; |
| | | } |
| | | |
| | | get reservedTxt() { |
| | | if (this.isReserved) { |
| | | return this.client.consultantReadTime ? '已讀' : '未讀'; |
| | | } else { |
| | | return '已聯絡' |
| | | } |
| | | } |
| | | |
| | | get latestUpdateTime() { |
| | | if (this.isReserved) { |
| | | return this.client.consultantReadTime ? this.client.consultantReadTime : this.client.appointmentDate; |
| | | } else { |
| | | return this.client.contactTime; |
| | | } |
| | | } |
| | | |
| | | get time() { |
| | | const formatDate = (this.$options.filters as any).formatDate(this.latestUpdateTime); |
| | | return formatDate.split(' ')[1] |
| | | } |
| | | |
| | | get date() { |
| | | const formatDate = (this.$options.filters as any).formatDate(this.latestUpdateTime); |
| | | return formatDate.split(' ')[0]; |
| | | } |
| | | |
| | | openDetail() { |
| | |
| | | } |
| | | |
| | | markAppointment() { |
| | | markAsContact(this.client.id).then(res => this.$router.go(0)) |
| | | markAsContact(this.client.id).then(data => { |
| | | // TODO: 要接後台傳回的 updated client 資料 - Ben 2021/11/16 |
| | | |
| | | const updatedClient = {...this.client}; |
| | | updatedClient.communicateStatus = 'contacted'; |
| | | updatedClient.contactTime = new Date(); |
| | | |
| | | this.updateMyAppointment(updatedClient); |
| | | this.isVisibleDialog = false; |
| | | |
| | | }) |
| | | } |
| | | |
| | | close() { |
| | | if (!this.client.consultantReadTime) { |
| | | recordRead(this.client.id).then(res => { |
| | | const updatedClient = {...this.client}; |
| | | updatedClient.consultantReadTime = new Date(); |
| | | |
| | | this.updateMyAppointment(updatedClient); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | <style lang="scss" scoped> |
| | | .rowStyle { |
| | | padding: 10px; |
| | | padding: 10px 15px 10px 5px; |
| | | background-color: $PRIMARY_WHITE; |
| | | margin-bottom: 10px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | |
| | | &.new { |
| | | border-left: solid 4px $YELLOW; |
| | | } |
| | | |
| | | .unread { |
| | | align-self: center; |
| | | |
| | | .circle { |
| | | width: 10px; |
| | | height: 10px; |
| | | border-radius: 50px; |
| | | background-color: $PRIMARY_RED; |
| | | margin: auto; |
| | | } |
| | | } |
| | | |
| | | .satisfaction { |
| | | font-size: 12px; |
| | | font-weight: bold; |
| | | margin-top: 5px; |
| | | |
| | | .unfilled { |
| | | font-weight: lighter; |
| | | color: $MID_GREY; |
| | | } |
| | | } |
| | | |
| | | .message { |
| | |
| | | } |
| | | } |
| | | |
| | | .reserved { |
| | | .unread-txt { |
| | | @extend .text--primary; |
| | | } |
| | | |
| | | .contacted { |
| | | .read-txt { |
| | | color: $SKY_BLUE; |
| | | } |
| | | |
| | | } |
| | | |
| | | .flex-column { |
| | |
| | | |
| | | .dialogTxt { |
| | | font-size: 20px; |
| | | overflow-y:scroll; |
| | | max-height: 45vh; |
| | | @include desktop { |
| | | height: 400px; |
| | | } |
| | | } |
| | | |
| | | .text-right { |
| | | text-align: right; |
| | | } |
| | | </style> |
| | | </style> |