Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import "./App.css";

const HomePage = React.lazy(() => import("./pages/Home"));

export default function App() {
export default function App () {
return (
<UserContextProvider>
<div className="App">
Expand All @@ -33,7 +33,7 @@ export default function App() {
<Route component={HomePage} path="/" />
<Route
component={SearchResults}
path="/search/:keyword/:rating?"
path="/search/:keyword/:rating?/:lang?"
/>
<Route component={Detail} path="/gif/:id" />
<Route component={Login} path="/login" />
Expand Down
18 changes: 14 additions & 4 deletions src/components/SearchForm/hook.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useReducer } from "react";
const ACTIONS = {
CHANGE_KEYWORD: "change_keyword",
CHANGE_RATING: "change_rating",
CHANGE_LANG: "change_lang",
};

const ACTIONS_REDUCERS = {
Expand All @@ -15,28 +16,37 @@ const ACTIONS_REDUCERS = {
...state,
rating: action.payload,
}),
[ACTIONS.CHANGE_LANG]: (state, action) => ({
...state,
lang: action.payload,
}),
};

const reducer = (state, action) => {
const actionReducer = ACTIONS_REDUCERS[action.type];
return actionReducer ? actionReducer(state, action) : state;
};

export default function useForm({
export default function useForm ({
initialKeyword = "",
initialRating = "g",
initialLang = "es",
} = {}) {
const [{ keyword, rating }, dispatch] = useReducer(reducer, {
const [{ keyword, rating, lang }, dispatch] = useReducer(reducer, {
keyword: decodeURIComponent(initialKeyword),
rating: initialRating
rating: initialRating,
lang: initialLang
});

return {
changeKeyword: ({ keyword }) =>
dispatch({ type: ACTIONS.CHANGE_KEYWORD, payload: keyword }),
changeRating: ({ rating }) =>
dispatch({ type: ACTIONS.CHANGE_RATING, payload: rating }),
changeLang: ({ lang }) =>
dispatch({ type: ACTIONS.CHANGE_LANG, payload: lang }),
keyword,
rating
rating,
lang
};
}
22 changes: 18 additions & 4 deletions src/components/SearchForm/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@ import css from "./SearchForm.module.css"
import Button from 'components/Button'

const RATINGS = ["g", "pg", "pg-13", "r"]
const LANGS = ["es", "en", "it", "pr"]

export default function SearchForm({
export default function SearchForm ({
initialKeyword = '',
initialRating = RATINGS[0]
initialRating = RATINGS[0],
initialLang = LANGS[0],
}) {
const [_, pushLocation] = useLocation()

const {keyword, rating, changeKeyword, changeRating} = useForm({ initialKeyword, initialRating })
const { keyword, rating, lang, changeKeyword, changeRating, changeLang } = useForm({ initialKeyword, initialRating, initialLang })

const onSubmit = ({ keyword }) => {
if (keyword !== '') {
// navegar a otra ruta
pushLocation(`/search/${keyword}/${rating}`)
pushLocation(`/search/${keyword}/${rating}/${lang}`)
}
}

Expand All @@ -34,6 +36,10 @@ export default function SearchForm({
changeRating({ rating: evt.target.value })
}

const handleChangeLang = (evt) => {
changeLang({ lang: evt.target.value })
}

return (
<>
<form onSubmit={handleSubmit} className={css["c-search"]}>
Expand All @@ -53,6 +59,14 @@ export default function SearchForm({
<option key={rating}>{rating}</option>
))}
</select>
<select className={css["c-search-list"]} value={lang} onChange={handleChangeLang}>
<option disabled>
Lang:
</option>
{LANGS.map((lang) => (
<option key={lang}>{lang}</option>
))}
</select>
</form>
</>
)
Expand Down
16 changes: 8 additions & 8 deletions src/hooks/useGifs.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
import {useContext, useEffect, useState} from 'react'
import { useContext, useEffect, useState } from 'react'
import getGifs from '../services/getGifs'
import GifsContext from '../context/GifsContext'

const INITIAL_PAGE = 0

export function useGifs ({ keyword, rating } = { keyword: null }) {
export function useGifs ({ keyword, rating, lang } = { keyword: null }) {
const [loading, setLoading] = useState(false)
const [loadingNextPage, setLoadingNextPage] = useState(false)

const [page, setPage] = useState(INITIAL_PAGE)
const {gifs, setGifs} = useContext(GifsContext)
const { gifs, setGifs } = useContext(GifsContext)

// recuperamos la keyword del localStorage
const keywordToUse = keyword || localStorage.getItem('lastKeyword') || 'random'

useEffect(function () {
setLoading(true)

getGifs({ keyword: keywordToUse, rating })
getGifs({ keyword: keywordToUse, rating, lang })
.then(gifs => {
setGifs(gifs)
setLoading(false)
// guardamos la keyword en el localStorage
localStorage.setItem('lastKeyword', keyword)
})
}, [keyword, keywordToUse, rating, setGifs])
}, [keyword, keywordToUse, lang, rating, setGifs])

useEffect(function () {
if (page === INITIAL_PAGE) return

setLoadingNextPage(true)

getGifs({ keyword: keywordToUse, page, rating })
getGifs({ keyword: keywordToUse, page, rating, lang })
.then(nextGifs => {
setGifs(prevGifs => prevGifs.concat(nextGifs))
setLoadingNextPage(false)
})
}, [keywordToUse, page, rating, setGifs])
}, [keywordToUse, lang, page, rating, setGifs])

return {loading, loadingNextPage, gifs, setPage}
return { loading, loadingNextPage, gifs, setPage }
}
16 changes: 8 additions & 8 deletions src/pages/SearchResults/index.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import React, {useCallback, useRef, useEffect} from 'react'
import React, { useCallback, useRef, useEffect } from 'react'
import Spinner from 'components/Spinner'
import ListOfGifs from 'components/ListOfGifs'
import SearchForm from 'components/SearchForm'

import {useGifs} from 'hooks/useGifs'
import { useGifs } from 'hooks/useGifs'
import useNearScreen from 'hooks/useNearScreen'

import debounce from 'just-debounce-it'
import {Helmet} from 'react-helmet'
import { Helmet } from 'react-helmet'

export default function SearchResults ({ params }) {
const { keyword, rating } = params
const { loading, gifs, setPage } = useGifs({ keyword, rating })
const { keyword, rating, lang } = params
const { loading, gifs, setPage } = useGifs({ keyword, rating, lang })

const externalRef = useRef()
const {isNearScreen} = useNearScreen({
const { isNearScreen } = useNearScreen({
externalRef: loading ? null : externalRef,
once: false
})
Expand All @@ -39,7 +39,7 @@ export default function SearchResults ({ params }) {
<meta name="rating" content="General" />
</Helmet>
<header className="o-header">
<SearchForm initialKeyword={keyword} initialRating={rating} />
<SearchForm initialKeyword={keyword} initialRating={rating} initialLang={lang} />
</header>
<div className="App-wrapper">
<h3 className="App-title">
Expand Down
14 changes: 7 additions & 7 deletions src/services/getGifs.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {API_KEY, API_URL} from './settings'
import { API_KEY, API_URL } from './settings'

const fromApiResponseToGifs = apiResponse => {
const {data = []} = apiResponse
const { data = [] } = apiResponse
if (Array.isArray(data)) {
const gifs = data.map(image => {
const {images, title, id} = image
const { images, title, id } = image
const { url } = images.downsized_medium
return { title, id, url }
})
Expand All @@ -13,15 +13,15 @@ const fromApiResponseToGifs = apiResponse => {
return []
}

export default function getGifs({
export default function getGifs ({
limit = 15,
rating = "g",
keyword = "morty",
page = 0,
lang = 'es'
} = {}) {
const apiURL = `${API_URL}/gifs/search?api_key=${API_KEY}&q=${keyword}&limit=${limit}&offset=${
page * limit
}&rating=${rating}&lang=en`
const apiURL = `${API_URL}/gifs/search?api_key=${API_KEY}&q=${keyword}&limit=${limit}&offset=${page * limit
}&rating=${rating}&lang=${lang}`

return fetch(apiURL)
.then((res) => res.json())
Expand Down