Created
May 4, 2020 23:33
-
-
Save chukwumaijem/33e5c00ca8ef3c093e42cac5149cd945 to your computer and use it in GitHub Desktop.
Revisions
-
Chukwuma Ezumezu created this gist
May 4, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,16 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import * as serviceWorker from './serviceWorker'; import Todos from './Todos/Todos'; import { store } from './store'; ReactDOM.render( <Provider store={store}> <Todos /> </Provider>, document.getElementById('root') ); serviceWorker.unregister(); This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,50 @@ import React from 'react'; import { connect } from 'react-redux'; import { deleteTodo, updateTodo } from './TodosSlice'; import { REMOVE_TODO, UPDATE_TODO } from './queries'; function Todo({ todo, deleteTodoAction, updateTodoAction }) { const { id, text, completed } = todo; const handleTodoDelete = () => { deleteTodoAction(REMOVE_TODO(id)); }; const handleTodoUpdate = () => { updateTodoAction(UPDATE_TODO(id)); }; return ( <div className={` row card-body list-group-item-${completed ? 'success' : 'info'} `} > <span className="col-sm-8">{text}</span> <button onClick={handleTodoUpdate} className={`col-sm-2 btn btn-${completed ? 'success' : 'info'}`} type="button" > {completed ? 'Done' : 'Pending'} </button> <button onClick={handleTodoDelete} className="col-sm-2 btn btn-danger" type="button" > Remove </button> </div> ); } const mapDispatchToProps = { deleteTodoAction: deleteTodo, updateTodoAction: updateTodo, }; export default connect(null, mapDispatchToProps)(Todo); This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,63 @@ import React, { useEffect, useState } from 'react'; import { connect } from 'react-redux'; import { fetchTodos, createTodo } from './TodosSlice'; import { READ_TODOS, CREATE_TODO } from './queries'; import Todo from './Todo'; function Todos({ todos, fetchTodosActions, createTodoAction }) { const [newTodo, setNewTodo] = useState(''); useEffect(() => { fetchTodosActions(READ_TODOS); // eslint-disable-next-line }, []); const handleTodoSubmit = (e) => { e.preventDefault(); createTodoAction(CREATE_TODO(newTodo)); setNewTodo(''); }; const handleTodoChange = (e) => { setNewTodo(e.target.value); }; return ( <div className="container-sm"> <h4>Todo App</h4> <form onSubmit={handleTodoSubmit}> <div className="form-group row"> <input className="form-control col-sm-10" type="text" placeholder="Enter todo" value={newTodo} onChange={handleTodoChange} /> <button className="btn btn-primary col-sm-2" type="submit"> Submit </button> </div> </form> <div className="card"> {todos.map((todo) => ( <Todo todo={todo} key={todo.id} /> ))} </div> </div> ); } const mapStateToProps = (state) => { return { todos: state.todos, }; }; const mapDispatchToProps = { fetchTodosActions: fetchTodos, createTodoAction: createTodo, }; export default connect(mapStateToProps, mapDispatchToProps)(Todos); This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,12 @@ import axios from 'axios'; const API_URL = process.env.REACT_APP_GRAPHQL_URL; export const apiRequest = async (query) => { try { const { data: { data } } = await axios.post(API_URL, query); return data; } catch (error) { return { error }; } }; This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,31 @@ export const READ_TODOS = ` query todos { todos { id text completed } } `; export const CREATE_TODO = (text) => ` mutation { createTodo(text: "${text}") { id text completed } } `; export const REMOVE_TODO = (id) => ` mutation { removeTodo(id: "${id}") } `; export const UPDATE_TODO = (id) => ` mutation { updateTodo(id: "${id}") } `; This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,7 @@ import { configureStore } from '@reduxjs/toolkit'; import todosReducer from './Todos/TodosSlice'; export const store = configureStore({ reducer: todosReducer, }); This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,113 @@ import { createSlice } from '@reduxjs/toolkit'; import { apiRequest } from '../api'; const todosSlice = createSlice({ name: 'todos', initialState: { todos: [], loading: 'idle', }, reducers: { createTodoRequest(state) { if (state.loading === 'idle') { state.loading = 'pending'; } }, createTodoResponse(state, action) { if (state.loading === 'pending') { state.loading = 'idle'; state.todos.push(action.payload); } }, fetchTodoRequest(state) { if (state.loading === 'idle') { state.loading = 'pending'; } }, fetchTodoResponse(state, action) { if (state.loading === 'pending') { state.loading = 'idle'; state.todos = action.payload; } }, updateTodoRequest(state) { if (state.loading === 'idle') { state.loading = 'pending'; } }, updateTodoResponse(state, action) { if (state.loading === 'pending') { state.loading = 'idle'; const updatedTodoIndex = state.todos.findIndex( (todo) => todo.id === action.payload ); const updatedTodo = state.todos[updatedTodoIndex]; state.todos[updatedTodoIndex].completed = !updatedTodo.completed; } }, deleteTodoRequest(state) { if (state.loading === 'idle') { state.loading = 'pending'; } }, deleteTodoResponse(state, action) { if (state.loading === 'pending') { state.loading = 'idle'; state.todos = state.todos.filter((todo) => todo.id !== action.payload); } }, }, }); const { fetchTodoRequest, fetchTodoResponse, createTodoRequest, createTodoResponse, updateTodoRequest, updateTodoResponse, deleteTodoRequest, deleteTodoResponse, } = todosSlice.actions; export default todosSlice.reducer; export const createTodo = (query) => async (dispatch) => { dispatch(createTodoRequest()); const body = { query, }; const { createTodo: newTodo } = await apiRequest(body); dispatch(createTodoResponse(newTodo)); }; export const fetchTodos = (query) => async (dispatch) => { dispatch(fetchTodoRequest()); const body = { query, }; const { todos } = await apiRequest(body); dispatch(fetchTodoResponse(todos)); }; export const updateTodo = (query, variables = {}) => async (dispatch) => { dispatch(updateTodoRequest()); const body = { query, }; const { updateTodo: updatedTodoId } = await apiRequest(body); dispatch(updateTodoResponse(updatedTodoId)); }; export const deleteTodo = (query) => async (dispatch) => { dispatch(deleteTodoRequest()); const body = { query, }; const { removeTodo: removedTodoId } = await apiRequest(body); dispatch(deleteTodoResponse(removedTodoId)); };