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.

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