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.

324 lines
10 KiB

2 years ago
  1. <template>
  2. <div
  3. class="exhibitionListCard tw-border tw-border-solid tw-border-neutrals-200 tw-rounded-[20px] tw-p-[10px] tw-mb-[20px] md:tw-px-[20px] md:tw-py-[15px] md:tw-grid md:tw-grid-cols-[auto_28px]"
  4. >
  5. <!-- 手機版save exhibition -->
  6. <div
  7. class="tw-absolute tw-cursor-pointer md:tw-hidden"
  8. @click="onToggleFavorite"
  9. >
  10. <div v-if="item.saved">
  11. <nuxt-link :to="localePath('/exhibition/' + item.id)"
  12. ><img
  13. src="~/assets/svg/bookmark.svg"
  14. class="tw-w-[24px] md:tw-w-[28px]"
  15. alt=""
  16. /></nuxt-link>
  17. </div>
  18. <div v-else>
  19. <nuxt-link :to="localePath('/exhibition/' + item.id)"
  20. ><img
  21. src="~/assets/svg/bookmark_outline.svg"
  22. class="tw-w-[24px] md:tw-w-[28px]"
  23. alt=""
  24. /></nuxt-link>
  25. </div>
  26. </div>
  27. <!-- 電腦版exhibition status -->
  28. <!-- <div
  29. class="tw-hidden md:tw-block md:tw-absolute tw-border-solid tw-border tw-border-complementary-1 tw-text-complementary-1 tw-bg-white tw-rounded-[8px] tw-px-[10px] tw-py-[4px] tw-text-[12px] md:tw-text-[14px]"
  30. >
  31. Ongoing
  32. </div> -->
  33. <div
  34. class="tw-grid tw-grid-cols-[102px_auto] tw-gap-[10px] tw-items-center md:tw-grid-cols-[160px_auto]"
  35. >
  36. <div v-if="item.logo == null">
  37. <img src="~/assets/svg/noLogo.svg" alt="" />
  38. </div>
  39. <nuxt-link v-else :to="localePath('/exhibition/' + item.id)"
  40. ><img :src="item.logo" class="tw-py-[35px]" alt=""
  41. /></nuxt-link>
  42. <div>
  43. <div class="tw-flex tw-flex-row tw-mb-[8px]">
  44. <div
  45. v-if="item.isRecommend != null"
  46. class="tw-grid tw-grid-cols-[12px_auto] tw-gap-[4px] tw-items-center tw-w-fit tw-border tw-border-solid tw-border-primary-2 tw-bg-primary-1 tw-rounded-[8px] tw-px-[10px] tw-py-[4px] tw-mr-[8px] md:tw-grid-cols-[14px_auto]"
  47. >
  48. <img
  49. src="~/assets/svg/recommend.svg"
  50. class="tw-w-[12px] md:tw-w-[14px]"
  51. alt=""
  52. />
  53. <div class="tw-text-white tw-text-[12px] md:tw-text-[16px]">
  54. Recommend
  55. </div>
  56. </div>
  57. <!-- <div
  58. class="md:tw-hidden tw-border-solid tw-border tw-border-complementary-1 tw-text-complementary-1 tw-bg-white tw-rounded-[8px] tw-px-[10px] tw-py-[4px] tw-text-[12px] md:tw-text-[14px]"
  59. >
  60. Ongoing
  61. </div> -->
  62. <!-- exhibition status -->
  63. <!-- <div v-if="item.status != null && item.status.name != null">
  64. <div
  65. v-if="item.status.name == 'Upcoming'"
  66. class="tw-border-solid tw-border tw-border-primary-1 tw-text-primary-1 tw-bg-white tw-rounded-[8px] tw-px-[10px] tw-py-[4px] tw-text-[12px] md:tw-text-[14px]"
  67. >
  68. {{ item.status ? item.status.name : "" }}
  69. </div>
  70. <div
  71. v-else-if="item.status.name == 'Ongoing'"
  72. class="tw-border-solid tw-border tw-border-complementary-1 tw-text-complementary-1 tw-bg-white tw-rounded-[8px] tw-px-[10px] tw-py-[4px] tw-text-[12px] md:tw-text-[14px]"
  73. >
  74. {{ item.status ? item.status.name : "" }}
  75. </div>
  76. <div
  77. v-else-if="item.status.name == 'Finished'"
  78. class="tw-border-solid tw-border tw-border-neutrals-500 tw-text-neutrals-500 tw-bg-white tw-rounded-[8px] tw-px-[10px] tw-py-[4px] tw-text-[12px] md:tw-text-[14px]"
  79. >
  80. {{ item.status ? item.status.name : "" }}
  81. </div>
  82. <div
  83. v-else-if="item.status.name == 'Cancelled'"
  84. class="tw-border-solid tw-border tw-border-error-default tw-text-error-default tw-bg-white tw-rounded-[8px] tw-px-[10px] tw-py-[4px] tw-text-[12px] md:tw-text-[14px]"
  85. >
  86. {{ item.status ? item.status.name : "" }}
  87. </div>
  88. <div
  89. v-else
  90. class="tw-border-solid tw-border tw-bg-error-default tw-text-white tw-rounded-[8px] tw-px-[10px] tw-py-[4px] tw-text-[12px] md:tw-text-[14px]"
  91. >
  92. {{ item.status ? item.status.name : "" }}
  93. </div>
  94. </div> -->
  95. </div>
  96. <div class="tw-mb-[8px] xl:tw-mb-[10px]">
  97. <nuxt-link :to="localePath('/exhibition/' + item.id)">
  98. <div
  99. class="tw-line-clamp-3 md:tw-line-clamp-2 xl:tw-line-clamp-1 tw-text-base-primary tw-text-[14px] tw-font-medium md:tw-font-bold md:tw-text-[18px]"
  100. >
  101. {{ item.name }}
  102. </div>
  103. </nuxt-link>
  104. </div>
  105. <div
  106. v-if="$i18n.locale == 'zh-tw'"
  107. v-show="item.short_name != null"
  108. class="tw-mb-[8px] xl:tw-mb-[10px]"
  109. >
  110. <nuxt-link :to="localePath('/exhibition/' + item.id)">
  111. <div
  112. class="tw-line-clamp-3 md:tw-line-clamp-2 xl:tw-line-clamp-1 tw-text-base-primary tw-text-[14px] tw-font-medium md:tw-font-bold md:tw-text-[18px]"
  113. >
  114. {{ item.short_name }}
  115. </div>
  116. </nuxt-link>
  117. </div>
  118. <div
  119. class="tw-text-[14px] tw-font-normal tw-mb-[8px] md:tw-text-[16px] xl:tw-mb-[4px]"
  120. >
  121. <nuxt-link
  122. class="tw-text-neutrals-800"
  123. :to="localePath(`/exhibition?region=${item.region.id}`)"
  124. >{{
  125. item.region.name == null ? "" : item.region.name + "."
  126. }}</nuxt-link
  127. >
  128. <nuxt-link
  129. class="tw-text-neutrals-800"
  130. :to="localePath(`/exhibition?country=${item.country.id}`)"
  131. >{{
  132. item.country.name == null ? "" : item.country.name + "."
  133. }}</nuxt-link
  134. >
  135. <nuxt-link
  136. class="tw-text-neutrals-800"
  137. :to="localePath(`/exhibition?city=${item.city.id}`)"
  138. >{{ item.city.name == null ? "" : item.city.name }}</nuxt-link
  139. >
  140. </div>
  141. <div class="tw-hidden md:tw-block md:tw-mb-[8px] xl:tw-mb-[10px]">
  142. <div class="tw-flex tw-flex-row tw-items-center">
  143. <div class="tw-text-[14px] tw-text-primary-1 tw-mr-[4px]">
  144. {{ item.rating }}
  145. </div>
  146. <img src="~/assets/svg/start.svg" class="tw-w-[14px]" alt="" />
  147. <div class="tw-text-[14px] tw-text-neutral-600 tw-ml-[8px]">
  148. ({{ item.reviewCount ? item.reviewCount : "0" }} reviews)
  149. </div>
  150. </div>
  151. </div>
  152. <div>
  153. <div
  154. v-if="item.categories != null"
  155. class="md:tw-flex md:tw-flex-row md:tw-items-center tw-mb-[8px]"
  156. >
  157. <div
  158. v-for="(item, index) in item.categories"
  159. v-show="index < 1"
  160. :key="index"
  161. class="tw-bg-[#f6f6f6] tw-w-fit tw-rounded-[10px] tw-px-[10px] tw-py-[5px] tw-text-[14px] tw-mr-[10px]"
  162. >
  163. <nuxt-link
  164. class="tw-text-neutrals-800"
  165. :to="localePath('/exhibition?category=' + item.id)"
  166. >{{ item.name }}</nuxt-link
  167. >
  168. </div>
  169. <div
  170. class="tw-text-[12px] tw-text-complementary-1"
  171. v-if="item.categories.length > 1"
  172. >
  173. More
  174. </div>
  175. </div>
  176. </div>
  177. <div
  178. class="tw-hidden xl:tw-block xl:tw-line-clamp-2 tw-text-neutrals-600 tw-text-[14px] xl:tw-mb-[14px]"
  179. v-if="!!item.about"
  180. >
  181. <div v-html="item.about"></div>
  182. </div>
  183. <div class="tw-text-[16px] tw-text-base-primary md:tw-text-[18px]">
  184. {{ formatDate(item.startdate) + " - " + formatDate(item.enddate) }}
  185. </div>
  186. </div>
  187. </div>
  188. <!-- 電腦版save exhibition -->
  189. <div
  190. class="tw-hidden md:tw-cursor-pointer md:tw-block"
  191. @click="onToggleFavorite"
  192. >
  193. <div v-if="item.saved">
  194. <img
  195. src="~/assets/svg/bookmark.svg"
  196. class="tw-w-[24px] md:tw-w-[28px]"
  197. alt=""
  198. />
  199. </div>
  200. <div v-else>
  201. <img
  202. src="~/assets/svg/bookmark_outline.svg"
  203. class="tw-w-[24px] md:tw-w-[28px]"
  204. alt=""
  205. />
  206. </div>
  207. </div>
  208. </div>
  209. </template>
  210. <script>
  211. import CardStatus from "~/components/exhibition/CardStatus.vue";
  212. import { formatDate, dateCountDown } from "~/utils/assist";
  213. import { ExhibitCardStatus, needLeftTagStatus } from "~/utils/constant";
  214. export default {
  215. name: "ExhibitionListCard",
  216. props: {
  217. item: {
  218. type: Object,
  219. default: () => ({}),
  220. },
  221. },
  222. components: {
  223. CardStatus,
  224. },
  225. data: () => ({
  226. StatusMap: ExhibitCardStatus,
  227. }),
  228. methods: {
  229. formatDate,
  230. dateCountDown,
  231. needLeftTagStatus,
  232. onToggleFavorite(id) {
  233. if (this.$auth.loggedIn) {
  234. // this.$axios
  235. // .put(
  236. // `/member/exhibitions?jwt=${
  237. // this.$auth.$storage.getUniversal("jwt")
  238. // ? this.$auth.$storage.getUniversal("jwt").token
  239. // : ""
  240. // }&exhibition_id=${this.item.id}&delete=${
  241. // this.item.saved ? this.item.saved : false
  242. // }`
  243. // )
  244. // .then((result) => {
  245. // if (result.data.message == "successfully unsaved exhibition") {
  246. // this.item.saved = false;
  247. // } else if (result.data.message == "successfully saved exhibition") {
  248. // this.item.saved = true;
  249. // }
  250. // this.$emit("toggle-favorite", {
  251. // id: this.item.id,
  252. // saved: this.item.saved,
  253. // });
  254. // })
  255. // .catch((err) => {
  256. // console.log(err);
  257. // });
  258. // this.$nextTick(() => {
  259. // this.$forceUpdate();
  260. // });
  261. } else {
  262. this.$router.push(this.localePath("/user"));
  263. }
  264. },
  265. },
  266. };
  267. </script>
  268. <style scoped lang="scss">
  269. .exhibit-card {
  270. max-width: 836px;
  271. &.disabled .card__right {
  272. opacity: 0.5;
  273. }
  274. }
  275. .exhibit-title {
  276. position: relative;
  277. font-weight: bold;
  278. color: #232323;
  279. word-break: break-word;
  280. .bookmark-tag {
  281. position: absolute;
  282. color: $primary-light-orange;
  283. right: 0;
  284. top: 0.5em;
  285. }
  286. }
  287. .status-tag {
  288. position: absolute;
  289. top: 16px;
  290. left: 20px;
  291. }
  292. .recommend-tag {
  293. border: 1px solid $primary-light-orange;
  294. max-width: 108px !important;
  295. img {
  296. width: 11px;
  297. height: 12px;
  298. }
  299. }
  300. .category-tag {
  301. border: 1px solid #f7ede4;
  302. height: 16px;
  303. }
  304. .last-dates {
  305. color: #ef5a5a;
  306. }
  307. a {
  308. text-decoration: none;
  309. }
  310. </style>