Browse Source

FEAT: add types

master
valere 5 months ago
parent
commit
43fc013c78
6 changed files with 102 additions and 28 deletions
  1. +0
    -2
      README.md
  2. +13
    -4
      components/list.vue
  3. +2
    -2
      composables/useScrollEnd.ts
  4. +10
    -0
      package-lock.json
  5. +70
    -18
      pages/details/[id].vue
  6. +7
    -2
      server/api/explore.ts

+ 0
- 2
README.md View File

@@ -1,2 +0,0 @@
- variables typées
- tests

+ 13
- 4
components/list.vue View File

@@ -13,7 +13,7 @@
</b>
</nav>
<main class="flex max-w-screen-2xl justify-center flex-wrap m-6">
<NuxtLink v-for="(film, index) in films" :key="index" :href="film.title" :to="'/details/' + film.id"
<NuxtLink v-for="(film, index) in films" :key="index" :title="film.title" :to="'/details/' + film.id"
class="hover:bg-green-500 transition flex flex-col bg-slate-400 rounded-lg w-60 m-4">
<img @error="setPlaceholder" :src="config.public.IMG_BASE_URL + film.poster_path" :alt="film.title"
class="w-full rounded-t-lg">
@@ -37,9 +37,17 @@
<script setup lang="ts">
import { useDateFormat } from '@vueuse/core'

interface Film {
title: string,
id: number,
poster_path: string,
release_date: number,
vote_average: number,
}

const config = useRuntimeConfig()
const terms = ref('')
const films = ref([])
const films: Ref<Film[]> = ref([])
const page = ref(1)
const isLoading = ref(true)
const { onScrollEnd } = useScrollEnd()
@@ -63,8 +71,9 @@ const pressEnter = () => {
search()
}

