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.

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