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
17 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. <template>
  2. <div
  3. style="border: 1px solid red;"
  4. class="tw-px-[30px] tw-mt-[30px] tw-mb-[60px] md:tw-mb-[100px] xl:tw-px-[60px] xl:tw-max-w-screen-xl xl:tw-mx-auto xl:tw-grid xl:tw-grid-cols-[380px_auto] xl:tw-gap-[30px]">
  5. <section class="xl:tw-col-span-2 tw-mb-[36px] md:tw-mb-[24px] lg:tw-mb-[34px]">
  6. <Breadcrumbs></Breadcrumbs>
  7. <sort :results="result" :sortType="sortType" :sortBy="sortBy" @sort="updateSortBy($event)"
  8. @filter="$modal.show(`sidebar-filter-modal`)"></sort>
  9. </section>
  10. <section class="tw-grid tw-grid-cols-1 tw-gap-[30px] tw-auto-rows-min">
  11. <div v-if="$vuetify.breakpoint.xl">
  12. <multipleLevel :label="'Categories'" :placeholder="$t('Find category/subcategory ...')" :list="categoryList" :queryItem="categoryQueryFilter"
  13. @update="updateCategoryFilter"></multipleLevel>
  14. </div>
  15. <div v-if="$vuetify.breakpoint.xl">
  16. <multipleLevel :label="'Location'" :placeholder="$t('Find country/city ...')" :list="locationList"
  17. :queryItem="locationQueryFilter" @update="updateLocationFilter"></multipleLevel>
  18. </div>
  19. <!-- <div v-if="$vuetify.breakpoint.xl">
  20. <price :max="maxPrice" :currentValue="priceRangeFilter" @update="updatePriceRange"></price>
  21. </div> -->
  22. <!-- <div v-if="$vuetify.breakpoint.xl">
  23. <rating @update="updateRatingRange"></rating>
  24. </div> -->
  25. </section>
  26. <section class="">
  27. <ServiceListCard class="tw-mb-[30px]" v-for="(item, index) in serviceList" :key="index" :service="item">
  28. </ServiceListCard>
  29. <div class="tw-mt-[34px] tw-flex tw-justify-end">
  30. <pagination :pageLength="pageLength" @update="updateCurrentPage"></pagination>
  31. </div>
  32. </section>
  33. <div v-if="!$vuetify.breakpoint.xl">
  34. <sidebarFilterModal :max="maxPrice" :locationList="locationList"
  35. :locationChecked="locationNameFilter" :categoryChecked="categoryFilter" :priceChecked="priceRangeFilter"
  36. @updatePriceRange="updatePriceRange" @updateCategoryFilter="updateCategoryFilter"
  37. @updateLocationFilter="updateLocationFilter"></sidebarFilterModal>
  38. </div>
  39. <loading :isLoading="isPageLoading"></loading>
  40. </div>
  41. </template>
  42. <script>
  43. import Breadcrumbs from "@/components/Breadcrumbs";
  44. import sort from "@/components/newComponent/sort/sort";
  45. import oneLevel from "@/components/newComponent/filter/oneLevel";
  46. import multipleLevel from "@/components/newComponent/filter/multipleLevel";
  47. import price from "@/components/newComponent/filter/price";
  48. import rating from "@/components/newComponent/filter/rating.vue";
  49. import pagination from "@/components/newComponent/pagination/pagination.vue";
  50. import sidebarFilterModal from "@/components/newComponent/modal/sidebarFilterModal.vue";
  51. import ServiceListCard from "@/components/service/ServiceListCard";
  52. import loading from "@/components/newComponent/loading/loading.vue";
  53. export default {
  54. name: "ServiceList",
  55. auth: false,
  56. components: {
  57. Breadcrumbs,
  58. sort,
  59. oneLevel,
  60. multipleLevel,
  61. price,
  62. rating,
  63. sidebarFilterModal,
  64. ServiceListCard,
  65. pagination,
  66. loading,
  67. },
  68. meta: {
  69. pageName: "Service List",
  70. },
  71. data() {
  72. return {
  73. renderList: [],
  74. serviceList: [],
  75. sortType: [
  76. // { name: "Ratings", value: "Ratings" },
  77. // { name: "ShowEasy Recommended", value: "ShowEasy Recommended" },
  78. { name: "Popularity", value: "CreateDate" },
  79. { name: "Price (Low to High)", value: "MinPrice" },
  80. { name: "Recently Added", value: "LaunchDateS" },
  81. ],
  82. locationList: [],
  83. categoryList: [],
  84. // regionNameList: ['123'],
  85. countryNameList: ['Asia','Asia1'],
  86. cityNameList: ['Taiwan','Taiwan1'],
  87. categoryNameList: ['Rental cars','Rental cars1'],
  88. subcategoryNameList: ['子類1'],
  89. sortBy: "CreateDate",
  90. maxPrice: 100,
  91. priceRangeFilter: [0,100],
  92. ratingRangeFilter: [0, 5],
  93. locationNameFilter: ['Asia','Taiwan'],
  94. categoryFilter: ['Rental cars','Rental cars1'],
  95. perPageItems: 10,
  96. currentPage: 1,
  97. total: 0,
  98. locationQueryFilter: "",
  99. categoryQueryFilter: "",
  100. isPageLoading: false,
  101. mainCategoryMap: new Map(),
  102. subCategoryMap: new Map(),
  103. mainLocationMap: new Map(),
  104. subLocationMap: new Map(),
  105. subLocationMap2: new Map(),
  106. mainCategoryQuery: '',
  107. subCategoryQuery: '',
  108. };
  109. },
  110. async created() {
  111. this.isPageLoading = true;
  112. await this.getQuery();
  113. await this.getServiceList();
  114. await this.getCategoryList();
  115. await this.getLocationList();
  116. // await this.getPriceRange();
  117. // this.renderList = this.sliceRenderList(this.serviceFilter);
  118. this.$nextTick(()=>{
  119. this.isPageLoading = false;
  120. });
  121. },
  122. mounted() { },
  123. computed: {
  124. // serviceFilter() {
  125. // var vm = this;
  126. // if (Array.isArray(vm.serviceList)) {
  127. // let priceList = vm.filterByPrice(
  128. // vm.serviceList,
  129. // vm.priceRangeFilter[0],
  130. // vm.priceRangeFilter[1]
  131. // );
  132. // priceList = priceList == undefined ? [] : priceList;
  133. // let locationList = vm.filterByLocation(
  134. // priceList,
  135. // vm.locationNameFilter
  136. // );
  137. // locationList = locationList == undefined ? [] : locationList;
  138. // let categoryList = vm.filterByCategory(
  139. // locationList,
  140. // vm.categoryFilter
  141. // );
  142. // categoryList = categoryList == undefined ? [] : categoryList;
  143. // if(categoryList.length<1){
  144. // return [];
  145. // }
  146. // let sortedList = vm.sortServiceList(categoryList);
  147. // return sortedList;
  148. // } else {
  149. // return [];
  150. // }
  151. // },
  152. result() {
  153. return this.total;
  154. },
  155. pageLength() {
  156. return Math.ceil(this.result / this.perPageItems);
  157. },
  158. // renderList() {
  159. // let arr = this.sliceRenderList(this.serviceFilter);
  160. // return arr;
  161. // },
  162. currency() {
  163. return this.$store.getters.getCurrency;
  164. },
  165. },
  166. watch: {
  167. currency: {
  168. handler: async function (newVal, oldVal) {
  169. let vm = this;
  170. if (newVal !== oldVal) {
  171. vm.isPageLoading = true;
  172. await vm.getServiceList();
  173. // let data =await vm.mapServiceLocationName(
  174. // vm.serviceList,
  175. // vm.countryNameList,
  176. // vm.cityNameList
  177. // );
  178. // vm.serviceList = data == undefined ? [] : data;
  179. // vm.serviceList =await vm.mapServiceCategoryName(
  180. // vm.serviceList,
  181. // vm.categoryNameList
  182. // );
  183. // vm.serviceList = data == undefined ? [] : data;
  184. // vm.renderList =await vm.serviceList;
  185. // await vm.getPriceRange();
  186. vm.isPageLoading = false;
  187. }
  188. },
  189. },
  190. // $route: {
  191. // handler: function () {
  192. // this.getQuery();
  193. // },
  194. // },
  195. },
  196. methods: {
  197. async getServiceList() {
  198. let vm = this;
  199. let keyword = "";
  200. let subcatg = "";
  201. let sortField = "CreateDate";
  202. if(vm.sortBy){
  203. sortField = vm.sortBy;
  204. }
  205. let location = "";
  206. // let category = "";
  207. let currency = this.$store.getters.getCurrency;
  208. if (vm.$route.query.q) {
  209. keyword = vm.$route.query.q;
  210. }
  211. // if (vm.$route.query.category) {
  212. // category = "&category=" + vm.$route.query.category;
  213. // }
  214. // if (vm.categoryQueryFilter) {
  215. // subcatg = vm.categoryQueryFilter;
  216. // }else if(vm.$route.query.subcatg){
  217. // subcatg = vm.$route.query.subcatg;
  218. // }
  219. // if(vm.locationQueryFilter){
  220. // location = vm.locationQueryFilter;
  221. // }
  222. await vm.$axios.get(`/trending/api/Onsite/ServiceLists?Lang=${vm.$i18n.localeProperties["langQuery"]}&PageIndex=${vm.currentPage}
  223. &PageSize=${vm.perPageItems}&SortField=${sortField}&sortOrder=desc&KeyWord=${keyword}&Categories=${subcatg}&Locations=${location}
  224. &Currency=${currency}&MinPrice=0&MaxPrice=0`).then((response) => {
  225. if(response && response.data && response.data.DATA && response.data.DATA.rel){
  226. let data = response.data.DATA.rel
  227. if(data.DataList.length>0){
  228. vm.total = data.Total;
  229. vm.serviceList = data.DataList;
  230. }
  231. }
  232. })
  233. .catch((err) => {
  234. console.log(err);
  235. });
  236. },
  237. async getCategoryList() {
  238. await this.$axios
  239. .get(`/trending/api/Onsite/Categories?Lang=${this.$i18n.localeProperties["langQuery"]}`)
  240. .then((response) => {
  241. if(response && response.data && response.data.DATA && response.data.DATA.rel){
  242. let data = response.data.DATA.rel
  243. if(data.length>0){
  244. this.categoryList = data.map((item) => {
  245. this.mainCategoryMap.set(item.CategoryID, item);
  246. if(item.SubCategoryList && item.SubCategoryList.length>0){
  247. item.SubCategoryList = item.SubCategoryList.map(
  248. (children) => {
  249. this.subCategoryMap.set(children.CategoryID, children);
  250. return {
  251. title: children.CategoryName,
  252. key: children.CategoryID,
  253. };
  254. }
  255. );
  256. }else{
  257. item.SubCategoryList = [];
  258. }
  259. return {
  260. title: item.CategoryName,
  261. key: item.CategoryID,
  262. children: item.SubCategoryList,
  263. };
  264. });
  265. }
  266. }
  267. })
  268. .catch((error) =>
  269. console.log(error)
  270. );
  271. },
  272. async getLocationList() {
  273. await this.$axios
  274. .get(`/trending/api/Onsite/Locations?Lang=${this.$i18n.localeProperties["langQuery"]}`)
  275. .then((response) => {
  276. if(response && response.data && response.data.DATA && response.data.DATA.rel){
  277. let data = response.data.DATA.rel
  278. if(data.length>0){
  279. // this.locationList = data;
  280. this.locationList = data.map((item) => {
  281. this.mainLocationMap.set(item.RegionID, item);
  282. if(item.CountryList && item.CountryList.length>0){
  283. item.CountryList = item.CountryList.map(
  284. (children) => {
  285. this.subLocationMap.set(children.CountryID, children);
  286. if(children.CityList && children.CityList.length>0){
  287. children.CityList = children.CityList.map(
  288. (children2) => {
  289. this.subLocationMap2.set(children2.CityID, children2);
  290. return {
  291. title: children2.CityName,
  292. key: children2.CityID,
  293. };
  294. }
  295. );
  296. }else{
  297. children.CityList = [];
  298. }
  299. return {
  300. title: children.CountryName,
  301. key: children.CountryID,
  302. children: children.CityList,
  303. };
  304. }
  305. );
  306. }else{
  307. item.CountryList = [];
  308. }
  309. return {
  310. title: item.RegionName,
  311. key: item.RegionID,
  312. children: item.CountryList,
  313. };
  314. });
  315. }
  316. }
  317. })
  318. .catch((error) =>
  319. console.log(error)
  320. );
  321. },
  322. updateSortBy(data) {
  323. this.sortBy = data;
  324. // console.log("排序:"+this.sortBy);
  325. this.getServiceList();
  326. },
  327. // sortServiceList(data) {
  328. // switch (this.sortBy) {
  329. // // case "Ratings":
  330. // // function Ratings(a, b) {
  331. // // if (Number(a.rating) < Number(b.rating)) return 1;
  332. // // if (Number(a.rating) > Number(b.rating)) return -1;
  333. // // return 0;
  334. // // }
  335. // // return data.sort(Ratings);
  336. // // case "ShowEasy Recommended":
  337. // // return data;
  338. // case "Popularity":
  339. // function Views(a, b) {
  340. // if (Number(a.view_counts) < Number(b.view_counts)) return 1;
  341. // if (Number(a.view_counts) > Number(b.view_counts)) return -1;
  342. // return 0;
  343. // }
  344. // return data.sort(Views);
  345. // case "Price":
  346. // function Price(a, b) {
  347. // if (Number(a.price) < Number(b.price)) return -1;
  348. // if (Number(a.price) > Number(b.price)) return 1;
  349. // return 0;
  350. // }
  351. // return data.sort(Price);
  352. // case "Recently Added":
  353. // function Date(a, b) {
  354. // if (
  355. // a.launch_dates[0].replace(/-/g, "") <
  356. // b.launch_dates[0].replace(/-/g, "")
  357. // )
  358. // return 1;
  359. // if (
  360. // a.launch_dates[0].replace(/-/g, "") >
  361. // b.launch_dates[0].replace(/-/g, "")
  362. // )
  363. // return -1;
  364. // return 0;
  365. // }
  366. // return data.sort(Date);
  367. // default:
  368. // return data;
  369. // }
  370. // },
  371. mapSavedService(data, savedList) {
  372. return data.map((item) => {
  373. item.liked = false;
  374. if (savedList.includes(item.id)) {
  375. item.liked = true;
  376. }
  377. return item;
  378. });
  379. },
  380. mapServiceLocationName(data, countryList, cityList) {
  381. data = data.map((item) => {
  382. Number(item.country) > 0
  383. ? (item.countryName = countryList[item.country])
  384. : (item.countryName = "");
  385. return item;
  386. });
  387. data = data.map((item) => {
  388. Number(item.city) > 0
  389. ? (item.cityName = cityList[item.city])
  390. : (item.cityName = "");
  391. return item;
  392. });
  393. return data;
  394. },
  395. mapServiceCategoryName(data, categoryList) {
  396. data = data.map((item) => {
  397. Number(item.category) > 0
  398. ? (item.categoryName = categoryList[item.category])
  399. : (item.categoryName = "");
  400. return item;
  401. });
  402. return data;
  403. },
  404. async getPriceRange() {
  405. let max = 0;
  406. let vm = this;
  407. if(vm.serviceList){
  408. vm.serviceList.forEach((element) => {
  409. if (element.price > max) {
  410. max = element.price;
  411. }
  412. });
  413. }
  414. vm.maxPrice = max;
  415. vm.priceRangeFilter = [0, max];
  416. },
  417. filterByPrice(data, min, max) {
  418. let item = data.filter((item) => item.price >= min && item.price <= max);
  419. return item;
  420. },
  421. updatePriceRange(value) {
  422. this.priceRangeFilter = [...value];
  423. },
  424. filterByRating(data, min, max) {
  425. return data.filter((item) => item.price >= min && item.price <= max);
  426. },
  427. updateRatingRange(value) {
  428. // console.log(value);
  429. },
  430. filterByLocation(data, locations) {
  431. let list = data.filter(
  432. (item) =>
  433. locations.includes(item.cityName) ||
  434. locations.includes(item.countryName)
  435. );
  436. return list;
  437. },
  438. updateLocationFilter(value) {
  439. // console.log("位置勾選");
  440. this.locationQueryFilter = "";
  441. // this.getServiceList();
  442. },
  443. filterByCategory(data, categories) {
  444. return data.filter((item) => categories.includes(item.categoryName));
  445. },
  446. updateCategoryFilter(value) {
  447. // console.log("類型勾選:" + value);
  448. this.categoryQueryFilter = "";
  449. // this.getServiceList();
  450. },
  451. updateCurrentPage(value) {
  452. // console.log("分頁變化");
  453. this.currentPage = value;
  454. this.getServiceList();
  455. },
  456. sliceRenderList(data) {
  457. return data.slice(
  458. (this.currentPage - 1) * this.perPageItems,
  459. this.currentPage * this.perPageItems
  460. );
  461. },
  462. async getQuery() {
  463. let vm = this;
  464. // this.locationQueryFilter = "";
  465. this.categoryQueryFilter = "";
  466. // if (this.$route.query.hasOwnProperty("country") && this.countryNameList.length>0) {
  467. // this.locationQueryFilter =
  468. // this.countryNameList[Number(this.$route.query.country)];
  469. // }
  470. // if (this.$route.query.hasOwnProperty("city") && this.cityNameList.length>0) {
  471. // this.locationQueryFilter =
  472. // this.cityNameList[Number(this.$route.query.city)];
  473. // }
  474. // if (this.$route.query.hasOwnProperty("region")) {
  475. // this.locationQueryFilter =
  476. // this.regionNameList[Number(this.$route.query.region)];
  477. // }
  478. // if (this.$route.query.hasOwnProperty("category") && this.categoryNameList.length>0) {
  479. // this.categoryQueryFilter =
  480. // this.categoryNameList[Number(this.$route.query.category)];
  481. // }
  482. // if (this.$route.query.hasOwnProperty("subcategory")) {
  483. // this.categoryQueryFilter =
  484. // this.unsortSubcategoryList[Number(this.$route.query.subcategory)];
  485. // }
  486. if(vm.$route.query.hasOwnProperty("category")){
  487. // vm.categoryQueryFilter = vm.$route.query.category;
  488. }else if(vm.$route.query.hasOwnProperty("subcatg")){
  489. vm.categoryQueryFilter = vm.$route.query.subcatg;
  490. }
  491. },
  492. },
  493. };
  494. </script>
  495. <style lang="scss" scoped>
  496. </style>