const setPlaceholder = (event) => {
event.target.src = 'https://via.placeholder.com/200x300'
const setPlaceholder = (event: Event) => {
const target = event.target as HTMLImageElement
target.src = 'https://via.placeholder.com/200x300'
}

onScrollEnd(() => {


+ 2
- 2
composables/useScrollEnd.ts View File

@@ -1,6 +1,6 @@

export function useScrollEnd() {
let callback = null
let callback: Function | null = null

const handleScroll = () => {
const scrollPosition = window.innerHeight + window.scrollY
@@ -11,7 +11,7 @@ export function useScrollEnd() {
}
}

const onScrollEnd = (cb) => {
const onScrollEnd = (cb: Function | null) => {
callback = cb
}



+ 10
- 0
package-lock.json View File

@@ -8,6 +8,7 @@
"hasInstallScript": true,
"dependencies": {
"@pinia/nuxt": "^0.5.5",
"@types/node-fetch": "^2.6.11",
"axios": "^1.7.7",
"node-fetch": "^3.3.2",
"nuxt": "^3.12.3",
@@ -1712,6 +1713,15 @@
"undici-types": "~5.26.4"
}
},
"node_modules/@types/node-fetch": {
"version": "2.6.11",
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz",
"integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==",
"dependencies": {
"@types/node": "*",
"form-data": "^4.0.0"
}
},
"node_modules/@types/resolve": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",


+ 70
- 18
pages/details/[id].vue View File

@@ -4,61 +4,113 @@
<NuxtLink class="w-full m-4 flex justify-end" :to="'/'">
<uiClose />
</NuxtLink>
<img class="rounded-lg mb-6" :src="config.public.IMG_BASE_URL + film.poster_path" :alt="film.title">
<img class="rounded-lg mb-6" :src="config.public.IMG_BASE_URL + film?.poster_path" :alt="film?.title">

<div class="poster flex flex-col lg:flex-row w-full justify-center">
<span>
<h1 class="text-4xl font-bold leading-relaxed">
{{ film.title }}
{{ film?.title }}
</h1>
<h2 class="text-2xl text-slate-700">
{{ director }}
</h2>
<p class="my-8">
{{ film.overview }}
{{ film?.overview }}
</p>
<p>
{{ formatPercent(film.vote_average) }} %
{{ formatPercent(film?.vote_average as number) }} %
</p>
<p>
{{ film.vote_count }} votes
{{ film?.vote_count }} votes
</p>
<div class="flex justify-center">
<ul class="flex items-center overflow-y-hidden overflow-x-scroll w-full max-w-lg">
<li v-for="star in film.credits.cast" class="flex flex-col items-center p-4 bg-slate-200 rounded m-4">
<li v-for="star in film?.credits.cast" class="flex flex-col items-center p-4 bg-slate-200 rounded m-4">
<UiPerson class="h-10" />
{{ star.name }}
</li>
</ul>
</div>
<ul class="flex">
<li v-for="genre in film.genres" class="p-8"> {{ genre.name }} </li>
<li v-for="genre in film?.genres" class="p-8"> {{ genre.name }} </li>
</ul>
</span>
</div>
<div>
<CommentForm :filmId="film.id" />
<CommentList :filmId="film.id" />
<CommentForm :filmId="film?.id" />
<CommentList :filmId="film?.id" />
</div>
</div>
</section>
</template>

<script setup lang="ts">
const router = useRouter()
const config = useRuntimeConfig()
const film = ref()
const route = useRoute()
const filmId = ref('')
const director = ref('')
const config = useRuntimeConfig()

interface FilmDetails {
title: string,
id: number,
poster_path: string,
release_date: number,
vote_average: number,
vote_count: number,
genres: genre[],
overview: string,
credits: Credits,
}

interface genre {
id: number,
name: string,
}

interface Credits {
id: string,
cast: Cast[],
crew: Crew[],
}

interface Cast {
adult: boolean,
gender: number,
id: number,
known_for_department: string,
name: string,
original_name: string,
popularity: number,
profile_path: string,
cast_id: number,
character: string,
credit_id: string,
order: number,
}

interface Crew {
adult: boolean,
gender: number,
id: number,
known_for_department: string,
name: string,
original_name: string,
popularity: number,
profile_path: string | null,
credit_id: string,
department: string,
job: string,
}

const film: Ref<FilmDetails | null> = ref(null)
const filmId: Ref<string> = ref('')
const director: Ref<string> = ref('')

filmId.value = route.params.id
filmId.value = route.params.id as string

if (filmId.value !== '') {
const { data } = await useFetch(`/api/details/${filmId.value}`)
film.value = data.value
director.value = film.value.credits.crew.filter((member) => member.job === 'Director')
director.value = director.value[0].name
film.value = data.value as FilmDetails
const dataDirector = film.value.credits.crew.filter((member) => member.job === 'Director')
director.value = dataDirector[0].name
}

onMounted(() => {


+ 7
- 2
server/api/explore.ts View File

@@ -1,13 +1,18 @@
import fetch from 'node-fetch'

interface Data {

}

export default eventHandler(async (req) => {
const page = req.context.params?.page || 1
const url = `https://api.themoviedb.org/3/discover/movie?include_adult=false&include_video=false&language=en-US&page=${page}&sort_by=popularity.desc`

const response = await fetch(url, {
const response: Response = await fetch(url, {
method: 'get',
headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI2MmVmZmYzYWU2YWYyNWQ0NTY4OGY3OTkxYjgyNmNhOCIsIm5iZiI6MTcyODA1NTIwMy4wNzcyNywic3ViIjoiNjcwMDA2ZjQ5ZWJlYTE5MDA2ZjgxZmJhIiwic2NvcGVzIjpbImFwaV9yZWFkIl0sInZlcnNpb24iOjF9.XuH-_0UggmULCgQQajKc-QsmlRYW2rqSenyhguE6wRU' }
})
const data = await response.json()
return data.results

return data
})

Loading…
Cancel
Save