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
22 changes: 22 additions & 0 deletions Answers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
- [ ] Explain what a token is used for.

A token is used to allow a consistent user experience while keeping the web app secure. Implementing a token replaces the need for a user to login at every route change.


- [ ] What steps can you take in your web apps to keep your data secure?

I can keep my web apps secure by implementing tokens and private routes.


- [ ] Describe how web servers work.

Web servers are very strict, ridged, and forgetful (meaning it makes no friends and won't remember who you are...Have your token ready at the port). This makes them a perfect candidate to store, process and deliver web pages to clients.


- [ ] Which HTTP methods can be mapped to the CRUD acronym that we use when interfacing with APIs/Servers.

Create = PUT with a new URI
POST to a base URI returning a newly created URI
Read = GET
Update = PUT with an existing URI
Delete = DELETE
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ This challenge allows you to practice the concepts and techniques learned over t

This is an individual assessment. All work must be your own. Your challenge score is a measure of your ability to work independently using the material covered through this sprint. You need to demonstrate proficiency in the concepts and objectives introduced and practiced in preceding days.

You are not allowed to collaborate during the Sprint Challenge. However, you are encouraged to follow the twenty-minute rule and seek support from your PM and Instructor in your cohort help channel on Slack. Your work reflects your proficiency ReactJS Fundamentals and your command of the concepts and techniques in the Function Components and Class Components.
You are not allowed to collaborate during the Sprint Challenge. However, you are encouraged to follow the twenty-minute rule and seek support from your TL and Instructor in your cohort help channel on Slack. Your work reflects your proficiency ReactJS Fundamentals and your command of the concepts and techniques in the Function Components and Class Components.

You have three hours to complete this challenge. Plan your time accordingly.

## Commits

Commit your code regularly and meaningfully. This helps both you (in case you ever need to return to old code for any number of reasons and your project manager).
Commit your code regularly and meaningfully. This helps both you (in case you ever need to return to old code for any number of reasons and your Team Lead).

## Description

Expand All @@ -26,7 +26,9 @@ In this project you will create a login page and request a token from the server

## Self-Study/Essay Questions

Demonstrate your understanding of this Sprint's concepts by answering the following free-form questions. Edit this document to include your answers after each question. Make sure to leave a blank line above and below your answer so it is clear and easy to read by your project manager.
Demonstrate your understanding of this Sprint's concepts by answering the following free-form questions. Edit this document to include your answers after each question. Make sure to leave a blank line above and below your answer so it is clear and easy to read by your Team Lead.

`Answers found in Answers.md`

- [ ] Explain what a token is used for.
- [ ] What steps can you take in your web apps to keep your data secure?
Expand All @@ -39,14 +41,14 @@ Demonstrate your understanding of this Sprint's concepts by answering the follow
Follow these steps to set up and work on your project:

- [ ] Create a forked copy of this project.
- [ ] Add PM as collaborator on Github.
- [ ] Add TL as collaborator on Github.
- [ ] Clone your OWN version of Repo (Not Lambda's by mistake!).
- [ ] Create a new Branch on the clone: git checkout -b `<firstName-lastName>`.
- [ ] Implement the project on this Branch, committing changes regularly.
- [ ] Push commits: git push origin `<firstName-lastName>`.
- [ ] **RUN** `yarn install or npm install` at the root to retrieve all the dependencies for the node server. You will not need to create any react apps here nor will you need to install any other dependencies. You should have all you need in this repo.
- [ ] **LOOK** at all the files you've been given for this project. One important file to note is `server.js`. This file contains an **API** that you are going to be interfacing with. Below is documentation on how to interact with the **API**.
- [ ] **RUN** `yarn start or npm start` to get your API up and running on `http://localhost:3333`. This is the **URL** you're going to need to use within your React app in order to make AJAX requests for data.
- [ ] **RUN** `yarn start or npm start` to get your API up and running on `http://localhost:5000`. This is the **URL** you're going to need to use within your React app in order to make AJAX requests for data.
- [ ] **LOOK** at your `client` directory and notice it's just a plain ol' React App that we've built using `create-react-app`.
- [ ] **cd** into `client` and run `yarn install or npm install` to retrieve the client side dependencies.
- [ ] **RUN** `yarn start or npm start` to fire up your React application.
Expand Down Expand Up @@ -93,4 +95,5 @@ Build a login form to authenticate your users.
**Data Visualization**

- [ ] Look at [Potion JS](https://potion.js.org/). This is the library used to display the color data
- [ ] Play around with the data visualation happening in `Bubbles.js`. Have fun with this! Try different components from the library, or see if you can add props to change the UI a bit.
- [ ] Play around with the data visualization happening in `Bubbles.js`. Have fun with this! Try different components from the library, or see if you can add props to change the UI a bit.
Random thing
22 changes: 9 additions & 13 deletions client/src/App.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
import React, { useState } from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import React, { useState } from "react"
import { Route } from "react-router-dom"
import { PrivateRoute } from './utilities/PrivateRoute'
import BubblePage from './components/BubblePage'

import Login from "./components/Login";
import "./styles.scss";
import Login from "./components/Login"
import "./styles.scss"

function App() {
const [colorList, setColorList] = useState([]);
return (
<Router>
<div className="App">
<Route exact path="/" component={Login} />
{/*
Build a PrivateRoute component that will
display BubblePage when you're authenticated
*/}
<PrivateRoute exact path ='/bubbles' component={BubblePage} />
</div>
</Router>
);
)
}

export default App;
export default App
25 changes: 16 additions & 9 deletions client/src/components/BubblePage.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
import React, { useState, useEffect } from "react";
import axios from "axios";

import Bubbles from "./Bubbles";
import ColorList from "./ColorList";
import React, { useState, useEffect } from "react"
import { axiosWithAuth } from '../utilities/axiosWithAuth'
import Bubbles from "./Bubbles"
import ColorList from "./ColorList"

const BubblePage = () => {
const [colorList, setColorList] = useState([]);
const [colorList, setColorList] = useState([])
// fetch your colors data from the server when the component mounts
// set that data to the colorList state property
useEffect(() => {
axiosWithAuth().get('/api/colors')
.then(res => {
console.log(res)
setColorList(res.data)
})
.catch(err => console.log(err))
}, [])

return (
<>
<ColorList colors={colorList} updateColors={setColorList} />
<Bubbles colors={colorList} />
</>
);
};
)
}

