| | |
| | | <template> |
| | | <div> |
| | | <div class="quickBtnBlock"> |
| | | <el-button |
| | | v-for="(question, index) in questionList" |
| | | :key="index" |
| | | class="subTitle quickBtn" |
| | | :class="{'isActive': isActive(question.name)}" |
| | | @click="openPopUp(question)" |
| | | >{{question.title}}</el-button> |
| | | </div> |
| | | <h5 class="mdTxt mb-10 mt-30">篩選條件</h5> |
| | | <div> |
| | | <template v-if="confirmItem.length > 0"> |
| | | <UiTags |
| | | v-for="(item, index) in confirmItem" :key="index" |
| | | @removeTag="removeTag(item.value)" |
| | | > |
| | | <span v-if="item.option === 'gender'">{{item.value === 'male' ? '男性' : '女性'}}</span> |
| | | <!-- TODO:隱藏滿意度 --> |
| | | <!-- <span v-else-if="item.option === 'avgScore'">{{item.value + '星以上滿意度'}}</span> --> |
| | | <span v-else>{{item.value}}</span> |
| | | </UiTags> |
| | | </template> |
| | | <div |
| | | v-else |
| | | class="emptyBox text--mid_grey" |
| | | > |
| | | <p class="smTxt">尚無篩選</p> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="mb-10 mt-30"> |
| | | <span class="mdTxt">快速篩選推薦</span> |
| | | <span class="smTxt_bold text--prudential_grey ml-10">共 {{consultantList.length}} 筆</span> |
| | | </div> |
| | | <div class="recommend pam-paragraph"> |
| | | <img class="img" src="~/assets/images/quickFilter/recommend.svg" alt=""> |
| | | |
| | | <template v-if="consultantList.length > 0"> |
| | | <QuickFilterConsultantList :consultantList="consultantList"></QuickFilterConsultantList> |
| | | </template> |
| | | |
| | | <template v-else> |
| | | <div class="emptyBox text--mid_grey recommendStyle"> |
| | | <p class="smTxt">尚無推薦資料</p> |
| | | </div> |
| | | </template> |
| | | </div> |
| | | |
| | | <PopUpFrame |
| | | :isOpen.sync="isOpenQuestionPopUp" |
| | | :dialogWidth="'400px'" |
| | | class="pam-myDemand-dialog" |
| | | > |
| | | <QuickFilterSelector |
| | | ref="quickFilterRef" |
| | | :isOpenQuestionPopUp="isOpenQuestionPopUp" |
| | | :questionOption="questionOption" |
| | | @confirm="confirm" |
| | | :confirmItem="confirmItem" |
| | | ></QuickFilterSelector> |
| | | </PopUpFrame> |
| | | <div> |
| | | <div class="pam-paragraph pam-quick-filter__options"> |
| | | <el-button v-for="(question, index) in questionList" |
| | | :key="index" |
| | | class="subTitle pam-quick-filter__btn" |
| | | :class="{'is-active': isActive(question.name)}" |
| | | @click="openPopUp(question)">{{question.title}}</el-button> |
| | | </div> |
| | | |
| | | <div class="pam-paragraph"> |
| | | <div class="mdTxt">篩選條件</div> |
| | | <div class="mt-10"> |
| | | <template v-if="confirmItem.length > 0"> |
| | | <UiTags v-for="(item, index) in confirmItem" |
| | | :key="index" |
| | | @removeTag="removeTag(item.value)"> |
| | | <span v-if="item.option === 'gender'"> |
| | | {{item.value === 'male' ? '男性' : '女性'}} |
| | | </span> |
| | | <span v-else-if="item.option === 'seniority'"> |
| | | {{item.value | formatSeniorityTitle}} |
| | | <span class="smTxt">{{item.value | formatSenioritySubTitle}}</span> |
| | | </span> |
| | | <span v-else-if="item.option === 'avgScore' && !hideReviews">{{item.value + '星以上滿意度'}}</span> |
| | | <span v-else>{{item.value}}</span> |
| | | </UiTags> |
| | | </template> |
| | | <div v-else |
| | | class="pam-quick-filter__empty text--mid_grey"> |
| | | <p class="smTxt">尚無篩選</p> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="pam-paragraph"> |
| | | <span class="mdTxt">快速篩選推薦</span> |
| | | <span class="smTxt_bold text--prudential_grey ml-10">共 {{consultantList.length}} 筆</span> |
| | | </div> |
| | | |
| | | <div class="pam-paragraph pam-quick-filter__recommend"> |
| | | <img class="img" |
| | | alt="" |
| | | src="~/assets/images/quickFilter/recommend.svg"> |
| | | <template v-if="consultantList.length > 0"> |
| | | <QuickFilterConsultantList :consultantList="consultantList"></QuickFilterConsultantList> |
| | | </template> |
| | | <template v-else> |
| | | <div class="pam-quick-filter__empty text--mid_grey pam-quick-filter__empty--white"> |
| | | <p class="smTxt">尚無推薦資料</p> |
| | | </div> |
| | | </template> |
| | | </div> |
| | | |
| | | <PopUpFrame class="pam-myDemand-dialog" |
| | | dialogWidth="400px" |
| | | :isOpen.sync="isOpenQuestionPopUp"> |
| | | <QuickFilterSelector ref="quickFilterRef" |
| | | :isOpenQuestionPopUp="isOpenQuestionPopUp" |
| | | :questionOption="questionOption" |
| | | @confirm="confirm" |
| | | :confirmItem="confirmItem"></QuickFilterSelector> |
| | | </PopUpFrame> |
| | | </div> |
| | | </template> |
| | | |
| | | <script lang="ts"> |
| | | import { Vue, Component, namespace } from 'nuxt-property-decorator'; |
| | | import { Consultant } from '~/assets/ts/models/consultant.model'; |
| | | import { fastQuery } from '~/assets/ts/api/consultant'; |
| | | import { questionList } from '~/assets/ts/const/quickFilter-questionList'; |
| | | import { FastQueryParams, QuestionOption, Selected } from '~/assets/ts/models/quickFilter.model'; |
| | | import { Consultant } from '~/shared/models/consultant.model'; |
| | | import { FastQueryParams, QuestionOption, Selected } from '~/shared/models/quick-filter.model'; |
| | | import { questionList } from '~/shared/const/quickFilter-questionList'; |
| | | import { Seniority } from '~/shared/models/enum/seniority'; |
| | | import { Vue, Component, namespace } from 'nuxt-property-decorator'; |
| | | import queryConsultantService from '~/shared/services/query-consultant.service'; |
| | | |
| | | const localStorage = namespace('localStorage'); |
| | | @Component |
| | | export default class QuickFilter extends Vue { |
| | | @localStorage.Mutation storageQuickFilter!: (token: string) => void; |
| | | @localStorage.Getter quickFilterSelectedData!: Selected[]; |
| | | const localStorage = namespace('localStorage'); |
| | | const seniorityMap={ |
| | | [Seniority.SENIOR]:{ |
| | | title:'資深', |
| | | subTitle:'薑是老的辣' |
| | | }, |
| | | [Seniority.YOUNG]:{ |
| | | title:'年輕', |
| | | subTitle:'給年輕人一個機會' |
| | | }, |
| | | [Seniority.UNLIMITED]:{ |
| | | title:'不限', |
| | | subTitle:'年齡不是問題' |
| | | }, |
| | | } |
| | | @Component({ |
| | | filters: { |
| | | formatSeniorityTitle(value): string{ |
| | | return seniorityMap[value].title |
| | | }, |
| | | formatSenioritySubTitle(value): string { |
| | | return seniorityMap[value].subTitle |
| | | } |
| | | } |
| | | }) |
| | | export default class QuickFilter extends Vue { |
| | | @localStorage.Mutation |
| | | storageQuickFilter!: (token: string) => void; |
| | | |
| | | @localStorage.Getter |
| | | quickFilterSelectedData!: Selected[]; |
| | | |
| | | isOpenQuestionPopUp = false; |
| | | consultantList: Consultant[] = []; |
| | |
| | | confirmItem: Selected[] = []; |
| | | questionList = questionList; |
| | | |
| | | //////////////// lifecycle //////////////// |
| | | ////////////////////////////////////////////////////////////////////// Vue lifeCycle |
| | | mounted() { |
| | | if (this.quickFilterSelectedData && this.quickFilterSelectedData.length > 0) { |
| | | this.confirmItem = this.quickFilterSelectedData; |
| | | this.getRecommendList(); |
| | | } |
| | | if (this.quickFilterSelectedData && this.quickFilterSelectedData.length > 0) { |
| | | this.confirmItem = this.quickFilterSelectedData; |
| | | this.getRecommendList(); |
| | | } |
| | | } |
| | | |
| | | |
| | | ////////////////////////////////////////// |
| | | ////////////////////////////////////////////////////////////////////// |
| | | openPopUp(question: QuestionOption) { |
| | | this.questionOption = question; |
| | | this.isOpenQuestionPopUp =true; |
| | | this.questionOption = question; |
| | | this.isOpenQuestionPopUp = true; |
| | | } |
| | | |
| | | removeTag(value: string) { |
| | | this.confirmItem = this.confirmItem.filter(item => item.value !== value); |
| | | this.confirmItem.length > 0 ? this.getRecommendList() : this.consultantList = []; |
| | | this.confirmItem = this.confirmItem.filter(item => item.value !== value); |
| | | this.confirmItem.length > 0 ? this.getRecommendList() : this.consultantList = []; |
| | | } |
| | | |
| | | confirm(event: Selected) { |
| | | this.setConfirmData(event); |
| | | this.confirmItem.length > 0 ? this.getRecommendList() : this.consultantList = []; |
| | | this.isOpenQuestionPopUp = false; |
| | | this.setConfirmData(event); |
| | | this.confirmItem.length > 0 ? this.getRecommendList() : this.consultantList = []; |
| | | this.isOpenQuestionPopUp = false; |
| | | } |
| | | |
| | | isActive(name: string) { |
| | | return name === 'gender' && !!this.gender() |
| | | || name === 'avgScore' && !!this.avgScore() |
| | | || name === 'communicationStyles' && !!this.communicationStyles().length |
| | | return name === 'gender' && !!this.getGender() |
| | | || name === 'avgScore' && !!this.getAvgScore() |
| | | || name === 'communicationStyles' && !!this.getCommunicationStyles().length |
| | | || name === 'seniority' && !!this.getSeniority() |
| | | } |
| | | |
| | | |
| | | //////////////// private //////////////// |
| | | private gender(): string { |
| | | const filter = this.confirmItem.filter(item => item.option === 'gender').map(i => i.value); |
| | | return filter.length === 0 ? '' : filter[0]; |
| | | ////////////////////////////////////////////////////////////////////// |
| | | private getGender(): string { |
| | | return this.filterSingleSelected('gender'); // maybe can use enum ? |
| | | } |
| | | |
| | | private avgScore(): number { |
| | | const filter = this.confirmItem.filter(item => item.option === 'avgScore').map(i => i.value); |
| | | return filter.length === 0 ? '' : filter[0]; |
| | | private getAvgScore(): number { |
| | | return this.filterSingleSelected('avgScore'); |
| | | } |
| | | |
| | | private communicationStyles(): string[] { |
| | | return this.confirmItem.filter(item => item.option === 'communicationStyles').map(i => i.value); |
| | | private getSeniority(): string { |
| | | return this.filterSingleSelected('seniority'); |
| | | } |
| | | |
| | | private getCommunicationStyles(): string[] { |
| | | return this.confirmItem.filter(item => item.option === 'communicationStyles').map(i => i.value); |
| | | } |
| | | |
| | | private filterSingleSelected(name: string) { |
| | | const filter = this.confirmItem.filter(item => item.option === name); |
| | | return filter.length > 0 ? |
| | | filter[0].value : |
| | | (name === 'avgScore' ? 0 : ''); |
| | | } |
| | | |
| | | private setConfirmData(event: Selected) { |
| | | if (event.option === 'communicationStyles') { |
| | | this.filterCommunicationStyles(event); |
| | | } else { |
| | | const findIndex = this.confirmItem.findIndex(item => item.option === event.option); |
| | | findIndex === -1 ? this.confirmItem.push(event) : this.confirmItem[findIndex] = event; |
| | | } |
| | | if (event.option === 'communicationStyles') { |
| | | this.filterCommunicationStyles(event); |
| | | } else { |
| | | const findIndex = this.confirmItem.findIndex(item => item.option === event.option); |
| | | findIndex === -1 ? this.confirmItem.push(event) : this.confirmItem[findIndex] = event; |
| | | } |
| | | } |
| | | |
| | | private filterCommunicationStyles(event: Selected) { |
| | | const confirmValue = this.confirmItem |
| | | .filter(item => item.option === 'communicationStyles') |
| | | .map(i => i.value); |
| | | const pickerValue = event.value; |
| | | const confirmValue = this.confirmItem |
| | | .filter(item => item.option === 'communicationStyles') |
| | | .map(i => i.value); |
| | | const pickerValue = event.value; |
| | | |
| | | this.confirmItem = this.confirmItem |
| | | .filter(item => pickerValue.includes(item.value) || item.option !== 'communicationStyles'); |
| | | this.confirmItem = this.confirmItem |
| | | .filter(item => pickerValue.includes(item.value) || item.option !== 'communicationStyles'); |
| | | |
| | | const addValue = pickerValue.filter(item => !confirmValue.includes(item)).map(i => { |
| | | return { |
| | | option: 'communicationStyles', |
| | | value: i |
| | | } |
| | | }) |
| | | if (addValue.length > 0) { |
| | | this.confirmItem.push(...addValue); |
| | | const addValue = pickerValue.filter(item => !confirmValue.includes(item)).map(i => { |
| | | return { |
| | | option: 'communicationStyles', |
| | | value: i |
| | | } |
| | | }) |
| | | if (addValue.length > 0) { |
| | | this.confirmItem.push(...addValue); |
| | | } |
| | | } |
| | | |
| | | private getRecommendList() { |
| | | const data: FastQueryParams = { |
| | | gender: this.gender(), |
| | | communicationStyles: this.communicationStyles(), |
| | | avgScore: this.avgScore(), |
| | | status: '' |
| | | } |
| | | const data: FastQueryParams = { |
| | | gender: this.getGender(), |
| | | communicationStyles: this.getCommunicationStyles(), |
| | | avgScore: this.getAvgScore(), |
| | | status: '', |
| | | seniority: this.getSeniority() |
| | | } |
| | | |
| | | fastQuery(data).then((consultantList) => { |
| | | this.consultantList = consultantList; |
| | | this.storageQuickFilter(JSON.stringify(this.confirmItem)) |
| | | }) |
| | | queryConsultantService.fastQuery(data).then((consultantList) => { |
| | | this.consultantList = consultantList; |
| | | this.storageQuickFilter(JSON.stringify(this.confirmItem)) |
| | | }) |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .emptyBox { |
| | | width: 100%; |
| | | height: 100px; |
| | | border: solid 1px $LIGHT_GREY; |
| | | text-align: center; |
| | | border-radius: 10px; |
| | | .pam-quick-filter__options { |
| | | display: flex; |
| | | width: 100%; |
| | | height: 132px; |
| | | flex-wrap: wrap; |
| | | justify-content: space-between; |
| | | |
| | | .smTxt { |
| | | line-height: 100px; |
| | | } |
| | | .pam-quick-filter__btn { |
| | | width: 48%; |
| | | height: 56px; |
| | | text-align: center; |
| | | box-shadow: 0 0 6px #22222229; |
| | | border-radius: 10px; |
| | | border-color: $CORAL; |
| | | |
| | | &.is-active { |
| | | background-color: $CORAL; |
| | | color: $PRIMARY_WHITE; |
| | | } |
| | | } |
| | | |
| | | .recommendStyle { |
| | | box-shadow: 0 0 6px #00000029; |
| | | background-color: $PRIMARY_WHITE; |
| | | .pam-quick-filter__btn+.pam-quick-filter__btn { |
| | | margin-left: 0; |
| | | } |
| | | } |
| | | |
| | | .quickBtnBlock { |
| | | display: flex; |
| | | width: 100%; |
| | | // height: 132px; |
| | | flex-wrap: wrap; |
| | | justify-content: space-between; |
| | | .pam-quick-filter__empty { |
| | | width: 100%; |
| | | height: 100px; |
| | | border: solid 1px $LIGHT_GREY; |
| | | text-align: center; |
| | | border-radius: 10px; |
| | | |
| | | .quickBtn { |
| | | width: 48%; |
| | | height: 56px; |
| | | text-align: center; |
| | | box-shadow: 0 0 6px #22222229; |
| | | border-radius: 10px; |
| | | border-color: $CORAL; |
| | | |
| | | &.isActive { |
| | | background-color: $CORAL; |
| | | color: $PRIMARY_WHITE; |
| | | } |
| | | } |
| | | .quickBtn+.quickBtn { |
| | | margin-left: 0; |
| | | } |
| | | |
| | | .smTxt { |
| | | line-height: 100px; |
| | | } |
| | | |
| | | .recommend { |
| | | position: relative; |
| | | |
| | | .img { |
| | | position: absolute; |
| | | top: -50px; |
| | | right: 10px; |
| | | } |
| | | .pam-quick-filter__empty--white{ |
| | | box-shadow: 0 0 6px #00000029; |
| | | background-color: $PRIMARY_WHITE; |
| | | } |
| | | } |
| | | |
| | | </style> |
| | | .pam-quick-filter__recommend { |
| | | position: relative; |
| | | |
| | | .img { |
| | | position: absolute; |
| | | top: -50px; |
| | | right: 10px; |
| | | } |
| | | } |
| | | </style> |