mirror of
				https://github.com/mmahdium/TBW.git
				synced 2025-11-04 09:09:24 +01:00 
			
		
		
		
	Added improved types
This commit is contained in:
		@@ -11,9 +11,14 @@ const store = useMoviesStore()
 | 
			
		||||
const imageLoadFailed = ref(false)
 | 
			
		||||
const loaded = ref(false)
 | 
			
		||||
 | 
			
		||||
const alreadyAdded = computed(() =>
 | 
			
		||||
  store.movieList.some((movie) => movie.imdbID === props.movie.imdbID),
 | 
			
		||||
)
 | 
			
		||||
const alreadyAdded = computed(() => store.movieList.some((movie) => movie.Id === props.movie.Id))
 | 
			
		||||
 | 
			
		||||
const imageSource = computed(() => {
 | 
			
		||||
  if (!props.movie.PosterPath) {
 | 
			
		||||
    return ''
 | 
			
		||||
  }
 | 
			
		||||
  return `https://image.tmdb.org/t/p/w300${props.movie.PosterPath}`
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
@@ -22,7 +27,7 @@ const alreadyAdded = computed(() =>
 | 
			
		||||
    v-motion-fade-visible-once
 | 
			
		||||
  >
 | 
			
		||||
    <!-- Poster -->
 | 
			
		||||
    <router-link :to="{ name: 'details', params: { id: props.movie.imdbID } }">
 | 
			
		||||
    <router-link :to="{ name: 'details', params: { type: props.movie.MediaType, id: props.movie.Id } }">
 | 
			
		||||
      <figure class="overflow-hidden flex items-center justify-center aspect-[2/3] bg-gray-50">
 | 
			
		||||
        <span v-if="!loaded" class="loading loading-ring loading-lg text-primary"></span>
 | 
			
		||||
 | 
			
		||||
@@ -45,7 +50,7 @@ const alreadyAdded = computed(() =>
 | 
			
		||||
 | 
			
		||||
        <img
 | 
			
		||||
          v-show="loaded && !imageLoadFailed"
 | 
			
		||||
          :src="props.movie.Poster"
 | 
			
		||||
          :src="imageSource"
 | 
			
		||||
          :alt="props.movie.Title"
 | 
			
		||||
          class="object-cover w-full h-full transform transition-transform duration-500 hover:scale-105"
 | 
			
		||||
          @load="loaded = true"
 | 
			
		||||
@@ -61,13 +66,13 @@ const alreadyAdded = computed(() =>
 | 
			
		||||
 | 
			
		||||
    <!-- Body -->
 | 
			
		||||
    <div class="card-body p-4 flex flex-col">
 | 
			
		||||
      <router-link :to="{ name: 'details', params: { id: props.movie.imdbID } }">
 | 
			
		||||
      <router-link :to="{ name: 'details', params: { type: props.movie.MediaType, id: props.movie.Id } }">
 | 
			
		||||
        <h2
 | 
			
		||||
          class="card-title text-base font-semibold bg-gradient-to-r from-gray-700 to-gray-500 bg-clip-text text-transparent"
 | 
			
		||||
        >
 | 
			
		||||
          {{ props.movie.Title }}
 | 
			
		||||
        </h2>
 | 
			
		||||
        <p class="text-sm text-gray-400">{{ props.movie.Year }}</p>
 | 
			
		||||
        <p class="text-sm text-gray-400">{{ props.movie.ReleaseDate.slice(0, 4) }}</p>
 | 
			
		||||
      </router-link>
 | 
			
		||||
 | 
			
		||||
      <div class="card-actions justify-end mt-auto">
 | 
			
		||||
@@ -83,7 +88,7 @@ const alreadyAdded = computed(() =>
 | 
			
		||||
          v-motion-fade-visible-once
 | 
			
		||||
          v-else
 | 
			
		||||
          class="btn btn-sm px-4 bg-gradient-to-r from-red-50 to-red-100 border border-red-200 text-red-600 hover:from-red-100 hover:to-red-200 hover:text-red-700 transition"
 | 
			
		||||
          @click="store.removeMovie(props.movie.imdbID)"
 | 
			
		||||
          @click="store.removeMovie(props.movie.Id)"
 | 
			
		||||
        >
 | 
			
		||||
          Remove
 | 
			
		||||
        </button>
 | 
			
		||||
 
 | 
			
		||||
@@ -29,10 +29,10 @@ const emit = defineEmits<{ (e: 'loaded', id: string): void; (e: 'loadMore'): voi
 | 
			
		||||
      v-else
 | 
			
		||||
      class="grid gap-4 grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5"
 | 
			
		||||
    >
 | 
			
		||||
      <li v-for="movie in props.movies" :key="movie.imdbID" v-auto-animate>
 | 
			
		||||
      <li v-for="movie in props.movies" :key="movie.Id" v-auto-animate>
 | 
			
		||||
        <MovieCard :movie="movie" />
 | 
			
		||||
      </li>
 | 
			
		||||
      <li>
 | 
			
		||||
      <li v-if="!props.isSearch">
 | 
			
		||||
        <AddMoreCard />
 | 
			
		||||
      </li>
 | 
			
		||||
    </ul>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,53 +1,96 @@
 | 
			
		||||
import type { MovieResponseType, MovieType } from '@/types/Movie'
 | 
			
		||||
import type { MediaResponseType } from '@/types/Media'
 | 
			
		||||
import { mapMedia } from '@/types/MediaMap'
 | 
			
		||||
import axios from 'axios'
 | 
			
		||||
 | 
			
		||||
const API_KEY = '595695c3' // I know this should not be here and I dont care
 | 
			
		||||
const TMDB_READ_API_KEY =
 | 
			
		||||
  'eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIzZjY3MDNmM2UyYTBiMmI0MGZlNGZiYjNlMTU0NjI0NCIsIm5iZiI6MTc2MDU3NDcwNi45MjQsInN1YiI6IjY4ZjAzY2YyNGZmNGM0NjI1NmM3N2EyNyIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.HHReb_7Oue_o1wkgH2mmbCgdMJ8buFfRdCtwQqj_1Us' // I know this should not be here and I dont care
 | 
			
		||||
 | 
			
		||||
const instance = axios.create({
 | 
			
		||||
  baseURL: 'https://www.omdbapi.com/',
 | 
			
		||||
  baseURL: 'https://api.themoviedb.org/3',
 | 
			
		||||
  timeout: 6969,
 | 
			
		||||
  params: {
 | 
			
		||||
    apikey: API_KEY,
 | 
			
		||||
  headers: {
 | 
			
		||||
    'Content-Type': 'application/json',
 | 
			
		||||
    Authorization: `Bearer ${TMDB_READ_API_KEY}`,
 | 
			
		||||
  },
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export const searchMovies = async (query: string): Promise<MovieResponseType> => {
 | 
			
		||||
  const response = await instance.get(``, {
 | 
			
		||||
export const searchMovies = async (query: string): Promise<MediaResponseType> => {
 | 
			
		||||
  const response = await instance.get(`/search/multi`, {
 | 
			
		||||
    params: {
 | 
			
		||||
      s: query,
 | 
			
		||||
      query: query,
 | 
			
		||||
      include_adult: true,
 | 
			
		||||
    },
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  // if (response.data.Response === 'False') {
 | 
			
		||||
  //   throw new Error(response.data.Error)
 | 
			
		||||
  // }
 | 
			
		||||
  if (response.status !== 200) {
 | 
			
		||||
    return {
 | 
			
		||||
      Results: [],
 | 
			
		||||
      Page: 0,
 | 
			
		||||
      totalResults: 0,
 | 
			
		||||
      totalPages: 0,
 | 
			
		||||
      ErrorMessage: response.data.Error,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const data: MovieResponseType = {
 | 
			
		||||
    Search: response.data.Search as MovieType[],
 | 
			
		||||
    totalResults: response.data.totalResults,
 | 
			
		||||
    Response: response.data.Response === 'True',
 | 
			
		||||
    ErrorMessage: response.data.Error || '',
 | 
			
		||||
  const filtered = response.data.results.filter((result: { media_type: string }) => {
 | 
			
		||||
    return result.media_type === 'movie' || result.media_type === 'tv'
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const data: MediaResponseType = {
 | 
			
		||||
    Results: filtered.map(mapMedia),
 | 
			
		||||
    Page: response.data.page,
 | 
			
		||||
    totalResults: response.data.total_results,
 | 
			
		||||
    totalPages: response.data.total_pages,
 | 
			
		||||
    ErrorMessage: '',
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return data
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const loadMoreMovies = async (query: string, page: number) => {
 | 
			
		||||
  const response = await instance.get(``, {
 | 
			
		||||
export const loadMoreMovies = async (query: string, page: number): Promise<MediaResponseType> => {
 | 
			
		||||
    const response = await instance.get(`/search/multi`, {
 | 
			
		||||
    params: {
 | 
			
		||||
      s: query,
 | 
			
		||||
      page: page,
 | 
			
		||||
      query: query,
 | 
			
		||||
      include_adult: true,
 | 
			
		||||
      page: page
 | 
			
		||||
    },
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  if (response.data.Response === 'False') {
 | 
			
		||||
    throw new Error(response.data.Error)
 | 
			
		||||
  if (response.status !== 200) {
 | 
			
		||||
    return {
 | 
			
		||||
      Results: [],
 | 
			
		||||
      Page: 0,
 | 
			
		||||
      totalResults: 0,
 | 
			
		||||
      totalPages: 0,
 | 
			
		||||
      ErrorMessage: response.data.Error,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const filtered = response.data.results.filter((result: { media_type: string }) => {
 | 
			
		||||
    return result.media_type === 'movie' || result.media_type === 'tv'
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  const data: MediaResponseType = {
 | 
			
		||||
    Results: filtered.map(mapMedia),
 | 
			
		||||
    Page: response.data.page,
 | 
			
		||||
    totalResults: response.data.total_results,
 | 
			
		||||
    totalPages: response.data.total_pages,
 | 
			
		||||
    ErrorMessage: '',
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return data
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getMovieDetails = async (id: string) => {
 | 
			
		||||
  const response = await instance.get(`movie/${id}`, {
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  return response.data
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getMovie = async (id: string) => {
 | 
			
		||||
export const getSeriesDetails = async (id: string) => {
 | 
			
		||||
  const response = await instance.get(``, {
 | 
			
		||||
    params: {
 | 
			
		||||
      i: id,
 | 
			
		||||
@@ -55,9 +98,5 @@ export const getMovie = async (id: string) => {
 | 
			
		||||
    },
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  if (response.data.Response === 'False') {
 | 
			
		||||
    throw new Error(response.data.Error)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return response.data
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ const routes: RouteRecordRaw[] = [
 | 
			
		||||
    component: () => import('@/views/ListView.vue'),
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: '/details/:id',
 | 
			
		||||
    path: '/details/:type/:id',
 | 
			
		||||
    name: 'details',
 | 
			
		||||
    component: () => import('@/views/DetailsView.vue'),
 | 
			
		||||
  },
 | 
			
		||||
 
 | 
			
		||||
@@ -15,14 +15,14 @@ export const useMoviesStore = defineStore('movies', () => {
 | 
			
		||||
  const movieList = ref<MovieType[]>(loadMovies())
 | 
			
		||||
 | 
			
		||||
  function addMovie(movie: MovieType) {
 | 
			
		||||
    if (!movieList.value.find((m) => m.imdbID === movie.imdbID)) {
 | 
			
		||||
    if (!movieList.value.find((m) => m.Id === movie.Id)) {
 | 
			
		||||
      movieList.value.push(movie)
 | 
			
		||||
      saveMovies(movieList.value)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function removeMovie(movieId: string) {
 | 
			
		||||
    movieList.value = movieList.value.filter((m) => m.imdbID !== movieId)
 | 
			
		||||
  function removeMovie(movieId: number) {
 | 
			
		||||
    movieList.value = movieList.value.filter((m) => m.Id !== movieId)
 | 
			
		||||
    saveMovies(movieList.value)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								src/types/Media.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/types/Media.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
export type MediaType = {
 | 
			
		||||
  Adult: boolean
 | 
			
		||||
  BackdropPath: string
 | 
			
		||||
  Id: number
 | 
			
		||||
  Title: string
 | 
			
		||||
  OriginalTitle: string
 | 
			
		||||
  OriginalLanguage: string
 | 
			
		||||
  MediaType: 'movie' | 'tv' | 'person' | 'collection'
 | 
			
		||||
  Overview: string
 | 
			
		||||
  PosterPath: string
 | 
			
		||||
  Popularity: number
 | 
			
		||||
  ReleaseDate: string  // For movies
 | 
			
		||||
  FirstAirDate: string // For TV series
 | 
			
		||||
  VoteAverage: number
 | 
			
		||||
  VoteCount: number
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type MediaResponseType = {
 | 
			
		||||
  Results: MediaType[]
 | 
			
		||||
  Page: number
 | 
			
		||||
  totalResults: number
 | 
			
		||||
  totalPages: number
 | 
			
		||||
  ErrorMessage: string
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								src/types/MediaMap.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/types/MediaMap.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
import type { MediaType } from "./Media"
 | 
			
		||||
 | 
			
		||||
type TMDBMedia = {
 | 
			
		||||
  adult: boolean
 | 
			
		||||
  backdrop_path: string | null
 | 
			
		||||
  id: number
 | 
			
		||||
  title?: string
 | 
			
		||||
  name?: string
 | 
			
		||||
  original_title?: string
 | 
			
		||||
  original_name?: string
 | 
			
		||||
  original_language: string
 | 
			
		||||
  overview: string
 | 
			
		||||
  poster_path: string | null
 | 
			
		||||
  popularity: number
 | 
			
		||||
  release_date?: string
 | 
			
		||||
  first_air_date?: string
 | 
			
		||||
  vote_average: number
 | 
			
		||||
  vote_count: number
 | 
			
		||||
  media_type: 'movie' | 'tv' | 'person' | 'collection'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const mapMedia = (m: TMDBMedia): MediaType => ({
 | 
			
		||||
  Adult: m.adult,
 | 
			
		||||
  BackdropPath: m.backdrop_path ?? '',
 | 
			
		||||
  Id: m.id,
 | 
			
		||||
  Title: m.title ?? m.name ?? '',
 | 
			
		||||
  OriginalTitle: m.original_title ?? m.original_name ?? '',
 | 
			
		||||
  OriginalLanguage: m.original_language,
 | 
			
		||||
  MediaType: m.media_type,
 | 
			
		||||
  Overview: m.overview,
 | 
			
		||||
  PosterPath: m.poster_path ?? '',
 | 
			
		||||
  Popularity: m.popularity,
 | 
			
		||||
  ReleaseDate: m.release_date ?? '',
 | 
			
		||||
  FirstAirDate: m.first_air_date ?? '',
 | 
			
		||||
  VoteAverage: m.vote_average,
 | 
			
		||||
  VoteCount: m.vote_count,
 | 
			
		||||
})
 | 
			
		||||
@@ -1,28 +1,38 @@
 | 
			
		||||
export type MovieType = {
 | 
			
		||||
  Title: string
 | 
			
		||||
  Year: string
 | 
			
		||||
  imdbID: string
 | 
			
		||||
  Type: string
 | 
			
		||||
  Poster: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type MovieResponseType = {
 | 
			
		||||
  Search: MovieType[]
 | 
			
		||||
  totalResults: string
 | 
			
		||||
  Response: boolean
 | 
			
		||||
  ErrorMessage: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type MovieDetailsType = {
 | 
			
		||||
  Adult: boolean
 | 
			
		||||
  BackdropPath: string
 | 
			
		||||
  Budget: number
 | 
			
		||||
  Genres: Array<{ id: number; name: string }>
 | 
			
		||||
  Homepage: string
 | 
			
		||||
  Id: number
 | 
			
		||||
  ImdbId: string
 | 
			
		||||
  OriginalLanguage: string
 | 
			
		||||
  OriginalTitle: string
 | 
			
		||||
  Overview: string
 | 
			
		||||
  Popularity: number
 | 
			
		||||
  PosterPath: string
 | 
			
		||||
  ProductionCompanies: Array<{
 | 
			
		||||
    id: number
 | 
			
		||||
    logoPath: string | null
 | 
			
		||||
    name: string
 | 
			
		||||
    originCountry: string
 | 
			
		||||
  }>
 | 
			
		||||
  ProductionCountries: Array<{
 | 
			
		||||
    iso31661: string
 | 
			
		||||
    name: string
 | 
			
		||||
  }>
 | 
			
		||||
  ReleaseDate: string
 | 
			
		||||
  Revenue: number
 | 
			
		||||
  Runtime: number
 | 
			
		||||
  SpokenLanguages: Array<{
 | 
			
		||||
    englishName: string
 | 
			
		||||
    iso6391: string
 | 
			
		||||
    name: string
 | 
			
		||||
  }>
 | 
			
		||||
  Status: string
 | 
			
		||||
  Tagline: string
 | 
			
		||||
  Title: string
 | 
			
		||||
  Year: string
 | 
			
		||||
  imdbID: string
 | 
			
		||||
  Type: string
 | 
			
		||||
  Poster: string
 | 
			
		||||
  Plot: string
 | 
			
		||||
  Language: string
 | 
			
		||||
  Country: string
 | 
			
		||||
  imdbRating: string
 | 
			
		||||
  Error: boolean
 | 
			
		||||
  ErrorMessage: string
 | 
			
		||||
  Video: boolean
 | 
			
		||||
  VoteAverage: number
 | 
			
		||||
  VoteCount: number
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										82
									
								
								src/types/MovieMap.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								src/types/MovieMap.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
import type { MovieDetailsType } from "./Movie"
 | 
			
		||||
 | 
			
		||||
type TMDBMovieDetails = {
 | 
			
		||||
  adult: boolean
 | 
			
		||||
  backdrop_path: string | null
 | 
			
		||||
  budget: number
 | 
			
		||||
  genres: Array<{ id: number; name: string }>
 | 
			
		||||
  homepage: string
 | 
			
		||||
  id: number
 | 
			
		||||
  imdb_id: string
 | 
			
		||||
  original_language: string
 | 
			
		||||
  original_title: string
 | 
			
		||||
  overview: string
 | 
			
		||||
  popularity: number
 | 
			
		||||
  poster_path: string | null
 | 
			
		||||
  production_companies: Array<{
 | 
			
		||||
    id: number
 | 
			
		||||
    logo_path: string | null
 | 
			
		||||
    name: string
 | 
			
		||||
    origin_country: string
 | 
			
		||||
  }>
 | 
			
		||||
  production_countries: Array<{
 | 
			
		||||
    iso_3166_1: string
 | 
			
		||||
    name: string
 | 
			
		||||
  }>
 | 
			
		||||
  release_date: string
 | 
			
		||||
  revenue: number
 | 
			
		||||
  runtime: number
 | 
			
		||||
  spoken_languages: Array<{
 | 
			
		||||
    english_name: string
 | 
			
		||||
    iso_639_1: string
 | 
			
		||||
    name: string
 | 
			
		||||
  }>
 | 
			
		||||
  status: string
 | 
			
		||||
  tagline: string
 | 
			
		||||
  title: string
 | 
			
		||||
  video: boolean
 | 
			
		||||
  vote_average: number
 | 
			
		||||
  vote_count: number
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const mapMovieDetails = (m: TMDBMovieDetails): MovieDetailsType => ({
 | 
			
		||||
  Adult: m.adult,
 | 
			
		||||
  BackdropPath: m.backdrop_path ?? '',
 | 
			
		||||
  Budget: m.budget,
 | 
			
		||||
  Genres: m.genres.map(genre => ({
 | 
			
		||||
    id: genre.id,
 | 
			
		||||
    name: genre.name
 | 
			
		||||
  })),
 | 
			
		||||
  Homepage: m.homepage,
 | 
			
		||||
  Id: m.id,
 | 
			
		||||
  ImdbId: m.imdb_id,
 | 
			
		||||
  OriginalLanguage: m.original_language,
 | 
			
		||||
  OriginalTitle: m.original_title,
 | 
			
		||||
  Overview: m.overview,
 | 
			
		||||
  Popularity: m.popularity,
 | 
			
		||||
  PosterPath: m.poster_path ?? '',
 | 
			
		||||
  ProductionCompanies: m.production_companies.map(company => ({
 | 
			
		||||
    id: company.id,
 | 
			
		||||
    logoPath: company.logo_path,
 | 
			
		||||
    name: company.name,
 | 
			
		||||
    originCountry: company.origin_country
 | 
			
		||||
  })),
 | 
			
		||||
  ProductionCountries: m.production_countries.map(country => ({
 | 
			
		||||
    iso31661: country.iso_3166_1,
 | 
			
		||||
    name: country.name
 | 
			
		||||
  })),
 | 
			
		||||
  ReleaseDate: m.release_date,
 | 
			
		||||
  Revenue: m.revenue,
 | 
			
		||||
  Runtime: m.runtime ?? 0,
 | 
			
		||||
  SpokenLanguages: m.spoken_languages.map(lang => ({
 | 
			
		||||
    englishName: lang.english_name,
 | 
			
		||||
    iso6391: lang.iso_639_1,
 | 
			
		||||
    name: lang.name
 | 
			
		||||
  })),
 | 
			
		||||
  Status: m.status,
 | 
			
		||||
  Tagline: m.tagline ?? '',
 | 
			
		||||
  Title: m.title,
 | 
			
		||||
  Video: m.video,
 | 
			
		||||
  VoteAverage: m.vote_average,
 | 
			
		||||
  VoteCount: m.vote_count,
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										78
									
								
								src/types/TvSeries.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/types/TvSeries.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
export type TvSeriesDetailsType = {
 | 
			
		||||
  Adult: boolean
 | 
			
		||||
  BackdropPath: string
 | 
			
		||||
  CreatedBy: Array<{
 | 
			
		||||
    id: number
 | 
			
		||||
    creditId: string
 | 
			
		||||
    name: string
 | 
			
		||||
    gender: number
 | 
			
		||||
    profilePath: string | null
 | 
			
		||||
  }>
 | 
			
		||||
  EpisodeRunTime: number[]
 | 
			
		||||
  FirstAirDate: string
 | 
			
		||||
  Genres: Array<{ id: number; name: string }>
 | 
			
		||||
  Homepage: string
 | 
			
		||||
  Id: number
 | 
			
		||||
  InProduction: boolean
 | 
			
		||||
  Languages: string[]
 | 
			
		||||
  LastAirDate: string
 | 
			
		||||
  LastEpisodeToAir: {
 | 
			
		||||
    id: number
 | 
			
		||||
    name: string
 | 
			
		||||
    overview: string
 | 
			
		||||
    voteAverage: number
 | 
			
		||||
    voteCount: number
 | 
			
		||||
    airDate: string
 | 
			
		||||
    episodeNumber: number
 | 
			
		||||
    productionCode: string
 | 
			
		||||
    runtime: number
 | 
			
		||||
    seasonNumber: number
 | 
			
		||||
    showId: number
 | 
			
		||||
    stillPath: string | null
 | 
			
		||||
  } | null
 | 
			
		||||
  Name: string
 | 
			
		||||
  Networks: Array<{
 | 
			
		||||
    id: number
 | 
			
		||||
    logoPath: string | null
 | 
			
		||||
    name: string
 | 
			
		||||
    originCountry: string
 | 
			
		||||
  }>
 | 
			
		||||
  NumberOfEpisodes: number
 | 
			
		||||
  NumberOfSeasons: number
 | 
			
		||||
  OriginCountry: string[]
 | 
			
		||||
  OriginalLanguage: string
 | 
			
		||||
  OriginalName: string
 | 
			
		||||
  Overview: string
 | 
			
		||||
  Popularity: number
 | 
			
		||||
  PosterPath: string
 | 
			
		||||
  ProductionCompanies: Array<{
 | 
			
		||||
    id: number
 | 
			
		||||
    logoPath: string | null
 | 
			
		||||
    name: string
 | 
			
		||||
    originCountry: string
 | 
			
		||||
  }>
 | 
			
		||||
  ProductionCountries: Array<{
 | 
			
		||||
    iso31661: string
 | 
			
		||||
    name: string
 | 
			
		||||
  }>
 | 
			
		||||
  Seasons: Array<{
 | 
			
		||||
    airDate: string | null
 | 
			
		||||
    episodeCount: number
 | 
			
		||||
    id: number
 | 
			
		||||
    name: string
 | 
			
		||||
    overview: string
 | 
			
		||||
    posterPath: string | null
 | 
			
		||||
    seasonNumber: number
 | 
			
		||||
    voteAverage: number
 | 
			
		||||
  }>
 | 
			
		||||
  SpokenLanguages: Array<{
 | 
			
		||||
    englishName: string
 | 
			
		||||
    iso6391: string
 | 
			
		||||
    name: string
 | 
			
		||||
  }>
 | 
			
		||||
  Status: string
 | 
			
		||||
  Tagline: string
 | 
			
		||||
  Type: string
 | 
			
		||||
  VoteAverage: number
 | 
			
		||||
  VoteCount: number
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										162
									
								
								src/types/TvSeriesMap.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								src/types/TvSeriesMap.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,162 @@
 | 
			
		||||
import type { TvSeriesDetailsType } from "./TvSeries"
 | 
			
		||||
 | 
			
		||||
type TMDBTvSeriesDetails = {
 | 
			
		||||
  adult: boolean
 | 
			
		||||
  backdrop_path: string | null
 | 
			
		||||
  created_by: Array<{
 | 
			
		||||
    id: number
 | 
			
		||||
    credit_id: string
 | 
			
		||||
    name: string
 | 
			
		||||
    gender: number
 | 
			
		||||
    profile_path: string | null
 | 
			
		||||
  }>
 | 
			
		||||
  episode_run_time: number[]
 | 
			
		||||
  first_air_date: string
 | 
			
		||||
  genres: Array<{ id: number; name: string }>
 | 
			
		||||
  homepage: string
 | 
			
		||||
  id: number
 | 
			
		||||
  in_production: boolean
 | 
			
		||||
  languages: string[]
 | 
			
		||||
  last_air_date: string
 | 
			
		||||
  last_episode_to_air: {
 | 
			
		||||
    id: number
 | 
			
		||||
    name: string
 | 
			
		||||
    overview: string
 | 
			
		||||
    vote_average: number
 | 
			
		||||
    vote_count: number
 | 
			
		||||
    air_date: string
 | 
			
		||||
    episode_number: number
 | 
			
		||||
    production_code: string
 | 
			
		||||
    runtime: number
 | 
			
		||||
    season_number: number
 | 
			
		||||
    show_id: number
 | 
			
		||||
    still_path: string | null
 | 
			
		||||
  } | null
 | 
			
		||||
  name: string
 | 
			
		||||
  networks: Array<{
 | 
			
		||||
    id: number
 | 
			
		||||
    logo_path: string | null
 | 
			
		||||
    name: string
 | 
			
		||||
    origin_country: string
 | 
			
		||||
  }>
 | 
			
		||||
  number_of_episodes: number
 | 
			
		||||
  number_of_seasons: number
 | 
			
		||||
  origin_country: string[]
 | 
			
		||||
  original_language: string
 | 
			
		||||
  original_name: string
 | 
			
		||||
  overview: string
 | 
			
		||||
  popularity: number
 | 
			
		||||
  poster_path: string | null
 | 
			
		||||
  production_companies: Array<{
 | 
			
		||||
    id: number
 | 
			
		||||
    logo_path: string | null
 | 
			
		||||
    name: string
 | 
			
		||||
    origin_country: string
 | 
			
		||||
  }>
 | 
			
		||||
  production_countries: Array<{
 | 
			
		||||
    iso_3166_1: string
 | 
			
		||||
    name: string
 | 
			
		||||
  }>
 | 
			
		||||
  seasons: Array<{
 | 
			
		||||
    air_date: string | null
 | 
			
		||||
    episode_count: number
 | 
			
		||||
    id: number
 | 
			
		||||
    name: string
 | 
			
		||||
    overview: string
 | 
			
		||||
    poster_path: string | null
 | 
			
		||||
    season_number: number
 | 
			
		||||
    vote_average: number
 | 
			
		||||
  }>
 | 
			
		||||
  spoken_languages: Array<{
 | 
			
		||||
    english_name: string
 | 
			
		||||
    iso_639_1: string
 | 
			
		||||
    name: string
 | 
			
		||||
  }>
 | 
			
		||||
  status: string
 | 
			
		||||
  tagline: string
 | 
			
		||||
  type: string
 | 
			
		||||
  vote_average: number
 | 
			
		||||
  vote_count: number
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const mapTvSeriesDetails = (tv: TMDBTvSeriesDetails): TvSeriesDetailsType => ({
 | 
			
		||||
  Adult: tv.adult,
 | 
			
		||||
  BackdropPath: tv.backdrop_path ?? '',
 | 
			
		||||
  CreatedBy: tv.created_by.map(creator => ({
 | 
			
		||||
    id: creator.id,
 | 
			
		||||
    creditId: creator.credit_id,
 | 
			
		||||
    name: creator.name,
 | 
			
		||||
    gender: creator.gender,
 | 
			
		||||
    profilePath: creator.profile_path
 | 
			
		||||
  })),
 | 
			
		||||
  EpisodeRunTime: tv.episode_run_time,
 | 
			
		||||
  FirstAirDate: tv.first_air_date ?? '',
 | 
			
		||||
  Genres: tv.genres.map(genre => ({
 | 
			
		||||
    id: genre.id,
 | 
			
		||||
    name: genre.name
 | 
			
		||||
  })),
 | 
			
		||||
  Homepage: tv.homepage,
 | 
			
		||||
  Id: tv.id,
 | 
			
		||||
  InProduction: tv.in_production,
 | 
			
		||||
  Languages: tv.languages,
 | 
			
		||||
  LastAirDate: tv.last_air_date ?? '',
 | 
			
		||||
  LastEpisodeToAir: tv.last_episode_to_air ? {
 | 
			
		||||
    id: tv.last_episode_to_air.id,
 | 
			
		||||
    name: tv.last_episode_to_air.name,
 | 
			
		||||
    overview: tv.last_episode_to_air.overview,
 | 
			
		||||
    voteAverage: tv.last_episode_to_air.vote_average,
 | 
			
		||||
    voteCount: tv.last_episode_to_air.vote_count,
 | 
			
		||||
    airDate: tv.last_episode_to_air.air_date ?? '',
 | 
			
		||||
    episodeNumber: tv.last_episode_to_air.episode_number,
 | 
			
		||||
    productionCode: tv.last_episode_to_air.production_code,
 | 
			
		||||
    runtime: tv.last_episode_to_air.runtime ?? 0,
 | 
			
		||||
    seasonNumber: tv.last_episode_to_air.season_number,
 | 
			
		||||
    showId: tv.last_episode_to_air.show_id,
 | 
			
		||||
    stillPath: tv.last_episode_to_air.still_path
 | 
			
		||||
  } : null,
 | 
			
		||||
  Name: tv.name,
 | 
			
		||||
  Networks: tv.networks.map(network => ({
 | 
			
		||||
    id: network.id,
 | 
			
		||||
    logoPath: network.logo_path,
 | 
			
		||||
    name: network.name,
 | 
			
		||||
    originCountry: network.origin_country
 | 
			
		||||
  })),
 | 
			
		||||
  NumberOfEpisodes: tv.number_of_episodes,
 | 
			
		||||
  NumberOfSeasons: tv.number_of_seasons,
 | 
			
		||||
  OriginCountry: tv.origin_country,
 | 
			
		||||
  OriginalLanguage: tv.original_language,
 | 
			
		||||
  OriginalName: tv.original_name,
 | 
			
		||||
  Overview: tv.overview,
 | 
			
		||||
  Popularity: tv.popularity,
 | 
			
		||||
  PosterPath: tv.poster_path ?? '',
 | 
			
		||||
  ProductionCompanies: tv.production_companies.map(company => ({
 | 
			
		||||
    id: company.id,
 | 
			
		||||
    logoPath: company.logo_path,
 | 
			
		||||
    name: company.name,
 | 
			
		||||
    originCountry: company.origin_country
 | 
			
		||||
  })),
 | 
			
		||||
  ProductionCountries: tv.production_countries.map(country => ({
 | 
			
		||||
    iso31661: country.iso_3166_1,
 | 
			
		||||
    name: country.name
 | 
			
		||||
  })),
 | 
			
		||||
  Seasons: tv.seasons.map(season => ({
 | 
			
		||||
    airDate: season.air_date,
 | 
			
		||||
    episodeCount: season.episode_count,
 | 
			
		||||
    id: season.id,
 | 
			
		||||
    name: season.name,
 | 
			
		||||
    overview: season.overview,
 | 
			
		||||
    posterPath: season.poster_path,
 | 
			
		||||
    seasonNumber: season.season_number,
 | 
			
		||||
    voteAverage: season.vote_average
 | 
			
		||||
  })),
 | 
			
		||||
  SpokenLanguages: tv.spoken_languages.map(lang => ({
 | 
			
		||||
    englishName: lang.english_name,
 | 
			
		||||
    iso6391: lang.iso_639_1,
 | 
			
		||||
    name: lang.name
 | 
			
		||||
  })),
 | 
			
		||||
  Status: tv.status,
 | 
			
		||||
  Tagline: tv.tagline,
 | 
			
		||||
  Type: tv.type,
 | 
			
		||||
  VoteAverage: tv.vote_average,
 | 
			
		||||
  VoteCount: tv.vote_count,
 | 
			
		||||
})
 | 
			
		||||
@@ -21,15 +21,16 @@ async function searchMovie() {
 | 
			
		||||
    isSearching.value = true
 | 
			
		||||
    searchPage.value = 1
 | 
			
		||||
    const result = await searchMovies(searchQuery.value)
 | 
			
		||||
    if (!result.Response) {
 | 
			
		||||
    console.log(result)
 | 
			
		||||
    if (result.totalResults === 0) {
 | 
			
		||||
      movies.value = []
 | 
			
		||||
      seachError.value = result.ErrorMessage
 | 
			
		||||
      seachError.value = 'No results found'
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    seachError.value = ''
 | 
			
		||||
    movies.value = result.Search
 | 
			
		||||
    movies.value = result.Results
 | 
			
		||||
 | 
			
		||||
    state.setState(searchPage.value, searchQuery.value, result.Search)
 | 
			
		||||
    state.setState(searchPage.value, searchQuery.value, result.Results)
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    movies.value = []
 | 
			
		||||
    console.error(error)
 | 
			
		||||
@@ -44,7 +45,7 @@ async function loadMore() {
 | 
			
		||||
    isLoadingMore.value = true
 | 
			
		||||
    searchPage.value++
 | 
			
		||||
    const result = await loadMoreMovies(searchQuery.value, searchPage.value)
 | 
			
		||||
    movies.value?.push(...result.Search)
 | 
			
		||||
    movies.value?.push(...result.Results)
 | 
			
		||||
    state.setState(searchPage.value, searchQuery.value, movies.value ? movies.value : [])
 | 
			
		||||
  } catch (error) {
 | 
			
		||||
    searchPage.value = 1
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user