export default BubblePage;
export default BubblePage
23 changes: 14 additions & 9 deletions client/src/components/Bubbles.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import React, { useState, useEffect } from "react";
import { Pack } from "@potion/layout";
import { Svg, Circle } from "@potion/element";
import React, { useState, useEffect } from "react"
import { Pack, Chord } from "@potion/layout"
import { Svg, Circle } from "@potion/element"
import Ribbon from "@potion/element/lib/Ribbon"

const Bubbles = ({ colors }) => {
const [bubbleData, setBubbleData] = useState([]);
console.log(bubbleData)
useEffect(() => {
const generateBubbleData = colors.map((_, i) => ({
value: Math.floor(Math.random() * (colors.length * 2)) + 1,
key: `${i + 1}`
}));
}))
setBubbleData(generateBubbleData);
}, [colors]);

}, [colors])
const codes = colors.map(item => item.code)
const hexes = codes.map(item => item.hex)
console.log(hexes)

return (
<div className="bubble-wrap">
<p>bubbles</p>
Expand Down Expand Up @@ -47,7 +52,7 @@ const Bubbles = ({ colors }) => {
</Pack>
</Svg>
</div>
);
};
)
}

export default Bubbles;
export default Bubbles
99 changes: 82 additions & 17 deletions client/src/components/ColorList.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,66 @@
import React, { useState } from "react";
import axios from "axios";
import React, { useState } from "react"
import { axiosWithAuth } from '../utilities/axiosWithAuth'

const initialColor = {
color: "",
code: { hex: "" }
};
}

