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.

482 lines
18 KiB

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-h-[270px]">
  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.title)
  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] ">
  98. <li class="tw-list-none"><a
  99. :href="localePath(`/exhibition?category=${exhibitionsCategories[exhibitionActiveIndex].id}`)"
  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].subcategory" :key="index"
  104. class="tw-list-none"><a :href="localePath(`/exhibition?subcategory=${sub.id}`)"
  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.title }}</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-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. <div v-for="(item,index) in exhibitionsLocations" :key="index"
  121. @mouseover="locationActiveIndex=index;cityActiveIndex=0"
  122. :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']">
  123. {{
  124. $t(item.region)
  125. }}</div>
  126. </div>
  127. <div class="tw-overflow-x-hidden tw-overflow-y-auto">
  128. <ul class="tw-px-[20px] tw-list-none tw-flex tw-flex-col tw-flex-wrap">
  129. <li class="tw-list-none tw-mb-[20px]"><a
  130. :href="localePath(`/exhibition?region=${exhibitionsLocations[locationActiveIndex].id}`)"
  131. class="tw-block tw-body-4 tw-font-normal tw-text-neutral-800 hover:tw-text-primary-default">{{
  132. $t('All')}}</a>
  133. </li>
  134. <li v-for="(countries,index) in exhibitionsLocations[locationActiveIndex].countries" :key="index"
  135. @mouseover="cityActiveIndex=index"
  136. :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']">
  137. {{
  138. countries.country }}
  139. </li>
  140. </ul>
  141. </div>
  142. <div class="tw-overflow-x-hidden tw-overflow-y-auto">
  143. <ul class="tw-px-[20px] tw-list-none tw-flex tw-flex-col tw-flex-wrap">
  144. <li class="tw-list-none tw-mb-[20px]"><a
  145. :href="localePath(`/exhibition?region=${exhibitionsLocations[locationActiveIndex].countries[cityActiveIndex].id}`)"
  146. class="tw-block tw-body-4 tw-font-normal tw-text-neutral-800 hover:tw-text-primary-default">{{
  147. $t('All')}}</a>
  148. </li>
  149. <li
  150. v-for="(cities,index) in exhibitionsLocations[locationActiveIndex].countries[cityActiveIndex].cities"
  151. :key="index" class="tw-list-none tw-mb-[20px]"><a
  152. :href="localePath(`/exhibition?city=${cities.id}`)"
  153. class="tw-block tw-body-4 tw-font-normal tw-text-neutral-800 hover:tw-text-primary-default">{{
  154. cities.city }}</a>
  155. </li>
  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="(item, idx) in servicesSearchs" :key="idx" :to="localePath(`/service?q=${item}`)">
  175. {{ item }}
  176. </nuxt-link>
  177. </div>
  178. </div> -->
  179. <div>
  180. <div class="tw-body-3 tw-font-bold tw-text-black tw-mb-[20px]">{{ $t('Location') }} </div>
  181. <div class="tw-flex tw-flex-wrap">
  182. <nuxt-link
  183. 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"
  184. v-for="(servicesLocation, idx) in servicesLocations" :key="idx"
  185. :to="localePath(`/service?q=${servicesLocation}`)">
  186. {{ servicesLocation }}
  187. </nuxt-link>
  188. </div>
  189. </div>
  190. </div>
  191. </v-container>
  192. <!-- service -->
  193. </div>
  194. </div>
  195. </template>
  196. <script>
  197. import axios from "axios";
  198. export default {
  199. props: {
  200. servicesSearchs: {
  201. type: Array,
  202. default: () => []
  203. },
  204. servicesLocations: {
  205. type: Array,
  206. default: () => []
  207. },
  208. exhibitionsSearchs: {
  209. type: Array,
  210. default: () => []
  211. },
  212. exhibitionsLocations: {
  213. type: Array,
  214. default: () => []
  215. },
  216. exhibitionsCategories: {
  217. type: Array,
  218. default: () => []
  219. },
  220. serviceKeywords: {
  221. type: Array,
  222. default: () => []
  223. },
  224. exhibitionsKeywords: {
  225. type: Array,
  226. default: () => []
  227. },
  228. populars: {
  229. type: Object,
  230. default: () => { }
  231. },
  232. },
  233. data() {
  234. return {
  235. type: 'exhibition',
  236. toggle_exclusive: 1,
  237. inputs: "",
  238. keywords: [],
  239. tabToggle: 0,
  240. tab: null,
  241. tab2: null,
  242. tabs: 'exhibitionsCategories',
  243. exhibition: false,
  244. service: false,
  245. keyword: false,
  246. locationsIdx: 0,
  247. countriesIdx: 0,
  248. categoriesIdx: 0,
  249. exhibitionActiveIndex: 0,
  250. locationActiveIndex: 0,
  251. cityActiveIndex: 0,
  252. WindowsWidth: undefined,
  253. bigSearch: false,
  254. customPlaceholder: 'Search exhibitions or services...',
  255. };
  256. },
  257. created() {
  258. if (process.client) {
  259. this.WindowsWidth = window.innerWidth;
  260. }
  261. },
  262. methods: {
  263. onResize() {
  264. if (process.client) {
  265. this.WindowsWidth = window.innerWidth;
  266. }
  267. },
  268. open() {
  269. let vm = this;
  270. vm.bigSearch = true;
  271. vm.$nextTick(() => {
  272. vm.$refs.search.focus();
  273. setTimeout(function () {
  274. vm.handleClick();
  275. }, 300)
  276. }
  277. );
  278. },
  279. handleClick() {
  280. if (this.tabToggle == 0) {
  281. this.exhibition = true;
  282. this.service = false;
  283. } else {
  284. this.exhibition = false;
  285. this.service = true;
  286. }
  287. if (this.inputs.length > 0) {
  288. this.keyword = true;
  289. this.exhibition = false;
  290. this.service = false;
  291. }
  292. if (this.WindowsWidth < 1366) {
  293. this.$store.dispatch('toggleSearchDialog', true);
  294. }
  295. },
  296. handleInput() {
  297. this.keyword = true;
  298. this.exhibition = false;
  299. this.service = false;
  300. this.keywords = [];
  301. },
  302. clickOutSide() {
  303. this.exhibition = false;
  304. this.service = false;
  305. this.bigSearch = false;
  306. this.tabs = 'exhibitionsCategories';
  307. this.exhibitionActiveIndex = 0;
  308. this.locationActiveIndex = 0;
  309. this.cityActiveIndex = 0;
  310. this.tabToggle = 0;
  311. },
  312. clickExhibition() {
  313. let oringalToggle = this.tabToggle;
  314. if (this.tabToggle != 0) {
  315. this.tabToggle = 0;
  316. }
  317. if (this.service == true) {
  318. this.service = false;
  319. this.exhibition = true;
  320. }
  321. if (this.keyword == true) {
  322. this.keyword = false;
  323. }
  324. if (this.inputs.length > 0) {
  325. this.exhibition = false;
  326. this.service = false;
  327. this.keyword = true;
  328. } else {
  329. if (oringalToggle == 0) {
  330. this.exhibition = false;
  331. }
  332. }
  333. this.keywords = this.exhibitionsKeywords;
  334. this.type = 'exhibition';
  335. if (this.WindowWidth >= 1366) {
  336. this.customPlaceholder = 'Explore global exhibitions';
  337. }
  338. },
  339. clickService() {
  340. let oringalToggle = this.tabToggle;
  341. if (this.tabToggle != 1) {
  342. this.tabToggle = 1;
  343. }
  344. if (this.exhibition == true) {
  345. this.service = true;
  346. this.exhibition = false;
  347. }
  348. if (this.keyword == true) {
  349. this.keyword = false;
  350. }
  351. if (this.inputs.length > 0) {
  352. this.exhibition = false;
  353. this.service = false;
  354. this.keyword = true;
  355. } else {
  356. if (oringalToggle == 1) {
  357. this.service = false;
  358. }
  359. }
  360. this.keywords = this.serviceKeywords;
  361. this.type = 'service';
  362. if (this.WindowWidth >= 1366) {
  363. this.customPlaceholder = 'Search exhibitions or services...';
  364. }
  365. },
  366. },
  367. computed: {
  368. WindowWidth() {
  369. if (process.client) {
  370. this.WindowsWidth = window.innerWidth;
  371. }
  372. return this.WindowsWidth;
  373. },
  374. },
  375. mounted() {
  376. this.$nextTick(() => {
  377. window.addEventListener("resize", this.onResize);
  378. if (this.WindowWidth >= 1366) {
  379. this.customPlaceholder = 'Explore global exhibitions';
  380. } else {
  381. this.customPlaceholder = 'Search exhibitions or services...';
  382. }
  383. });
  384. },
  385. beforeDestroy() {
  386. window.removeEventListener("resize", this.onResize);
  387. },
  388. };
  389. </script>
  390. <style lang="scss" scoped>
  391. .search-result {
  392. position: absolute;
  393. left: 0px;
  394. top: 70px;
  395. width: 100%;
  396. z-index: 10;
  397. }
  398. .v-tab {
  399. margin: 0;
  400. }
  401. :deep() {
  402. .above {
  403. z-index: 99 !important;
  404. }
  405. }
  406. .custom-control:focus {
  407. outline: none !important;
  408. }
  409. .nuxt-link-active {
  410. color: #232323;
  411. text-decoration: none;
  412. }
  413. .nuxt-link-active:hover {
  414. color: primary;
  415. text-decoration: underline;
  416. text-decoration-style: dashed;
  417. }
  418. .nuxt-link-exact-active {
  419. color: #232323;
  420. text-decoration: none;
  421. }
  422. .tabs {
  423. .tab {
  424. position: relative;
  425. padding-bottom: 15px;
  426. &.active {
  427. &::after {
  428. position: absolute;
  429. bottom: 0;
  430. left: 0;
  431. content: '';
  432. display: block;
  433. width: 100%;
  434. height: 3px;
  435. background-color: #f48800;
  436. }
  437. }
  438. }
  439. }
  440. .exhibitionDropdownLink {
  441. &.active {
  442. background-image: url('@/assets/svg/icon-arrow.svg');
  443. background-position: right center;
  444. background-size: 16px;
  445. background-repeat: no-repeat;
  446. }
  447. }
  448. @media screen and (min-width:1366px) {
  449. .btn-group {
  450. position: relative;
  451. &::before {
  452. content: '';
  453. display: inline-block;
  454. position: absolute;
  455. right: 0;
  456. top: 0;
  457. bottom: 0;
  458. width: 1px;
  459. height: 16px;
  460. background-color: #f5cda8;
  461. margin: auto;
  462. }
  463. }
  464. }
  465. </style>