You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
768 lines
31 KiB
768 lines
31 KiB
<template>
|
|
<div
|
|
class="service-content tw-mb-[60px] tw-grid tw-grid-cols-1 tw-gap-[30px] md:tw-mb-[100px] xl:tw-px-[60px] xl:tw-max-w-screen-xl xl:tw-mx-auto xl:tw-grid-cols-[auto_364px]">
|
|
<mobileFixTopBar ref="stickySwiper" :fixBar="fixBar" :currStep="currStep" :list="fixBarList"></mobileFixTopBar>
|
|
<section class="step sercion-1 tw-w-full md:tw-px-[30px] xl:tw-px-0 xl:tw-col-span-2">
|
|
<div class="tw-mt-[20px] md:tw-mb-[11px] md:tw-mt-[40px]">
|
|
<Breadcrumbs></Breadcrumbs>
|
|
</div>
|
|
<div v-if="content.banners.length" class="tw-w-full">
|
|
<slideshow :banners="content.banners"></slideshow>
|
|
</div>
|
|
</section>
|
|
<section class="sercion-2 tw-px-[30px] md:tw-px-[30px] xl:tw-px-0 xl:tw-col-start-1 xl:tw-row-start-2">
|
|
<h1 class="t16 tw-mb-[18px] md:t24">{{ content.name }}</h1>
|
|
<div v-if="content.supplier"
|
|
class="supplier tw-flex tw-items-center tw-mb-[20px] tw-text-base-primary t14 md:tw-mb-[30px] md:t16 md:tw-font-normal">
|
|
<img :src="content.supplier.logo" class="tw-max-w-[40px] md:tw-max-w-[80px]" />
|
|
<div class="t14 tw-font-normal tw-ml-[10px] md:t18 md:tw-font-normal">
|
|
{{ content.supplier.brand }}
|
|
</div>
|
|
</div>
|
|
<div class="editor-styleguide tw-text-base-primary" v-html="content.highlights"></div>
|
|
</section>
|
|
<section
|
|
class="sercion-3 tw-grid tw-grid-cols-1 tw-gap-[30px] md:tw-gap-[40px] md:tw-px-[30px] xl:tw-px-0 xl:tw-col-start-1 xl:tw-row-start-3">
|
|
<div ref="packageOptions" id="packageOptions" class="step">
|
|
<div class="tw-px-[30px] md:tw-px-0">
|
|
<h2 class="title-icon-left t16 tw-mb-[20px] md:t20">
|
|
{{ $t("Package Options") }}
|
|
</h2>
|
|
<p>{{ $t("Select date and package options") }}</p>
|
|
</div>
|
|
<div class="tw-w-full tw-bg-neutrals-100 tw-p-[20px] md:tw-p-[30px]">
|
|
<div class="">
|
|
<div class="group tw-mb-[40px]" v-if="content.dateStatus == 'active'">
|
|
<h3 class="t14 tw-font-bold tw-mb-[20px] md:t16">
|
|
{{ $t("Select Date") }}
|
|
</h3>
|
|
<selectDate :start="content.start" :end="content.end" @selected="selectDates = $event"></selectDate>
|
|
</div>
|
|
<div class="group tw-mb-[40px]" v-if="content.timeStatus == 'active'">
|
|
<h3 class="t14 tw-font-bold tw-mb-[20px] md:t16">
|
|
{{ $t("Time") }}
|
|
</h3>
|
|
<timeButtonGroup v-if="content.times.length > 0" :list="content.times" @selected="selectTime = $event">
|
|
</timeButtonGroup>
|
|
</div>
|
|
<div class="group tw-mb-[20px]">
|
|
<h3 class="t14 tw-font-bold tw-mb-[20px] md:t16">
|
|
{{ $t("Package Type") }}
|
|
</h3>
|
|
<typeGroup :packages="content.packages" @type="changeType($event)"></typeGroup>
|
|
</div>
|
|
<template v-for="(item, index) in content.packages">
|
|
<div :key="index" v-if="index === activePackage" class="">
|
|
<div v-if="content.packages[index].is_customize == 1">
|
|
<div class="group tw-mb-[20px]">
|
|
<h3 class="t14 tw-font-bold tw-mb-[20px] md:t16">
|
|
{{ item.plan_title }}
|
|
</h3>
|
|
</div>
|
|
<buttonGroup :list="item.choices" @choicesIdx="choicesIdx($event)"></buttonGroup>
|
|
<customSelectGroup ref="customSelectGroup" :label="'Specification'" :package="item.specifications"
|
|
:choices="item.choices" :choicesIndex="choicesIndex" @totalPrice="customPlanPrice = $event">
|
|
</customSelectGroup>
|
|
</div>
|
|
<div v-else>
|
|
<selectGroup :label="'Specification'" :package="item.specifications"
|
|
@totalPrice="totalPrice = $event"></selectGroup>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<div v-show="content.additionalServices.length > 0" class="group tw-mb-[20px]">
|
|
<additionalGroup :label="'Additional Services'" :package="content.additionalServices"
|
|
@totalPrice="additionTotalPrice = $event"></additionalGroup>
|
|
</div>
|
|
<div class="md:tw-flex md:tw-justify-between md:tw-items-center">
|
|
<div class="tw-flex tw-justify-between tw-items-start md:tw-w-full md:tw-basis-10/12">
|
|
<div class="tw-flex tw-flex-col tw-justify-center">
|
|
<div class="tw-flex tw-items-center tw-mb-[8px] md:tw-mb-0">
|
|
<div class="tw-body-4 tw-text-neutrals-900 tw-mr-[10px] md:t24">
|
|
${{ finalPrice }} {{ currency }}
|
|
</div>
|
|
<!-- <div
|
|
class="tw-body-4 tw-text-base-hint tw-line-through md:t20 md:tw-font-medium"
|
|
>
|
|
${{ totalPrice.toLocaleString() }}
|
|
</div> -->
|
|
</div>
|
|
<div class="tw-hidden tw-body-4 tw-text-neutrals-600 md:tw-hidden">
|
|
Deposit fee: $5 {{ currency }} (10%)
|
|
</div>
|
|
</div>
|
|
<like></like>
|
|
</div>
|
|
<button
|
|
class="tw-transition tw-btn-md tw-text-white tw-border tw-border-solid tw-border-primary-default tw-bg-primary-default tw-py-[8.5px] tw-mt-[20px] tw-w-full tw-rounded-xl md:tw-mt-0 md:tw-ml-[36px] md:tw-w-auto md:tw-basis-2/12 disabled:tw-bg-neutral-100 disabled:tw-text-base-disable disabled:tw-border-neutral-200"
|
|
@click="bookNow" :disabled="btnDisabled">
|
|
{{ $t("Book Now") }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="serviceDetails" class="serviceDetails step">
|
|
<div class="tw-px-[30px] md:tw-px-0">
|
|
<h2 class="title-icon-left t16 tw-mb-[20px] md:t20 xl:tw-font-bold">
|
|
{{ $t("Service Details") }}
|
|
</h2>
|
|
<div v-if="content.details.length < 800">
|
|
<div ref="details" class="editor-styleguide tw-text-base-primary t14 md:t16 md:tw-font-normal"
|
|
v-html="content.details"></div>
|
|
</div>
|
|
<div v-else>
|
|
<div :class="[
|
|
button.details ? 'seeMore-hide' : 'seeMore-show',
|
|
'editor-styleguide tw-text-base-primary tw-transition t14 md:t16 md:tw-font-normal',
|
|
]" ref="details" v-html="content.details"></div>
|
|
<button v-show="seeMore.details" :class="[
|
|
'seeMore tw-transition tw-btn-md tw-text-primary-1 tw-border tw-border-solid tw-border-primary-1 tw-px-[30px] tw-py-[8.5px] tw-mt-[20px] tw-w-full tw-rounded-xl hover:tw-bg-primary-3 xl:hover:tw-bg-transparent xl:tw-border-none',
|
|
button.details ? '' : 'open',
|
|
]" @click="opendetail()">
|
|
{{ $t(seeMoreDetailsText) }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div id="cancellationPolicy" class="cancellationPolicy step tw-px-[30px] md:tw-px-0">
|
|
<h2 class="title-icon-left t16 tw-mb-[20px] md:t20 xl:tw-font-bold">
|
|
{{ $t("Cancellation Policy") }}
|
|
</h2>
|
|
<div v-if="content.cancellation_policy.length < 800">
|
|
<div ref="cancellation_policy" class="editor-styleguide tw-text-base-primary t14 md:t16 md:tw-font-normal"
|
|
v-html="content.cancellation_policy">
|
|
</div>
|
|
</div>
|
|
<div v-else>
|
|
<div :class="[
|
|
button.cancellation_policy ? 'seeMore-hide' : 'seeMore-show',
|
|
'editor-styleguide tw-text-base-primary tw-transition t14 md:t16 md:tw-font-normal',
|
|
]" ref="cancellation_policy" v-html="content.cancellation_policy"></div>
|
|
<button v-show="seeMore.cancellation_policy" :class="[
|
|
'seeMore tw-transition tw-btn-md tw-text-primary-1 tw-border tw-border-solid tw-border-primary-1 tw-px-[30px] tw-py-[8.5px] tw-mt-[20px] tw-w-full tw-rounded-xl hover:tw-bg-primary-3 xl:hover:tw-bg-transparent xl:tw-border-none',
|
|
button.cancellation_policy ? '' : 'open',
|
|
]" @click="openCancellationPolicy()">
|
|
{{ $t(seeMoreCancellationPolicyText) }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div id="faq" ref="faq" class="step tw-px-[30px] md:tw-px-0">
|
|
<h2 class="title-icon-left t16 tw-mb-[20px] md:t20 xl:tw-font-bold">
|
|
{{ $t("FAQ") }}
|
|
</h2>
|
|
<faq :faq="content.faq" class="tw-z-[8]"></faq>
|
|
</div>
|
|
<div id="contactUs" class="step tw-px-[30px] md:tw-px-0">
|
|
<h2 class="title-icon-left t16 tw-mb-[20px] md:t20 xl:tw-font-bold">
|
|
{{ $t("Contact Us") }}
|
|
</h2>
|
|
<div class="tw-body-3 tw-text-base-primary tw-mb-[20px]">
|
|
886-2-2725-5000
|
|
</div>
|
|
<div class="tw-body-3 tw-text-base-primary">info@showeasy.com</div>
|
|
</div>
|
|
<div :class="[
|
|
'tw-bg-white tw-flex tw-flex-cols tw-justify-between tw-items-center tw-px-[30px] tw-py-[16px] tw-w-full',
|
|
fixBar
|
|
? 'tw-fixed tw-left-[0px] tw-bottom-[0px] tw-z-[8] tw-shadow-[1px_0px_2px_rgba(0,0,0,0.25)]'
|
|
: 'tw-hidden',
|
|
]">
|
|
<div :class="[
|
|
'tw-flex tw-flex-col tw-justify-between tw-items-start tw-grow md:tw-w-full md:tw-flex-row md:tw-items-center',
|
|
]">
|
|
<div class="tw-flex tw-items-center tw-mb-[12px] md:tw-mb-0">
|
|
<div class="t16 tw-text-neutrals-900 tw-mr-[10px] md:t20 md:tw-mr-0">
|
|
${{ finalPrice }} {{ currency }}
|
|
</div>
|
|
</div>
|
|
<div class="tw-flex tw-justify-center tw-items-center tw-w-full md:tw-w-fit">
|
|
<like></like>
|
|
<button
|
|
class="tw-transition tw-whitespace-nowrap tw-body-4 tw-text-white tw-border tw-border-solid tw-border-primary-default tw-bg-primary-default tw-ml-[22px] tw-px-[24px] tw-py-[8.5px] tw-rounded-xl tw-w-full md:tw-body-2 md:tw-min-w-[130px] md:tw-max-w-[130px] md:tw-mt-0 disabled:tw-bg-neutral-100 disabled:tw-text-base-disable disabled:tw-border-neutral-200"
|
|
@click="bookNow" :disabled="btnDisabled">
|
|
{{ $t("Book Now") }}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<section
|
|
class="sercion-4 tw-px-[30px] tw-grid tw-grid-cols-1 tw-gap-[40px] tw-z-[8] md:tw-px-[30px] xl:tw-px-0 xl:tw-col-start-1 xl:tw-row-start-4">
|
|
<detailsModal :detail="content.details"></detailsModal>
|
|
<cancellationPolicyModal :cancellationPolicy="content.cancellation_policy"></cancellationPolicyModal>
|
|
</section>
|
|
<section class="sercion-5 tw-hidden md:tw-px-[30px] xl:tw-px-0 xl:tw-block xl:tw-row-start-2 xl:tw-row-end-5">
|
|
<div class="tw-mb-[40px]">
|
|
<sidebarSelectOption :totalPrice="finalPrice" :currency="currency" :confirmationTime="content.confirmationTime">
|
|
</sidebarSelectOption>
|
|
</div>
|
|
<sideBarMenu :fixBarList="fixBarList" :currStep="currStep"></sideBarMenu>
|
|
</section>
|
|
<section class="step sercion-6 tw-pl-[30px] tw-w-full xl:tw-px-0 xl:tw-col-span-2">
|
|
<h2 class="title-icon-left t16 md:t20 xl:tw-font-bold">
|
|
{{ $t("You might like ...") }}
|
|
</h2>
|
|
<youMightLikeslideshow :list="list" :countrycode="countrycode" :regionName="regionName"></youMightLikeslideshow>
|
|
</section>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
import Breadcrumbs from "@/components/Breadcrumbs";
|
|
import slideshow from "@/components/swiper/serviceContent.vue";
|
|
import detailsModal from "@/components/service/contentModal/DetailsModal.vue";
|
|
import cancellationPolicyModal from "@/components/service/contentModal/cancellationPolicyModal.vue";
|
|
import selectDate from "@/components/service/content/selectDate.vue";
|
|
import typeGroup from "@/components/service/content/typeGroup.vue";
|
|
import selectGroup from "@/components/service/content/selectGroup.vue";
|
|
import customSelectGroup from "@/components/service/content/customSelectGroup.vue";
|
|
import additionalGroup from "@/components/service/content/additionalGroup.vue";
|
|
import faq from "@/components/service/content/faq.vue";
|
|
import sidebarSelectOption from "@/components/service/content/sidebarSelectOption.vue";
|
|
import sideBarMenu from "@/components/service/content/sideBarMenu.vue";
|
|
import Swiper from "swiper/bundle";
|
|
import { scrollama } from "scrollama";
|
|
import youMightLikeslideshow from "@/components/swiper/youMightLike.vue";
|
|
import mobileFixTopBar from "@/components/swiper/mobileFixTopBar.vue";
|
|
import timeButtonGroup from "@/components/service/content/timeButtonGroup";
|
|
import buttonGroup from "@/components/service/content/buttonGroup.vue";
|
|
import like from "@/components/newComponent/like/like.vue";
|
|
export default {
|
|
auth: false,
|
|
components: {
|
|
Swiper,
|
|
scrollama,
|
|
Breadcrumbs,
|
|
slideshow,
|
|
detailsModal,
|
|
cancellationPolicyModal,
|
|
selectDate,
|
|
typeGroup,
|
|
timeButtonGroup,
|
|
buttonGroup,
|
|
selectGroup,
|
|
customSelectGroup,
|
|
additionalGroup,
|
|
faq,
|
|
sidebarSelectOption,
|
|
sideBarMenu,
|
|
youMightLikeslideshow,
|
|
mobileFixTopBar,
|
|
like,
|
|
},
|
|
data() {
|
|
return {
|
|
apiUrl: process.env.SERVICE_CONSOLE,
|
|
btnDisabled: process.env.ENV == 'production',
|
|
currStep: null,
|
|
stickySwiper: null,
|
|
content: {
|
|
banners: [{
|
|
banner_id: '123e41',
|
|
image: require('/assets/img/service_banner.png')
|
|
},{
|
|
banner_id: '123e31',
|
|
image: require('/assets/img/service_banner.png')
|
|
},{
|
|
banner_id: '123e12',
|
|
image: require('/assets/img/service_banner.png')
|
|
}],
|
|
country: null,
|
|
city: null,
|
|
name: "科隆機場接送服務",
|
|
highlights: '<ul><li>接送車輛皆為車況良好的八人座(含司機)賓士商務車。</li><li>安排熟悉路況及駕駛經驗豐富的當地專業導遊擔任司機,免費提供旅宿與交通安排基本諮詢服務。</li><li>司機精通德語與華語,可加價選購英文服務。</li><li>本服務包含於出關處舉牌迎賓,提供親切專業的接送服務。</li></ul>',
|
|
details: '<div data-v-5da7b8eb="" class="seeMore-show tw-text-base-primary tw-transition t14 md:t16 md:tw-font-normal"><h2>經典服務經驗</h2><p><br></p><p>從2020起,柏林政府啟用新機場,此機場位於柏林東南郊區,離市中心遙遠,由機場出發至市中心,需要多次轉車,柏林公眾交通系統,播報站名以德文為主,容易因為聽不懂德文而錯失過站,此外地鐵超過百年,建造時間較早,諸多車站沒有規劃電梯,必須手搬著行李,自行上下樓梯,對旅客而言,行動非常不便。</p><p><br></p><p>為解決上述問題,本公司提供華人專業導遊接送服務,提前抵達機場,在您的出機口舉牌等待您的到來,接送車輛賓士8人座(含司機)商務車,駕駛人員接送經驗豐富,熟悉當地路況,華文與德文流利,以最舒適的方式,從機場送達您想去的地點</p><p><br></p><h2>商品詳細說明</h2><ul><li>預定接機服務請至少於5個日曆天之前完成訂購與付費手續。</li><li>八人座(含司機)賓士商務車,最多可以搭乘7位貴賓,行李數量因空間有限需限制,搭載行李的數量會因乘客人數增加而對應減少,</li></ul><p> 請參考如下資訊並請於訂購本服務時提供搭乘人數與行李數量:</p><p> 乘客1~4人,可搭載4件可置於腿上的隨身行李及4件28吋的托運行李。</p><p> 乘客5~7人,可搭載7件可置於腿上的隨身行李及2件28吋的托運行李。</p><ul><li>用車距離為30公里以內,每超過 一公里加收5歐元,費用請現場支付給司機。</li><li>機場接機等待時間為飛機落地起算1小時以內。</li><li>本服務限定一個下車地,可加價選購增加停靠地點服務,服務終止時間以最後一位乘客抵達下車地點為準。</li><li>搭車前24小時將以電子郵件及簡訊提供給客戶必要資訊,包括司機的名字、手機、車牌等,而司機會在事先約定好的位置手持歡迎牌等待。</li><li>若遇航班提早抵達,仍須依您原預約時間提供服務,請恕無法提前;若您選擇自行離開放棄服務則費用恕不退還。</li><li>若乘車現場發現與訂購人數或行李數不符,導致超載,司機有權拒絕提供服務,恕不退費。</li><li>因車輛安排考量,預約之貴賓如欲變更時間或預約資料,需於原預約時間(班機抵達時間)之 48小時前告知,如未於可受理異動時間之前告知,預約時間與接送資料無法變更。</li></ul><p><br></p><h2>商品購買說明</h2><p><br></p><ul><li>可加價指定司機具備英文溝通能力的服務 </li><li>可加價增加停靠地點(每新增一處停靠地點加收20歐元),若事前無訂購增加停靠地點,則請於當日現場給付現金給司機。 </li><li>提供兒童安全座椅及兒童增高墊加價租用服務,如有特殊需求(如兒童安全座椅)須事前告知,以便安排,當天現場恕無法追加。 </li><li>如需協助辦理飯店入住,請點選加值服務,現場須提供飯店飯店預定證明及入住人護照正本。 </li></ul><p><br></p></div>',
|
|
cancellation_policy: "<ul><li>所選日期 5天(含)之前取消,收取手續費 0%</li><li>所選日期 4天(含)之前取消,收取手續費 50%</li><li>所選日期 3天(含)之前取消,收取手續費 100%</li></ul>",
|
|
saved: false,
|
|
confirmation_time: 24,
|
|
supplier: {
|
|
logo: require('/assets/img/Footer.png'),
|
|
brand: 'ShowEasy'
|
|
},
|
|
available_sections: null,
|
|
timeStatus: 'active',
|
|
dateStatus: 'active',
|
|
times: [{
|
|
start_time: '2023-02-06',
|
|
end_time: '2023-03-06',
|
|
},{
|
|
start_time: '2023-02-06',
|
|
end_time: '2023-03-06',
|
|
},{
|
|
start_time: '2023-02-06',
|
|
end_time: '2023-03-06',
|
|
}],
|
|
start: '2023-02-06',
|
|
end: '2023-06-06',
|
|
faq: [{
|
|
question: '超過限定里程(30公里)如何計費加價?',
|
|
answer: '每超過一公里加收5歐元,費用請現場支付給司機。',
|
|
}],
|
|
confirmationTime: '',
|
|
packages: [{
|
|
package_id: '1',
|
|
name: '嘉義',
|
|
photo: require('/assets/img/Frame.jpg'),
|
|
is_customize: 1
|
|
},{
|
|
package_id: '1',
|
|
name: '臺南',
|
|
photo: require('/assets/img/Frame.jpg'),
|
|
is_customize: 0
|
|
}],
|
|
additionalServices: [],
|
|
},
|
|
list: [],
|
|
choicesIndex: 0,
|
|
countrycode: [],
|
|
regionName: [],
|
|
elementHeight: {
|
|
details: null,
|
|
cancellation_policy: null,
|
|
faq: null,
|
|
},
|
|
seeMore: {
|
|
details: true,
|
|
cancellation_policy: true,
|
|
},
|
|
button: {
|
|
details: true,
|
|
cancellation_policy: true,
|
|
},
|
|
offset: {
|
|
packageOptions: 0,
|
|
faq: 0,
|
|
},
|
|
contentId: "",
|
|
packageId: "",
|
|
packageName: "",
|
|
window: {
|
|
width: 0,
|
|
},
|
|
fixBar: false,
|
|
fixBarList: [
|
|
{ id: "packageOptions", title: "Package Options", show: true },
|
|
{ id: "serviceDetails", title: "Service Details", show: true },
|
|
{ id: "cancellationPolicy", title: "Cancellation Policy", show: true },
|
|
{ id: "faq", title: "FAQ", show: true },
|
|
{ id: "contactUs", title: "Contact Us", show: true },
|
|
],
|
|
activePackage: 0,
|
|
totalPrice: [],
|
|
additionTotalPrice: [],
|
|
customPlanPrice: [],
|
|
selectDates: '',
|
|
selectTime: {
|
|
start_time: '2023-02-06',
|
|
end_time: '2023-03-06',
|
|
},
|
|
};
|
|
},
|
|
async created() {
|
|
// await this.getServiceData();
|
|
// await this.getFaq();
|
|
// await this.getPackages();
|
|
// await this.getAdditionalServices();
|
|
// await this.addViewCount();
|
|
// await this.getYouMightLikeData();
|
|
// await this.getRegionName();
|
|
// await this.getCountryCode();
|
|
if (process.browser) {
|
|
window.addEventListener("resize", this.handleResize);
|
|
}
|
|
this.handleResize();
|
|
},
|
|
mounted() {
|
|
let vm = this;
|
|
vm.contentId = vm.$route.params.id;
|
|
vm.offset.packageOptions = vm.$refs.packageOptions.offsetTop;
|
|
vm.offset.faq = vm.$refs.faq.offsetTop;
|
|
vm.$nextTick(function () {
|
|
// instantiate the scrollama
|
|
const scrollama = require("scrollama");
|
|
const scroller = scrollama();
|
|
// setup the instance, pass callback functions
|
|
scroller
|
|
.setup({
|
|
step: ".service-content .step",
|
|
offset: 0.6,
|
|
})
|
|
.onStepEnter((response) => {
|
|
// { element, index, direction }
|
|
vm.currStep = response.element.id;
|
|
let fb_messenger = document.querySelector(".fb_dialog_content");
|
|
if (response.index > 3) {
|
|
vm.$refs.stickySwiper.slideTo(4);
|
|
} else {
|
|
vm.$refs.stickySwiper.slideTo(0);
|
|
}
|
|
if (response.index >= 1 && response.index < 6) {
|
|
vm.fixBar = true;
|
|
if (fb_messenger) {
|
|
fb_messenger.classList.add("hasBar");
|
|
}
|
|
} else {
|
|
vm.fixBar = false;
|
|
if (fb_messenger) {
|
|
fb_messenger.classList.remove("hasBar");
|
|
}
|
|
}
|
|
})
|
|
.onStepExit((response) => {
|
|
// { element, index, direction }
|
|
vm.currStep = response.element.id;
|
|
let fb_messenger = document.querySelector(".fb_dialog_content");
|
|
if (response.index >= 1 && response.index < 6) {
|
|
vm.fixBar = true;
|
|
if (fb_messenger) {
|
|
fb_messenger.classList.add("hasBar");
|
|
}
|
|
} else {
|
|
vm.fixBar = false;
|
|
if (fb_messenger) {
|
|
fb_messenger.classList.remove("hasBar");
|
|
}
|
|
}
|
|
});
|
|
})
|
|
},
|
|
computed: {
|
|
currency() {
|
|
return this.$store.getters.getCurrency;
|
|
},
|
|
seeMoreDetailsText() {
|
|
if (this.button.details == false) {
|
|
return "See less";
|
|
} else {
|
|
return "See more";
|
|
}
|
|
},
|
|
seeMoreCancellationPolicyText() {
|
|
if (this.button.cancellation_policy == false) {
|
|
return "See less";
|
|
} else {
|
|
return "See more";
|
|
}
|
|
},
|
|
finalPrice() {
|
|
let option = 0;
|
|
let custom = 0;
|
|
let addition = 0;
|
|
if (this.additionTotalPrice) {
|
|
this.additionTotalPrice.forEach((item) => {
|
|
addition += Number(item.total);
|
|
});
|
|
}
|
|
if (this.customPlanPrice) {
|
|
this.customPlanPrice.forEach((item) => {
|
|
custom += Number(item.total);
|
|
});
|
|
}
|
|
if (this.totalPrice) {
|
|
this.totalPrice.forEach((item) => {
|
|
option += Number(item.total);
|
|
});
|
|
}
|
|
if (this.currency == 'USD') {
|
|
return Number(addition + custom + option).toFixed(2).toLocaleString();
|
|
} else {
|
|
return Number(addition + custom + option).toLocaleString();
|
|
}
|
|
},
|
|
},
|
|
watch: {
|
|
currency: {
|
|
handler: function () {
|
|
this.getServiceData();
|
|
this.getPackages();
|
|
this.getAdditionalServices();
|
|
},
|
|
},
|
|
activePackage: {
|
|
handler: function (newVal, oldVal) {
|
|
if (newVal !== oldVal) {
|
|
this.customPlanPrice = [];
|
|
this.totalPrice = [];
|
|
}
|
|
},
|
|
},
|
|
choicesIndex: {
|
|
handler: function (newVal, oldVal) {
|
|
if (newVal !== oldVal) {
|
|
this.customPlanPrice = [];
|
|
this.totalPrice = [];
|
|
}
|
|
},
|
|
}
|
|
},
|
|
destroyed() {
|
|
if (process.browser) {
|
|
window.removeEventListener("resize", this.handleResize);
|
|
}
|
|
},
|
|
methods: {
|
|
async getServiceData() {
|
|
await this.$axios
|
|
.get(
|
|
`${this.apiUrl}/user-services/content?service_id=${this.$route.params.id}&lang_code=${this.$i18n.localeProperties["langQuery"]}¤cy=${this.currency}`
|
|
)
|
|
.then((res) => {
|
|
this.content.banners = res.data.banners;
|
|
this.content.name = res.data.name;
|
|
this.content.country = res.data.country;
|
|
this.content.city = res.data.city;
|
|
this.content.highlights = res.data.highlights;
|
|
this.content.details = res.data.details;
|
|
this.content.cancellation_policy = res.data.cancellation_policy;
|
|
this.content.supplier = res.data.supplier;
|
|
this.content.available_sections = res.data.available_sections;
|
|
this.content.times = res.data.available_sections.times;
|
|
this.content.timeStatus = res.data.available_sections.time_status;
|
|
this.content.dateStatus = res.data.available_sections.date_status;
|
|
this.content.start = res.data.available_sections.start;
|
|
this.content.end = res.data.available_sections.end;
|
|
this.content.payment_currency = res.data.payment_currency;
|
|
this.content.confirmationTime = res.data.confirmation_time.toString();
|
|
})
|
|
.catch((error) => console.log(error));
|
|
},
|
|
|
|
async getFaq() {
|
|
await this.$axios
|
|
.get(
|
|
`${this.apiUrl}/user-services/faqs?service_id=${this.$route.params.id}&lang_code=${this.$i18n.localeProperties["langQuery"]}`
|
|
)
|
|
.then((res) => {
|
|
this.content.faq = res.data;
|
|
})
|
|
.catch((error) => console.log(error));
|
|
},
|
|
async getPackages() {
|
|
await this.$axios
|
|
.get(
|
|
`${this.apiUrl}/user-services/packages?service_id=${this.$route.params.id}&lang_code=${this.$i18n.localeProperties["langQuery"]}¤cy=${this.currency}`
|
|
)
|
|
.then((res) => {
|
|
this.content.packages = res.data;
|
|
this.packageId = res.data[0].package_id ? res.data[0].package_id : "";
|
|
})
|
|
.catch((error) => console.log(error));
|
|
},
|
|
async getAdditionalServices() {
|
|
await this.$axios
|
|
.get(
|
|
`${this.apiUrl}/user-services/additional?service_id=${this.$route.params.id}&lang_code=${this.$i18n.localeProperties["langQuery"]}¤cy=${this.currency}`
|
|
)
|
|
.then((res) => {
|
|
this.content.additionalServices =
|
|
res.data.services == [] ? null : res.data;
|
|
})
|
|
.catch((error) => console.log(error));
|
|
},
|
|
async addViewCount() {
|
|
let Obj = {
|
|
service_id: `${this.$route.params.id}`,
|
|
lang_code: `${this.$i18n.localeProperties["langQuery"]}`,
|
|
add_number: 1,
|
|
};
|
|
await this.$axios
|
|
.put(`${this.apiUrl}/user-services/view-counts`, Obj)
|
|
.then((res) => { })
|
|
.catch((error) => console.log(error));
|
|
},
|
|
opendetail() {
|
|
if (this.window.width >= 1366) {
|
|
this.button.details = !this.button.details;
|
|
} else {
|
|
this.$modal.show("Details");
|
|
}
|
|
},
|
|
openCancellationPolicy() {
|
|
if (this.window.width >= 1366) {
|
|
this.button.cancellation_policy = !this.button.cancellation_policy;
|
|
} else {
|
|
this.$modal.show("cancellationPolicy");
|
|
}
|
|
},
|
|
handleResize() {
|
|
if (process.browser) {
|
|
this.window.width = window.innerWidth;
|
|
}
|
|
},
|
|
changeType(index) {
|
|
let vm = this;
|
|
vm.activePackage = index;
|
|
vm.packageId = vm.content.packages[index].package_id
|
|
? vm.content.packages[index].package_id
|
|
: "";
|
|
vm.packageName = vm.content.packages[index].name
|
|
? vm.content.packages[index].name
|
|
: "";
|
|
},
|
|
async getYouMightLikeData() {
|
|
this.$axios
|
|
.get(
|
|
`${this.apiUrl}/user-services/advertisements?region=0&country=0&city=0&expo=0&counts=3&lang_code=${this.$i18n.localeProperties["langQuery"]}`
|
|
)
|
|
.then((res) => {
|
|
this.list = res.data;
|
|
})
|
|
.catch((error) => console.log(error));
|
|
},
|
|
async getCountryCode() {
|
|
this.$axios
|
|
.get(
|
|
`${this.apiUrl}/countries?lang_code=${this.$i18n.localeProperties["langQuery"]}`
|
|
)
|
|
.then((respone) => {
|
|
this.countrycode = respone.data;
|
|
})
|
|
.catch((error) => console.log(error));
|
|
},
|
|
async getRegionName() {
|
|
this.$axios
|
|
.get(
|
|
`/t/exhibitions/locations?lang=${this.$i18n.localeProperties["langQuery"]}&sort=False`
|
|
)
|
|
.then((respone) => {
|
|
this.regionName = respone.data.region_ori;
|
|
})
|
|
.catch((error) => console.log(error));
|
|
},
|
|
bookNow() {
|
|
let Obj = {
|
|
service_id: this.$route.params.id,
|
|
service_name: this.content.name,
|
|
select_dates: this.selectDates,
|
|
currency: this.currency,
|
|
lang_code: this.$i18n.localeProperties["langQuery"],
|
|
time: this.selectTime,
|
|
package_id: this.packageId,
|
|
package_name: this.packageName,
|
|
specification: this.totalPrice ? this.totalPrice : {},
|
|
additional_services: this.additionTotalPrice ? this.additionTotalPrice : {},
|
|
custom_plan: this.customPlanPrice ? this.customPlanPrice : {},
|
|
supplier_id: this.content.supplier.id ? this.content.supplier.id : '',
|
|
};
|
|
this.$axios
|
|
.post(`/order?jwt=${this.$auth.$storage.getUniversal("jwt").token || ""
|
|
}`, Obj)
|
|
.then((res) => {
|
|
if (res.status == "200") {
|
|
this.$router.push(this.localePath("/service/checkout/" + res.data.order_display_id))
|
|
}
|
|
|
|
})
|
|
.catch((error) => console.log(error));
|
|
},
|
|
choicesIdx(data) {
|
|
let vm = this;
|
|
vm.choicesIndex = data;
|
|
}
|
|
},
|
|
};
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
:deep() {
|
|
|
|
// .serviceDetails,
|
|
// .cancellationPolicy {
|
|
// p {
|
|
// margin-bottom: 6px;
|
|
// }
|
|
// }
|
|
}
|
|
|
|
.service-content {
|
|
|
|
|
|
.serviceDetails img {
|
|
width: 100%;
|
|
height: auto;
|
|
}
|
|
|
|
.fix-right {
|
|
position: fixed;
|
|
top: 120px;
|
|
right: 0 px;
|
|
max-width: 400px;
|
|
height: auto;
|
|
z-index: 100;
|
|
}
|
|
|
|
.title-icon-left {
|
|
background-position: left 0px center;
|
|
}
|
|
|
|
ul {
|
|
padding-left: 24px;
|
|
}
|
|
|
|
img {
|
|
// image-rendering: pixelated;
|
|
}
|
|
}
|
|
|
|
.seeMore {
|
|
&-hide {
|
|
position: relative;
|
|
max-height: 295px;
|
|
overflow: hidden;
|
|
|
|
&::after {
|
|
content: "";
|
|
display: block;
|
|
position: absolute;
|
|
background: url("~/assets/img/gradient_white.png") repeat-x left bottom;
|
|
width: 100%;
|
|
height: 130px;
|
|
left: 0;
|
|
bottom: 0;
|
|
z-index: 1;
|
|
transition: bottom 0.5s;
|
|
}
|
|
}
|
|
|
|
&-show {
|
|
position: relative;
|
|
max-height: 100%;
|
|
overflow: initial;
|
|
|
|
&::after {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
@media screen and (min-width: 1366px) {
|
|
position: relative;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
&::after {
|
|
content: "";
|
|
display: inline-block;
|
|
position: relative;
|
|
background-image: url("~/assets/svg/arrow-down-primary.svg");
|
|
background-position: center center;
|
|
background-repeat: no-repeat;
|
|
background-size: 100%;
|
|
width: 9px;
|
|
height: 6px;
|
|
margin-left: 16px;
|
|
}
|
|
|
|
&.open {
|
|
&::after {
|
|
transform: rotate(180deg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.section-7 {
|
|
>div {
|
|
box-shadow: 1px 0px 2px rgba(0, 0, 0, 0.25), 0px 1px 2px rgba(0, 0, 0, 0.1);
|
|
}
|
|
}
|
|
</style>
|