const ColorList = ({ colors, updateColors }) => {
console.log(colors);
const [editing, setEditing] = useState(false);
const [colorToEdit, setColorToEdit] = useState(initialColor);
console.log(colors)
const [editing, setEditing] = useState(false)
const [colorToEdit, setColorToEdit] = useState(initialColor)
const [newColor, setNewColor] = useState({
color: '',
hex: ''
})
console.log(newColor)

const editColor = color => {
setEditing(true);
setColorToEdit(color);
};
setEditing(true)
setColorToEdit(color)
}

const saveEdit = e => {
e.preventDefault();
e.preventDefault()
// Make a put request to save your updated color
// think about where will you get the id from...
// where is is saved right now?
};
axiosWithAuth().put(`/api/colors/${colorToEdit.id}`, colorToEdit)
.then(res => {
console.log(res)
setEditing(false)
updateColors(colors.map((item) => {
return item.id === colorToEdit.id ? colorToEdit : item

}))
})
.catch(err => console.log(err))
}

const deleteColor = color => {
// make a delete request to delete this color
};
axiosWithAuth().delete(`/api/colors/${color.id}`)
.then(res => {
console.log(res)
updateColors(colors.filter(item => item.id !== color.id))
})
}

const addColor = () => {
const colorObject ={
color: newColor.color,
code: {hex: `#${newColor.hex}`}
}
updateColors([...colors, colorObject])
console.log(colorObject)
axiosWithAuth().post('/api/colors', colorObject)
.then(res => {
console.log(res)

})
.catch(err => console.log(err))
}

return (
<div className="colors-wrap">
Expand All @@ -34,8 +69,12 @@ const ColorList = ({ colors, updateColors }) => {
{colors.map(color => (
<li key={color.color} onClick={() => editColor(color)}>
<span>
<span className="delete" onClick={() => deleteColor(color)}>
x
<span className="delete" onClick={e => {
e.stopPropagation()
deleteColor(color)
}
}>
x
</span>{" "}
{color.color}
</span>
Expand All @@ -45,7 +84,31 @@ const ColorList = ({ colors, updateColors }) => {
/>
</li>
))}
<form onSubmit={(e) => {
e.preventDefault()
addColor()
setNewColor({color:'', hex: ''})
}}>
<input
name='color'
placeholder='New Color Name'
value={newColor.color}
onChange={(e) => {
setNewColor({...newColor, [e.target.name]: e.target.value})
}}
/>
<input
name='hex'
placeholder='Hex Code'
value={newColor.hex}
onChange={(e) => {
setNewColor({...newColor, [e.target.name]: e.target.value})
}}
/>
<button type='submit'>Add Color</button>
</form>
</ul>

{editing && (
<form onSubmit={saveEdit}>
<legend>edit color</legend>
Expand Down Expand Up @@ -78,8 +141,10 @@ const ColorList = ({ colors, updateColors }) => {
)}
<div className="spacer" />
{/* stretch - build another form here to add a color */}


</div>
);
};
)
}

export default ColorList;
export default ColorList
51 changes: 45 additions & 6 deletions client/src/components/Login.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,53 @@
import React from "react";
import React, { useState } from "react"
import { axiosWithAuth } from '../utilities/axiosWithAuth'

const Login = () => {
const Login = (props) => {
// make a post request to retrieve a token from the api
// when you have handled the token, navigate to the BubblePage route
const [form, setForm] = useState({
username:'',
password: ''
})

const handleSubmit = () =>{
axiosWithAuth().post('/api/login', form)
.then(res => {
localStorage.setItem('token', res.data.payload)
setForm({username:'', password: ''})
props.history.push('/bubbles')
})
.catch(err => console.log(err))
}

return (
<>
<h1>Welcome to the Bubble App!</h1>
<p>Build a login page here</p>
<form onSubmit={(e) => {
e.preventDefault()
handleSubmit()

}}>
<input
name='username'
placeholder='User Name'
value={form.username}
onChange={(e) => {
setForm({...form, [e.target.name]: e.target.value})
}}
/>
<input
name='password'
type='password'
placeholder='Password'
value={form.password}
onChange={(e) => {
setForm({...form, [e.target.name]: e.target.value})
}}
/>
<button type='submit'>Login</button>
</form>
</>
);
};
)
}

export default Login;
export default Login
Loading