Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 
 
 

91 řádky
2.8 KiB

  1. <template>
  2. <section class="flex flex-col items-center min-h-screen">
  3. <uiLoader v-if="isLoading" class="fixed z-50 backdrop-blur-sm p-4 rounded-full top-1/2" />
  4. <div class="container w-full p-6 max-w-6xl grow flex flex-col items-center">
  5. <nav
  6. class="w-full flex bg-slate-800 font-semibold rounded-full backdrop-blur sticky top-0 justify-center items-center hover:ring">
  7. <input ref="searchInput" v-model="terms" autofocus placeholder="search" type="search"
  8. class="rounded-full text-xl w-full text-center text-white p-4 bg-transparent focus-visible:border-none"
  9. @keypress.enter="pressEnter()">
  10. <b v-if="films && films.length"
  11. class="px-4 py-2 absolute right-2 block bg-green-400 text-slate-800 rounded-full">
  12. {{ films.length }}
  13. </b>
  14. </nav>
  15. <main class="flex max-w-screen-2xl justify-center flex-wrap m-6">
  16. <NuxtLink v-for="(film, index) in films" :key="index" :title="film.title" :to="'/details/' + film.id"
  17. class="hover:bg-green-500 transition flex flex-col bg-slate-400 rounded-lg w-60 m-4">
  18. <img @error="setPlaceholder" :src="config.public.IMG_BASE_URL + film.poster_path" :alt="film.title"
  19. class="w-full rounded-t-lg">
  20. <span class="p-4 text-white flex flex-col">
  21. <h2 class="text-xl font-bold pb-2">
  22. {{ film.title }}
  23. </h2>
  24. <span v-if="film.release_date">
  25. {{ useDateFormat(film.release_date, 'D MMM YYYY') }}
  26. </span>
  27. <span class="font-bold">
  28. {{ formatPercent(film.vote_average) }}%
  29. </span>
  30. </span>
  31. </NuxtLink>
  32. </main>
  33. </div>
  34. </section>
  35. </template>
  36. <script setup lang="ts">
  37. import { useDateFormat } from '@vueuse/core'
  38. interface Film {
  39. title: string,
  40. id: number,
  41. poster_path: string,
  42. release_date: number,
  43. vote_average: number,
  44. }
  45. const config = useRuntimeConfig()
  46. const terms = ref('')
  47. const films: Ref<Film[]> = ref([])
  48. const page = ref(1)
  49. const isLoading = ref(true)
  50. const { onScrollEnd } = useScrollEnd()
  51. const search = async () => {
  52. isLoading.value = true
  53. if (terms.value !== '') {
  54. const { data } = await useFetch(`/api/search/${terms.value}-${page.value}`)
  55. console.log(data)
  56. films.value.push(...data.value)
  57. } else {
  58. const { data } = await useFetch(`/api/explore/${page.value}`)
  59. films.value.push(...data.value)
  60. }
  61. isLoading.value = false
  62. }
  63. const pressEnter = () => {
  64. page.value = 1
  65. films.value = []
  66. search()
  67. }
  68. const setPlaceholder = (event: Event) => {
  69. const target = event.target as HTMLImageElement
  70. target.src = 'https://via.placeholder.com/200x300'
  71. }
  72. onScrollEnd(() => {
  73. page.value += 1
  74. search()
  75. })
  76. onMounted(() => {
  77. nextTick(() => {
  78. search()
  79. })
  80. })
  81. </script>