import React from 'react'; import MovieObject from './MovieObject.jsx'; // StyleComponents import searchStyle from './styles/searchRequestStyle.jsx'; import movieStyle from './styles/movieObjectStyle.jsx'; import URI from 'urijs'; import InfiniteScroll from 'react-infinite-scroller'; var MediaQuery = require('react-responsive'); // TODO add option for searching multi, movies or tv shows class SearchRequest extends React.Component { constructor(props){ super(props) // Constructor with states holding the search query and the element of reponse. this.state = { lastApiCallURI: '', searchQuery: '', responseMovieList: null, movieFilter: false, showFilter: false, discoverType: '', page: 1, resultHeader: '', loadResults: false, scrollHasMore: true } this.allowedListTypes = [ 'discover', 'popular', 'nowplaying', 'upcoming' ] this.baseUrl = 'https://apollo.kevinmidboe.com/api/v1/tmdb/'; // this.baseUrl = 'http://localhost:31459/api/v1/tmdb/'; this.URLs = { searchRequest: 'https://apollo.kevinmidboe.com/api/v1/plex/request', // searchRequest: 'http://localhost:31459/api/v1/plex/request', upcoming: 'https://apollo.kevinmidboe.com/api/v1/tmdb/upcoming', // upcoming: 'http://localhost:31459/api/v1/tmdb/upcoming', sendRequest: 'https://apollo.kevinmidboe.com/api/v1/plex/request?query=' // sendRequest: 'http://localhost:31459/api/v1/plex/request?query=' } } componentDidMount(){ var that = this; // this.setState({responseMovieList: null}) this.resetPageNumber(); this.state.loadResults = true; this.fetchTmdbList('upcoming'); } // Handles all errors of the response of a fetch call handleErrors(response) { if (!response.ok) throw Error(response.status); return response; } handleQueryError(response) { if (!response.ok) { if (response.status === 404) { this.setState({ responseMovieList:

Nothing found for search query: { this.findQueryInURI(uri) }

}) } console.log('handleQueryError: ', error); } return response; } // Unpacks the query value of a uri findQueryValueInURI(uri) { let uriSearchValues = uri.query(true); let queryValue = uriSearchValues['query'] return queryValue; } // Unpacks the page value of a uri findPageValueInURI(uri) { let uriSearchValues = uri.query(true); let queryValue = uriSearchValues['page'] return queryValue; } resetPageNumber() { this.state.page = 1; } writeLoading() { this.setState({ responseMovieList: 'Loading...' }); } // Test this by calling missing endpoint or 404 query and see what code // and filter the error message based on the code. // Calls a uri and returns the response as json callURI(uri) { return fetch(uri) .then(response => { return response }) .catch(error => { throw Error('Something went wrong while fetching URI.'); }); } // Saves the input string as a h1 element in responseMovieList state fillResponseMovieListWithError(msg) { this.setState({ responseMovieList:

{ msg }

}) } // Here we first call api for a search with the input uri, handle any errors // and fill the reponseData from api into the state of reponseMovieList as movieObjects callSearchFillMovieList(uri) { // Write loading animation // this.writeLoading(); Promise.resolve() .then(() => this.callURI(uri)) .then(response => { // If we get a error code for the request if (!response.ok) { if (response.status === 404) { if (this.findPageValueInURI(new URI(response.url)) > 1) { this.state.scrollHasMore = false; console.log(this.state.scrollHasMore) return null let returnMessage = 'this is the return mesasge than will never be delivered' let theSecondReturnMsg = 'this is the second return messag ethat will NEVE be delivered' } else { let errorMsg = 'Nothing found for the search query: ' + this.findQueryValueInURI(uri); this.fillResponseMovieListWithError(errorMsg) } } else { let errorMsg = 'Error fetching query from server ' + this.response.status; this.fillResponseMovieListWithError(errorMsg) } } // Convert to json and update the state of responseMovieList with the results of the api call // mapped as a movieObject. response.json() .then(responseData => { if (this.state.page === 1) { this.setState({ responseMovieList: responseData.results.map((searchResultItem, index) => this.createMovieObjects(searchResultItem, index)), lastApiCallURI: uri // Save the value of the last sucessfull api call }) } else { let responseMovieObjects = responseData.results.map((searchResultItem, index) => this.createMovieObjects(searchResultItem, index)); let growingReponseMovieObjectList = this.state.responseMovieList.concat(responseMovieObjects); this.setState({ responseMovieList: growingReponseMovieObjectList, lastApiCallURI: uri // Save the value of the last sucessfull api call }) } }) .catch((error) => { console.log('CallSearchFillMovieList: ', error) }) }) .catch(() => { throw Error('Something went wrong when fetching query.') }) } callListFillMovieList(uri) { // Write loading animation // this.writeLoading(); Promise.resolve() .then(() => this.callURI(uri)) .then(response => { // If we get a error code for the request if (!response.ok) { if (response.status === 404) { let errorMsg = 'List not found'; this.fillResponseMovieListWithError(errorMsg) } else { let errorMsg = 'Error fetching list from server ' + this.response.status; this.fillResponseMovieListWithError(errorMsg) } } // Convert to json and update the state of responseMovieList with the results of the api call // mapped as a movieObject. response.json() .then(responseData => { if (this.state.page === 1) { this.setState({ responseMovieList: responseData.results.map((searchResultItem, index) => this.createMovieObjects(searchResultItem, index)), lastApiCallURI: uri // Save the value of the last sucessfull api call }) } else { let responseMovieObjects = responseData.results.map((searchResultItem, index) => this.createMovieObjects(searchResultItem, index)); let growingReponseMovieObjectList = this.state.responseMovieList.concat(responseMovieObjects); this.setState({ responseMovieList: growingReponseMovieObjectList, lastApiCallURI: uri // Save the value of the last sucessfull api call }) } }) }) .catch(() => { throw Error('Something went wrong when fetching query.') }) } searchSeasonedRequest() { this.state.resultHeader = 'Search result for: ' + this.state.searchQuery; // Build uri with the url for searching requests var uri = new URI(this.URLs.searchRequest); // Add input of search query and page count to the uri payload uri = uri.search({ 'query': this.state.searchQuery, 'page': this.state.page }); if (this.state.showFilter) uri = uri.addSearch('type', 'show'); else if (this.state.movieFilter) uri = uri.addSearch('type', 'movie') // Send uri to call and fill the response list with movie/show objects this.callSearchFillMovieList(uri); } fetchTmdbList(tmdbListType) { console.log(tmdbListType) // Check if it is a whitelisted list, this should be replaced with checking if the return call is 500 if (this.allowedListTypes.indexOf(tmdbListType) === -1) throw Error('Invalid discover type: ' + tmdbListType); this.state.responseMovieList = [] // Captialize the first letter of and save the discoverQueryType to resultHeader state. this.state.resultHeader = tmdbListType.toLowerCase().replace(/\b[a-z]/g, function(letter) { return letter.toUpperCase(); }); // Build uri with the url for searching requests var uri = new URI(this.baseUrl); uri.segment(tmdbListType); // Add input of search query and page count to the uri payload uri = uri.search({ 'page': this.state.page }); if (this.state.showFilter) uri = uri.addSearch('type', 'show'); // Send uri to call and fill the response list with movie/show objects this.callListFillMovieList(uri); } // Updates the internal state of the query search field. updateQueryState(event){ this.setState({ searchQuery: event.target.value }); } // For checking if the enter key was pressed in the search field. _handleQueryKeyPress(e) { if (e.key === 'Enter') { // this.fetchQuery(); // Reset page number for a new search this.resetPageNumber(); this.searchSeasonedRequest(); } } // When called passes the variable to MovieObject and calls it's interal function for // generating the wanted HTML createMovieObjects(item, index) { let movie = new MovieObject(item); return movie.getElement(index); } toggleFilter(filterType) { if (filterType == 'movies') { this.setState({ movieFilter: !this.state.movieFilter }) console.log(this.state.movieFilter); } else if (filterType == 'shows') { this.setState({ showFilter: !this.state.showFilter }) console.log(this.state.showFilter); } } pageBackwards() { if (this.state.page > 1) { let pageNumber = this.state.page - 1; let uri = this.state.lastApiCallURI; // Augment the page number of the uri with a callback uri.search(function(data) { data.page = pageNumber; }); // Call the api with the new uri this.callSearchFillMovieList(uri); // Update state of our page number after the call is done this.state.page = pageNumber; } } // TODO need to get total page number and save in a state to not overflow pageForwards() { // Wrap this in the check let pageNumber = this.state.page + 1; let uri = this.state.lastApiCallURI; // Augment the page number of the uri with a callback uri.search(function(data) { data.page = pageNumber; }); // Call the api with the new uri this.callSearchFillMovieList(uri); // Update state of our page number after the call is done this.state.page = pageNumber; } movieToggle() { if (this.state.movieFilter) return {this.toggleFilter('movies')}} id="category_active">Movies else return {this.toggleFilter('movies')}} id="category_active">Movies } showToggle() { if (this.state.showFilter) return {this.toggleFilter('shows')}} id="category_active">TV Shows else return {this.toggleFilter('shows')}} id="category_active">TV Shows } render(){ const loader =
Loading ...

; return(
Request new content
this._handleQueryKeyPress(event)} onChange={event => this.updateQueryState(event)} value={this.state.searchQuery}/>
{this.state.resultHeader}



{this.state.responseMovieList}
Request new content
this._handleQueryKeyPress(event)} onChange={event => this.updateQueryState(event)} value={this.state.searchQuery}/>
{this.state.resultHeader}



{this.state.responseMovieList}
) } } export default SearchRequest;