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
19 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
  1. <template>
  2. <div class="search">
  3. <v-card v-click-outside="clickOutSide"
  4. class="tw-flex tw-px-[16px] tw-py-[11px] tw-rounded-[16px] tw-w-[345px] md:tw-w-[382px] xl:tw-w-[760px]">
  5. <div class="btn-group tw-flex tw-rounded-none xl:tw-pr-[16px] xl:tw-mr-[16px]">
  6. <v-btn class="border-radius-14 remove-upper mx-0 tw-hidden xl:tw-block tw-text-white tw-bg-primary-default"
  7. style="font-size: 14px" height="40" text @click="clickExhibition">{{ $t('Exhibition')}}</v-btn>
  8. <!-- <v-btn class="border-radius-14 remove-upper mx-0 tw-hidden xl:tw-block"
  9. :class="tabToggle == 1 ? 'tw-text-white tw-bg-primary-default' : 'tw-text-primary-default'"
  10. style="font-size: 14px" text height="40" @click="clickService">{{ $t('Service')}}</v-btn> -->
  11. </div>
  12. <div class="custom-control flex-grow-1 tw-text-[16px] tw-text-base-tertiary xl:tw-hidden" @click="handleClick">
  13. {{ $t(customPlaceholder) }}
  14. </div>
  15. <input class="custom-control flex-grow-1 tw-text-[16px] tw-placeholder-text-[16px] tw-hidden xl:tw-block"
  16. v-model="inputs" :placeholder="$t(customPlaceholder)" @input="handleInput" @click="handleClick"
  17. v-on:keyup.enter="$router.push(localePath(`/${type}?q=${inputs}`));isPageLoading = true" />
  18. <svg width="24" height="24" class="tw-my-auto tw-pointer-events-none xl:tw-pointer-events-auto"
  19. shape-rendering="geometricPrecision" @click="goToSearch()">
  20. <image xlink:href="@/assets/svg/icon-search-small.svg" src="@/assets/svg/icon-search-small.svg" width="24"
  21. height="24" />
  22. </svg>
  23. <v-card class="search-result white rounded-lg above" v-if="keywords.length != 0 && keyword"
  24. style="z-index: 999 !important" :max-width="width">
  25. <template v-for="(keyword, idx) in populars.search">
  26. <v-row v-if="type=='exhibition'" :key="idx"
  27. class="mx-2 my-2 grey--text text--lighten-1">
  28. <nuxt-link :to="localePath(`/${type}?q=${keyword}`)" class="remove-underline"
  29. style="width: 100%; height: 100%">
  30. <v-card flat color="transparent" width="100%" height="40" style="padding: 0px 12px"
  31. class="d-flex align-center">
  32. {{ keyword }}
  33. </v-card>
  34. </nuxt-link>
  35. </v-row>
  36. </template>
  37. <!-- <template v-for="(keyword, idx) in popular.service">
  38. <v-row v-if="type=='service'" :key="idx"
  39. class="mx-2 my-2 grey--text text--lighten-1">
  40. <nuxt-link :to="localePath(`/${type}?q=${keyword}`)" class="remove-underline"
  41. style="width: 100%; height: 100%">
  42. <v-card flat color="transparent" width="100%" height="40" style="padding: 0px 12px"
  43. class="d-flex align-center">
  44. {{ keyword }}
  45. </v-card>
  46. </nuxt-link>
  47. </v-row>
  48. </template> -->
  49. </v-card>
  50. <!-- exhibition -->
  51. <v-container
  52. class="search-result white border-radius-16 hidden-sm-and-down xl:tw-px-[20px] xl:tw-py-[20px] tw-shadow-[0_1px_6px_0_rgba(0,0,0,0.4)]"
  53. v-if="exhibition">
  54. <!-- <div class="tw-mb-[20px]">
  55. <div class="tw-mb-[20px]">
  56. <div class="tw-body-3 tw-font-bold tw-text-black tw-mb-[20px]">{{ $t('History') }} </div>
  57. <div class="tw-flex tw-flex-wrap">
  58. <nuxt-link
  59. class="tw-mr-[16px] tw-mb-[10px] tw-px-[16px] tw-py-[7px] tw-border-solid tw-border-[1px] tw-rounded-[12px] tw-transition-all tw-duration-300 tw-ease-in-out tw-border-x-secondary-default tw-text-secondary-default hover:tw-border-transparent hover:tw-bg-secondary-default hover:tw-text-white"
  60. v-for="(servicesSearch, idx) in servicesSearchs" :key="idx"
  61. :to="localePath(`/exhibition?q=${servicesSearch}`)">
  62. {{ servicesSearch }}
  63. </nuxt-link>
  64. </div>
  65. </div>
  66. </div> -->
  67. <div class="tabs tw-flex tw-mb-[16px] md:tw-mb-[20px]">
  68. <button
  69. :class="['tw-mr-[30px] tw-body-3 tw-transition-all tw-duration-300 tw-ease-in-out tab',tabs == 'exhibitionsCategories' ? 'active tw-text-black tw-font-bold':'tw-text-neutrals-500']"
  70. @click="tabs = 'exhibitionsCategories'">{{
  71. $t('Exhibition Categories')
  72. }}</button>
  73. <button
  74. :class="['tw-body-3 tw-transition-all tw-duration-300 tw-ease-in-out tab',tabs == 'location' ? 'active tw-text-black tw-font-bold':'tw-text-neutrals-500']"
  75. @click="tabs = 'location'">{{ $t('Location')
  76. }}</button>
  77. </div>
  78. <div v-if="tabs=='exhibitionsCategories'">
  79. <div class="customMenuLink tw-relative tw-z-10" @mouseleave="exhibitionActiveIndex=0">
  80. <div class="customDropMenu exhibition tw-w-full">
  81. <div class="tw-relative tw-grid tw-grid-cols-2 tw-max-h-[270px]" v-if="exhibitionsCategories && exhibitionsCategories.length>0">
  82. <div
  83. class="tw-list-none tw-overflow-x-hidden tw-overflow-y-auto tw-h-auto tw-break-inside-avoid tw-grid tw-grid-cols-1 tw-gap-[20px]">
  84. <div class="tw-list-none tw-pr-[20px]" v-for="(item,index) in exhibitionsCategories" :key="index"
  85. @mouseover="exhibitionActiveIndex=index">
  86. <div
  87. :class="['exhibitionDropdownLink tw-w-full tw-body-4 tw-font-normal hover:tw-text-primary-default',exhibitionActiveIndex == index ? 'tw-text-primary-default active':'tw-text-neutrals-900']">
  88. <span class="tw-flex tw-items-center tw-min-w-[322px]">{{
  89. $t(item.CategoryName)
  90. }}</span>
  91. </div>
  92. </div>
  93. </div>
  94. <div class="tw-overflow-x-hidden tw-overflow-y-auto">
  95. <ul class="tw-list-none tw-grid tw-grid-cols-1 tw-gap-[20px] tw-px-[20px] " v-if="exhibitionsCategories[exhibitionActiveIndex].SubCategoryList && exhibitionsCategories[exhibitionActiveIndex].SubCategoryList.length>0">
  96. <li class="tw-list-none"><a
  97. :href="localePath(`/exhibition?category=${exhibitionsCategories[exhibitionActiveIndex].CategoryID}`)"
  98. class="tw-block tw-body-4 tw-font-normal tw-text-neutral-800 hover:tw-text-primary-default">{{
  99. $t('All')}}</a>
  100. </li>
  101. <li v-for="(sub,index) in exhibitionsCategories[exhibitionActiveIndex].SubCategoryList" :key="index"
  102. class="tw-list-none"><a :href="localePath(`/exhibition?subcategory=${sub.CategoryID}`)"
  103. class="tw-block tw-min-h-[30px] tw-body-4 tw-font-normal tw-min-w-[230px] tw-text-neutral-800 hover:tw-text-primary-default">{{
  104. sub.CategoryName }}</a>
  105. </li>
  106. </ul>
  107. </div>
  108. </div>
  109. </div>
  110. </div>
  111. </div>
  112. <div v-if="tabs=='location'">
  113. <div class="customMenuLink tw-relative tw-flex tw-justify-start tw-items-center tw-z-10">
  114. <div class="customDropMenu exhibition tw-w-full tw-overflow-hidden">
  115. <div class="tw-relative tw-grid tw-grid-cols-[1fr_1fr_1fr] tw-max-h-[270px]">
  116. <div
  117. class="tw-list-none tw-overflow-y-auto tw-h-auto tw-break-inside-avoid tw-flex tw-flex-col tw-pr-[20px]">
  118. <template v-if="exhibitionsLocations && exhibitionsLocations.length>0">
  119. <div v-for="(item,index) in exhibitionsLocations" :key="index"
  120. @mouseover="locationActiveIndex=index;cityActiveIndex=0"
  121. :class="['exhibitionDropdownLink tw-block tw-w-full tw-body-4 tw-font-normal tw-mb-[20px] tw-pr-[20px] hover:tw-text-primary-default',locationActiveIndex == index ? 'tw-text-primary-default active':'tw-text-neutrals-900']">
  122. {{
  123. $t(item.RegionName)
  124. }}</div></template>
  125. </div>
  126. <div class="tw-overflow-x-hidden tw-overflow-y-auto" v-if="exhibitionsLocations && exhibitionsLocations.length>0">
  127. <ul class="tw-px-[20px] tw-list-none tw-flex tw-flex-col tw-flex-wrap" v-if="exhibitionsLocations[locationActiveIndex].CountryList && exhibitionsLocations[locationActiveIndex].CountryList.length>0">
  128. <li class="tw-list-none tw-mb-[20px]"><a
  129. :href="localePath(`/exhibition?region=${exhibitionsLocations[locationActiveIndex].RegionID}`)"
  130. class="tw-block tw-body-4 tw-font-normal tw-text-neutral-800 hover:tw-text-primary-default">{{
  131. $t('All')}}</a>
  132. </li>
  133. <li v-for="(countries,index) in exhibitionsLocations[locationActiveIndex].CountryList" :key="index"
  134. @mouseover="cityActiveIndex=index"
  135. :class="['exhibitionDropdownLink tw-block tw-w-full tw-body-4 tw-font-normal tw-mb-[20px] tw-pr-[20px] hover:tw-text-primary-default',cityActiveIndex == index ? 'tw-text-primary-default active':'tw-text-neutrals-900']">
  136. {{
  137. countries.CountryName }}
  138. </li>
  139. </ul>
  140. </div>
  141. <div class="tw-overflow-x-hidden tw-overflow-y-auto" v-if="exhibitionsLocations && exhibitionsLocations.length>0">
  142. <ul class="tw-px-[20px] tw-list-none tw-flex tw-flex-col tw-flex-wrap" v-if="exhibitionsLocations[locationActiveIndex].CountryList && exhibitionsLocations[locationActiveIndex].CountryList.length>0">
  143. <li class="tw-list-none tw-mb-[20px]"><a
  144. :href="localePath(`/exhibition?region=${exhibitionsLocations[locationActiveIndex].CountryList[cityActiveIndex].CountryID}`)"
  145. class="tw-block tw-body-4 tw-font-normal tw-text-neutral-800 hover:tw-text-primary-default">{{
  146. $t('All')}}</a>
  147. </li>
  148. <template v-if="exhibitionsLocations[locationActiveIndex].CountryList[cityActiveIndex].cities && exhibitionsLocations[locationActiveIndex].CountryList[cityActiveIndex].cities.length>0">
  149. <li
  150. v-for="(cities,index) in exhibitionsLocations[locationActiveIndex].CountryList[cityActiveIndex].cities"
  151. :key="index" class="tw-list-none tw-mb-[20px]"><a
  152. :href="localePath(`/exhibition?city=${cities.CityID}`)"
  153. class="tw-block tw-body-4 tw-font-normal tw-text-neutral-800 hover:tw-text-primary-default">{{
  154. cities.CityName }}</a>
  155. </li></template>
  156. </ul>
  157. </div>
  158. </div>
  159. </div>
  160. </div>
  161. </div>
  162. </v-container>
  163. <!-- exhibition -->
  164. <!-- service -->
  165. <!-- <v-container
  166. class="search-result tw-px-[30px] tw-py-[20px] tw-bg-white tw-rounded-[16px] tw-hidden xl:tw-px-[20px] xl:tw-py-[20px] tw-shadow-[0_1px_6px_0_rgba(0,0,0,0.4)] xl:tw-block"
  167. v-if="service" v-click-outside="">
  168. <div class="">
  169. <div class="tw-mb-[20px]">
  170. <div class="tw-body-3 tw-font-bold tw-text-black tw-mb-[20px]">{{ $t('History') }} </div>
  171. <div class="tw-flex tw-flex-wrap">
  172. <nuxt-link
  173. class="tw-mr-[16px] tw-mb-[10px] tw-px-[16px] tw-py-[7px] tw-border-solid tw-border-[1px] tw-rounded-[12px] tw-transition-all tw-duration-300 tw-ease-in-out tw-border-x-secondary-default tw-text-secondary-default hover:tw-border-transparent hover:tw-bg-secondary-default hover:tw-text-white"
  174. v-for="(servicesSearch, idx) in servicesSearchs" :key="idx"
  175. :to="localePath(`/service?q=${servicesSearch}`)">
  176. {{ servicesSearch }}
  177. </nuxt-link>
  178. </div>
  179. </div>
  180. <div>
  181. <div class="tw-body-3 tw-font-bold tw-text-black tw-mb-[20px]">{{ $t('Location') }} </div>
  182. <div class="tw-flex tw-flex-wrap">
  183. <nuxt-link
  184. class="tw-mr-[16px] tw-mb-[10px] tw-px-[16px] tw-py-[7px] tw-border-solid tw-border-[1px] tw-rounded-[12px] tw-transition-all tw-duration-300 tw-ease-in-out tw-border-x-secondary-default tw-text-secondary-default hover:tw-border-transparent hover:tw-bg-secondary-default hover:tw-text-white"
  185. v-for="(servicesLocation, idx) in servicesLocations" :key="idx"
  186. :to="localePath(`/service?q=${servicesLocation}`)">
  187. {{ servicesLocation }}
  188. </nuxt-link>
  189. </div>
  190. </div>
  191. </div>
  192. </v-container> -->
  193. <!-- service -->
  194. </v-card>
  195. <loading :isLoading="isPageLoading"></loading>
  196. </div>
  197. </template>
  198. <script>
  199. import loading from "@/components/newComponent/loading/loading.vue";
  200. export default {
  201. props: {
  202. servicesSearchs: {
  203. type: Array,
  204. default: () => []
  205. },
  206. servicesLocations: {
  207. type: Array,
  208. default: () => []
  209. },
  210. exhibitionsSearchs: {
  211. type: Array,
  212. default: () => []
  213. },
  214. exhibitionsLocations: {
  215. type: Array,
  216. default: () => []
  217. },
  218. exhibitionsCategories: {
  219. type: Array,
  220. default: () => []
  221. },
  222. serviceKeywords: {
  223. type: Array,
  224. default: () => []
  225. },
  226. exhibitionsKeywords: {
  227. type: Array,
  228. default: () => []
  229. },
  230. populars: {
  231. type: Object,
  232. default: () => { }
  233. },
  234. type: {
  235. type: String
  236. },
  237. },
  238. components: {
  239. loading
  240. },
  241. data() {
  242. return {
  243. toggle_exclusive: 1,
  244. inputs: "",
  245. keywords: [],
  246. exhibitionTabTitles: ["Location", "Exhibition Categories"],
  247. tabToggle: 0,
  248. tab: null,
  249. tab2: null,
  250. tabs: 'exhibitionsCategories',
  251. exhibition: false,
  252. service: false,
  253. keyword: false,
  254. locationsIdx: 0,
  255. countriesIdx: 0,
  256. categoriesIdx: 0,
  257. exhibitionActiveIndex: 0,
  258. locationActiveIndex: 0,
  259. cityActiveIndex: 0,
  260. isPageLoading: false,
  261. WindowsWidth: undefined,
  262. customPlaceholder: 'Search exhibitions or services...',
  263. };
  264. },
  265. created() {
  266. if (process.client) {
  267. this.WindowsWidth = window.innerWidth;
  268. }
  269. },
  270. mounted() {
  271. this.$nextTick(() => {
  272. window.addEventListener("resize", this.onResize);
  273. if (this.WindowWidth >= 1366) {
  274. this.customPlaceholder = 'Explore global exhibitions';
  275. } else {
  276. this.customPlaceholder = 'Search exhibitions or services...';
  277. }
  278. });
  279. },
  280. beforeDestroy() {
  281. window.removeEventListener("resize", this.onResize);
  282. },
  283. computed: {
  284. WindowWidth() {
  285. if (process.client) {
  286. this.WindowsWidth = window.innerWidth;
  287. }
  288. return this.WindowsWidth;
  289. },
  290. },
  291. watch: {
  292. WindowsWidth: {
  293. handler: function () {
  294. if (this.WindowWidth >= 1366) {
  295. this.customPlaceholder = 'Explore global exhibitions';
  296. } else {
  297. this.customPlaceholder = 'Search exhibitions or services...';
  298. }
  299. }
  300. }
  301. },
  302. methods: {
  303. onResize() {
  304. if (process.client) {
  305. this.WindowsWidth = window.innerWidth;
  306. }
  307. },
  308. handleClick() {
  309. if (this.tabToggle == 0) {
  310. this.exhibition = true;
  311. // this.service = false;
  312. }
  313. // else {
  314. // this.exhibition = false;
  315. // this.service = true;
  316. // }
  317. if (this.inputs.length > 0) {
  318. this.keyword = true;
  319. this.exhibition = false;
  320. // this.service = false;
  321. }
  322. if (this.WindowsWidth < 1366) {
  323. this.$store.dispatch('toggleSearchDialog', true);
  324. }
  325. },
  326. async handleInput() {
  327. this.keyword = true;
  328. this.exhibition = false;
  329. this.service = false;
  330. this.keywords = []
  331. },
  332. clickOutSide() {
  333. this.exhibition = false;
  334. this.service = false;
  335. this.tabs = 'exhibitionsCategories';
  336. this.exhibitionActiveIndex = 0;
  337. this.locationActiveIndex = 0;
  338. this.cityActiveIndex = 0;
  339. },
  340. clickExhibition() {
  341. let oringalToggle = this.tabToggle;
  342. if (this.tabToggle != 0) {
  343. this.tabToggle = 0;
  344. }
  345. // if (this.service == true) {
  346. // this.service = false;
  347. // this.exhibition = true;
  348. // }
  349. if (this.keyword == true) {
  350. this.keyword = false;
  351. }
  352. if (this.inputs.length > 0) {
  353. this.exhibition = false;
  354. this.service = false;
  355. this.keyword = true;
  356. } else {
  357. if (oringalToggle == 0) {
  358. this.exhibition = false;
  359. }
  360. }
  361. this.keywords = this.exhibitionsKeywords;
  362. this.$emit('type', 'exhibition');
  363. if (this.WindowWidth >= 1366) {
  364. this.customPlaceholder = 'Explore global exhibitions';
  365. }
  366. },
  367. clickService() {
  368. let oringalToggle = this.tabToggle;
  369. if (this.tabToggle != 1) {
  370. this.tabToggle = 1;
  371. }
  372. if (this.exhibition == true) {
  373. this.service = true;
  374. this.exhibition = false;
  375. }
  376. if (this.keyword == true) {
  377. this.keyword = false;
  378. }
  379. if (this.inputs.length > 0) {
  380. this.exhibition = false;
  381. this.service = false;
  382. this.keyword = true;
  383. } else {
  384. if (oringalToggle == 1) {
  385. this.service = false;
  386. }
  387. }
  388. this.keywords = this.serviceKeywords;
  389. this.$emit('type', 'service');
  390. if (this.WindowWidth >= 1366) {
  391. this.customPlaceholder = 'Search exhibition services';
  392. }
  393. },
  394. goToSearch() {
  395. if (this.WindowsWidth >= 1366) {
  396. this.$router.push(this.localePath(`/${this.type}?q=${this.inputs}`));
  397. this.isPageLoading = true;
  398. }
  399. }
  400. },
  401. };
  402. </script>
  403. <style lang="scss" scoped>
  404. .search-result {
  405. position: absolute;
  406. left: 0px;
  407. top: 70px;
  408. width: 100%;
  409. z-index: 5;
  410. }
  411. .v-tab {
  412. margin: 0;
  413. }
  414. :deep() {
  415. .above {
  416. z-index: 99 !important;
  417. }
  418. }
  419. input[type="search"] {
  420. background-image: url('~/assets/svg/icon-search-small.svg');
  421. background-position: right 20px center;
  422. background-size: 24px;
  423. background-repeat: no-repeat;
  424. }
  425. .custom-control:focus {
  426. outline: none !important;
  427. }
  428. .nuxt-link-active {
  429. color: #232323;
  430. text-decoration: none;
  431. }
  432. .nuxt-link-active:hover {
  433. color: primary;
  434. text-decoration: underline;
  435. text-decoration-style: dashed;
  436. }
  437. .nuxt-link-exact-active {
  438. color: #232323;
  439. text-decoration: none;
  440. }
  441. .tabs {
  442. .tab {
  443. position: relative;
  444. padding-bottom: 15px;
  445. &.active {
  446. &::after {
  447. position: absolute;
  448. bottom: 0;
  449. left: 0;
  450. content: '';
  451. display: block;
  452. width: 100%;
  453. height: 3px;
  454. background-color: #f48800;
  455. }
  456. }
  457. }
  458. }
  459. .exhibitionDropdownLink {
  460. &.active {
  461. background-image: url('@/assets/svg/icon-arrow.svg');
  462. background-position: right center;
  463. background-size: 16px;
  464. background-repeat: no-repeat;
  465. }
  466. }
  467. @media screen and (min-width:1366px) {
  468. .btn-group {
  469. position: relative;
  470. &::before {
  471. content: '';
  472. display: inline-block;
  473. position: absolute;
  474. right: 0;
  475. top: 0;
  476. bottom: 0;
  477. width: 1px;
  478. height: 16px;
  479. background-color: #f5cda8;
  480. margin: auto;
  481. }
  482. }
  483. }
  484. </style>