No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Lista de películas favoritas

17/20
Recursos

Aportes 34

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Creo que la solución más fácil que pude encontrar es simplemente ejecutar la función getLikedMovies() en el listener, literalmente solo agregue esa linea y por el momento funciona en todas las paginas que se agrega la película sin necesidad de recargar

movieBtn.addEventListener('click', ()=>{
            movieBtn.classList.toggle('btnMovie--liked')
            likeMovie(movie);
            getLikedMovies() //única linea agregada
        })

Actualización de favoritos
.
Intente hacerla con el Windows.storage.event pero no pude. Leí la documentación y al parecer solo funciona cuando el localStorage se modifica desde otro documento. Hasta hay una nota al comienzo que dice:
.

Note: This won’t work on the same page that is making the changes — it is really a way for other pages on the domain using the storage to sync any changes that are made. Pages on other domains can’t access the same storage objects.

.
Quisiera saber si estoy en lo correcto y entendí bien, o de lo contrario como podría realizarla.

Yo lo solucioné de una forma bastante sencilla, haciendo recargar el home cuando se realiza un cambio estando en el mismo.
Así como está configurado el cache, el cambio es instantáneo con cualquier velocidad de internet. Antes intenté hacerla llamando a la funcion getLikedMovies() en vez de al homePage(), pero al quitar una película de favoritos sigue manteniendo el estilo en el resto de las secciones.

function likeMovie(movie) {
	...
  if (location.hash == ''){
    homePage();
  }
}

Ya que no me funcionó el window.storage, lo que hice fue volver a llamar a las funciones getTrendingMoviesPreview() y getLikedMovies() al final de la funcion likeMovies() y de momento funciona bien

function likeMovies(movie) {
    const likedMovies = likesMoviesList()

    if(likedMovies[movie.id]) {
        likedMovies[movie.id] = undefined
    } else {
        likedMovies[movie.id] = movie
    }
    localStorage.setItem("liked-movies", JSON.stringify(likedMovies))
    getTrendingMoviesPreview()
    getLikedMovies()
}

Basándome en el excelente aporte previo de Jonathan Alfonso, me dí cuenta que si hacía scroll horizontal en TrendingPreview y le daba like a una película, al recargárseme completamente el home el scroll horizontal volvía al comienzo. Siento que esto puede afectar un poco la Experiencia del Usuario, por lo que me pareció mejor que la función likeMovie llame a getTrendingPreviewMovie y a getLikedMovies:

function likeMovie(movie) {
	...
  if (location.hash == ''){
        getLikedMovies();
        getTrendingMoviesPreview(); 
  }
}

Estas dos funciones limpian sus contenedores de scroll para que no se dupliquen las películas:

const getLikedMovies = () => {
    likedMoviesScroll.innerHTML = "";
    let likedMovies = Object.values(likedMovieList());
    printMoviePosters(likedMovies, likedMoviesScroll, true);
}
 
const getTrendingMoviesPreview = async () => {
    const { data } = await api('/trending/movie/day');
    const movies = data.results;
    trendingMoviesPreviewList.innerHTML = "";
    printMoviePosters(movies, trendingMoviesPreviewList, true);
}

Si quieren ocultar toda la sección de favoritos cuando no hayan películas seleccionadas, se puede agregar la clase inactive dentro de la función getLikedMovies() de la siguiente forma:

function getLikedMovies() {
    const likedMovies = likedMovieList();
    const moviesArray = Object.values(likedMovies);

    likedMoviesListArticle.innerHTML = '';

    !moviesArray.length && likedMoviesSection.classList.add('inactive');

    createMovies(moviesArray, likedMoviesListArticle);
}

Saludos, por mi parte solo inserte la función homepage() en el evento de hacer click en el botón de me gusta de, así cada que se cliquee para gustar o no una película la pagina inicial se recargara

<code> 
movieBtn.addEventListener('click', () => {            
            movieBtn.classList.toggle('movie-btn--liked');
            likeMovie(movie);
            homePage();
        });

este código se encuentra dentro de la función createMovies()

Mi solución fue tan sencilla, que aun sigo mirando si cometí algun error jaja
Solo agregue un llamado a homepage() desde al final del evento click del botón movieBtn.

