Aplicación web de películas con ReactJS

Este artículo cubre cómo hacer una aplicación de película totalmente receptiva y elegante con React . React es un marco de JavaScript proporcionado por Facebook y se utiliza para crear aplicaciones web con todas las funciones. 

Seguiremos los siguientes pasos para crear nuestra aplicación:

Paso 1: Crear el proyecto: Comenzaremos creando un nuevo proyecto de reacción usando la herramienta create-react-app. Puede usar el siguiente comando para crear uno con el nombre deseado. Asegúrese de que Node y npm estén instalados en el sistema.

npx create-react-app movie-app

Estructura del proyecto: A continuación, eliminaremos todos los archivos que no sean necesarios. La estructura de archivos después de eliminar los archivos se muestra a continuación:

Paso 2: Abra la carpeta «src» y seleccione el archivo App.js y agregue el siguiente código.

App.js

import React, { useState } from "react";
import axios from "axios";
import Search from "./components/Search";
import Results from "./components/Results";
import Detail from "./components/Detail";
import "./App.css";
  
function App() {
  const [state, setState] = useState({
    s: "sherlock",
    results: [],
    selected: {},
  });
  
  const apiurl = "https://www.omdbapi.com/?apikey=a2526df0";
  
  const searchInput = (e) => {
    let s = e.target.value;
  
    setState((prevState) => {
      return { ...prevState, s: s };
    });
  };
  
  const search = (e) => {
    if (e.key === "Enter") {
      axios(apiurl + "&s=" + state.s).then(({ data }) => {
        let results = data.Search;
  
        console.log(results);
  
        setState((prevState) => {
          return { ...prevState, results: results };
        });
      });
    }
  };
  
  const openDetail = (id) => {
    axios(apiurl + "&i=" + id).then(({ data }) => {
      let result = data;
  
      setState((prevState) => {
        return { ...prevState, selected: result };
      });
    });
  };
  
  const closeDetail = () => {
    setState((prevState) => {
      return { ...prevState, selected: {} };
    });
  };
  
  return (
    <div className="App">
      <header className="App-header">
        <h1>Movie Mania</h1>
      </header>
      <main>
        <Search searchInput={searchInput} search={search} />
  
        <Results results={state.results} openDetail={openDetail} />
  
        {typeof state.selected.Title != "undefined" ? (
          <Detail selected={state.selected} closeDetail={closeDetail} />
        ) : (
          false
        )}
      </main>
    </div>
  );
}
  
export default App;

App.css

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
  
body {
  font-family: "montserrat", sans-serif;
  background: linear-gradient(to right, #000428, #004e92);
}
  
header {
  width: 100%;
  padding-top: 2rem;
  padding-bottom: 1rem;
}
  
header h1 {
  color: #ffffff;
  font-size: 4rem;
  font-weight: 700;
  text-align: center;
}
  
main {
  width: 100%;
  max-width: 90%;
  margin: 0 auto;
}
  
.results {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  /* margin: 0 -15px; */
}
  
.results .result {
  width: 20%;
  min-width: 250px;
  background: #000000;
  max-height: 500px;
  /* padding: 15px; */
  margin: 20px 25px;
  display: flex;
  flex-direction: column;
  cursor: pointer;
}
  
.results .not-found {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  margin: 2rem 0.5rem;
}
  
.results .not-found h2 {
  color: #ffffff;
}
  
.results .result img {
  /* display: block; */
  width: 100%;
  padding: 10px 2px;
  margin: 0 auto;
  height: 350px;
  width: 230px;
}
  
.results .result h3 {
  color: #fff;
  font-size: 20px;
  font-weight: 600;
  width: 100%;
  text-align: center;
  padding: 1rem;
  background: #272829;
  flex: 1 100%;
  transition: 0.4s ease-out;
}
  
.result:hover {
  box-shadow: 0 0 8px 3px #eaf0f7;
  /* background: #dfd8d8; */
}
  
.results .result h3:hover {
  background: #fff;
  color: #223343;
  box-shadow: 0 0 8px 3px #4484c4;
}
  
.detail {
  margin: 3rem 5rem;
  overflow-y: scroll;
}
  
.detail .content .rating {
  margin-left: 2rem;
  font-size: 1.5rem;
  margin-bottom: 0;
  margin-top: 1rem;
  padding-bottom: 0;
}
  
.detail .content {
  display: block;
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  max-width: 15000px;
  /* max-height: 600px; */
  padding: 25px;
  background: #000000;
  color: #fff;
  overflow-y: scroll;
}
  
.detail .content h2 {
  font-size: 3rem;
  padding: 2rem;
  padding-top: 0;
  padding-bottom: 0.5rem;
  font-weight: 600;
}
  
.detail .content span {
  font-size: 1.4rem;
  margin-left: 2rem;
  margin-bottom: 3rem;
  font-weight: 300;
  color: #ffffff;
}
  
.detail .content .rating {
  margin-bottom: 30px;
}
  
.detail .content .about {
  display: flex;
  flex-wrap: wrap;
  margin: 0 -15px 30px;
}
  
.detail .content .about img {
  flex: 1 1 50%;
  max-width: 300px;
  opacity: none;
  padding: 0 15px;
  margin-left: 2rem;
  margin-top: 1rem;
}
  
.detail .content .about p {
  flex: 1 50%;
  padding: 15px 25px;
  margin-top: 3rem;
  font-size: 1.5rem;
}
  
.detail .content .close {
  /* display: inline-block; */
  padding: 15px 30px;
  font-size: 18px;
  /* margin-top: 3rem;
  margin-right: 2rem;
  margin-bottom: 1rem; */
  font-weight: 700;
  background: #223343;
  color: #fff;
  /* border-radius: 8px; */
  border: none;
  outline: none;
  appearance: none;
  cursor: pointer;
  transition: 0.4s ease-out;
  
  width: 100%;
  display: flex;
  margin: auto;
  margin-top: 5rem;
  justify-content: center;
  align-items: center;
  border-radius: 5px;
}
  
.detail .content button:hover {
  background: #4484c4;
}
  
.detail .content .about .close:hover {
  background: #223343;
}
  
@media screen and (max-width: 1015px) {
  .results {
    justify-content: center;
    align-items: center;
  }
  
  .detail .content .close {
    width: 100%;
    display: flex;
    margin: auto;
    justify-content: center;
    align-items: center;
    border-radius: 5px;
  }
}
  
@media screen and (max-width: 683px) {
  .results {
    justify-content: center;
    align-items: center;
  }
  
  .results .result {
    margin: 10px;
    justify-content: center;
    align-items: center;
  }
}
  
@media screen and (max-width: 643px) {
  .results .result {
    margin: 15px;
  }
}
  
@media screen and (max-width: 638px) {
  .results .result {
    margin: 8px;
  }
}
  
@media screen and (max-width: 410px) {
  header h1 {
    font-size: 2.9rem;
  }
  
  .results {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  }
  
  .detail {
    overflow-y: scroll;
  }
  
  .detail .content .close {
    width: 100%;
    display: flex;
    margin: auto;
    justify-content: center;
    align-items: center;
    border-radius: 5px;
  }
  
  .detail .content span {
    margin-left: 0.5rem;
    font-style: italic;
    font-weight: bold;
  }
  
  .detail .content h2 {
    padding-left: 0.5rem;
    font-size: 2.1rem;
    margin-bottom: 0.5rem;
    font-weight: 100;
  }
  
  .detail .content .rating {
    margin-left: 0.5rem;
    font-weight: bold;
  }
  
  .detail .content .about img {
    margin-left: 0.5rem;
  }
}

 

Paso 3: Cree una nueva carpeta llamada Componentes en su carpeta src . En la carpeta src, cree archivos: Detail.js , Result.js , Results.js , Search.js y Search.css

Paso 4: Ahora agregue los siguientes códigos en los archivos respectivos.

Detail.js

import React from "react";
  
function Detail({ selected, closeDetail }) {
  return (
    <section className="detail">
      <div className="content">
        <h2>{selected.Title}</h2>
        <span>{selected.Year}</span>
        <p className="rating">Rating: {selected.imdbRating}</p>
  
        <div className="about">
          <img src={selected.Poster} alt="" />
            
<p>{selected.Plot}</p>
  
        </div>
        <button className="close" onClick={closeDetail}>
          Close
        </button>
      </div>
    </section>
  );
}
  
export default Detail;

Result.js

import React from "react";
  
function Result({ result, openDetail }) {
  return (
    <div className="result" onClick=
        {() => openDetail(result.imdbID)}>
      <img src={result.Poster} />
      <h3>{result.Title}</h3>
    </div>
  );
}
  
export default Result;

Results.js

import React from "react";
import Result from "./Result";
  
function Results({ results, openDetail }) {
  return (
    <section className="results">
      {typeof results != "undefined" ? (
        results.map((result) => (
          <Result key={result.imdbID} result
              ={result} openDetail={openDetail} />
        ))
      ) : (
        <div className="not-found">
          <h2>Sorry.. Movie not found in the database.</h2>
          <h2>
              Try checking the name you input 
            or search for another movie.
          </h2>
        </div>
      )}
    </section>
  );
}
  
export default Results;

Search.js

import React from "react";
import "./Search.css";
  
function Search({ searchInput, search }) {
  return (
    <div className="search-bar">
      <input
        type="text"
        placeholder="Search for a Movie..."
        className="search"
        onChange={searchInput}
        onKeyPress={search}
      />
    </div>
  );
}
  
export default Search;

Search.css

.search-bar {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 1rem 0;
}
  
.search {
  width: 60%;
  display: block;
  padding: 15px;
  border: none;
  outline: none;
  background: none;
  background-color: #fff;
  border-radius: 8px;
  color: dimgrey;
  font-size: 20px;
  font-weight: 300;
  transition: 0.4s ease-out;
}
  
.search:focus {
  box-shadow: 0 0 8px 3px #4484c4;
}
  
@media screen and (max-width: 685px) {
  .search {
    width: 75%;
  }
}
  
@media screen and (max-width: 410px) {
  .search {
    width: 85%;
  }
}

Paso 5: Ejecutar y construir la aplicación: Podemos ejecutar esta aplicación usando el siguiente comando. Esto iniciará el servidor de desarrollo de React que se puede usar para depurar nuestra aplicación.

npm run start

Salida: Verá la siguiente salida en la pantalla de su navegador.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *