Skip to content

Commit

Permalink
✨ PWA, Performance (lazy,memo)
Browse files Browse the repository at this point in the history
  • Loading branch information
silnose committed Oct 9, 2020
1 parent 27849f8 commit d337639
Show file tree
Hide file tree
Showing 23 changed files with 299 additions and 85 deletions.
2 changes: 1 addition & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default function App() {
<Logo />
<GlobalStyles />
<NavBar />
<Routes {...isAuth} />
<Routes isAuth={isAuth} />
</>
)
}
2 changes: 1 addition & 1 deletion src/Context.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const Provider = ({ children }) => {
activateAuth: (token) => {
setIsAuth(true)
window.sessionStorage.setItem('token', token)
navigate('/')
navigate('/favorites')
},
removeAuth: () => {
setIsAuth(false)
Expand Down
Binary file added src/assets/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions src/components/Category/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react'
import { Link, Image } from './styles.js'
import { PropTypes } from 'prop-types'

const DEFAULT_IMAGE = 'https://i.imgur.com/dJa0Hpl.jpg'

Expand All @@ -13,3 +14,9 @@ export const Category = ({
<p>{emoji}</p>
</Link>
)

Category.propTypes = {
cover: PropTypes.string,
path: PropTypes.string,
emoji: PropTypes.string
}
7 changes: 7 additions & 0 deletions src/components/FavButton/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react'
import { PropTypes } from 'prop-types'
import { MdFavorite, MdFavoriteBorder } from 'react-icons/md'
import { Button } from './style.js'

export const FavButton = ({ liked, likes, onClick }) => {
const Icon = liked ? MdFavorite : MdFavoriteBorder
return (
Expand All @@ -11,3 +13,8 @@ export const FavButton = ({ liked, likes, onClick }) => {
</>
)
}
FavButton.propTypes = {
liked: PropTypes.bool,
likes: PropTypes.number,
onClick: PropTypes.func.isRequired
}
18 changes: 18 additions & 0 deletions src/components/Layout/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react'
import { Helmet } from 'react-helmet'
import { Container, Title, Subtitle } from './styles'
export const Layout = ({ children, title = '', subtitle = '' }) => {
return (
<>
<Helmet>
<title>{`${title} | Petgram 🐕 `}</title>
<meta name='description' content={subtitle} />
</Helmet>
<Container>
<Title>{title}</Title>
<Subtitle>{subtitle}</Subtitle>
{children}
</Container>
</>
)
}
19 changes: 19 additions & 0 deletions src/components/Layout/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import styled from 'styled-components'

export const Container = styled.div`
padding: 16px;
`

export const Title = styled.h1`
font-size: 24px;
font-weight: 600px;
color: #222;
padding-bottom: 8px;
`

export const Subtitle = styled.small`
font-size: 14px;
font-weight: 400px;
color: #333;
padding-bottom: 4px;
`
33 changes: 7 additions & 26 deletions src/components/ListOfCategories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,9 @@ import React, { useState, useEffect } from 'react'
import { Category } from '../Category'
import NProgress from 'nprogress'
import { List, Item } from './styles.js'
import { useCategoryData } from '../../hooks/useCategoryData.js'

const useCategoryData = () => {
const [categories, setCategories] = useState([])
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')

useEffect(() => {
const getCategories = async () => {
setLoading(true)
try {
const response = await window.fetch(
'https://silnose-petgram-api.vercel.app/categories'
)
const data = await response.json()
setCategories(data)
setLoading(false)
} catch (error) {
setLoading(false)
setError(error.message)
}
}
getCategories()
}, [])

return { categories, loading, error }
}
export const ListOfCategories = () => {
const ListOfCategoriesComponent = () => {
const [showFixed, setShowFixed] = useState(false)
const { categories, loading, error } = useCategoryData()

Expand All @@ -51,6 +27,9 @@ export const ListOfCategories = () => {
}
}, [loading])

if (error) {
return <h1>Error :( </h1>
}
const renderList = (fixed) => (
<List fixed={fixed}>
{categories.map((category) => (
Expand All @@ -68,3 +47,5 @@ export const ListOfCategories = () => {
</>
)
}

export const ListOfCategories = React.memo(ListOfCategoriesComponent)
7 changes: 7 additions & 0 deletions src/components/ListOfFavorites/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react'
import { useGetFavoritesQuery } from '../../hooks/useGetFavoritesQuery'
import { Link, Image, Container } from './styles'
import { PropTypes } from 'prop-types'

export const ListOfFavorites = () => {
const { data, loading, error, refetch } = useGetFavoritesQuery()
Expand All @@ -25,3 +26,9 @@ export const ListOfFavorites = () => {
</>
)
}

ListOfFavorites.propTypes = {
data: PropTypes.arrayOf(
PropTypes.shape({ id: PropTypes.string, src: PropTypes.string })
)
}
5 changes: 5 additions & 0 deletions src/components/ListOfPhotoCard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react'
import { PhotoCard } from '../PhotoCard'
import { useGetPhotos } from '../../hooks/useGetPhotos.js'
import { List, Item } from './style.js'
import { PropTypes } from 'prop-types'

export const ListOfPhotoCard = ({ categoryID }) => {
const { loading, error, data } = useGetPhotos(categoryID)
Expand All @@ -25,3 +26,7 @@ export const ListOfPhotoCard = ({ categoryID }) => {
</>
)
}

ListOfPhotoCard.propTypes = {
categoryID: PropTypes.string
}
31 changes: 22 additions & 9 deletions src/components/PhotoCard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,23 @@ import React, { useContext } from 'react'
import { Context } from '../../Context'
import { FavButton } from '../FavButton/'
import { Image, ImgWrapper, Card } from './style.js'
import {
useLikePhotoAnonymous,
useLikePhoto
} from '../../hooks/useLikePhoto.js'
import { useLikePhoto } from '../../hooks/useLikePhoto.js'
import { useNearScreen } from '../../hooks/useNearScreen.js'
import { Link } from '@reach/router'
import { Link, navigate } from '@reach/router'
import { PropTypes } from 'prop-types'

const DEFAULT_IMAGE =
'https://images.unsplash.com/photo-1508280756091-9bdd7ef1f463?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60'

export const PhotoCard = ({ id, liked, likes = 0, src = DEFAULT_IMAGE }) => {
const { isAuth } = useContext(Context)
const [show, element] = useNearScreen()
const [toggleLikeAnonymous] = useLikePhotoAnonymous()
const [toggleLike] = useLikePhoto()
const handleFavButtonClick = () => {
if (isAuth) {
console.log('logueado')
toggleLike({ variables: { input: { id: id } } })
} else {
console.log('no logueado')
toggleLikeAnonymous({ variables: { input: { id: id } } })
navigate('/login')
}
}

Expand All @@ -48,3 +43,21 @@ export const PhotoCard = ({ id, liked, likes = 0, src = DEFAULT_IMAGE }) => {
</>
)
}

PhotoCard.propTypes = {
id: PropTypes.string.isRequired,
liked: PropTypes.bool.isRequired,
likes: function (props, propName, componentName) {
const propValue = props[propName]

if (propValue === undefined) {
return new Error(`${propName} value must be defined`)
}

if (propValue < 0) {
return new Error(`${propName} value must grether than zero`)
}
},
onClick: PropTypes.func,
src: PropTypes.string.isRequired
}
6 changes: 6 additions & 0 deletions src/components/PhotoDetail/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react'
import { PropTypes } from 'prop-types'
import { PhotoCard } from '../PhotoCard/'
import { useGetSinglePhoto } from '../../hooks/useGetSinglePhoto.js'

export const PhotoDetail = ({ id }) => {
const { loading, error, data } = useGetSinglePhoto(id)

Expand All @@ -17,3 +19,7 @@ export const PhotoDetail = ({ id }) => {
</>
)
}

PhotoDetail.propTypes = {
id: PropTypes.string.isRequired
}
7 changes: 7 additions & 0 deletions src/components/SubmitButton/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import React from 'react'
import { Button } from './styles.js'
import { PropTypes } from 'prop-types'
export const SubmitButton = ({ children, disabled = false, onClick }) => {
return (
<Button disabled={disabled} onClick={onClick}>
{children}
</Button>
)
}

SubmitButton.propTypes = {
children: PropTypes.node.isRequired,
disabled: PropTypes.bool,
onClick: PropTypes.func
}
27 changes: 27 additions & 0 deletions src/hooks/useCategoryData.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useState, useEffect } from 'react'

export const useCategoryData = () => {
const [categories, setCategories] = useState([])
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')

useEffect(() => {
const getCategories = async () => {
setLoading(true)
try {
const response = await window.fetch(
'https://silnose-petgram-api.vercel.app/categories'
)
const data = await response.json()
setCategories(data)
setLoading(false)
} catch (error) {
setLoading(false)
setError(error.message)
}
}
getCategories()
}, [])

return { categories, loading, error }
}
19 changes: 19 additions & 0 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,24 @@
</head>
<body>
<div id="app"></div>
<noscript>
<h3>
Your browser does not support JavaScript and this app need it ! :(
</h3>
</noscript>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker
.register('/service-worker.js')
.then((registration) => {
console.log('SW registered: ', registration)
})
.catch((registrationError) => {
console.log('SW registration failed: ', registrationError)
})
})
}
</script>
</body>
</html>
31 changes: 18 additions & 13 deletions src/pages/AnonymousUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import { Context } from '../Context'
import { UserForm, userFormActions } from '../components/UserForm'
import { useRegisterMutation } from '../hooks/useRegisterMutation'
import { useLoginMutation } from '../hooks/useLoginMutation'
import { Layout } from '../components/Layout/index'

export const AnonymousUser = () => {
const AnonymousUser = () => {
const { activateAuth } = useContext(Context)
const [register, { loadingRegister, errorRegister }] = useRegisterMutation()
const [login, { loadingLogin, errorLogin }] = useLoginMutation()
Expand All @@ -23,18 +24,22 @@ export const AnonymousUser = () => {

return (
<>
<UserForm
onSubmit={onSubmitRegister}
action={userFormActions.REGISTER}
error={errorRegister && errorRegister.message}
disabled={loadingRegister}
/>
<UserForm
onSubmit={onSubmitLogin}
action={userFormActions.LOGIN}
error={errorLogin && errorLogin.message}
disabled={loadingLogin}
/>
<Layout title='Sing In - Sing Up' subtitle='Welcome to petgram'>
<UserForm
onSubmit={onSubmitRegister}
action={userFormActions.REGISTER}
error={errorRegister && errorRegister.message}
disabled={loadingRegister}
/>
<UserForm
onSubmit={onSubmitLogin}
action={userFormActions.LOGIN}
error={errorLogin && errorLogin.message}
disabled={loadingLogin}
/>
</Layout>
</>
)
}

export default AnonymousUser
17 changes: 14 additions & 3 deletions src/pages/Detail.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import React from 'react'
import { PhotoDetail } from '../components/PhotoDetail/index'
import { Layout } from '../components/Layout'
import { PhotoDetail } from '../components/PhotoDetail'
import { PropTypes } from 'prop-types'

export const Detail = ({ detailId }) => {
return <PhotoDetail id={detailId} />
const Detail = ({ detailId }) => {
return (
<Layout title='More Details' subtitle='More Details of your pets'>
<PhotoDetail id={detailId} />
</Layout>
)
}
export default Detail

Detail.propTypes = {
id: PropTypes.number.isRequired
}
Loading

0 comments on commit d337639

Please sign in to comment.