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.

500 lines
16 KiB

2 years ago
  1. <template>
  2. <div
  3. class="tw-px-[15px] tw-mb-[60px] xl:tw-px-[60px] xl:tw-max-w-screen-xl xl:tw-mx-auto xl:tw-grid xl:tw-grid-cols-[822px_auto] xl:tw-gap-[30px]"
  4. >
  5. <section
  6. class="section section-one tw-my-[40px] md:tw-my-[50px] xl:tw-col-span-2"
  7. >
  8. <StepInfo :step_active="step"></StepInfo>
  9. </section>
  10. <section class="section section-two">
  11. <h2
  12. class="t18 title-icon-left tw-text-black tw-mb-[15px] xl:tw-mb-[10px] xl:tw-text-[24px]"
  13. >
  14. {{ $t("Booking Info") }}
  15. </h2>
  16. <div
  17. class="notice tw-body-3 tw-text-black tw-mb-[20px] tw-hidden xl:tw-block"
  18. >
  19. {{
  20. $t(
  21. "Please enter your info carefully. Once submitted it cannot be changed."
  22. )
  23. }}
  24. </div>
  25. <BookingInfoItem
  26. v-for="(item, index) in order"
  27. :key="index"
  28. :info="item"
  29. :content="content"
  30. :questions="content.booking_questions"
  31. :contact.sync="userContactList"
  32. :active="activeLabel"
  33. @changeActiveLabel="activeLabel = $event"
  34. @contact="contactData = $event"
  35. @answer="answerData = $event"
  36. @bookingDetail_validation="getBookingDetail_validation"
  37. >
  38. </BookingInfoItem>
  39. <h2
  40. class="t18 title-icon-left tw-text-black tw-mb-[15px] lg:tw-mb-[8px] xl:tw-text-[24px] xl:tw-mt-[60px]"
  41. >
  42. {{ $t("Complete Payment") }}
  43. </h2>
  44. <div
  45. class="notice tw-body-3 tw-text-black tw-mb-[20px] tw-hidden xl:tw-block"
  46. >
  47. {{
  48. $t(
  49. "Please enter your info carefully. Once submitted it cannot be changed."
  50. )
  51. }}
  52. </div>
  53. <PurchaserInfo
  54. :class="[bookingDetail_Validation ? 'noFilter' : 'haveFilter']"
  55. ref="purchaserInfo"
  56. :userCompanyList="userCompanyList"
  57. :countryOptions="countryOptions"
  58. :infoType="type"
  59. :bookingDetail_Validation="bookingDetail_Validation"
  60. @type="type = $event"
  61. @active="companyActiveLabel = $event"
  62. @individual="individualData = $event"
  63. @company="companyData = $event"
  64. @purchaserInfo_validation="getPurchaserInfo_validation"
  65. ></PurchaserInfo>
  66. <ChooseMethod
  67. :class="[purchaserInfo_Validation ? 'noFilter' : 'haveFilter']"
  68. :orderNo="orderNo"
  69. :purchaserInfo_Validation="purchaserInfo_Validation"
  70. @paymentType="paymentData.payment_type = $event"
  71. @update="updateToken($event)"
  72. >
  73. </ChooseMethod>
  74. <Invoice v-if="language == 'zh-tw'"></Invoice>
  75. <PcTotalPrice
  76. :subTotal="subTotal"
  77. :currency="currency"
  78. v-on:payNowClick="payNow()"
  79. ></PcTotalPrice>
  80. </section>
  81. <section class="section section-three">
  82. <PriceInfo
  83. v-for="(item, index) in order"
  84. :key="index"
  85. :info="item"
  86. :currency="currency"
  87. ></PriceInfo>
  88. <TotalPrice
  89. :subTotal="subTotal"
  90. :currency="currency"
  91. v-on:payNowClick="payNow()"
  92. ></TotalPrice>
  93. </section>
  94. <AddContactModal @update="updateContactList"></AddContactModal>
  95. <EditContactModal
  96. ref="EditContactModal"
  97. :contact.sync="userContactList[this.activeLabel - 1]"
  98. @update="getContactList"
  99. ></EditContactModal>
  100. <AddCompanyModal
  101. :selectList.sync="countryOptions"
  102. @update="updateCompanyList()"
  103. >
  104. </AddCompanyModal>
  105. <EditCompanyModal
  106. :selectList.sync="countryOptions"
  107. :company.sync="userCompanyList[companyActiveLabel - 1]"
  108. @update="getCompanyList()"
  109. ></EditCompanyModal>
  110. </div>
  111. </template>
  112. <script>
  113. import StepInfo from "@/components/service/StepInfo";
  114. import BookingInfoItem from "@/components/service/BookingInfoItem";
  115. import PurchaserInfo from "@/components/service/PurchaserInfo";
  116. import ChooseMethod from "@/components/service/ChooseMethod";
  117. import PriceInfo from "@/components/service/PriceInfo";
  118. import TotalPrice from "@/components/service/TotalPrice";
  119. import PcTotalPrice from "@/components/service/PcTotalPrice";
  120. import elementInput from "@/components/newComponent/form/ElementInput";
  121. import AddContactModal from "@/components/newComponent/modal/AddContactModal";
  122. import EditContactModal from "@/components/newComponent/modal/EditContactModal";
  123. import AddCompanyModal from "@/components/newComponent/modal/AddCompanyModal";
  124. import EditCompanyModal from "@/components/newComponent/modal/EditCompanyModal";
  125. import Invoice from "@/components/service/Invoice.vue";
  126. export default {
  127. name: "service",
  128. layout: "service",
  129. auth: true,
  130. components: {
  131. StepInfo,
  132. BookingInfoItem,
  133. PurchaserInfo,
  134. ChooseMethod,
  135. PriceInfo,
  136. TotalPrice,
  137. PcTotalPrice,
  138. elementInput,
  139. Invoice,
  140. AddContactModal,
  141. EditContactModal,
  142. AddCompanyModal,
  143. EditCompanyModal,
  144. },
  145. data() {
  146. return {
  147. apiUrl: process.env.SERVICE_CONSOLE,
  148. devECPayUrl: "https://dev-lambda.showeasy.com",
  149. language: this.$i18n.locale,
  150. step: "2",
  151. orderNo: this.$route.params.id,
  152. order: null,
  153. serviceId: "",
  154. currency: "",
  155. type: "Individual",
  156. individualData: {},
  157. companyData: {},
  158. contactData: {},
  159. paymentData: {},
  160. answerData: [],
  161. content: {
  162. preview_image: "",
  163. country: null,
  164. city: null,
  165. name: "",
  166. highlights: "",
  167. details: "",
  168. cancellation_policy: "",
  169. saved: false,
  170. confirmation_time: 24,
  171. supplier: null,
  172. available_sections: null,
  173. timeStatus: "",
  174. dateStatus: "",
  175. times: [],
  176. start: "",
  177. end: "",
  178. faq: null,
  179. packages: [],
  180. additionalServices: [],
  181. booking_questions: [],
  182. },
  183. subTotal: 0,
  184. activeLabel: 0,
  185. companyActiveLabel: 0,
  186. userContactList: [],
  187. userCompanyList: [],
  188. countryOptions: [],
  189. contact: [],
  190. method: "",
  191. payToken: "",
  192. three_d_url: "",
  193. validation: {
  194. bookingInfo: false,
  195. purchaserInfo: false,
  196. chooseMethod: false,
  197. },
  198. bookingDetail_Validation: false,
  199. purchaserInfo_Validation: false,
  200. };
  201. },
  202. async created() {
  203. if (this.$auth.loggedIn) {
  204. // await this.getContactList();
  205. // await this.getActiveLength();
  206. // await this.getOrder();
  207. // await this.getServiceData();
  208. // await this.getPackages();
  209. // await this.getAdditionalServices();
  210. // await this.getCountries();
  211. // await this.getCompanyList();
  212. }
  213. },
  214. mounted() {},
  215. methods: {
  216. async getContactList() {
  217. await this.$axios
  218. .get(
  219. `/member/contacts?jwt=${
  220. this.$auth.$storage.getUniversal("jwt").token
  221. }`
  222. )
  223. .then((result) => {
  224. this.userContactList = result.data.contacts;
  225. return result.data;
  226. })
  227. .catch((err) => {
  228. console.log(err);
  229. });
  230. },
  231. async updateContactList() {
  232. await this.$axios
  233. .get(
  234. `/member/contacts?jwt=${
  235. this.$auth.$storage.getUniversal("jwt").token
  236. }`
  237. )
  238. .then((result) => {
  239. this.userContactList = result.data.contacts;
  240. this.activeLabel = this.userContactList.length;
  241. return result.data;
  242. })
  243. .catch((err) => {
  244. console.log(err);
  245. });
  246. },
  247. async getOrder() {
  248. await this.$axios
  249. .get(
  250. `/order/${this.$route.params.id}?jwt=${
  251. this.$auth.$storage.getUniversal("jwt").token
  252. }`
  253. )
  254. .then((res) => {
  255. this.order = res.data;
  256. for (let index in this.order[0].order_item) {
  257. this.subTotal += this.order[0].order_item[index].item_amount;
  258. }
  259. for (let index in this.order[0].order_as) {
  260. this.subTotal += this.order[0].order_as[index].as_amount;
  261. }
  262. this.serviceId = this.order[0].service_id;
  263. this.currency = this.order[0].currency;
  264. })
  265. .catch((err) => {
  266. console.log(err);
  267. });
  268. },
  269. async getServiceData() {
  270. await this.$axios
  271. .get(
  272. `${this.apiUrl}/user-services/content?service_id=${this.serviceId}&lang_code=${this.$i18n.localeProperties["langQuery"]}&currency=${this.currency}`
  273. )
  274. .then((res) => {
  275. this.content.preview_image = res.data.preview_image;
  276. this.content.name = res.data.name;
  277. this.content.country = res.data.country;
  278. this.content.city = res.data.city;
  279. this.content.highlights = res.data.highlights;
  280. this.content.details = res.data.details;
  281. this.content.cancellation_policy = res.data.cancellation_policy;
  282. this.content.supplier = res.data.supplier;
  283. this.content.available_sections = res.data.available_sections;
  284. this.content.times = res.data.available_sections.times;
  285. this.content.timeStatus = res.data.available_sections.time_status;
  286. this.content.dateStatus = res.data.available_sections.date_status;
  287. this.content.start = res.data.available_sections.start;
  288. this.content.end = res.data.available_sections.end;
  289. this.content.payment_currency = res.data.payment_currency;
  290. this.content.booking_questions = res.data.booking_questions;
  291. })
  292. .catch((error) => console.log(error));
  293. },
  294. async getPackages() {
  295. let orderPackageId = this.order[0].order_item[0].package_id
  296. ? this.order[0].order_item[0].package_id
  297. : "";
  298. await this.$axios
  299. .get(
  300. `${this.apiUrl}/user-services/packages?service_id=${this.serviceId}&lang_code=${this.$i18n.localeProperties["langQuery"]}&currency=${this.currency}`
  301. )
  302. .then((res) => {
  303. this.content.packages = res.data;
  304. let packageObject =
  305. this.content.packages[
  306. this.content.packages.findIndex(
  307. (item) => item.package_id === orderPackageId
  308. )
  309. ];
  310. for (let i in packageObject.questions) {
  311. packageObject.questions[i].required =
  312. packageObject.questions[i].required_ans;
  313. this.content.booking_questions.push(packageObject.questions[i]);
  314. }
  315. })
  316. .catch((error) => console.log(error));
  317. },
  318. async getAdditionalServices() {
  319. await this.$axios
  320. .get(
  321. `${this.apiUrl}/user-services/additional?service_id=${this.serviceId}&lang_code=${this.$i18n.localeProperties["langQuery"]}&currency=${this.currency}`
  322. )
  323. .then((res) => {
  324. this.content.additionalServices =
  325. res.data.services == [] ? null : res.data;
  326. if (this.order[0].order_as.length > 0) {
  327. for (let i in this.content.additionalServices[0].questions) {
  328. this.content.additionalServices[0].questions[i].required =
  329. this.content.additionalServices[0].questions[i].required_ans;
  330. this.content.booking_questions.push(
  331. this.content.additionalServices[0].questions[i]
  332. );
  333. }
  334. }
  335. })
  336. .catch((error) => console.log(error));
  337. },
  338. async payNow() {
  339. let vm = this;
  340. if (this.paymentData.payment_type == "Credit Card") {
  341. try {
  342. ECPay.getPayToken(function (paymentInfo, errMsg) {
  343. //console.log("response => getPayToken(paymentInfo, errMsg):", paymentInfo, errMsg);
  344. if (errMsg != null) {
  345. vm.ErrHandle(errMsg);
  346. return;
  347. }
  348. vm.payToken = paymentInfo.PayToken;
  349. vm.updateOrder(Object);
  350. return true;
  351. });
  352. } catch (err) {
  353. this.ErrHandle(err);
  354. }
  355. } else {
  356. vm.updateOrder(Object);
  357. }
  358. },
  359. async getCountries() {
  360. await this.$axios
  361. .get(`/users/countries?lang=${this.$i18n.locale.replace("-", "")}`)
  362. .then((result) => {
  363. this.countryOptions = result.data.result;
  364. })
  365. .catch((err) => {
  366. console.log(err);
  367. });
  368. },
  369. async getCompanyList() {
  370. await this.$axios
  371. .get(
  372. `/member/company?jwt=${this.$auth.$storage.getUniversal("jwt").token}`
  373. )
  374. .then((result) => {
  375. this.userCompanyList = result.data.data;
  376. Array.from(this.userCompanyList).forEach((item) => {
  377. let id = item.company_country;
  378. let countryName = this.countryOptions.filter(
  379. (item) => item.id === id || null
  380. );
  381. item.company_country_name = countryName[0].name ?? 0;
  382. });
  383. return result.data;
  384. })
  385. .catch((err) => {
  386. console.log(err);
  387. });
  388. },
  389. updateCompanyList() {
  390. this.$axios
  391. .get(
  392. `/member/company?jwt=${this.$auth.$storage.getUniversal("jwt").token}`
  393. )
  394. .then((result) => {
  395. this.userCompanyList = result.data.data;
  396. this.companyActiveLabel = this.userCompanyList.length;
  397. this.Company.company_name =
  398. result.data.data[this.activeLabel].company_name;
  399. this.Company.company_tax_no =
  400. result.data.data[this.activeLabel].company_tax_no;
  401. this.Company.company_address1 =
  402. result.data.data[this.activeLabel].company_address1;
  403. this.Company.company_address2 =
  404. result.data.data[this.activeLabel].company_address2;
  405. this.Company.company_city =
  406. result.data.data[this.activeLabel].company_city;
  407. this.Company.company_state =
  408. result.data.data[this.activeLabel].company_state;
  409. this.Company.company_country =
  410. result.data.data[this.activeLabel].company_country_name;
  411. this.Company.company_zipcode =
  412. result.data.data[this.activeLabel].company_zipcode;
  413. return result.data;
  414. })
  415. .catch((err) => {
  416. console.log(err);
  417. });
  418. },
  419. updateOrder() {
  420. let Object = {
  421. order_id: this.order[0].order_id,
  422. total: this.subTotal,
  423. amount: this.subTotal,
  424. discount: 0,
  425. contact: [this.contactData],
  426. answer: this.answerData,
  427. };
  428. if (this.type == "Individual") {
  429. Object.purchase_personal = this.individualData;
  430. } else {
  431. Object.purchase_company = this.companyData;
  432. }
  433. Object.payment = [this.paymentData];
  434. Object.payment[0].payment_index = 0;
  435. Object.payment[0].amount = this.subTotal;
  436. this.$axios
  437. .put(
  438. `/order/${this.$route.params.id}?jwt=${
  439. this.$auth.$storage.getUniversal("jwt").token || ""
  440. }`,
  441. Object
  442. )
  443. .then((res) => {
  444. if (res.status == "200") {
  445. if (this.paymentData.payment_type == "Credit Card") {
  446. this.createPayment();
  447. } else {
  448. this.$router.push(
  449. this.localePath("/service/done/" + this.$route.params.id)
  450. );
  451. }
  452. }
  453. })
  454. .catch((error) => {
  455. console.log(error);
  456. });
  457. },
  458. getActiveLength() {
  459. this.activeLabel = this.userContactList.length > 0 ? 1 : 0;
  460. },
  461. updateToken(token) {
  462. this.payToken = token;
  463. },
  464. createPayment() {
  465. this.$axios
  466. .post(`${this.devECPayUrl}/payment/ecpay/create-payment`, {
  467. pay_token: this.payToken,
  468. payment_flow: "ecpay",
  469. product_order_no: this.orderNo,
  470. })
  471. .then((response) => {
  472. if (response.data.status_code === 200) {
  473. window.location.assign(response.data.three_d_url);
  474. }
  475. })
  476. .catch((error) => console.log(error));
  477. },
  478. getBookingDetail_validation(data) {
  479. this.bookingDetail_Validation = data;
  480. },
  481. getPurchaserInfo_validation(data) {
  482. this.purchaserInfo_Validation = data;
  483. },
  484. },
  485. };
  486. </script>
  487. <style lang="scss" scoped>
  488. .noFilter {
  489. pointer-events: auto;
  490. cursor: auto;
  491. }
  492. .haveFilter {
  493. cursor: not-allowed;
  494. pointer-events: none;
  495. filter: opacity(50%);
  496. }
  497. </style>