Mi solución fue llamar a homePage para que refresque la página. No sé si está bien, pero fue una solución rápida. En este caso, item reemplaza a movie.

        movieBtn.addEventListener('click',()=>{
            movieBtn.classList.toggle('movie-btn--liked');
                likeMovie(item);
                homePage();
        })
Un push a la lista de películas favoritas
yo llame en la función q actualiza el storage a las funciones q refrescan tanto las trending movies preview como las peliculas likeadas. Anda perfecto y actualiza todos los botones de like, aparecen y desaparecen de la lista de likeadas,etc. Voy a probar con el evento del localStorage, supongo q es mucho mas elegante!

Esta fue mi solución, ejecutar la función likedMovies y recorrer el arreglo resultante verificando si la película en cuestión tenía el mismo ID de la película que se estaba renderizando en ese momento en la función renderMovie (createMovie):
.

 const moviesArr = Object.values(likedMoviesList());
            if(moviesArr){
                moviesArr.forEach(m => {
                if(m.id == movie.id){
                    
                    movieBtn.classList.add('movie-btn--liked');
                
                } else {
                    movieBtn.classList.add('movie-btn');
                }
                movieBtn.addEventListener('click', () => {
                    movieBtn.classList.toggle('movie-btn--liked');
    
                    likeMovie(movie) //function to add movies to localStorage and to the favorites section
                })
            })
            }


            movieContainer.append(movieImage);
            movieContainer.append(movieBtn);

la solucion a la que llegue es sencilla pero me tomo como una hora llegar a ella para enviar los datos de forma correcta

function getFavoriteMovies () {
  const movies = likedMovieList()
  const moviesArray = Object.values(movies)
  console.log(Object.values(movies))
  if (movies != {}) {
    createMovieList(moviesArray, favoriteMovieList, { lazyLoad : true , clean : true } )
  }
}

Yo intente hacer esto antes de verlo y lo único que hice distinto es la parte de darle el estilo o no. Por si a alguien le sirve mi lógica:

const existMovieInLikes= localStorage.liked_movies.includes(movie.id);
        console.log(existMovieInLikes)
        if (existMovieInLikes){
            movieBtn.classList.add("movie-btn","movie-btn--liked");

        }else{
            movieBtn.classList.add("movie-btn")
        }
 movieBtn.addEventListener("click", ()=>{
            movieBtn.classList.toggle("movie-btn--liked")
           likeMovie(movie);
           insertFavoritedMovies();
/* Y aca hice que se ejecute la accion cada vez que se haga click en el boton para actualizar la seccion de likes*/
        })

Mi solucion fue crear una funcion que verifica si movie-id esta en la lista de localStorage, y si ese es el caso, entonces agregar la clase movie-btn–liked

aqui dejo mi solucion

function isLiked(id) {
    const movieList = likedMovieList();
    return movieList[id] ? true : false
}

if(isLiked(movie.id)){
    movieBtn.classList.add('movie-btn--liked');
 }

Solo hay ejecutar getLikedMovies() en el evento click de del movie btn

    $movieBtn.addEventListener('click', () => {
     	$movieBtn.classList.toggle('movie-btn--liked');
      	likeMovie(movie);
	//esta es la línea agregada, sea actualizara cada vez que demos click al boton de like
      	getLikedMovies();
    })

Mi solucion

likeBtn.addEventListener("click", () => {
  likeBtn.classList.toggle("like-btn--liked");
  likeMovie(movie);
  if(location.hash = "#home"){
     getLikedMovies();
  }
});

Guardar favoritos en la API de TMDB

Les comparto la forma de agregar y eliminar las películas de favoritos usando la API de TMDB V3. Les dejo el código utilizando Axios como fetch. 😀

Recuerden leer siempre la documentación de la API atentamente, así no tienen dólares de cabeza como yo los tuve. 😅

fetch

Obtener request_token

const getRequestToken = async () => {
	const REQUEST_TOKEN_URL = 'authentication/token/new';
	const init = {
		method  : 'GET',
		headers : {
			'Content-Type' : 'application/json;charset=utf-8'
		}
	};
	const RESPONSE = await fetch(`${URL}/${REQUEST_TOKEN_URL}?api_key=${YOUR_API_KEY}`, init);
	const DATA = await RESPONSE.json();
	const REQUEST_TOKEN = DATA.request_token;

	return REQUEST_TOKEN;
};

