diff --git a/client/app/components/SearchRequest.jsx b/client/app/components/SearchRequest.jsx index 7bed5a9..2f5c31b 100644 --- a/client/app/components/SearchRequest.jsx +++ b/client/app/components/SearchRequest.jsx @@ -4,6 +4,7 @@ import MovieObject from './MovieObject.jsx'; // StyleComponents import searchStyle from './styles/searchRequestStyle.jsx'; +import movieStyle from './styles/movieObjectStyle.jsx' import URI from 'urijs'; @@ -13,23 +14,25 @@ class SearchRequest extends React.Component { super(props) // Constructor with states holding the search query and the element of reponse. this.state = { + lastApiCallURI: '', searchQuery: '', responseMovieList: null, movieFilter: true, showFilter: false, discoverType: '', - page: 1 + page: 1, + resultHeader: '' } - this.allowedDiscoverTypes = [ + this.allowedListTypes = [ 'discover', 'popular', 'nowplaying', 'upcoming' ] - this.baseUrl = 'https://apollo.kevinmidboe.com/api/v1/tmdb'; + this.baseUrl = 'https://apollo.kevinmidboe.com/api/v1/tmdb/'; // this.baseUrl = 'http://localhost:31459/api/v1/tmdb/'; this.URLs = { - request: 'https://apollo.kevinmidboe.com/api/v1/plex/request?page='+this.state.page+'&query=', + searchRequest: 'https://apollo.kevinmidboe.com/api/v1/plex/request', // request: 'http://localhost:31459/api/v1/plex/request?page='+this.state.page+'&query=', upcoming: 'https://apollo.kevinmidboe.com/api/v1/tmdb/upcoming', // upcoming: 'http://localhost:31459/api/v1/tmdb/upcoming', @@ -45,26 +48,125 @@ class SearchRequest extends React.Component { this.fetchDiscover('upcoming'); } - // Handles all errors of the response of a fetch call - handleErrors(response) { - if (!response.ok) { - throw Error(response.status); + // Handles all errors of the response of a fetch call + handleErrors(response) { + if (!response.ok) + throw Error(response.status); + return response; } - return response; - } + + handleQueryError(response) { + if (!response.ok) { + if (response.status === 404) { + this.setState({ + responseMovieList:

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

+ }) + } + console.log(error); + } + return response; + } + + // Unpacks the query value of a uri + findQueryValueInURI(uri) { + let uriSearchValues = uri.query(true); + let queryValue = uriSearchValues['query'] + + return queryValue; + } + + resetPageNumber() { + this.state.page = 1; + } + + // 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) { + 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 = '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 => { + this.setState({ + responseMovieList: responseData.results.map(searchResultItem => this.createMovieObjects(searchResultItem)), + lastApiCallURI: uri // Save the value of the last sucessfull api call + }) + }) + }) + .catch(() => { + throw Error('Something went wrong when fetching query.') + }) + } + + searchSeasonedRequest() { + // 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'); + + + // Send uri to call and fill the response list with movie/show objects + this.callSearchFillMovieList(uri); + } + + + + + fetchDiscover(queryDiscoverType) { - if (this.allowedDiscoverTypes.indexOf(queryDiscoverType) === -1) + if (this.allowedListTypes.indexOf(queryDiscoverType) === -1) throw Error('Invalid discover type: ' + queryDiscoverType); + // Captialize the first letter of and save the discoverQueryType to resultHeader state. + this.state.resultHeader = queryDiscoverType.toLowerCase().replace(/\b[a-z]/g, function(letter) { + return letter.toUpperCase(); + }); + var uri = new URI(this.baseUrl); uri.segment(queryDiscoverType) uri = uri.setSearch('page', this.state.page); if (this.state.showFilter) uri = uri.addSearch('type', 'show'); - console.log(uri) + + this.state.lastApiCallURI = uri; this.setState({ responseMovieList: 'Loading...' @@ -96,11 +198,15 @@ class SearchRequest extends React.Component { fetchQuery() { - let url = this.URLs.request + this.state.searchQuery + let url = this.URLs.request + this.state.searchQuery; if (this.state.showFilter) { url = url + '&type=tv' } + this.state.apiQuery = url; + console.log(this.state.apiQuery.toString()); + this.state.resultHeader = "Results for: " + this.state.searchQuery + ""; + fetch(url) // Check if the response is ok .then(response => this.handleErrors(response)) @@ -135,7 +241,10 @@ class SearchRequest extends React.Component { // For checking if the enter key was pressed in the search field. _handleQueryKeyPress(e) { if (e.key === 'Enter') { - this.fetchQuery(); + // this.fetchQuery(); + // Reset page number for a new search + this.resetPageNumber(); + this.searchSeasonedRequest(); } } @@ -161,21 +270,39 @@ class SearchRequest extends React.Component { } } - pageBackwards() { - if (this.state.page > 1) { - console.log('backwards'); - this.state.page--; - this.getUpcoming(); - } - console.log(this.state.page) - } + 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; + }); - pageForwards() { - this.state.page++; - this.getUpcoming(); - console.log('forwards'); - console.log(this.state.page) - } + // 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; + } render(){ @@ -186,40 +313,44 @@ class SearchRequest extends React.Component { -
-
- Request new movies or tv shows -
+
+
+ Request new movies or tv shows +
-
-
- +
+
+ - this._handleQueryKeyPress(event)} - onChange={event => this.updateQueryState(event)} - value={this.state.searchQuery}/> + this._handleQueryKeyPress(event)} + onChange={event => this.updateQueryState(event)} + value={this.state.searchQuery}/> - {this.toggleFilter('movies')}} - id="category_active">Movies - {this.toggleFilter('shows')}} - id="category_inactive">TV Shows -
+ {this.toggleFilter('movies')}} + id="category_active">Movies + {this.toggleFilter('shows')}} + id="category_inactive">TV Shows
+
-
- {this.state.responseMovieList} -
-
- - -
-
+
+ +

{this.state.resultHeader}

+ + {this.state.responseMovieList} +
+ +
+ + +
+
) }