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.

492 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
  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. @keyup.enter="goToSearch()" />
  20. <svg width="24" height="24" class="tw-my-auto tw-cursor-pointer" shape-rendering="geometricPrecision"
  21. @click="goToSearch()">
  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-min-h-[110px]" 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-min-h-[110px]">
  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. export default {
  200. props: {
  201. servicesSearchs: {
  202. type: Array,
  203. default: () => []
  204. },
  205. servicesLocations: {
  206. type: Array,
  207. default: () => []
  208. },
  209. exhibitionsSearchs: {
  210. type: Array,
  211. default: () => []
  212. },
  213. exhibitionsLocations: {
  214. type: Array,
  215. default: () => []
  216. },
  217. exhibitionsCategories: {
  218. type: Array,
  219. default: () => []
  220. },
  221. serviceKeywords: {
  222. type: Array,
  223. default: () => []
  224. },
  225. exhibitionsKeywords: {
  226. type: Array,
  227. default: () => []
  228. },
  229. populars: {
  230. type: Object,
  231. default: () => { }
  232. },
  233. },
  234. data() {
  235. return {
  236. type: 'exhibition',
  237. toggle_exclusive: 1,
  238. inputs: "",
  239. keywords: [],
  240. tabToggle: 0,
  241. tab: null,
  242. tab2: null,
  243. tabs: 'exhibitionsCategories',
  244. exhibition: false,
  245. service: false,
  246. keyword: false,
  247. locationsIdx: 0,
  248. countriesIdx: 0,
  249. categoriesIdx: 0,
  250. exhibitionActiveIndex: 0,
  251. locationActiveIndex: 0,
  252. cityActiveIndex: 0,
  253. WindowsWidth: undefined,
  254. bigSearch: false,
  255. customPlaceholder: 'Search exhibitions or services...',
  256. };
  257. },
  258. created() {
  259. if (process.client) {
  260. this.WindowsWidth = window.innerWidth;
  261. }
  262. },
  263. methods: {
  264. onResize() {
  265. if (process.client) {
  266. this.WindowsWidth = window.innerWidth;
  267. }
  268. },
  269. open() {
  270. let vm = this;
  271. vm.bigSearch = true;
  272. vm.$nextTick(() => {
  273. vm.$refs.search.focus();
  274. setTimeout(function () {
  275. vm.handleClick();
  276. }, 300)
  277. }
  278. );
  279. },
  280. handleClick() {
  281. if (this.tabToggle == 0) {
  282. this.exhibition = true;
  283. // this.service = false;
  284. } else {
  285. this.exhibition = false;
  286. // this.service = true;
  287. }
  288. if (this.inputs.length > 0) {
  289. this.keyword = true;
  290. this.exhibition = false;
  291. // this.service = false;
  292. }
  293. if (this.WindowsWidth < 1366) {
  294. this.$store.dispatch('toggleSearchDialog', true);
  295. }
  296. },
  297. handleInput() {
  298. this.keyword = true;
  299. this.exhibition = false;
  300. // this.service = false;
  301. this.keywords = [];
  302. },
  303. clickOutSide() {
  304. this.exhibition = false;
  305. // this.service = false;
  306. this.bigSearch = false;
  307. this.tabs = 'exhibitionsCategories';
  308. this.exhibitionActiveIndex = 0;
  309. this.locationActiveIndex = 0;
  310. this.cityActiveIndex = 0;
  311. this.tabToggle = 0;
  312. },
  313. clickExhibition() {
  314. let oringalToggle = this.tabToggle;
  315. if (this.tabToggle != 0) {
  316. this.tabToggle = 0;
  317. }
  318. // if (this.service == true) {
  319. // this.service = false;
  320. // this.exhibition = true;
  321. // }
  322. if (this.keyword == true) {
  323. this.keyword = false;
  324. }
  325. if (this.inputs.length > 0) {
  326. this.exhibition = false;
  327. this.service = false;
  328. this.keyword = true;
  329. } else {
  330. if (oringalToggle == 0) {
  331. this.exhibition = false;
  332. }
  333. }
  334. this.keywords = this.exhibitionsKeywords;
  335. this.type = 'exhibition';
  336. if (this.WindowWidth >= 1366) {
  337. this.customPlaceholder = 'Explore global exhibitions';
  338. }
  339. },
  340. clickService() {
  341. let oringalToggle = this.tabToggle;
  342. if (this.tabToggle != 1) {
  343. this.tabToggle = 1;
  344. }
  345. if (this.exhibition == true) {
  346. this.service = true;
  347. this.exhibition = false;
  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 == 1) {
  358. this.service = false;
  359. }
  360. }
  361. this.keywords = this.serviceKeywords;
  362. this.type = 'service';
  363. if (this.WindowWidth >= 1366) {
  364. this.customPlaceholder = 'Search exhibitions or services...';
  365. }
  366. },
  367. goToSearch() {
  368. this.$emit('loaading', true);
  369. this.$router.push(this.localePath(`/${this.type}?q=${this.inputs}`));
  370. this.$nextTick(()=>{
  371. this.$emit('loaading', false);
  372. });
  373. },
  374. },
  375. computed: {
  376. WindowWidth() {
  377. if (process.client) {
  378. this.WindowsWidth = window.innerWidth;
  379. }
  380. return this.WindowsWidth;
  381. },
  382. },
  383. mounted() {
  384. this.$nextTick(() => {
  385. window.addEventListener("resize", this.onResize);
  386. if (this.WindowWidth >= 1366) {
  387. this.customPlaceholder = 'Explore global exhibitions';
  388. } else {
  389. this.customPlaceholder = 'Search exhibitions or services...';
  390. }
  391. });
  392. },
  393. beforeDestroy() {
  394. window.removeEventListener("resize", this.onResize);
  395. },
  396. };
  397. </script>
  398. <style lang="scss" scoped>
  399. .search-result {
  400. position: absolute;
  401. left: 0px;
  402. top: 70px;
  403. width: 100%;
  404. z-index: 10;
  405. }
  406. .v-tab {
  407. margin: 0;
  408. }
  409. :deep() {
  410. .above {
  411. z-index: 99 !important;
  412. }
  413. }
  414. .custom-control:focus {
  415. outline: none !important;
  416. }
  417. .nuxt-link-active {
  418. color: #232323;
  419. text-decoration: none;
  420. }
  421. .nuxt-link-active:hover {
  422. color: primary;
  423. text-decoration: underline;
  424. text-decoration-style: dashed;
  425. }
  426. .nuxt-link-exact-active {
  427. color: #232323;
  428. text-decoration: none;
  429. }
  430. .tabs {
  431. .tab {
  432. position: relative;
  433. padding-bottom: 15px;
  434. &.active {
  435. &::after {
  436. position: absolute;
  437. bottom: 0;
  438. left: 0;
  439. content: '';
  440. display: block;
  441. width: 100%;
  442. height: 3px;
  443. background-color: #f48800;
  444. }
  445. }
  446. }
  447. }
  448. .exhibitionDropdownLink {
  449. &.active {
  450. background-image: url('@/assets/svg/icon-arrow.svg');
  451. background-position: right center;
  452. background-size: 16px;
  453. background-repeat: no-repeat;
  454. }
  455. }
  456. @media screen and (min-width:1366px) {
  457. .btn-group {
  458. position: relative;
  459. &::before {
  460. content: '';
  461. display: inline-block;
  462. position: absolute;
  463. right: 0;
  464. top: 0;
  465. bottom: 0;
  466. width: 1px;
  467. height: 16px;
  468. background-color: #f5cda8;
  469. margin: auto;
  470. }
  471. }
  472. }
  473. </style>