Obtener session_id

Antes de obtener nuestro session_id tenemos que aceptar la autenticación de terceros desde nuestra cuenta de TMDB, lo realizamos desde la siguiente URL

www.themoviedb.org/authenticate/{your_request_token}.

Una vez aceptado ya podés seguir con el siguiente código.

const getSession = async () => {
	const SESSION_ID_URL = 'authentication/session/new';
	const request_token = 'your_request_token';
	const REQUEST_BODY = JSON.stringify({
		request_token
	});
	const init = {
		method  : 'POST',
		headers : {
			'Content-Type' : 'application/json;charset=utf-8'
		},
		body : REQUEST_BODY
	};
	// *Tenemos que aceptar, en nuestra cuenta de The Movie DB, la autenticación de terceros en https://www.themoviedb.org/authenticate/{request_token}
	const RESPONSE = await fetch(`${URL}/${SESSION_ID_URL}?api_key=${YOUR_API_KEY}`, init);
	const DATA = await RESPONSE.json();
	const SESSION_ID = DATA.session_id;

	return SESSION_ID;
};

Obtener account_id

const getAccountId = async () => {
	const SESSION_ID = 'your_session_id';
	const ACCOUNT_URL = 'account';
	const init = {
		method  : 'GET',
		headers : {
			'Content-Type' : 'application/json;charset=utf-8'
		},
	};
	const RESPONSE = await fetch(`${URL}/${ACCOUNT_URL}?api_key=${YOUR_API_KEY}&session_id=${SESSION_ID}`, init);
	const ACCOUNT = await RESPONSE.json();
	const ID = ACCOUNT.id;

	return ID;
};

Agregar o eliminar una película de favoritos

El parámetro favorite(boolean) es el que nos permite agregar o eliminar una película de favoritos.

favorite = true add movie.

favorite = false remove movie.

const addOrDeleteFavoriteMovie = async ({ media_id, remove = false }) => {
	// Si queremos eliminar la película de favoritos tenemos que pasar el parámetro favorite = false;
	const SESSION_ID = 'your_session_id';
	const media_type = 'movie';
	const favorite = !remove;
	const ACCOUNT_ID = await getAccountId();
	const REQUEST_BODY = JSON.stringify({
		media_type,
		media_id,
		favorite
	});
	const init = {
		method  : 'POST',
		headers : {
			'Content-Type' : 'application/json;charset=utf-8'
		},
		body : REQUEST_BODY
	};
	const RESPONSE = await fetch(`${URL}/account/${ACCOUNT_ID}/favorite?api_key=${YOUR_API_KEY}&session_id=${SESSION_ID}`, init);
	const STATUS = await RESPONSE.json();

	return STATUS;
};

Ver las películas guardadas

const getFavoriteMovies = async () => {
	const SESSION_ID = 'your_session_id';
	const ACCOUNT_ID = await getAccountId();
	const init = {
		method  : 'GET',
		headers : {
			'Content-Type' : 'application/json;charset=utf-8'
		}
	};
	const RESPONSE = await fetch(`${URL}/account/${ACCOUNT_ID}/favorite/movies?api_key=${YOUR_API_KEY}&session_id=${SESSION_ID}`);
	const DATA = await RESPONSE.json();
	const MOVIES = DATA.results;

	return MOVIES;
};

Axios

Una cosa para aclarar, el parámetro params son los query parameters y nuestro parámetro data es el body que utilizamos con fetch.

Creando instancia para usar la API

const config = {
	baseURL : 'https://api.themoviedb.org/3/',
	headers : {
		'Content-Type' : 'application/json;charset=utf-8'
	},
	params : {
		api_key : YOUR_API_KEY
	}
};

const api = axios.create(config);

Obtener request_token

const getRequestToken = async () => {
	const RESPONSE = await api('authentication/token/new');
	const DATA = RESPONSE.data;
	const REQUEST_TOKEN = DATA.request_token;

	return REQUEST_TOKEN;
};

Obtener session_id

Antes de obtener nuestro session_id tenemos que aceptar la autenticación de terceros desde nuestra cuenta de TMDB, lo realizamos desde la siguiente URL

www.themoviedb.org/authenticate/{your_request_token}.

