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.

431 lines
18 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
  1. <template>
  2. <div
  3. :class="['searchDialog tw-overflow-auto tw-fixed tw-top-0 tw-bottom-0 tw-left-0 tw-right-0 tw-w-full tw-h-full tw-z-10 tw-bg-white tw-transition-all tw-duration-300 tw-delay-75 tw-ease-in-out tw-border-0 tw-border-t tw-border-neutral-200',searchDialogActive ? 'tw-translate-y-0' : 'tw-translate-y-full']">
  4. <div class="tw-px-[20px]">
  5. <div class="tw-flex tw-justify-end tw-my-[15px]">
  6. <v-btn @click="closeDialog" icon>
  7. <img src="@/assets/svg/X.svg" />
  8. </v-btn>
  9. </div>
  10. <!-- v2.0 -->
  11. <div
  12. class="tw-grid tw-grid-cols-2 tw-border-solid tw-border-[1px] tw-border-neutrals-200 tw-rounded-[14px] tw-mb-[16px] md:tw-mb-[20px]">
  13. <button
  14. :class="['tw-py-[11px] tw-rounded-[14px] tw-transition-all tw-duration-100 tw-delay-75 tw-ease-in-out',type == 'exhibition' ? 'tw-bg-primary-default tw-text-white':'tw-bg-white tw-text-primary-default']"
  15. @click="type = 'exhibition'">{{
  16. $t('Exhibition')
  17. }}</button>
  18. <button
  19. :class="['tw-py-[11px] tw-rounded-[14px] tw-transition-all tw-duration-300 tw-ease-in-out',type == 'service' ? 'tw-bg-primary-default tw-text-white':'tw-bg-white tw-text-primary-default']"
  20. @click="type = 'service'">{{ $t('Service')
  21. }}</button>
  22. </div>
  23. <input type="search" v-model="searchQuery"
  24. class="tw-text-[16px] tw-rounded-[16px] tw-w-full tw-h-[48px] tw-border-solid tw-border-[1px] tw-border-neutrals-200 tw-outline-none tw-px-[20px] tw-py-[15px] tw-mb-[20px] md:tw-mb-[25px] focus:tw-border-primary-default"
  25. @focus="show= true" @blur="show= false" @keyup.enter="search" />
  26. <!-- v2.0 -->
  27. <div v-if="type=='exhibition'">
  28. <div>
  29. <!-- <div class="tw-mb-[30px]">
  30. <div class="tw-body-4 tw-font-bold tw-text-black tw-mb-[10px] md:tw-mb-[20px]">{{ $t('History') }}
  31. </div>
  32. <div class="tw-flex tw-flex-wrap">
  33. <nuxt-link :to="localePath(`/exhibition?q=${servicesSearch}`)"
  34. class="tw-mr-[16px] tw-mb-[10px] tw-px-[16px] tw-py-[7px] tw-border-solid tw-border-[1px] tw-rounded-[12px] tw-border-x-secondary-default tw-text-secondary-default"
  35. v-for="(servicesSearch, idx) in servicesSearchs" :key="idx">
  36. {{ servicesSearch }}
  37. </nuxt-link>
  38. </div>
  39. </div> -->
  40. <Transition name="bounce">
  41. <div class="tw-mb-[30px]" v-show="show">
  42. <div class="tw-body-4 tw-font-bold tw-text-black tw-mb-[10px] md:tw-mb-[20px]">{{ $t('Popular search') }}
  43. </div>
  44. <div class="tw-flex tw-flex-wrap">
  45. <nuxt-link :to="localePath(`/exhibition?q=${servicesLocation}`)" @click.native="closeDialog()"
  46. class="tw-mr-[16px] tw-mb-[10px] tw-px-[16px] tw-py-[7px] tw-border-solid tw-border-[1px] tw-rounded-[12px] tw-border-x-secondary-default tw-text-secondary-default hover:tw-border-transparent hover:tw-bg-secondary-default hover:tw-text-white"
  47. v-for="(servicesLocation, idx) in populars.search" :key="idx">
  48. {{ servicesLocation }}
  49. </nuxt-link>
  50. </div>
  51. </div>
  52. </Transition>
  53. </div>
  54. <div class="tabs tw-flex tw-mb-[20px]">
  55. <button
  56. :class="['tw-transition-all tw-duration-300 tw-ease-in-out tw-mr-[30px] tab',tabs == 'exhibitionsCategories' ? 'active tw-text-black tw-font-bold':'tw-text-neutrals-500']"
  57. @click="tabs = 'exhibitionsCategories'">{{
  58. $t('Exhibition Categories')
  59. }}</button>
  60. <button
  61. :class="['tw-transition-all tw-duration-300 tw-ease-in-out tab',tabs == 'location' ? 'active tw-text-black tw-font-bold':'tw-text-neutrals-500']"
  62. @click="tabs = 'location'">{{ $t('Location')
  63. }}</button>
  64. </div>
  65. <div v-if="tabs=='exhibitionsCategories'">
  66. <div class="customMenuLink tw-relative tw-flex tw-justify-start tw-items-center tw-z-10">
  67. <div class="customDropMenu exhibition tw-w-full tw-overflow-hidden">
  68. <div class="tw-relative tw-grid tw-grid-cols-[210px_auto] tw-h-[344px] md:tw-grid-cols-[3fr_2fr]">
  69. <div
  70. class="tw-list-none tw-overflow-y-auto tw-h-auto tw-break-inside-avoid tw-flex tw-flex-col tw-pr-[20px]">
  71. <template v-if="exhibitionsCategoryList.length>0">
  72. <div v-for="(item,index) in exhibitionsCategoryList" :key="index" @click="exhibitionActiveIndex=index"
  73. :class="['exhibitionDropdownLink tw-block tw-w-full tw-body-4 tw-font-normal tw-mb-[20px] tw-pr-[20px] hover:tw-text-primary-default',exhibitionActiveIndex == index ? 'tw-text-primary-default active':'tw-text-neutrals-900']">
  74. {{
  75. $t(item.CategoryName)
  76. }}</div></template>
  77. </div>
  78. <div class="tw-overflow-x-hidden tw-overflow-y-auto" v-if="exhibitionsCategoryList.length>0">
  79. <div class="tw-list-none tw-flex tw-flex-col tw-flex-wrap tw-px-[20px]">
  80. <div class="tw-list-none tw-mb-[20px] tw-w-full">
  81. <nuxt-link
  82. :to="localePath(`/exhibition?category=${exhibitionsCategoryList[exhibitionActiveIndex].CategoryID}`)"
  83. @click.native="closeDialog()"
  84. class="tw-block tw-body-4 tw-font-normal tw-text-neutral-800 hover:tw-text-primary-default">{{
  85. $t('All')}}</nuxt-link>
  86. </div>
  87. <template v-if="exhibitionsCategoryList[
  88. exhibitionActiveIndex
  89. ].SubCategoryList && exhibitionsCategoryList[
  90. exhibitionActiveIndex
  91. ].SubCategoryList.length>0">
  92. <div v-for="(sub,index) in exhibitionsCategoryList[exhibitionActiveIndex].SubCategoryList" :key="index"
  93. class="tw-list-none tw-mb-[20px] tw-w-full">
  94. <nuxt-link :to="localePath(`/exhibition?subcategory=${sub.CategoryID}`)" @click.native="closeDialog()"
  95. class="tw-block tw-body-4 tw-font-normal tw-text-neutral-800 hover:tw-text-primary-default">{{
  96. sub.CategoryName }}</nuxt-link>
  97. </div></template>
  98. </div>
  99. </div>
  100. </div>
  101. </div>
  102. </div>
  103. </div>
  104. <div v-if="tabs=='location'">
  105. <div class="customMenuLink tw-relative tw-flex tw-justify-start tw-items-center tw-z-10">
  106. <div class="customDropMenu exhibition tw-w-full tw-overflow-hidden">
  107. <div class="tw-relative tw-grid tw-grid-cols-[120px_auto] tw-h-[344px] md:tw-grid-cols-[1fr_3fr]">
  108. <div class="tw-list-none tw-overflow-y-auto tw-h-auto tw-break-inside-avoid tw-flex tw-flex-col">
  109. <div v-for="(item,index) in exhibitionsLocations" :key="index" @click="locationActiveIndex=index"
  110. :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']">
  111. {{
  112. $t(item.region)
  113. }}</div>
  114. </div>
  115. <div class="tw-ml-[20px] tw-overflow-x-hidden tw-overflow-y-auto">
  116. <ul class="tw-list-none tw-flex tw-flex-col tw-flex-wrap">
  117. <li class="tw-list-none tw-mb-[20px]">
  118. <nuxt-link :to="localePath(`/exhibition?region=${exhibitionsLocations[locationActiveIndex].id}`)"
  119. @click.native="closeDialog()"
  120. class="tw-block tw-body-4 tw-font-normal tw-text-neutral-800 hover:tw-text-primary-default">{{
  121. $t('All')}}</nuxt-link>
  122. </li>
  123. <li v-for="(countries,index) in exhibitionsLocations[locationActiveIndex].countries" :key="index"
  124. class="tw-list-none tw-mb-[20px]">
  125. <nuxt-link :to="localePath(`/exhibition?country=${countries.id}`)" @click.native="closeDialog()"
  126. class="tw-block tw-body-4 tw-font-normal tw-text-neutral-800 hover:tw-text-primary-default">{{
  127. countries.country }}</nuxt-link>
  128. </li>
  129. </ul>
  130. </div>
  131. </div>
  132. </div>
  133. </div>
  134. <!-- <v-card flat width="100%" height="100%" class="d-flex"
  135. :height="$vuetify.breakpoint.smAndUp ? '700px' : '448px'">
  136. <v-card flat width="33%" class="d-flex flex-column overflow-y-auto"
  137. :height="$vuetify.breakpoint.smAndUp ? '700px' : '448px'">
  138. <v-card flat width="100%"
  139. :class="$vuetify.breakpoint.smOnly ? 'ps-3 pb-3 pt-3 text-size-14 d-flex align-center' : 'ps-3 pb-3 pt-3 text-size-12 d-flex align-center'"
  140. v-for="i in exhibitionsLocations.length" :key="i" @click.stop="
  141. locationsIdx = i - 1;
  142. countriesIdx = 0;
  143. ">
  144. <v-spacer :class="locationsIdx === i - 1 ? 'primary--text' : ''">
  145. {{ exhibitionsLocations[i - 1].region }}
  146. </v-spacer>
  147. <v-icon :color="locationsIdx === i - 1 ? 'primary' : ''" class="me-6">mdi-chevron-right</v-icon>
  148. </v-card>
  149. </v-card>
  150. <v-card flat width="33%" class="d-flex flex-column overflow-y-auto"
  151. :height="$vuetify.breakpoint.smAndUp ? '700px' : '448px'">
  152. <v-card flat width="100%"
  153. :class="$vuetify.breakpoint.smOnly ? 'ps-3 pb-3 pt-3 text-size-14' : 'ps-3 pb-3 pt-3 text-size-12'"
  154. @click="localeRegion(exhibitionsLocations[locationsIdx].id)">
  155. {{ $t('All') }}
  156. </v-card>
  157. <v-card flat width="100%"
  158. :class="$vuetify.breakpoint.smOnly ? 'ps-3 pb-3 pt-3 text-size-14 d-flex align-center' : 'ps-3 pb-3 pt-3 text-size-12 d-flex align-center'"
  159. v-for="j in exhibitionsLocations[locationsIdx].countries
  160. .length" :key="j" @click="countriesIdx = j - 1">
  161. <v-spacer :class="countriesIdx === j - 1 ? 'primary--text' : ''">
  162. {{
  163. exhibitionsLocations[locationsIdx].countries[j - 1].country
  164. }}
  165. </v-spacer>
  166. <v-icon :color="countriesIdx === j - 1 ? 'primary' : ''"
  167. :class="$vuetify.breakpoint.smOnly ? 'me-6' : 'me-2'">mdi-chevron-right</v-icon>
  168. </v-card>
  169. </v-card>
  170. <v-card flat width="34%" class="d-flex flex-column overflow-y-auto"
  171. v-if="exhibitionsLocations[locationsIdx].countries.length != 0"
  172. :height="$vuetify.breakpoint.smAndUp ? '700px' : '448px'">
  173. <v-card width="100%"
  174. :class="$vuetify.breakpoint.smOnly ? 'ps-3 pb-3 pt-3 text-size-14' : 'ps-3 pb-3 pt-3 text-size-12'" flat
  175. color="transparent"
  176. @click="localeCountry(exhibitionsLocations[locationsIdx].countries[countriesIdx].id)">
  177. {{ $t('All') }}
  178. </v-card>
  179. <v-card v-for="k in exhibitionsLocations[locationsIdx].countries[
  180. countriesIdx
  181. ].cities.length" :key="k" width="100%"
  182. :class="$vuetify.breakpoint.smOnly ? 'ps-3 pb-3 pt-3 text-size-14' : 'ps-3 pb-3 pt-3 text-size-12'" flat
  183. color="transparent" @click="localeCity(exhibitionsLocations[locationsIdx].countries[
  184. countriesIdx
  185. ].cities[k - 1].id)">
  186. {{
  187. exhibitionsLocations[locationsIdx].countries[countriesIdx].cities[k - 1].city
  188. }}
  189. </v-card>
  190. </v-card>
  191. </v-card> -->
  192. </div>
  193. </div>
  194. <div v-if="type=='service'">
  195. <div>
  196. <!-- <div class="tw-mb-[30px]">
  197. <div class="tw-body-4 tw-font-bold tw-text-black tw-mb-[10px] md:tw-mb-[20px]">{{ $t('History') }}
  198. </div>
  199. <div class="tw-flex tw-flex-wrap">
  200. <nuxt-link :to="localePath(`/exhibition?q=${servicesSearch}`)"
  201. class="tw-mr-[16px] tw-mb-[10px] tw-px-[16px] tw-py-[7px] tw-border-solid tw-border-[1px] tw-rounded-[12px] tw-border-x-secondary-default tw-text-secondary-default"
  202. v-for="(servicesSearch, idx) in servicesSearchs" :key="idx">
  203. {{ servicesSearch }}
  204. </nuxt-link>
  205. </div>
  206. </div> -->
  207. <div class="tw-mb-[30px]">
  208. <div class="tw-body-4 tw-font-bold tw-text-black tw-mb-[10px] md:tw-mb-[20px]">{{ $t('Popular search') }}
  209. </div>
  210. <div class="tw-flex tw-flex-wrap">
  211. <nuxt-link :to="localePath(`/service?q=${servicesLocation}`)" @click.native="closeDialog()"
  212. class="tw-mr-[16px] tw-mb-[10px] tw-px-[16px] tw-py-[7px] tw-border-solid tw-border-[1px] tw-rounded-[12px] tw-border-x-secondary-default tw-text-secondary-default hover:tw-border-transparent hover:tw-bg-secondary-default hover:tw-text-white"
  213. v-for="(servicesLocation, idx) in populars.service" :key="idx">
  214. {{ servicesLocation }}
  215. </nuxt-link>
  216. </div>
  217. </div>
  218. <div>
  219. <div class="tw-body-4 tw-font-bold tw-text-black tw-mb-[10px] md:tw-mb-[20px]">{{ $t('Location') }} </div>
  220. <div class="tw-flex tw-flex-wrap">
  221. <nuxt-link :to="localePath(`/service?q=${servicesLocation}`)" @click.native="closeDialog()"
  222. class="tw-mr-[16px] tw-mb-[10px] tw-px-[16px] tw-py-[7px] tw-border-solid tw-border-[1px] tw-rounded-[12px] tw-border-x-secondary-default tw-text-secondary-default hover:tw-border-transparent hover:tw-bg-secondary-default hover:tw-text-white"
  223. v-for="(servicesLocation, idx) in servicesLocations" :key="idx">
  224. {{ servicesLocation }}
  225. </nuxt-link>
  226. </div>
  227. </div>
  228. </div>
  229. </div>
  230. </div>
  231. </div>
  232. </template>
  233. <script>
  234. export default {
  235. name: 'SearchDialog',
  236. props: {
  237. exhibitionsCategoryList: {
  238. type: Array,
  239. required: true,
  240. default: () => []
  241. },
  242. exhibitionsLocations: {
  243. type: Array,
  244. required: true,
  245. default: () => []
  246. },
  247. exhibitionsCategories: {
  248. type: Array,
  249. required: true,
  250. default: () => []
  251. },
  252. servicesSearchs: {
  253. type: Array,
  254. required: true,
  255. default: () => []
  256. },
  257. servicesLocations: {
  258. type: Array,
  259. required: true,
  260. default: () => []
  261. },
  262. exhibitionsKeywords: {
  263. type: Array,
  264. default: () => []
  265. },
  266. populars: {
  267. type: Object,
  268. default: () => { }
  269. }
  270. },
  271. data() {
  272. return {
  273. type: 'exhibition',
  274. tabs: 'exhibitionsCategories',
  275. searchQuery: '',
  276. locationsIdx: 0,
  277. countriesIdx: 0,
  278. categoriesIdx: 0,
  279. exhibitionActiveIndex: 0,
  280. locationActiveIndex: 0,
  281. show: false,
  282. }
  283. },
  284. computed: {
  285. searchDialogActive: {
  286. get() {
  287. return this.$store.getters.getSearchDialogStatus
  288. },
  289. }
  290. },
  291. methods: {
  292. closeDialog() {
  293. this.$store.dispatch('toggleSearchDialog', false);
  294. this.type = 'exhibition';
  295. this.tabs = 'exhibitionsCategories';
  296. this.searchQuery = '';
  297. this.locationsIdx = 0;
  298. this.countriesIdx = 0;
  299. this.categoriesIdx = 0;
  300. this.exhibitionActiveIndex = 0;
  301. this.locationActiveIndex = 0;
  302. },
  303. search() {
  304. this.$emit('loaading', true);
  305. this.$router.push(this.localePath(`/${this.type}?q=${this.searchQuery}`))
  306. this.closeDialog()
  307. },
  308. localeRegion(id) {
  309. this.$router.push(this.localePath(`/exhibition?region=${id}`))
  310. this.closeDialog()
  311. },
  312. localeCountry(id) {
  313. this.$router.push(this.localePath(`/exhibition?country=${id}`))
  314. this.closeDialog()
  315. },
  316. localeCity(id) {
  317. this.$router.push(this.localePath(`/exhibition?city=${id}`))
  318. this.closeDialog()
  319. },
  320. localeCategory(id) {
  321. this.$router.push(this.localePath(`/exhibition?category=${id}`))
  322. this.closeDialog()
  323. },
  324. localeSubcategory(id) {
  325. this.$router.push(this.localePath(`/exhibition?subcategory=${id}`))
  326. this.closeDialog()
  327. }
  328. }
  329. };
  330. </script>
  331. <style lang="scss" scoped>
  332. :deep() {
  333. .v-btn--outlined {
  334. border: 1px solid #E5E5E5;
  335. }
  336. }
  337. input[type="search"] {
  338. background-image: url('~/assets/svg/icon-search-small.svg');
  339. background-position: right 20px center;
  340. background-size: 24px;
  341. background-repeat: no-repeat;
  342. }
  343. .searchDialog {
  344. min-height: 100vh !important;
  345. min-height: -webkit-fill-available !important;
  346. @media (min-width: 768px) {
  347. min-height: max-content !important;
  348. }
  349. }
  350. .nuxt-link-active {
  351. color: #232323;
  352. text-decoration: none;
  353. }
  354. .custom-control:focus {
  355. outline: none !important;
  356. }
  357. .v-dialog__content {
  358. z-index: 4 !important;
  359. }
  360. .v-dialog__content--active {
  361. z-index: 4 !important;
  362. }
  363. .tabs {
  364. .tab {
  365. position: relative;
  366. padding-bottom: 15px;
  367. &.active {
  368. &::after {
  369. position: absolute;
  370. bottom: 0;
  371. left: 0;
  372. right: 0;
  373. margin: 0 auto;
  374. content: '';
  375. display: block;
  376. width: 44px;
  377. height: 3px;
  378. background-color: #f48800;
  379. }
  380. }
  381. }
  382. }
  383. .exhibitionDropdownLink {
  384. &.active {
  385. background-image: url('@/assets/svg/icon-arrow.svg');
  386. background-position: right top;
  387. background-size: 16px;
  388. background-repeat: no-repeat;
  389. }
  390. }
  391. .bounce-enter-active {
  392. animation: bounce-in 0.3s ease-out;
  393. }
  394. .bounce-leave-active {
  395. animation: bounce-in 0.3s cubic-bezier(1, 0.5, 0.8, 1) reverse;
  396. }
  397. @keyframes bounce-in {
  398. 0% {
  399. opacity: 0;
  400. transform: translateY(-10px);
  401. }
  402. 50% {
  403. opacity: 0.5;
  404. transform: translateY(-5px);
  405. }
  406. 100% {
  407. opacity: 1;
  408. transform: translateY(0);
  409. }
  410. }
  411. </style>