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.

502 lines
16 KiB

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