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.

425 lines
18 KiB

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