Una vez aceptado ya podés seguir con el siguiente código.

const getSession = async () => {
	const request_token = 'your_request_token';
	const config = {
		params : { request_token }
	};
	// *Tenemos que aceptar, en nuestra cuenta de The Movie DB, la autenticación de terceros en https://www.themoviedb.org/authenticate/{request_token}
	const RESPONSE = await api('authentication/session/new', config);
	const DATA = RESPONSE.data;
	const SESSION_ID = DATA.session_id;

	return SESSION_ID;
};

Obtener account_id

const getAccountId = async () => {
	const session_id = 'your_session_id';
	const config = {
		params : { session_id }
	};
	const RESPONSE = await api('account', config);
	const ACCOUNT = RESPONSE.data;
	const ID = ACCOUNT.id;

	return ID;
};

Agregar o eliminar una película de favoritos

El parámetro favorite(boolean) es el que nos permite agregar o eliminar una película de favoritos.

favorite = true add movie.

favorite = false remove movie.

const addOrDeleteFavoriteMovie = async ({ media_id, remove = false }) => {
	// Si queremos eliminar la película de favoritos tenemos que pasar el parámetro favorite = false;
	const session_id = 'your_request_token';
	const media_type = 'movie';
	const favorite = !remove;
	const ACCOUNT_ID = await getAccountId();
	const config = {
		method : 'POST',
		params : { session_id },
		data   : {
			media_type,
			media_id,
			favorite
		}
	};
	const RESPONSE = await api(`account/${ACCOUNT_ID}/favorite`, config);
	const STATUS = RESPONSE.data;

	return STATUS;
};

Ver las películas guardadas

const getFavoriteMovies = async () => {
	const session_id = 'your_request_token';
	const ACCOUNT_ID = await getAccountId();
	const config = {
		params : { session_id }
	};
	const RESPONSE = await api(`account/${ACCOUNT_ID}/favorite/movies`, config);
	const DATA = RESPONSE.data;
	const MOVIES = DATA.results;

	return MOVIES;
};

PD: No puedo dejar los links directos a la explicación de cada sección de la página de TMDB, ya que el sistema de comentarios lo detecta como “enlace malicioso”. Si quieren mayor detalles, pueden ver directo en la página de la API.

Para actualizar la sección de favoritos siempre que se haga clic sobre el botón de corazón, modifiqué la función likeMovie(). Lo primero que creó el profesor en esa función fue una variable likedMovies que contiene a la ejecución de la función likedMoviesList(), entonces, justo después de que se reescribe la información en local storage, creé una nueva variable llamada NewLikedMovies que contiene también a la ejecución de la función likedMoviesList() pero esta vez obviamente luego de la sobreescritura. Luego establezco un condicional para que si hay diferencia entre la primera variable y la segunda, ejecute la función getLikedMovies();

Así queda la función:

function likeMovie(movie) {
  const likedMovies = likedMoviesList();

  console.log(likedMovies);

  if(likedMovies[movie.id]) {
    likedMovies[movie.id] = undefined;
    console.log('La pelicula ya esta en storage');
  } else {
    likedMovies[movie.id] = movie;
    console.log('La pelicula no esta en storage');
  }
  localStorage.setItem('liked_movies', JSON.stringify(likedMovies));

  const NewlikedMovies = likedMoviesList();

  if(likedMovies !== NewlikedMovies) {
    getLikedMovies();
  }
}

No me funcionó escuchar el evento storage, pero lo solucioné llamando a las funciones getLikedMovies y getTrendingMoviesPreview al hacer click en el botón de favoritos.

Mi solución de que los botones que están en la lista de favoritos estén con la clase de botón likeado fue simplemente preguntar si el container era el de las películas likeadas, y de ser así pues les agrega tal clase:

mi solución para recargar al hacer like o don´t like:
en el evento del botón de like le agregue estas 3 lineas de código para recargar y volver al inicio de la pantalla

<         
 window.location.reload();
             document.documentElement.scrollTop=0;
             document.body.scrollTop=0;> 

para actualizar en el momento las películas de favoritos, solo agregue dentro de createMovies, en el botón movieBtn en el evento ya existente de addEventListener a getLikeMovies() y me funciono.

