From e6bcddfa3e685581d142bbc18884ad258d754eee Mon Sep 17 00:00:00 2001 From: Savy Date: Sun, 14 May 2023 18:18:02 +0530 Subject: [PATCH] Finished 7.13 --- Part_7/bloglist-frontend/.prettierrc.json | 2 +- Part_7/bloglist-frontend/src/App.js | 145 +++++------------- .../bloglist-frontend/src/components/Blog.js | 4 +- .../src/components/BlogForm.js | 2 +- Part_7/bloglist-frontend/src/index.js | 9 +- .../bloglist-frontend/src/services/blogs.js | 47 ------ .../bloglist-frontend/src/services/login.js | 2 +- .../src/utils/NotifContext.js | 18 ++- .../src/utils/UserContext.js | 26 ++++ .../bloglist-frontend/src/utils/requests.js | 8 +- 10 files changed, 99 insertions(+), 164 deletions(-) delete mode 100644 Part_7/bloglist-frontend/src/services/blogs.js create mode 100644 Part_7/bloglist-frontend/src/utils/UserContext.js diff --git a/Part_7/bloglist-frontend/.prettierrc.json b/Part_7/bloglist-frontend/.prettierrc.json index a636c6c..5922486 100644 --- a/Part_7/bloglist-frontend/.prettierrc.json +++ b/Part_7/bloglist-frontend/.prettierrc.json @@ -4,7 +4,7 @@ "singleQuote": true, "bracketSpacing": true, "bracketSameLine": false, - "arrowParens": "always", + "arrowParens": "avoid", "endOfLine": "lf", "singleAttributePerLine": true } \ No newline at end of file diff --git a/Part_7/bloglist-frontend/src/App.js b/Part_7/bloglist-frontend/src/App.js index 63ed095..9b2fa16 100644 --- a/Part_7/bloglist-frontend/src/App.js +++ b/Part_7/bloglist-frontend/src/App.js @@ -2,10 +2,8 @@ import { useState, useEffect, useRef, useContext } from 'react' import Blog from './components/Blog' import BlogForm from './components/BlogForm' import Toggleable from './components/Toggleable' -// eslint-disable-next-line no-unused-vars -import blogService from './services/blogs' import loginService from './services/login' -import NotifContext from './utils/NotifContext' +import NotifContext, { useNotification } from './utils/NotifContext' import { useMutation, useQuery, useQueryClient } from 'react-query' import { postBlog, @@ -14,43 +12,42 @@ import { putBlog, removeBlog, } from './utils/requests' +import UserContext from './utils/UserContext' const App = () => { - // eslint-disable-next-line no-unused-vars - const [blogsList, setBlogs] = useState([]) const [username, setUsername] = useState('') const [password, setPassword] = useState('') - const [user, setUser] = useState(null) - const [notif, dispatch] = useContext(NotifContext) + // eslint-disable-next-line no-unused-vars + const [notif, notifDispatch] = useContext(NotifContext) + const [user, userDispatch] = useContext(UserContext) const blogFormRef = useRef() const queryClient = useQueryClient() + const setNotif = useNotification() const result = useQuery('blogs', getAllBlogs, { retry: 1 }) const blogs = result.data const createBlogMutation = useMutation(postBlog, { - onSuccess: (newBlog) => { + onSuccess: newBlog => { const blogsList = queryClient.getQueryData('blogs') queryClient.invalidateQueries('blogs', blogsList.concat(newBlog)) }, }) const updateBlogMutation = useMutation(putBlog, { - onSuccess: (votedBlog) => { + onSuccess: votedBlog => { const prevBlogs = queryClient.getQueryData('blogs') - const updatedBlog = prevBlogs.find((b) => b.id === votedBlog.id) + const updatedBlog = prevBlogs.find(b => b.id === votedBlog.id) updatedBlog.votes = votedBlog.likes queryClient.invalidateQueries('blogs', prevBlogs) }, }) const deleteBlogMutation = useMutation(removeBlog, { - onSuccess: (deletedBlog) => { + onSuccess: deletedBlog => { const prevBlogs = queryClient.getQueryData('blogs') - const filteredBlogs = prevBlogs.filter( - (b) => b.id !== deletedBlog.id - ) + const filteredBlogs = prevBlogs.filter(b => b.id !== deletedBlog.id) queryClient.invalidateQueries('blogs', filteredBlogs) }, }) @@ -60,140 +57,82 @@ const App = () => { if (loggedUserJSON) { const user = JSON.parse(loggedUserJSON) - setUser(user) - setToken(user.token) + userDispatch({ type: 'SET_USER', payload: user }) + if (user.token) { + setToken(user.token) + } } }, []) - const handleLogin = async (event) => { + const handleLogin = async event => { event.preventDefault() try { - const user = await loginService.login({ username, password }) + const loggedUser = await loginService.login({ username, password }) window.localStorage.setItem( 'loggedBlogAppUser', - JSON.stringify(user) + JSON.stringify(loggedUser) ) - setToken(user.token) - setUser(user) + userDispatch({ type: 'SET_USER', payload: loggedUser }) + setToken(loggedUser.token) setUsername('') setPassword('') - } catch (exception) { - dispatch({ type: 'SET', payload: 'Wrong Credentials' }) - setTimeout(() => { - dispatch({ type: 'CLEAR' }) - }, 5000) + } catch (err) { + setNotif('Wrong Credentials', 5000) - console.error(exception) + console.error(err) } } - const handleLogout = (event) => { + const handleLogout = event => { event.preventDefault() window.localStorage.removeItem('loggedBlogAppUser') - setUser(null) + userDispatch({ type: 'CLEAR_USER' }) } - const createBlog = async (blogObj) => { + const createBlog = async blogObj => { blogFormRef.current.toggleVisibility() try { createBlogMutation.mutateAsync(blogObj) - dispatch({ - type: 'SET', - payload: `Blog '${blogObj.title}' by ${blogObj.author} added!`, - }) - setTimeout(() => { - dispatch({ type: 'CLEAR' }) - }, 5000) + setNotif( + `Blog '${blogObj.title}' by ${blogObj.author} added!`, + 5000 + ) } catch (err) { - dispatch({ - type: 'SET', - payload: `Error occured while creating '${blogObj.title}'`, - }) - setTimeout(() => { - dispatch({ type: 'CLEAR' }) - }, 5000) + setNotif(`Error occured while creating '${blogObj.title}'`, 5000) console.error(err) } } - const updateBlog = async (blogObj) => { + const updateBlog = async blogObj => { try { updateBlogMutation.mutateAsync(blogObj) - dispatch({ - type: 'SET', - payload: `Liked '${blogObj.title}' by ${blogObj.author}`, - }) - setTimeout(() => { - dispatch({ type: 'CLEAR' }) - }, 5000) + setNotif(`Liked '${blogObj.title}' by ${blogObj.author}`, 5000) } catch (err) { - dispatch({ - type: 'SET', - payload: `Error occured while updating '${blogObj.title}'`, - }) - setTimeout(() => { - dispatch({ type: 'CLEAR' }) - }, 5000) + setNotif(`Error occured while updating '${blogObj.title}'`, 5000) console.error(err) } } - const deleteBlog = async (blogObj) => { + const deleteBlog = async blogObj => { try { const confirmation = window.confirm(`Delete ${blogObj.title}?`) if (confirmation) { deleteBlogMutation.mutateAsync(blogObj) - dispatch({ - type: 'SET', - payload: `Deleted '${blogObj.title}' by ${blogObj.author}`, - }) - setTimeout(() => { - dispatch({ type: 'CLEAR' }) - }, 5000) + setNotif( + `Deleted '${blogObj.title}' by ${blogObj.author}`, + 5000 + ) } - dispatch({ - type: 'SET', - payload: 'Deletition Cancelled', - }) - setTimeout(() => { - dispatch({ type: 'CLEAR' }) - }, 5000) + setNotif('Deletition Cancelled', 5000) } catch (err) { + setNotif(`Error occured while Deleting '${blogObj.title}'`, 5000) console.log(err) } } - /*const deleteBlog = async (blogObj) => { - try { - const confirmation = window.confirm(`Delete ${blogObj.title}`) - if (confirmation) { - await blogService.remove(blogObj) - await blogService - .getAll() - .then((updatedBlogs) => setBlogs(updatedBlogs)) - } - dispatch({ - type: 'SET', - payload: `Deleted '${blogObj.title}' by ${blogObj.author}`, - }) - setTimeout(() => { - dispatch({ type: 'CLEAR' }) - }, 5000) - } catch (exception) { - dispatch({ - type: 'SET', - payload: `Error occured while deleting '${blogObj.title}'`, - }) - setTimeout(() => { - dispatch({ type: 'CLEAR' }) - }, 5000) - console.error(exception) - } - }*/ - const NotifBox = () => { const style = { padding: 5, @@ -279,7 +218,7 @@ const App = () => {
{blogs .sort((a, b) => b.likes - a.likes) - .map((blog) => ( + .map(blog => ( { const showWhenVisible = { display: visible ? '' : 'none' } const buttonLabel = visible ? 'Hide' : 'Show' - const likeBlog = (event) => { + const likeBlog = event => { event.preventDefault() const updatedBlog = { @@ -27,7 +27,7 @@ const Blog = ({ blog, user, updateBlog, deleteBlog }) => { setBlogObj(updatedBlog) } - const removeBlog = (event) => { + const removeBlog = event => { event.preventDefault() deleteBlog(blogObj) } diff --git a/Part_7/bloglist-frontend/src/components/BlogForm.js b/Part_7/bloglist-frontend/src/components/BlogForm.js index 9337527..a8ce627 100644 --- a/Part_7/bloglist-frontend/src/components/BlogForm.js +++ b/Part_7/bloglist-frontend/src/components/BlogForm.js @@ -10,7 +10,7 @@ const BlogForm = ({ createBlog }) => { createBlog: propTypes.func.isRequired, } - const addBlog = (event) => { + const addBlog = event => { event.preventDefault() createBlog({ title, author, url }) diff --git a/Part_7/bloglist-frontend/src/index.js b/Part_7/bloglist-frontend/src/index.js index 06e93af..395a930 100644 --- a/Part_7/bloglist-frontend/src/index.js +++ b/Part_7/bloglist-frontend/src/index.js @@ -1,6 +1,7 @@ import React from 'react' import ReactDOM from 'react-dom/client' import { NotifContextProvider } from './utils/NotifContext' +import { UserContextProvider } from './utils/UserContext' import { QueryClient, QueryClientProvider } from 'react-query' import App from './App' import './index.css' @@ -9,8 +10,10 @@ const queryClient = new QueryClient() ReactDOM.createRoot(document.getElementById('root')).render( - - - + + + + + ) diff --git a/Part_7/bloglist-frontend/src/services/blogs.js b/Part_7/bloglist-frontend/src/services/blogs.js deleted file mode 100644 index 521a218..0000000 --- a/Part_7/bloglist-frontend/src/services/blogs.js +++ /dev/null @@ -1,47 +0,0 @@ -import axios from 'axios' -const baseUrl = 'http://localhost:3001/api/blogs' - -let token = null - -const setToken = (newToken) => { - token = `Bearer ${newToken}` -} - -const getAll = async () => { - const response = await axios.get(baseUrl) - - return response.data -} - -const create = async (blogContents) => { - const config = { - headers: { Authorization: token }, - } - const response = await axios.post(baseUrl, blogContents, config) - - return response.data -} - -const update = async (blogContents) => { - const config = { - headers: { Authorization: token }, - } - const response = await axios.put( - `${baseUrl}/${blogContents.id}`, - blogContents, - config - ) - - return response.data -} - -const remove = async (blogContents) => { - const config = { - headers: { Authorization: token }, - } - const response = await axios.delete(`${baseUrl}/${blogContents.id}`, config) - - return response.data -} - -export default { getAll, create, update, remove, setToken } diff --git a/Part_7/bloglist-frontend/src/services/login.js b/Part_7/bloglist-frontend/src/services/login.js index 29ccbd9..6a56886 100644 --- a/Part_7/bloglist-frontend/src/services/login.js +++ b/Part_7/bloglist-frontend/src/services/login.js @@ -1,7 +1,7 @@ import axios from 'axios' const baseUrl = 'http://localhost:3001/api/login' -const login = async (credentials) => { +const login = async credentials => { const response = await axios.post(baseUrl, credentials) return response.data } diff --git a/Part_7/bloglist-frontend/src/utils/NotifContext.js b/Part_7/bloglist-frontend/src/utils/NotifContext.js index b519da7..17913c9 100644 --- a/Part_7/bloglist-frontend/src/utils/NotifContext.js +++ b/Part_7/bloglist-frontend/src/utils/NotifContext.js @@ -1,4 +1,4 @@ -import { useReducer, createContext } from 'react' +import { useReducer, createContext, useContext } from 'react' const notifReducer = (state, action) => { switch (action.type) { @@ -13,7 +13,7 @@ const notifReducer = (state, action) => { const NotifContext = createContext() -export const NotifContextProvider = (props) => { +export const NotifContextProvider = props => { const [notif, notifDispatch] = useReducer(notifReducer, '') return ( @@ -23,4 +23,18 @@ export const NotifContextProvider = (props) => { ) } +export const useNotification = () => { + // eslint-disable-next-line no-unused-vars + const [notif, notifDispatch] = useContext(NotifContext) + + const setNotif = (message, time) => { + notifDispatch({ type: 'SET', payload: message }) + setTimeout(() => { + notifDispatch({ type: 'CLEAR' }) + }, time) + } + + return setNotif +} + export default NotifContext diff --git a/Part_7/bloglist-frontend/src/utils/UserContext.js b/Part_7/bloglist-frontend/src/utils/UserContext.js new file mode 100644 index 0000000..c2dcea6 --- /dev/null +++ b/Part_7/bloglist-frontend/src/utils/UserContext.js @@ -0,0 +1,26 @@ +import { createContext, useReducer } from 'react' + +const userReducer = (state, action) => { + switch (action.type) { + case 'SET_USER': + return action.payload + case 'CLEAR_USER': + return null + default: + return state + } +} + +const UserContext = createContext() + +export const UserContextProvider = props => { + const [user, userDispatch] = useReducer(userReducer, null) + + return ( + + {props.children} + + ) +} + +export default UserContext diff --git a/Part_7/bloglist-frontend/src/utils/requests.js b/Part_7/bloglist-frontend/src/utils/requests.js index bda039f..8bb43ab 100644 --- a/Part_7/bloglist-frontend/src/utils/requests.js +++ b/Part_7/bloglist-frontend/src/utils/requests.js @@ -3,7 +3,7 @@ const baseUrl = 'http://localhost:3001/api/blogs' let token = null -export const setToken = (newToken) => { +export const setToken = newToken => { token = `Bearer ${newToken}` } @@ -13,7 +13,7 @@ export const getAllBlogs = async () => { return response.data } -export const postBlog = async (blogContents) => { +export const postBlog = async blogContents => { const config = { headers: { Authorization: token }, } @@ -22,7 +22,7 @@ export const postBlog = async (blogContents) => { return response.data } -export const putBlog = async (blogContents) => { +export const putBlog = async blogContents => { const config = { headers: { Authorization: token }, } @@ -35,7 +35,7 @@ export const putBlog = async (blogContents) => { return response.data } -export const removeBlog = async (blogContents) => { +export const removeBlog = async blogContents => { const config = { headers: { Authorization: token }, } -- 2.51.2