From a0236507518efa595f593a23a029369331db301f Mon Sep 17 00:00:00 2001 From: andres alcocer Date: Sat, 26 Nov 2022 10:52:48 -0500 Subject: [PATCH] converted redux store to ts --- package-lock.json | 68 ++++++++++++ package.json | 2 + src/components/MainContent.js | 54 +++++----- src/index.js.tsx | 6 +- src/pages/{Search.js => Search.tsx} | 21 ++-- src/store/actions/index.ts | 1 - src/store/index.ts | 33 ++++++ src/store/reducers/index.ts | 26 ----- src/store/reducers/reducerActionMovies.ts | 11 -- src/store/reducers/reducerMovieDetails.ts | 29 ----- src/store/reducers/reducerSearchMovie.ts | 29 ----- src/store/slices/actionMovieSlice.ts | 43 ++++++++ src/store/slices/movieDetailsSlice.ts | 100 ++++++++++++++++++ .../reducerComedyMovies.ts | 0 .../reducerDocumentary.ts | 0 .../reducerHorrorMovies.ts | 0 .../reducerNetflixOriginals.ts | 0 .../reducerRomanceMovies.ts | 0 .../{reducers => slices}/reducerTopRated.ts | 0 .../{reducers => slices}/reducerTrending.ts | 0 src/store/slices/searchSlice.ts | 66 ++++++++++++ 21 files changed, 355 insertions(+), 134 deletions(-) rename src/pages/{Search.js => Search.tsx} (85%) create mode 100644 src/store/index.ts delete mode 100644 src/store/reducers/index.ts delete mode 100644 src/store/reducers/reducerActionMovies.ts delete mode 100644 src/store/reducers/reducerMovieDetails.ts delete mode 100644 src/store/reducers/reducerSearchMovie.ts create mode 100644 src/store/slices/actionMovieSlice.ts create mode 100644 src/store/slices/movieDetailsSlice.ts rename src/store/{reducers => slices}/reducerComedyMovies.ts (100%) rename src/store/{reducers => slices}/reducerDocumentary.ts (100%) rename src/store/{reducers => slices}/reducerHorrorMovies.ts (100%) rename src/store/{reducers => slices}/reducerNetflixOriginals.ts (100%) rename src/store/{reducers => slices}/reducerRomanceMovies.ts (100%) rename src/store/{reducers => slices}/reducerTopRated.ts (100%) rename src/store/{reducers => slices}/reducerTrending.ts (100%) create mode 100644 src/store/slices/searchSlice.ts diff --git a/package-lock.json b/package-lock.json index 9c333b3..c598588 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,12 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "@reduxjs/toolkit": "^1.9.0", "@types/jest": "^29.2.3", "@types/node": "^18.11.9", "@types/react": "^18.0.25", "@types/react-dom": "^18.0.9", + "@types/react-redux": "^7.1.24", "axios": "^1.2.0", "dotenv": "^16.0.3", "firebase": "^9.14.0", @@ -3929,6 +3931,29 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "node_modules/@reduxjs/toolkit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.0.tgz", + "integrity": "sha512-ak11IrjYcUXRqlhNPwnz6AcvA2ynJTu8PzDbbqQw4a3xR4KZtgiqbNblQD+10CRbfK4+5C79SOyxnT9dhBqFnA==", + "dependencies": { + "immer": "^9.0.16", + "redux": "^4.2.0", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.7" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.0.2" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, "node_modules/@remix-run/router": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.3.tgz", @@ -4944,6 +4969,17 @@ "@types/react": "*" } }, + "node_modules/@types/react-redux": { + "version": "7.1.24", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz", + "integrity": "sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -21112,6 +21148,11 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, + "node_modules/reselect": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz", + "integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==" + }, "node_modules/resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", @@ -27617,6 +27658,17 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "@reduxjs/toolkit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.0.tgz", + "integrity": "sha512-ak11IrjYcUXRqlhNPwnz6AcvA2ynJTu8PzDbbqQw4a3xR4KZtgiqbNblQD+10CRbfK4+5C79SOyxnT9dhBqFnA==", + "requires": { + "immer": "^9.0.16", + "redux": "^4.2.0", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.7" + } + }, "@remix-run/router": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.0.3.tgz", @@ -28410,6 +28462,17 @@ "@types/react": "*" } }, + "@types/react-redux": { + "version": "7.1.24", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz", + "integrity": "sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==", + "requires": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -40182,6 +40245,11 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, + "reselect": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz", + "integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A==" + }, "resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", diff --git a/package.json b/package.json index f9d263d..0d8bd5a 100644 --- a/package.json +++ b/package.json @@ -13,10 +13,12 @@ "author": "Andres Alcocer", "license": "ISC", "dependencies": { + "@reduxjs/toolkit": "^1.9.0", "@types/jest": "^29.2.3", "@types/node": "^18.11.9", "@types/react": "^18.0.25", "@types/react-dom": "^18.0.9", + "@types/react-redux": "^7.1.24", "axios": "^1.2.0", "dotenv": "^16.0.3", "firebase": "^9.14.0", diff --git a/src/components/MainContent.js b/src/components/MainContent.js index 712b4bf..0221abf 100644 --- a/src/components/MainContent.js +++ b/src/components/MainContent.js @@ -1,40 +1,40 @@ import React, { useEffect } from 'react' -import { useDispatch, useSelector } from 'react-redux' -import * as movieActions from '../store/actions' +import * as actionMovies from '../store/slices/actionMovieSlice' +import { useAppSelector, useAppDispatch } from '../store' import Header from './Header' import DisplayMovieRow from './DisplayMovieRow' const MainContent = ({ selectMovieHandler }) => { - const { movieDetails } = useSelector((state) => state.movieDetails) - const netflixOriginals = useSelector((state) => state.netflixOriginals) - const trending = useSelector((state) => state.trending) - const topRated = useSelector((state) => state.topRated) - const actionMovies = useSelector((state) => state.action) - const comedyMovies = useSelector((state) => state.comedy) - const horrorMovies = useSelector((state) => state.horror) - const romanceMovies = useSelector((state) => state.romance) - const documentaries = useSelector((state) => state.documentary) + // const { movieDetails } = useSelector((state) => state.movieDetails) + // const netflixOriginals = useSelector((state) => state.netflixOriginals) + // const trending = useSelector((state) => state.trending) + // const topRated = useSelector((state) => state.topRated) + const actionMoviesState = useAppSelector((state) => state.action) + // const comedyMovies = useSelector((state) => state.comedy) + // const horrorMovies = useSelector((state) => state.horror) + // const romanceMovies = useSelector((state) => state.romance) + // const documentaries = useSelector((state) => state.documentary) - const dispatch = useDispatch() + const dispatch = useAppDispatch() useEffect(() => { - dispatch(movieActions.fetchMovieDetails('tv', '63351')) - dispatch(movieActions.fetchNetflixOriginals()) - dispatch(movieActions.fetchTrending()) - dispatch(movieActions.fetchTopRated()) - dispatch(movieActions.fetchActionMovies()) - dispatch(movieActions.fetchComedyMovies()) - dispatch(movieActions.fetchHorrorMovies()) - dispatch(movieActions.fetchRomanceMovies()) - dispatch(movieActions.fetchDocumentaries()) + // dispatch(movieActions.fetchMovieDetails('tv', '63351')) + // dispatch(movieActions.fetchNetflixOriginals()) + // dispatch(movieActions.fetchTrending()) + // dispatch(movieActions.fetchTopRated()) + dispatch(actionMovies.getActionMoviesAsync()) + // dispatch(movieActions.fetchComedyMovies()) + // dispatch(movieActions.fetchHorrorMovies()) + // dispatch(movieActions.fetchRomanceMovies()) + // dispatch(movieActions.fetchDocumentaries()) }, [dispatch]) return (
-
+ {/*
*/}
- { title='Top Rated' selectMovieHandler={selectMovieHandler} movies={topRated.data} - /> + /> */} - { title='Documentaries' selectMovieHandler={selectMovieHandler} movies={documentaries.data} - /> + /> */}
) diff --git a/src/index.js.tsx b/src/index.js.tsx index 0f6a4a9..2244be2 100644 --- a/src/index.js.tsx +++ b/src/index.js.tsx @@ -1,11 +1,9 @@ import React from 'react' import * as ReactDOM from 'react-dom/client' import { Provider } from 'react-redux' -import { createStore, applyMiddleware } from 'redux' -import ReduxThunk from 'redux-thunk' import '@babel/polyfill' -import reducers from './store/reducers' +import { store } from './store' import AppRouter from './AppRouter' // Import Swiper styles @@ -15,8 +13,6 @@ import 'swiper/css/pagination' // Import main sass file to apply global styles import './static/sass/style.scss' -const store = createStore(reducers, applyMiddleware(ReduxThunk)) - const app = ( diff --git a/src/pages/Search.js b/src/pages/Search.tsx similarity index 85% rename from src/pages/Search.js rename to src/pages/Search.tsx index fe8d326..7e8d9b7 100644 --- a/src/pages/Search.js +++ b/src/pages/Search.tsx @@ -1,11 +1,18 @@ import React, { useEffect, useState } from 'react' -import { useDispatch, useSelector } from 'react-redux' import { useLocation } from 'react-router-dom' + +import { useAppSelector, useAppDispatch } from '../store' import ModalMovieDetails from '../components/ModalMovieDetails' import Modal from '../components/UI/Modal' import { useDebounce } from '../hooks/useDebounce' import * as movieActions from '../store/actions' +interface IMovie { + id: string + media_type?: string + backdrop_path?: string +} + // A custom hook that builds on useLocation to parse // the query string for you. const useQuery = () => { @@ -16,9 +23,11 @@ const Search = () => { let query = useQuery() const debouncedSearchTerm = useDebounce(query.get('q'), 500) const [isToggleModal, setIsToggleModal] = useState(false) - const { searchResults, isLoading } = useSelector((state) => state.searchMovie) - const { movieDetails } = useSelector((state) => state.movieDetails) - const dispatch = useDispatch() + const { searchResults, isLoading } = useAppSelector( + (state) => state.searchMovie + ) + const { movieDetails } = useAppSelector((state) => state.movieDetails) + const dispatch = useAppDispatch() useEffect(() => { if (debouncedSearchTerm) { @@ -30,7 +39,7 @@ const Search = () => { setIsToggleModal(false) } - const onSelectMovieHandler = (movie) => { + const onSelectMovieHandler = (movie: IMovie) => { dispatch(movieActions.fetchMovieDetails(movie.media_type, movie.id)) setIsToggleModal(true) } @@ -39,7 +48,7 @@ const Search = () => { return searchResults.length > 0 ? ( <>
- {searchResults.map((movie) => { + {searchResults.map((movie: IMovie) => { if (movie.backdrop_path !== null && movie.media_type !== 'person') { const movieImageUrl = 'https://image.tmdb.org/t/p/w500' + movie.backdrop_path diff --git a/src/store/actions/index.ts b/src/store/actions/index.ts index d271906..1afe835 100644 --- a/src/store/actions/index.ts +++ b/src/store/actions/index.ts @@ -31,7 +31,6 @@ export const fetchMovieDetails = (mediaType: string, mediaId: string) => { urlPath = `/movie/${mediaId}?api_key=${process.env.API_KEY}` if (mediaType === media_type.tv) urlPath = `/tv/${mediaId}?api_key=${process.env.API_KEY}` - console.log('media type', mediaType, urlPath) const request = await axios.get(urlPath) dispatch({ type: FETCH_MOVIE_DETAILS_SUCCESS, payload: request }) } catch (error) { diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..3b79271 --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,33 @@ +import { configureStore } from '@reduxjs/toolkit' +import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux' + +import TrendingReducer from './slices/reducerTrending' +import NetflixOriginalsReducer from './slices/reducerNetflixOriginals' +import TopRatedReducer from './slices/reducerTopRated' +import ActionMoviesReducer from './slices/actionMovieSlice' +import ComedyMoviesReducer from './slices/reducerComedyMovies' +import HorrorMoviesReducer from './slices/reducerHorrorMovies' +import RomanceMoviesReducer from './slices/reducerRomanceMovies' +import DocumentaryReducer from './slices/reducerDocumentary' +import SearchMovieReducer from './slices/searchSlice' +import MovieDetailsReducer from './slices/movieDetailsSlice' + +export const store = configureStore({ + reducer: { + // trending: TrendingReducer, + // netflixOriginals: NetflixOriginalsReducer, + // topRated: TopRatedReducer, + action: ActionMoviesReducer, + // comedy: ComedyMoviesReducer, + // horror: HorrorMoviesReducer, + // romance: RomanceMoviesReducer, + searchMovie: SearchMovieReducer, + // documentary: DocumentaryReducer, + movieDetails: MovieDetailsReducer, + }, +}) + +export type RootState = ReturnType +export type AppDispatch = typeof store.dispatch +export const useAppDispatch = () => useDispatch() +export const useAppSelector: TypedUseSelectorHook = useSelector diff --git a/src/store/reducers/index.ts b/src/store/reducers/index.ts deleted file mode 100644 index 195fc1d..0000000 --- a/src/store/reducers/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { combineReducers } from 'redux' -import TrendingReducer from './reducerTrending' -import NetflixOriginalsReducer from './reducerNetflixOriginals' -import TopRatedReducer from './reducerTopRated' -import ActionMoviesReducer from './reducerActionMovies' -import ComedyMoviesReducer from './reducerComedyMovies' -import HorrorMoviesReducer from './reducerHorrorMovies' -import RomanceMoviesReducer from './reducerRomanceMovies' -import DocumentaryReducer from './reducerDocumentary' -import SearchMovieReducer from './reducerSearchMovie' -import MovieDetailsReducer from './reducerMovieDetails' - -const rootReducer = combineReducers({ - trending: TrendingReducer, - netflixOriginals: NetflixOriginalsReducer, - topRated: TopRatedReducer, - action: ActionMoviesReducer, - comedy: ComedyMoviesReducer, - horror: HorrorMoviesReducer, - romance: RomanceMoviesReducer, - documentary: DocumentaryReducer, - searchMovie: SearchMovieReducer, - movieDetails: MovieDetailsReducer, -}) - -export default rootReducer diff --git a/src/store/reducers/reducerActionMovies.ts b/src/store/reducers/reducerActionMovies.ts deleted file mode 100644 index e18ab42..0000000 --- a/src/store/reducers/reducerActionMovies.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { FETCH_ACTION_MOVIES } from '../actions/index' - -export default function (state = {}, action: any) { - switch (action.type) { - case FETCH_ACTION_MOVIES: - const data = action.payload.data.results - return { ...state, data } - default: - return state - } -} diff --git a/src/store/reducers/reducerMovieDetails.ts b/src/store/reducers/reducerMovieDetails.ts deleted file mode 100644 index 1bec55c..0000000 --- a/src/store/reducers/reducerMovieDetails.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { - FETCH_MOVIE_DETAILS, - FETCH_MOVIE_DETAILS_SUCCESS, - FETCH_MOVIE_DETAILS_FAIL, -} from '../actions/index' - -interface IInitialState { - isLoading: boolean - movieDetails: [] -} - -const initialState: IInitialState = { - isLoading: false, - movieDetails: [], -} - -export default function (state = initialState, action: any) { - 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 - } -} diff --git a/src/store/reducers/reducerSearchMovie.ts b/src/store/reducers/reducerSearchMovie.ts deleted file mode 100644 index 1ad802d..0000000 --- a/src/store/reducers/reducerSearchMovie.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { - FETCH_SEARCH_MOVIE, - FETCH_SEARCH_MOVIE_FAIL, - FETCH_SEARCH_MOVIE_SUCCESS, -} from '../actions/index' - -interface IInitialState { - isLoading: boolean - searchResults: [] -} - -const initialState: IInitialState = { - isLoading: false, - searchResults: [], -} - -export default function (state = initialState, action: any) { - switch (action.type) { - case FETCH_SEARCH_MOVIE: - 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 - } -} diff --git a/src/store/slices/actionMovieSlice.ts b/src/store/slices/actionMovieSlice.ts new file mode 100644 index 0000000..b946e6e --- /dev/null +++ b/src/store/slices/actionMovieSlice.ts @@ -0,0 +1,43 @@ +import { createSlice, createAsyncThunk } from '@reduxjs/toolkit' + +import axios from '../../axios-movies' +// import { FETCH_ACTION_MOVIES } from '../actions/index' +import { RootState } from '../index' + +// export default function (state = {}, action: any) { +// switch (action.type) { +// case FETCH_ACTION_MOVIES: +// const data = action.payload.data.results +// return { ...state, data } +// default: +// return state +// } +// } + +const initialState = { + data: [{}], +} + +export const getActionMoviesAsync = createAsyncThunk< + any, + void, + { state: RootState } +>('action/getActionMovies', async () => { + const response = await axios.get( + `/discover/movie?api_key=${process.env.API_KEY}&with_genres=28` + ) + return response.data.results +}) + +const actionMovieSlice = createSlice({ + name: 'actionMovie', + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(getActionMoviesAsync.fulfilled, (state, { payload }) => { + state.data = payload + }) + }, +}) + +export default actionMovieSlice.reducer diff --git a/src/store/slices/movieDetailsSlice.ts b/src/store/slices/movieDetailsSlice.ts new file mode 100644 index 0000000..9aae25a --- /dev/null +++ b/src/store/slices/movieDetailsSlice.ts @@ -0,0 +1,100 @@ +import { createSlice, createAsyncThunk } from '@reduxjs/toolkit' + +import axios from '../../axios-movies' +import { RootState } from '../index' +import { + FETCH_MOVIE_DETAILS, + FETCH_MOVIE_DETAILS_SUCCESS, + FETCH_MOVIE_DETAILS_FAIL, +} from '../actions/index' +import { string } from 'prop-types' + +interface IMovieDetails { + backdrop_path?: string + poster_path?: string + title: any + name: any + vote_average: any + release_date: any + first_air_date: any + runtime: any + episode_run_time: any + number_of_episodes: any + number_of_seasons: any + overview: any +} + +interface IInitialState { + isLoading: boolean + movieDetails: IMovieDetails +} + +const media_type = { + tv: 'tv', + movie: 'movie', +} + +// const initialState: IInitialState = { +// isLoading: false, +// movieDetails: [], +// } + +// export default function (state = initialState, action: any) { +// 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 +// } +// } + +const initialState: IInitialState = { + isLoading: false, + movieDetails: { + backdrop_path: '', + poster_path: '', + title: '', + name: '', + vote_average: '', + release_date: '', + first_air_date: '', + runtime: '', + episode_run_time: '', + number_of_episodes: '', + number_of_seasons: '', + overview: '', + }, +} + +export const getMovieDetailsAsync = createAsyncThunk< + any, + string, + { state: RootState } +>('movieDetails/getMovieDetailsAsync', async (mediaType, mediaId) => { + 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 response = await axios.get(urlPath) + return response.data.results +}) + +const movieDetailsSlice = createSlice({ + name: 'movieDetails', + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(getMovieDetailsAsync.fulfilled, (state, { payload }) => { + state.isLoading = false + state.movieDetails = payload + }) + }, +}) + +export default movieDetailsSlice.reducer diff --git a/src/store/reducers/reducerComedyMovies.ts b/src/store/slices/reducerComedyMovies.ts similarity index 100% rename from src/store/reducers/reducerComedyMovies.ts rename to src/store/slices/reducerComedyMovies.ts diff --git a/src/store/reducers/reducerDocumentary.ts b/src/store/slices/reducerDocumentary.ts similarity index 100% rename from src/store/reducers/reducerDocumentary.ts rename to src/store/slices/reducerDocumentary.ts diff --git a/src/store/reducers/reducerHorrorMovies.ts b/src/store/slices/reducerHorrorMovies.ts similarity index 100% rename from src/store/reducers/reducerHorrorMovies.ts rename to src/store/slices/reducerHorrorMovies.ts diff --git a/src/store/reducers/reducerNetflixOriginals.ts b/src/store/slices/reducerNetflixOriginals.ts similarity index 100% rename from src/store/reducers/reducerNetflixOriginals.ts rename to src/store/slices/reducerNetflixOriginals.ts diff --git a/src/store/reducers/reducerRomanceMovies.ts b/src/store/slices/reducerRomanceMovies.ts similarity index 100% rename from src/store/reducers/reducerRomanceMovies.ts rename to src/store/slices/reducerRomanceMovies.ts diff --git a/src/store/reducers/reducerTopRated.ts b/src/store/slices/reducerTopRated.ts similarity index 100% rename from src/store/reducers/reducerTopRated.ts rename to src/store/slices/reducerTopRated.ts diff --git a/src/store/reducers/reducerTrending.ts b/src/store/slices/reducerTrending.ts similarity index 100% rename from src/store/reducers/reducerTrending.ts rename to src/store/slices/reducerTrending.ts diff --git a/src/store/slices/searchSlice.ts b/src/store/slices/searchSlice.ts new file mode 100644 index 0000000..4ade615 --- /dev/null +++ b/src/store/slices/searchSlice.ts @@ -0,0 +1,66 @@ +import { createSlice, createAsyncThunk } from '@reduxjs/toolkit' + +import axios from '../../axios-movies' +import { RootState } from '../index' +import { + FETCH_SEARCH_MOVIE, + FETCH_SEARCH_MOVIE_FAIL, + FETCH_SEARCH_MOVIE_SUCCESS, +} from '../actions/index' + +// interface IInitialState { +// isLoading: boolean +// searchResults: [] +// } + +// const initialState: IInitialState = { +// isLoading: false, +// searchResults: [], +// } + +// export default function (state = initialState, action: any) { +// switch (action.type) { +// case FETCH_SEARCH_MOVIE: +// 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 +// } +// } + +const initialState = { + searchResults: [{}], + isLoading: true, +} + +export const searchItemsAsync = createAsyncThunk< + any, + void, + { state: RootState } +>('search/getSearchItems', async (searchTerm) => { + const response = await axios.get( + `/search/multi?api_key=${process.env.API_KEY}&language=en-US&include_adult=false&query=${searchTerm}` + ) + return response.data.results +}) + +const searchSlice = createSlice({ + name: 'search', + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addCase(searchItemsAsync.fulfilled, (state, { payload }) => { + state.isLoading = false + state.searchResults = payload + }) + builder.addCase(searchItemsAsync.pending, (state) => { + state.isLoading = true + }) + }, +}) + +export default searchSlice.reducer