Probablemente no sea la mejor, pero si fue la mas rápida en este momento…

Vaya, la solución del botón like de JD es muy sencilla y eficiente, la mía fue crear una función isMovieLiked, y retornar true o false según el caso y después agregar o quitar la clase movie-btn–liked, funcionó pero metí código innecesario y una función que prácticamente repite lo que hace otra. Me falta experiencia.

Sobre el reto, pues la solución de @Jonathan Alfonso es la mejor. Intenté hacer algo escuchando con el MutationObserver modificaciones en aquellos lugares que cambian con los likes, pero me genera muchos.

Saludos.

Hice algo muy, pero, muy sencillo.

Solo mandé a llamar la función **getLikedMovies ** en el evento del botón de like. ❤

No sabía cuál era el problema hasta que vi que tenía un data.results :v ![](https://static.platzi.com/media/user_upload/image-b3435002-90cb-4313-9082-6fc28f517016.jpg)
Yo lo solucioné solamente llamando la función getLikedMovies(), dentro de la función likeMovie(movie).
min 16:30 al dar al boton de click en favoritos desencadena la logica de local storage que a su vez renderiza las nuevas imgs ![](https://static.platzi.com/media/user_upload/image-df4d33b2-b3f9-4059-9f76-8752554fcf6a.jpg)
min 12 implemente una logica similar ![](https://static.platzi.com/media/user_upload/image-cb15f58e-4919-4d65-b5ff-e1323c472d1b.jpg)
asi min 4:30 ![](https://static.platzi.com/media/user_upload/image-c5c91995-7cb2-4c48-9df3-825e4c0e6051.jpg)
Yo lo resolvi poniendo la function getLikedMovies() dentro del eventListener de like y borrando todo el contenido de #liked con innerHtml ='' dentro de la funcion movieBtn.addEventListener('click', ()=>{      movieBtn.classList.toggle('movie-btn--liked')       likeMovie(*movie*);      getLikedMovies()    })```js movieBtn.addEventListener('click', ()=>{ movieBtn.classList.toggle('movie-btn--liked') likeMovie(movie); getLikedMovies() }) ``` ```js function getLikedMovies(){ const likedMovies = likedMoviesList() // nos ayuda a convertir objetos en arrays likedMoviesListArticle.innerHTML ='' const moviesArray = Object.values(likedMovies) createMovies( moviesArray, likedMoviesListArticle, {lazyLoad : true, clean : true }) console.log(likedMovies) } ```function getLikedMovies(){  const likedMovies = likedMoviesList()   *// nos ayuda a convertir objetos en arrays*  likedMoviesListArticle.innerHTML =''  const moviesArray = Object.values(likedMovies)   createMovies( moviesArray, likedMoviesListArticle, {lazyLoad : true, clean : true })   console.log(likedMovies) }
De esto hablaba en mi post anterior ![](https://static.platzi.com/media/user_upload/image-58c68942-45d4-403e-adeb-1322715c2d6f.jpg)

Llegaste aquí

ERES UN CRACK

Siguiente paso:

REACT O ALGÚN FRAMEWORK

Lo único que hice fue insertar getLikedMovies() en el evento click del botón de dar like y listo. Me pareció la solución más sencilla.

    movieBtn.classList.add('movie-btn');
    likedMoviesList()[movie.id] && movieBtn.classList.add('movie-btn--liked')
    movieBtn.addEventListener('click', () => {
      movieBtn.classList.toggle('movie-btn--liked');
      likeMovie(movie);
      getLikedMovies(); // Solo inserté esta línea
    });
    
    if(lazyLoad) {
      lazyLoader.observe(movieImg);
    }
  

Mi propuesta

Repositorio commit actual: Click Aquí

.

Funcionalidades:

  • Almacenamiento de los datos de movies en un array con objetos en el local storage
  • Si le damos like verifica si ya está en el storage por si hay error
  • Si damos like me lo agrega de forma dinámica a la lista de favoritos desde cualquier sección
  • Si damos dislike me lo elimina de la lista de favorita desde cualquier sección
  • Cargar lista de favoritos al iniciar la sección de home
    .

Por hacer

  • Cargar los likes de todas las movies al cargar la sección consultando al local storage
  • Si doy dislike desde la sección de favorito actualizar ese dislike en trending movies en el home