refactored Search component

This commit is contained in:
andres alcocer
2021-10-08 17:42:00 -04:00
parent d77db5757b
commit 0266ed339c
7 changed files with 151 additions and 162 deletions

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react'
import React, { useState, useEffect, useRef } from 'react'
import { NavLink } from 'react-router-dom'
import { withRouter } from 'react-router-dom'
@@ -10,6 +10,7 @@ import DropdownArrow from '../static/images/drop-down-arrow.svg'
import DropdownContent from '../components/DropdownContent'
const Navbar = ({ history }) => {
const searchInput = React.useRef(null)
const [userInput, setUserInput] = useState('')
const [scrollDimensions] = useScroll()
const { scrollY } = scrollDimensions
@@ -19,10 +20,14 @@ const Navbar = ({ history }) => {
}
useEffect(() => {
userInput.length <= 0
? history.push('/')
: history.push(`/search?q=${userInput}`)
}, [userInput])
if (
document.activeElement === searchInput.current &&
userInput.length === 0
) {
history.push('/browse')
}
if (userInput.length > 0) history.push(`/search?q=${userInput}`)
}, [userInput, searchInput])
const onLogoClick = () => {
setUserInput('')
@@ -50,6 +55,7 @@ const Navbar = ({ history }) => {
<div className='navigation__container--left'>
<SearchLogo className='logo' />
<input
ref={searchInput}
value={userInput}
onChange={(event) => onChange(event)}
className='navigation__container--left__input'

View File

@@ -6,8 +6,10 @@ const Modal = ({
show,
modalClosed,
children,
movie,
movie: { backdrop_path, poster_path },
}) => {
console.log('Modal.movie', movie)
const backgroundStyle = {
backgroundSize: 'cover',
backgroundImage: `url(https://image.tmdb.org/t/p/original/${

View File

@@ -3,10 +3,10 @@ import { useLocation } from 'react-router-dom'
import { useDispatch, useSelector } from 'react-redux'
import { useDebounce } from '../hooks/useDebounce'
import * as movieActions from '../store/actions'
import Modal from '../components/UI/Modal'
import MovieDetails from '../components/Movie/MovieDetails'
import Movie from '../components/Movie/Movie'
import axios from '../axios-movies'
// A custom hook that builds on useLocation to parse
// the query string for you.
@@ -14,171 +14,80 @@ const useQuery = () => {
return new URLSearchParams(useLocation().search)
}
const Search = ({ history }) => {
const Search = () => {
let query = useQuery()
const debouncedSearchTerm = useDebounce(query.get('q'), 500)
const [isToggleModal, setIsToggleModal] = useState(false)
const searchResults = useSelector((state) => state.searchMovie)
const { searchResults, isLoading } = useSelector((state) => state.searchMovie)
const { movieDetails } = useSelector((state) => state.movieDetails)
const dispatch = useDispatch()
// constructor(props) {
// super(props)
// this.state = {
// movies: [],
// toggleModal: false,
// /** Holds the movie information for a single movie. */
// movieOverview: {},
// }
// }
useEffect(() => {
if (debouncedSearchTerm) {
console.log('maing api call....')
dispatch(movieActions.fetchSearchMovie(debouncedSearchTerm))
}
}, [debouncedSearchTerm])
console.log('location', query.get('q'))
// componentDidMount = async () => {
// console.log('movie roww', movieRows)
// const { movieRows } = this.props.history.location;
// if (movieRows) {
// await this.setState({ movies: movieRows });
// }
// }
// useEffect(() => {
// if (!userInput) {
// console.log('Search.useEffect()')
// history.push('/')
// }
// }, [userInput])
// useEffect(() => {
// console.log('searchResults', searchResults)
// }, [searchResults])
// componentDidUpdate = async (prevProps) => {
// console.log('hiiiiiii')
// if (
// prevProps.location.movieRows.length !==
// this.props.location.movieRows.length
// ) {
// await this.setState({ movies: this.props.location.movieRows });
// }
// }
const closeModal = () => {
const onCloseModalHandler = () => {
setIsToggleModal(false)
}
// /* Get the appropriate details for a specific movie that was clicked */
// selectMovieHandler = (movie) => {
// this.setState({ toggleModal: true });
const onSelectMovieHandler = (movie) => {
dispatch(movieActions.fetchMovieDetails(movie.media_type, movie.id))
setIsToggleModal(true)
}
// let url;
// /** Make the appropriate API call to get the details for a single movie or tv show. */
// if (movie.media_type === "movie") {
// const movieId = movie.id;
// url = `https://api.themoviedb.org/3/movie/${movieId}?api_key=${process.env.API_KEY}`;
const renderSearchResults = () => {
return searchResults.length > 0 ? (
<>
<div className='search-container'>
{searchResults.map((movie) => {
let movieRows = []
let movieImageUrl
if (movie.poster_path !== null && movie.media_type !== 'person') {
movieImageUrl =
'https://image.tmdb.org/t/p/w500' + movie.poster_path
const movieComponent = (
<Movie
movieDetails={() => onSelectMovieHandler(movie)}
key={movie.id}
movieImage={movieImageUrl}
movie={movie}
/>
)
movieRows.push(movieComponent)
}
return movieRows
})}
</div>
<Modal
Modal
show={isToggleModal}
modalClosed={onCloseModalHandler}
movie={movieDetails}
>
<MovieDetails movie={movieDetails} />
</Modal>
</>
) : (
<div className='no-results'>
<div className='no-results__text'>
<p>
Your search for "{debouncedSearchTerm}" did not have any matches.
</p>
<p>Suggestions:</p>
<ul>
<li>Try different keywords</li>
<li>Looking for a movie or TV show?</li>
<li>Try using a movie, TV show title, an actor or director</li>
<li>Try a genre, like comedy, romance, sports, or drama</li>
</ul>
</div>
</div>
)
}
// } else if (movie.media_type === "tv") {
// const tvId = movie.id
// url = `https://api.themoviedb.org/3/tv/${tvId}?api_key=${process.env.API_KEY}`;
// }
// axios.get(url)
// .then(res => {
// const movieData = res.data;
// this.setState({ movieOverview: movieData });
// }).catch(error => {
// console.log(error);
// });
// }
// const { movies } = this.state
// const { userInput } = this.props.location
// console.log('search().render()', this.props.history.location)
return <h1>hello</h1>
// searchResults === undefined ? (
// <Redirect to='/' />
// ) : (
// <div className='search-container'>
// {searchResults.map((movie) => {
// let movieRows = []
// let movieImageUrl
// if (movie.poster_path !== null && movie.media_type !== 'person') {
// movieImageUrl = 'https://image.tmdb.org/t/p/w500' + movie.poster_path
// /** Set the movie object to our Movie component */
// const movieComponent = (
// <Movie
// // movieDetails={() => this.selectMovieHandler(movie)}
// key={movie.id}
// movieImage={movieImageUrl}
// movie={movie}
// />
// )
// /** Push our movie component to our movieRows array */
// movieRows.push(movieComponent)
// }
// return movieRows
// })}
// </div>
// )
// <>
// {searchResults && searchResults.data.length > 0 ? (
// <div className='search-container'>
// {searchResults.map((movie) => {
// let movieRows = []
// let movieImageUrl
// if (movie.poster_path !== null && movie.media_type !== 'person') {
// movieImageUrl =
// 'https://image.tmdb.org/t/p/w500' + movie.poster_path
// /** Set the movie object to our Movie component */
// const movieComponent = (
// <Movie
// // movieDetails={() => this.selectMovieHandler(movie)}
// key={movie.id}
// movieImage={movieImageUrl}
// movie={movie}
// />
// )
// /** Push our movie component to our movieRows array */
// movieRows.push(movieComponent)
// }
// return movieRows
// })}
// </div>
// ) : (
// <div className='no-results'>
// <div className='no-results__text'>
// <p>Your search for "{userInput}" did not have any matches.</p>
// <p>Suggestions:</p>
// <ul>
// <li>Try different keywords</li>
// <li>Looking for a movie or TV show?</li>
// <li>Try using a movie, TV show title, an actor or director</li>
// <li>Try a genre, like comedy, romance, sports, or drama</li>
// </ul>
// </div>
// </div>
// )}
/* <Modal
Modal
show={isToggleModal}
modalClosed={closeModal}
// movie={this.state.movieOverview}
> */
/* <MovieDetails movie={this.state.movieOverview} /> */
/* </Modal> */
// </>
return !isLoading ? renderSearchResults() : <h1>Loading...</h1>
}
export default Search

View File

@@ -1,7 +1,6 @@
import axios from '../../axios-movies'
export const FETCH_HEADER_MOVIE = 'FETCH_HEADER_MOVIE'
export const FETCH_SEARCH_MOVIE = 'FETCH_SEARCH_MOVIE'
export const FETCH_TRENDING = 'FETCH_TRENDING'
export const FETCH_NETFLIX_ORIGINALS = 'FETCH_NETFLIX_ORIGINALS'
export const FETCH_TOP_RATED = 'FETCH_TOP_RATED'
@@ -10,15 +9,49 @@ export const FETCH_COMEDY_MOVIES = 'FETCH_COMEDY_MOVIES'
export const FETCH_HORROR_MOVIES = 'FETCH_HORROR_MOVIES'
export const FETCH_ROMANCE_MOVIES = 'FETCH_ROMANCE_MOVIES'
export const FETCH_DOCUMENTARIES = 'FETCH_DOCUMENTARIES'
// movie details
export const FETCH_MOVIE_DETAILS = 'FETCH_MOVIE_DETAILS'
export const FETCH_MOVIE_DETAILS_SUCCESS = 'FETCH_MOVIE_DETAILS_SUCCESS'
export const FETCH_MOVIE_DETAILS_FAIL = 'FETCH_MOVIE_DETAILS_FAIL'
// search
export const FETCH_SEARCH_MOVIE = 'FETCH_SEARCH_MOVIE'
export const FETCH_SEARCH_MOVIE_FAIL = 'FETCH_SEARCH_MOVIE_FAIL'
export const FETCH_SEARCH_MOVIE_SUCCESS = 'FETCH_SEARCH_MOVIE_SUCCESS'
const media_type = {
tv: 'tv',
movie: 'movie',
}
export const fetchMovieDetails = (mediaType, mediaId) => {
return async (dispatch) => {
try {
dispatch({ type: FETCH_MOVIE_DETAILS })
let urlPath
if (mediaType === media_type.movie)
urlPath = `/movie/${mediaId}?api_key=${process.env.API_KEY}`
if (mediaType === media_type.tv)
urlPath = `/tv/${mediaId}?api_key=${process.env.API_KEY}`
const request = await axios.get(urlPath)
dispatch({ type: FETCH_MOVIE_DETAILS_SUCCESS, payload: request })
} catch (error) {
console.log('error', error)
dispatch({ type: FETCH_MOVIE_DETAILS_FAIL })
}
}
}
export const fetchSearchMovie = (searchTerm) => {
return async (dispatch) => {
try {
dispatch({ type: FETCH_SEARCH_MOVIE })
const request = await axios.get(
`/search/multi?api_key=${process.env.API_KEY}&language=en-US&include_adult=false&query=${searchTerm}`
)
dispatch({ type: FETCH_SEARCH_MOVIE, payload: request })
dispatch({ type: FETCH_SEARCH_MOVIE_SUCCESS, payload: request })
} catch (error) {
dispatch({ type: FETCH_SEARCH_MOVIE_FAIL })
console.log('error', error)
}
}

View File

@@ -9,6 +9,7 @@ import RomanceMoviesReducer from './reducerRomanceMovies'
import DocumentaryReducer from './reducerDocumentary'
import HeaderMovieReducer from './reducerHeaderMovie'
import SearchMovieReducer from './reducerSearchMovie'
import MovieDetailsReducer from './reducerMovieDetails'
const rootReducer = combineReducers({
trending: TrendingReducer,
@@ -21,6 +22,7 @@ const rootReducer = combineReducers({
documentary: DocumentaryReducer,
headerMovie: HeaderMovieReducer,
searchMovie: SearchMovieReducer,
movieDetails: MovieDetailsReducer,
})
export default rootReducer

View File

@@ -0,0 +1,24 @@
import {
FETCH_MOVIE_DETAILS,
FETCH_MOVIE_DETAILS_SUCCESS,
FETCH_MOVIE_DETAILS_FAIL,
} from '../actions/index'
const initialState = {
isLoading: false,
movieDetails: [],
}
export default function (state = initialState, action) {
switch (action.type) {
case FETCH_MOVIE_DETAILS:
return { ...state, isLoading: true }
case FETCH_MOVIE_DETAILS_FAIL:
return { ...state, isLoading: false }
case FETCH_MOVIE_DETAILS_SUCCESS:
const movieDetails = action.payload.data
return { ...state, movieDetails, isLoading: false }
default:
return state
}
}

View File

@@ -1,10 +1,23 @@
import { FETCH_SEARCH_MOVIE } from '../actions/index'
import {
FETCH_SEARCH_MOVIE,
FETCH_SEARCH_MOVIE_FAIL,
FETCH_SEARCH_MOVIE_SUCCESS,
} from '../actions/index'
export default function (state = {}, action) {
const initialState = {
isLoading: false,
searchResults: [],
}
export default function (state = initialState, action) {
switch (action.type) {
case FETCH_SEARCH_MOVIE:
const data = action.payload.data.results
return { ...state, data }
return { ...state, isLoading: true }
case FETCH_SEARCH_MOVIE_FAIL:
return { ...state, isLoading: false }
case FETCH_SEARCH_MOVIE_SUCCESS:
const searchResults = action.payload.data.results
return { ...state, searchResults, isLoading: false }
default:
return state
}