Skip to content
Snippets Groups Projects
Commit 1958d149 authored by joningehe's avatar joningehe
Browse files

Added option for sort and filtration

- Added option for sort and filtration
- Still some bugs
parent 521bc9a6
No related branches found
No related tags found
1 merge request!9Add sorting and filtration
...@@ -85,11 +85,29 @@ export default class MovieController { ...@@ -85,11 +85,29 @@ export default class MovieController {
public static async getMovieByTitle (ctx: Context) { public static async getMovieByTitle (ctx: Context) {
const movieRepository: Repository<Movie> = getManager().getRepository(Movie); const movieRepository: Repository<Movie> = getManager().getRepository(Movie);
const movies: Movie[] = await movieRepository.find({ const movies: Movie[] = await movieRepository.find({
where: `"Title" ILIKE '%${ctx.params.title}%'`, where: `"Title" ILIKE '%${ctx.params.title}%'`,
// order has to be either DESC or ASC // order has to be either DESC or ASC
order: {Title: "ASC"}, order: {Title: ctx.params.order || "ASC"},
take: ctx.params.take,
skip: Math.max(ctx.params.take-10, 0)
});
if(movies) {
ctx.status = 200;
ctx.body = movies;
} else {
ctx.status = 400;
ctx.body = ERROR_MSG1;
}
}
public static async getMovieByTitleAndGenre (ctx: Context) {
const movieRepository: Repository<Movie> = getManager().getRepository(Movie);
const movies: Movie[] = await movieRepository.find({
where: `"Title" ILIKE '%${ctx.params.title}%' AND "Genre" ILIKE '%${ctx.params.genre}%'`,
// order has to be either DESC or ASC
order: {Title: ctx.params.order || "ASC"},
take: ctx.params.take, take: ctx.params.take,
skip: Math.max(ctx.params.take-10, 0) skip: Math.max(ctx.params.take-10, 0)
}); });
......
...@@ -12,7 +12,9 @@ restRouter.get("/movies/:id", controller.movie.getMovieId); ...@@ -12,7 +12,9 @@ restRouter.get("/movies/:id", controller.movie.getMovieId);
// Post request for finding movies based on search // Post request for finding movies based on search
restRouter.post("/movies/search", controller.movie.searchMovie); restRouter.post("/movies/search", controller.movie.searchMovie);
// Get request for finding movies based on search // Get request for finding movies based on search
restRouter.get("/movies/:title/:take", controller.movie.getMovieByTitle); restRouter.get("/movies/:title/:take/:order", controller.movie.getMovieByTitle)
// Get request for finding movies based on search and genre
restRouter.get("/movies/:title/:take/:order/:genre", controller.movie.getMovieByTitleAndGenre);
// Post request for finding movies based on category // Post request for finding movies based on category
restRouter.post("/movies/genre", controller.movie.searchMoviesByGenre); restRouter.post("/movies/genre", controller.movie.searchMoviesByGenre);
......
...@@ -20,7 +20,6 @@ const SearchHandler = (): JSX.Element => { ...@@ -20,7 +20,6 @@ const SearchHandler = (): JSX.Element => {
} }
}, [debouncedSearch]); }, [debouncedSearch]);
// TODO: this function should be exported to ensure modularity
const searchMovies = async () => { const searchMovies = async () => {
const body = { const body = {
Title: search, Title: search,
......
...@@ -38,8 +38,8 @@ export const movieSlice = createSlice({ ...@@ -38,8 +38,8 @@ export const movieSlice = createSlice({
searchTerm: state.searchTerm, searchTerm: state.searchTerm,
movies: [...state.movies, action.payload], movies: [...state.movies, action.payload],
}), }),
clearMovies: () => ({ clearMovies: (state: MovieState) => ({
searchTerm: "", searchTerm: state.searchTerm,
movies: [], movies: [],
}), }),
}, },
......
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { View, FlatList, StyleSheet } from "react-native"; import { View, FlatList, StyleSheet, Picker } from "react-native";
import axios from "axios"; import axios from "axios";
import { AppState, useAppDispatch } from "../store/redux/store"; import { AppState, useAppDispatch } from "../store/redux/store";
...@@ -18,6 +18,8 @@ const Home: React.FC = (): JSX.Element => { ...@@ -18,6 +18,8 @@ const Home: React.FC = (): JSX.Element => {
const searchTerm = useSelector((state: AppState) => state.movies.searchTerm); const searchTerm = useSelector((state: AppState) => state.movies.searchTerm);
const count = useSelector((state: AppState) => state.system.count); const count = useSelector((state: AppState) => state.system.count);
const [refreshing, setRefreshing] = useState(false); const [refreshing, setRefreshing] = useState(false);
const [sortValue, setSortValue] = useState("ASC");
const [filterValue, setFilterValue] = useState("");
// This does not work, dispatch is async, so we will have to rework pagination. The list works. // This does not work, dispatch is async, so we will have to rework pagination. The list works.
const refreshMovies = () => { const refreshMovies = () => {
...@@ -30,8 +32,18 @@ const Home: React.FC = (): JSX.Element => { ...@@ -30,8 +32,18 @@ const Home: React.FC = (): JSX.Element => {
if (movies.length >= count) { if (movies.length >= count) {
return; return;
} }
const endpoint =
filterValue == ""
? `${api.defaults.baseURL}/movies/${searchTerm}/${
movies.length + 10
}/${sortValue}`
: `${api.defaults.baseURL}/movies/${searchTerm}/${
movies.length + 10
}/${sortValue}/${filterValue}`;
axios axios
.get(`${api.defaults.baseURL}/movies/${searchTerm}/${movies.length + 10}`) .get(endpoint)
.then((response) => { .then((response) => {
response.data.map((movie: Movie) => { response.data.map((movie: Movie) => {
if (!movies.includes(movie)) { if (!movies.includes(movie)) {
...@@ -42,11 +54,40 @@ const Home: React.FC = (): JSX.Element => { ...@@ -42,11 +54,40 @@ const Home: React.FC = (): JSX.Element => {
.catch((e) => console.log(e)); .catch((e) => console.log(e));
}; };
// TODO: add useEffect to re-render on state change? useEffect(() => {
dispatch(movieSlice.actions.clearMovies());
fetchMoreMovies();
}, [filterValue, sortValue]);
return ( return (
<View style={styles.container}> <View style={styles.container}>
<SearchHandler /> <SearchHandler />
<View style={{ flexDirection: "row" }}>
<Picker
selectedValue={sortValue}
style={{ height: 50, width: "50%" }}
onValueChange={(itemValue, itemIndex) => setSortValue(itemValue)}
>
<Picker.Item label="Ascending A-Z" value="ASC" />
<Picker.Item label="Descending Z-A" value="DESC" />
</Picker>
<Picker
selectedValue={filterValue}
style={{ height: 50, width: "50%" }}
onValueChange={(itemValue, itemIndex) => setFilterValue(itemValue)}
>
<Picker.Item label="All" value="" />
<Picker.Item label="Action" value="Action" />
<Picker.Item label="Adventure" value="Adventure" />
<Picker.Item label="Biography" value="Biography" />
<Picker.Item label="Comedy" value="Comedy" />
<Picker.Item label="Crime" value="Crime" />
<Picker.Item label="Drama" value="Drama" />
<Picker.Item label="Fantasy" value="Fantasy" />
<Picker.Item label="History" value="History" />
<Picker.Item label="Thriller" value="Thriller" />
</Picker>
</View>
<View> <View>
<FlatList <FlatList
data={movies} data={movies}
...@@ -69,3 +110,9 @@ const styles = StyleSheet.create({ ...@@ -69,3 +110,9 @@ const styles = StyleSheet.create({
}); });
export default Home; export default Home;
/*
Missing support:
<Picker.Item label="Top-bottom rated" value="top" />
<Picker.Item label="Bottom-top rated" value="bot" />
*/
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment