From 5c85f67ae4a41218c89025801d304b1d16dbbabd Mon Sep 17 00:00:00 2001 From: Rick Date: Thu, 19 Aug 2021 20:14:11 -0500 Subject: [PATCH 01/27] Rick Mansfield's push/pull trail for Advaned Web Apps Sprint --- README.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 15ca32e1bc..09e5448e1c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,24 @@ # Advanced Web Applications Sprint Challenge +- [Advanced Web Applications Sprint Challenge](#advanced-web-applications-sprint-challenge) + - [Overview](#overview) + - [Introduction](#introduction) + - [Instructions](#instructions) + - [Task 1: Project Setup](#task-1-project-setup) + - [Task 2: CodeGrade Setup](#task-2-codegrade-setup) + - [Task 3: Project Requirements](#task-3-project-requirements) + - [Authentication](#authentication) + - [Consuming the API](#consuming-the-api) + - [Testing](#testing) + - [Reference Materials](#reference-materials) + - [API Documentation](#api-documentation) + - [Hex Color Examples](#hex-color-examples) + - [Submission format](#submission-format) + - [Interview Questions](#interview-questions) + - [Rick Mansfield's push/pull trail for Advanced Web Apps Sprint](#rick-mansfields-pushpull-trail-for-advanced-web-apps-sprint) + +## Overview + **Read these instructions carefully. Understand exactly what is expected _before_ starting this Sprint Challenge.** This challenge allows you to practice the concepts and techniques learned over the past sprint and apply them in a concrete project. This sprint explored **advanced web applications**. During this sprint, you studied **React testing, client-side auth, HTTP methods, and Vercel**. @@ -100,4 +119,8 @@ Be prepared to demonstrate your understanding of this week's concepts by answeri 1. Explain what a token is used for. 2. What steps can you take in your web apps to keep your data secure? 3. Describe how web servers work. -4. Which HTTP methods can be mapped to the CRUD acronym that we use when interfacing with APIs/Servers. \ No newline at end of file +4. Which HTTP methods can be mapped to the CRUD acronym that we use when interfacing with APIs/Servers. + +## Rick Mansfield's push/pull trail for Advanced Web Apps Sprint + +- [Link for convenience]() \ No newline at end of file From 12a586637da38ef934314c50fbd277fa402e1e36 Mon Sep 17 00:00:00 2001 From: Rick Date: Thu, 19 Aug 2021 20:15:05 -0500 Subject: [PATCH 02/27] add TOC to README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 09e5448e1c..04dc9b5311 100644 --- a/README.md +++ b/README.md @@ -123,4 +123,4 @@ Be prepared to demonstrate your understanding of this week's concepts by answeri ## Rick Mansfield's push/pull trail for Advanced Web Apps Sprint -- [Link for convenience]() \ No newline at end of file +- [Link for convenience]() \ No newline at end of file From 8c0e5fc6e367a672d191b990465d4919546f304c Mon Sep 17 00:00:00 2001 From: Rick Date: Thu, 19 Aug 2021 20:17:37 -0500 Subject: [PATCH 03/27] added Pull Req to Readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 04dc9b5311..2143669c84 100644 --- a/README.md +++ b/README.md @@ -123,4 +123,4 @@ Be prepared to demonstrate your understanding of this week's concepts by answeri ## Rick Mansfield's push/pull trail for Advanced Web Apps Sprint -- [Link for convenience]() \ No newline at end of file +- [Link for convenience](https://github.com/LambdaSchool/web-sprint-challenge-advanced-web-applications/pull/141) \ No newline at end of file From 17e400b240f67aaa6ee5689dbb2940e1829aca51 Mon Sep 17 00:00:00 2001 From: Rick Date: Fri, 20 Aug 2021 09:30:26 -0500 Subject: [PATCH 04/27] Create a CodeGrade submission From 9f3d64d34b2cb3d25b1d060c8406106d7270096b Mon Sep 17 00:00:00 2001 From: Rick Date: Fri, 20 Aug 2021 09:55:23 -0500 Subject: [PATCH 05/27] Loging.js Steps 1 & 2 complete --- src/components/Login.js | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/components/Login.js b/src/components/Login.js index 8df9390633..d2bae177ef 100644 --- a/src/components/Login.js +++ b/src/components/Login.js @@ -1,6 +1,8 @@ import React from "react"; const Login = () => { + //2. Add whatever state necessary for form functioning. + const [credentials, setCredentials] = useState({ username: "", password: "" }) // make a post request to retrieve a token from the api // when you have handled the token, navigate to the BubblePage route @@ -11,7 +13,28 @@ const Login = () => {

Welcome to the Bubble App!

-

Build login form here

+ {/*

Build login form here

*/} + {/* //1. Build a form containing a username and password field. */} +
+ + + + +

{error}

@@ -24,6 +47,7 @@ export default Login; //Task List: //1. Build a form containing a username and password field. //2. Add whatever state necessary for form functioning. +//3. Missing? or ommitted? //4. If either the username or password is not entered, display the following words with the p tag provided: Username or Password not valid. //5. If the username / password is equal to "Lambda" / "School", save that token to localStorage and redirect to a BubblePage route. //6. MAKE SURE YOUR USERNAME AND PASSWORD INPUTS INCLUDE id="username" and id="password" From 6844f26f6b4fd42e3a7ac01c97df48624a4bf23d Mon Sep 17 00:00:00 2001 From: Rick Date: Fri, 20 Aug 2021 09:57:28 -0500 Subject: [PATCH 06/27] Login.js Step 4 complete --- src/components/Login.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/Login.js b/src/components/Login.js index d2bae177ef..099cbd684c 100644 --- a/src/components/Login.js +++ b/src/components/Login.js @@ -9,6 +9,13 @@ const Login = () => { const error = ""; //replace with error state + const submit = e => { + e.preventDefault(); + //4. If either the username or password is not entered, display the following words with the p tag provided: Username or Password not valid. + if (!credentials.username || !credentials.password) { + return (setError("Username or Password not valid.")); + } + return (

Welcome to the Bubble App!

From b910cb9045ad8ccc76f5f9898f1a8dd3b3079a9d Mon Sep 17 00:00:00 2001 From: Rick Date: Fri, 20 Aug 2021 09:58:56 -0500 Subject: [PATCH 07/27] Login.js add error state --- src/components/Login.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Login.js b/src/components/Login.js index 099cbd684c..5474496105 100644 --- a/src/components/Login.js +++ b/src/components/Login.js @@ -6,12 +6,12 @@ const Login = () => { // make a post request to retrieve a token from the api // when you have handled the token, navigate to the BubblePage route - const error = ""; - //replace with error state + // const error = ""; //replace with error state //Part of #4B + const [error, setError] = useState(""); const submit = e => { e.preventDefault(); - //4. If either the username or password is not entered, display the following words with the p tag provided: Username or Password not valid. + //4.A If either the username or password is not entered, display the following words with the p tag provided: Username or Password not valid. if (!credentials.username || !credentials.password) { return (setError("Username or Password not valid.")); } From 73012d60c06f45332a27bcd9a7f69c6a008f8157 Mon Sep 17 00:00:00 2001 From: Rick Date: Fri, 20 Aug 2021 10:00:41 -0500 Subject: [PATCH 08/27] Login.js Add handleChange event handler --- src/components/Login.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/Login.js b/src/components/Login.js index 5474496105..cfd3630e0d 100644 --- a/src/components/Login.js +++ b/src/components/Login.js @@ -15,6 +15,13 @@ const Login = () => { if (!credentials.username || !credentials.password) { return (setError("Username or Password not valid.")); } + + const handleChange = e => { + setCredentials({ + ...credentials, + [e.target.name]: e.target.value + }); + }; return (
From 974ec1b52c76ad5e0bb3ed4b3af09ad802a6b2fa Mon Sep 17 00:00:00 2001 From: Rick Date: Fri, 20 Aug 2021 10:04:33 -0500 Subject: [PATCH 09/27] Login.js Tasks #5-8 complete --- src/components/Login.js | 70 ++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/src/components/Login.js b/src/components/Login.js index cfd3630e0d..0f9933b955 100644 --- a/src/components/Login.js +++ b/src/components/Login.js @@ -1,27 +1,41 @@ -import React from "react"; +import React, { useState } from "react"; +import axios from 'axios'; -const Login = () => { - //2. Add whatever state necessary for form functioning. - const [credentials, setCredentials] = useState({ username: "", password: "" }) - // make a post request to retrieve a token from the api - // when you have handled the token, navigate to the BubblePage route - // const error = ""; //replace with error state //Part of #4B +const Login = (props) => { + //2. Add whatever state necessary for form functioning. + const [credentials, setCredentials] = useState({ username: "", password: "" }) + + // const error = ""; //replace with error state const [error, setError] = useState(""); + const handleChange = e => { + setCredentials({ + ...credentials, + [e.target.name]: e.target.value + }); + }; + const submit = e => { e.preventDefault(); - //4.A If either the username or password is not entered, display the following words with the p tag provided: Username or Password not valid. + //4. If either the username or password is not entered, display the following words with the p tag provided: Username or Password not valid. if (!credentials.username || !credentials.password) { return (setError("Username or Password not valid.")); } - const handleChange = e => { - setCredentials({ - ...credentials, - [e.target.name]: e.target.value - }); - }; + // make a post request to retrieve a token from the api + axios.post('http://localhost:5000/api/login', credentials) + .then(res => { + //5. If the username / password is equal to Lambda / i<3Lambd4, save that token to localStorage. + // ABOVE CREDENTIALS DO NOT RETURN A TOKEN; ONLY A 403 ERROR! I have to use Lambda School per the readme. Looks like these are outdated tasks. + localStorage.setItem("token", res.data.payload); + // when you have handled the token, navigate to the BubblePage route + props.history.push('/bubble'); + }) + .catch(err => { + setError("Error logging in"); + }) + }; return (
@@ -29,8 +43,9 @@ const Login = () => {
{/*

Build login form here

*/} {/* //1. Build a form containing a username and password field. */} -
- +
+ {/* //6. MAKE SURE YOUR USERNAME AND PASSWORD INPUTS INCLUDE id="username" and id="password" */} + { value={credentials.password} onChange={handleChange} /> +
+ {/* //7. MAKE SURE YOUR SUBMIT BUTTON INCLUDES id="submit" */} + +
+
- -

{error}

+ {/* //8. MAKE SURE YOUR ERROR p tag contains the id="error" */} +

{error}

); }; @@ -59,11 +81,7 @@ const Login = () => { export default Login; //Task List: -//1. Build a form containing a username and password field. -//2. Add whatever state necessary for form functioning. -//3. Missing? or ommitted? -//4. If either the username or password is not entered, display the following words with the p tag provided: Username or Password not valid. -//5. If the username / password is equal to "Lambda" / "School", save that token to localStorage and redirect to a BubblePage route. -//6. MAKE SURE YOUR USERNAME AND PASSWORD INPUTS INCLUDE id="username" and id="password" -//7. MAKE SURE YOUR SUBMIT BUTTON INCLUDES id="submit" -//8. MAKE SURE YOUR ERROR p tag contains the id="error" \ No newline at end of file + +//3??? missing + + From d203e6eb77cffc795059858c324f156b00d93de3 Mon Sep 17 00:00:00 2001 From: Rick Date: Fri, 20 Aug 2021 10:07:58 -0500 Subject: [PATCH 10/27] refactor comments as breadcrumbs for later --- src/components/Login.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/Login.js b/src/components/Login.js index 0f9933b955..1e90c56735 100644 --- a/src/components/Login.js +++ b/src/components/Login.js @@ -26,8 +26,7 @@ const Login = (props) => { // make a post request to retrieve a token from the api axios.post('http://localhost:5000/api/login', credentials) .then(res => { - //5. If the username / password is equal to Lambda / i<3Lambd4, save that token to localStorage. - // ABOVE CREDENTIALS DO NOT RETURN A TOKEN; ONLY A 403 ERROR! I have to use Lambda School per the readme. Looks like these are outdated tasks. + //5. If the username / password is equal to "Lambda" / "School", save that token to localStorage and redirect to a BubblePage route. localStorage.setItem("token", res.data.payload); // when you have handled the token, navigate to the BubblePage route props.history.push('/bubble'); From 8d9432e535ca748550377a910cf4d65492166742 Mon Sep 17 00:00:00 2001 From: Rick Date: Fri, 20 Aug 2021 10:09:58 -0500 Subject: [PATCH 11/27] Built out fetchColorService.js --- src/services/fetchColorService.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/services/fetchColorService.js b/src/services/fetchColorService.js index a914deb477..9c97bbe08c 100644 --- a/src/services/fetchColorService.js +++ b/src/services/fetchColorService.js @@ -1,6 +1,16 @@ import axiosWithAuth from '../helpers/axiosWithAuth'; -const fetchColorService = () => { +const fetchColorService = (getColors) => { + axiosWithAuth() + .get(`/api/colors`) + .then((res)=>{ + console.log('fetchColorsServices res:', res); + getColors(res.data) + console.log('this is the setColors res.data', res.data); + }) + .catch(err => { + console.log(err); + }) } From 38efa27dc9bc9bd689b3e16f73618a6fe2d5d94e Mon Sep 17 00:00:00 2001 From: Rick Date: Fri, 20 Aug 2021 10:11:52 -0500 Subject: [PATCH 12/27] fixed typo readme from 'BubblePages' to BubblePage --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2143669c84..f928873b47 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Your finished project must include all of the following requirements. **Unlike o > *Add in the http requests and state changes needed to connect our api to the web application. Consider the effect of authentication on your api requests.* * [ ] In `services/fetchColorServices.js`, build out fetchColorService function to make a GET request to fetch the color data for your bubbles. -* [ ] When `BubblePages` mounts, call fetchColorServices and save it's result in state. +* [ ] When `BubblePage` mounts, call fetchColorServices and save it's result in state. * [ ] In `BubblePage.js`, complete `saveEdit`, and `deleteColor` functions to make API requests for to editing and delete data. * [ ] Watch and enjoy as your app responds to updates in the data. Check out `Bubbles.js` to see how this is built. From e4e50c4b5e49731f586c32183c343f010c5c7cb7 Mon Sep 17 00:00:00 2001 From: Rick Date: Fri, 20 Aug 2021 10:14:40 -0500 Subject: [PATCH 13/27] Complete Tasks 1 & 2 for BubblePage.js --- src/components/BubblePage.js | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/components/BubblePage.js b/src/components/BubblePage.js index 47a88f2291..15af9077b4 100644 --- a/src/components/BubblePage.js +++ b/src/components/BubblePage.js @@ -3,19 +3,37 @@ import React, { useEffect, useState } from "react"; import Bubbles from "./Bubbles"; import ColorList from "./ColorList"; import fetchColorService from '../services/fetchColorService'; +import axiosWithAuth from "../helpers/axiosWithAuth"; +import editColorService from "../services/saveEditService"; +import deleteColorService from "../services/deleteColorService"; -const BubblePage = () => { +const BubblePage = (props) => { const [colors, setColors] = useState([]); const [editing, setEditing] = useState(false); + //1. When the component mounts, make an axios call to retrieve all color data and push to state.useEffect + useEffect(()=>{ + axiosWithAuth() + fetchColorService(setColors); + },[editing]);//inserted "editing to prevent memory leak" + const toggleEdit = (value) => { setEditing(value); }; + +//2. Complete toggleEdit, saveEdit, deleteColor and functions const saveEdit = (editColor) => { + editColorService(editColor); + fetchColorService(setColors); + props.history.push('/bubble'); + toggleEdit(false) }; const deleteColor = (colorToDelete) => { + console.log('colorToDelete Obj in BubblePage.js', colorToDelete); + deleteColorService(colorToDelete.id); + fetchColorService(setColors); }; return ( From b1b39abd55c1374273906939c7e27ba3493cee6e Mon Sep 17 00:00:00 2001 From: Rick Date: Fri, 20 Aug 2021 10:23:07 -0500 Subject: [PATCH 14/27] Add Private route, axiosWithAuth delete & save fn --- README.md | 8 ++++---- src/App.js | 21 ++++++++++++++++++--- src/PrivateRoute.js | 14 ++++++++++++++ src/helpers/axiosWithAuth.js | 14 +++++++++++++- src/services/deleteColorService.js | 9 +++++++++ src/services/saveEditService.js | 9 +++++++++ 6 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 src/PrivateRoute.js create mode 100644 src/services/deleteColorService.js create mode 100644 src/services/saveEditService.js diff --git a/README.md b/README.md index f928873b47..f75de233a6 100644 --- a/README.md +++ b/README.md @@ -67,10 +67,10 @@ Your finished project must include all of the following requirements. **Unlike o * [ ] Build in functionality that would allow an error to be displayed in the provided p tag if either the username or password is incorrect. * [ ] **Make sure your error p tag has an id="error" attribute attached. Codegrade autotests will fail without them.** * [ ] Construct an http request that retrieves an auth token from the server when the username `Lambda` and the password `School` is passed into the request. -* [ ] Save the token to localStorage. -* [ ] Build a `axiosWithAuth` module within the helpers folder to create an instance of axios with the authentication header. -* [ ] Build a `PrivateRoute` component within the components folder and use it to protect the route that renders the `BubblesPage` component. -* [ ] In `App.js`, build the backend to the logout button. When pressed, send an http request to the logout endpoint and remove the authentication token from localStorage. Use window.location.href to redirect to the login page. +* [x] Save the token to localStorage. +* [x] Build a `axiosWithAuth` module within the helpers folder to create an instance of axios with the authentication header. +* [x] Build a `PrivateRoute` component within the components folder and use it to protect the route that renders the `BubblesPage` component. +* [x] In `App.js`, build the backend to the logout button. When pressed, send an http request to the logout endpoint and remove the authentication token from localStorage. Use window.location.href to redirect to the login page. #### Consuming the API > *Add in the http requests and state changes needed to connect our api to the web application. Consider the effect of authentication on your api requests.* diff --git a/src/App.js b/src/App.js index 4054971a97..01ec1b41fa 100644 --- a/src/App.js +++ b/src/App.js @@ -1,17 +1,32 @@ -import React, { useState } from "react"; -import { BrowserRouter as Router, Route } from "react-router-dom"; +import React from "react"; +import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; +import PrivateRoute from './components/PrivateRoute'; +import BubblePage from './components/BubblePage'; import Login from "./components/Login"; import "./styles.scss"; +//3A Build the logout button to call the logout endpoint, remove the localStorage Item and redirect to the login page. +const logout = () => { + localStorage.removeItem("token"); + window.location.href = "login"; +} function App() { return (
Color Picker Sprint Challenge - logout + {/* //3b. Build the logout button to call the logout endpoint, remove the localStorage Item and redirect to the login page. */} + logout
+ + {/* //2. Render BubblePage as a PrivateRoute */} + + {/* //1. Add in two routes that link to the Login Component, one for the default path '/' and one for the '/login'. */} + + +
); diff --git a/src/PrivateRoute.js b/src/PrivateRoute.js new file mode 100644 index 0000000000..23abd0e05e --- /dev/null +++ b/src/PrivateRoute.js @@ -0,0 +1,14 @@ +//Task List: +//1. Build a PrivateRoute component that redirects if user is not logged in +import React from 'react'; +import { Route, Redirect } from 'react-router-dom'; + +const PrivateRoute = ({component:Component, ...rest}) => { + if (localStorage.getItem("token")) { + return + } else { + return + } +} + +export default PrivateRoute; \ No newline at end of file diff --git a/src/helpers/axiosWithAuth.js b/src/helpers/axiosWithAuth.js index 1da418ff86..29c07554bc 100644 --- a/src/helpers/axiosWithAuth.js +++ b/src/helpers/axiosWithAuth.js @@ -1,4 +1,16 @@ import axios from "axios"; //Task List: -//Build and export a function used to send in our authorization token \ No newline at end of file +//Build and export a function used to send in our authorization token +const axiosWithAuth = () => { + const token = localStorage.getItem('token'); + + return axios.create({ + headers: { + Authorization: token + }, + baseURL: 'http://localhost:5000' + }) +} + +export default axiosWithAuth; \ No newline at end of file diff --git a/src/services/deleteColorService.js b/src/services/deleteColorService.js new file mode 100644 index 0000000000..76b0f0f8c2 --- /dev/null +++ b/src/services/deleteColorService.js @@ -0,0 +1,9 @@ +import axiosWithAuth from "../helpers/axiosWithAuth"; + +const deleteColorService = (colorToDeleteID) =>{ + console.log('colorToDeleteID is:', colorToDeleteID); + axiosWithAuth() + .delete(`api/colors/${colorToDeleteID}`) +} + +export default deleteColorService; \ No newline at end of file diff --git a/src/services/saveEditService.js b/src/services/saveEditService.js new file mode 100644 index 0000000000..fdd657ed4f --- /dev/null +++ b/src/services/saveEditService.js @@ -0,0 +1,9 @@ +import axiosWithAuth from "../helpers/axiosWithAuth"; + +const editColorService = (saveEditedColor) =>{ + const {id} = saveEditedColor; + axiosWithAuth() + .put(`api/colors/${id}`, saveEditedColor) +} + +export default editColorService; \ No newline at end of file From 66d8d8c4bb139ed01a723c569c50c2b38f241c1c Mon Sep 17 00:00:00 2001 From: Rick Date: Fri, 20 Aug 2021 10:28:26 -0500 Subject: [PATCH 15/27] Moved Private route to component folder --- src/PrivateRoute.js | 14 -------------- src/components/PrivateRoute.js | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 15 deletions(-) delete mode 100644 src/PrivateRoute.js diff --git a/src/PrivateRoute.js b/src/PrivateRoute.js deleted file mode 100644 index 23abd0e05e..0000000000 --- a/src/PrivateRoute.js +++ /dev/null @@ -1,14 +0,0 @@ -//Task List: -//1. Build a PrivateRoute component that redirects if user is not logged in -import React from 'react'; -import { Route, Redirect } from 'react-router-dom'; - -const PrivateRoute = ({component:Component, ...rest}) => { - if (localStorage.getItem("token")) { - return - } else { - return - } -} - -export default PrivateRoute; \ No newline at end of file diff --git a/src/components/PrivateRoute.js b/src/components/PrivateRoute.js index e718313bdf..ca8b875fe8 100644 --- a/src/components/PrivateRoute.js +++ b/src/components/PrivateRoute.js @@ -1,2 +1,15 @@ //Task List: -//1. Build a PrivateRoute component that redirects if user is not logged in \ No newline at end of file +//1. Build a PrivateRoute com//Task List: +//1. Build a PrivateRoute component that redirects if user is not logged in +import React from 'react'; +import { Route, Redirect } from 'react-router-dom'; + +const PrivateRoute = ({component:Component, ...rest}) => { + if (localStorage.getItem("token")) { + return + } else { + return + } +} + +export default PrivateRoute; \ No newline at end of file From 481f15ca13cc5eab3c07b4a3de71319ee4840eef Mon Sep 17 00:00:00 2001 From: Rick Date: Fri, 20 Aug 2021 10:30:24 -0500 Subject: [PATCH 16/27] Consumbing the API complete --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f75de233a6..5f55401411 100644 --- a/README.md +++ b/README.md @@ -75,10 +75,10 @@ Your finished project must include all of the following requirements. **Unlike o #### Consuming the API > *Add in the http requests and state changes needed to connect our api to the web application. Consider the effect of authentication on your api requests.* -* [ ] In `services/fetchColorServices.js`, build out fetchColorService function to make a GET request to fetch the color data for your bubbles. -* [ ] When `BubblePage` mounts, call fetchColorServices and save it's result in state. -* [ ] In `BubblePage.js`, complete `saveEdit`, and `deleteColor` functions to make API requests for to editing and delete data. -* [ ] Watch and enjoy as your app responds to updates in the data. Check out `Bubbles.js` to see how this is built. +* [x] In `services/fetchColorServices.js`, build out fetchColorService function to make a GET request to fetch the color data for your bubbles. +* [x] When `BubblePage` mounts, call fetchColorServices and save it's result in state. +* [x] In `BubblePage.js`, complete `saveEdit`, and `deleteColor` functions to make API requests for to editing and delete data. +* [x] Watch and enjoy as your app responds to updates in the data. Check out `Bubbles.js` to see how this is built. #### Testing * [ ] Finish the test in `Color.test.js`, `ColorList.test.js`, `BubblePage.test.js`. You will need to use rerendering, function mocking and spies in order to complete. From d6611e4f7ce1a7dcf9b39a15a5f21f320b415cb1 Mon Sep 17 00:00:00 2001 From: Rick Date: Fri, 20 Aug 2021 10:42:26 -0500 Subject: [PATCH 17/27] Refactor