Forked from myraft/gist:2c8de889438a58d0e5d2bf24d03d3650
Created
May 19, 2020 22:26
-
-
Save Deanout/4fe7fa45fdcefd09fb95a0785d549ccc to your computer and use it in GitHub Desktop.
This file contains 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 characters
import React from "react"; | |
import Grid from "@material-ui/core/Grid" | |
import Paper from "@material-ui/core/Paper" | |
import { makeStyles } from "@material-ui/core/styles" | |
import Button from "@material-ui/core/Button" | |
import DeleteIcon from "@material-ui/icons/Delete" | |
import UpdateIcon from "@material-ui/icons/Update" | |
import { Typography } from "@material-ui/core"; | |
import TextField from '@material-ui/core/TextField'; | |
import TextareaAutosize from '@material-ui/core/TextareaAutosize'; | |
const useStyles = makeStyles({ | |
root: { | |
height: "auto", | |
margin: "1em", | |
padding: "2em", | |
}, | |
divider: { | |
width: "25%", | |
margin: "1em" | |
}, | |
paper: { | |
margin: "1em", | |
padding: "2em", | |
textAlign: "justify" | |
}, | |
heading: { | |
textAlign: "center" | |
}, | |
todo_body: { | |
padding: "1em" | |
} | |
}) | |
export default function TodoItem(props) { | |
const classes = useStyles(); | |
// handleInPlaceChanges = event => { | |
// console.log('Click'); | |
// console.log(event.target.value); | |
// console.log("Farooq 2.1 - handleInPlaceChanges") | |
// // props.item.body = this.body_input | |
// console.log("Faroow 2.1.1 - " + props.item.body) | |
// console.log("Faroow 2.1.2 - " + JSON.stringify(props.item, null, 2)) | |
// // console.log("Faroow 2.1.2 - " + JSON.stringify(event, null, 2)) | |
// props.changeItem(props.item) | |
// console.log("Farooq 2.2 - handleInPlaceChanges") | |
// }; | |
function handleBodyChange() { | |
console.log("handleBodyChange called when page is loaded: " + props.item.id) | |
} | |
function handleDelete() { | |
props.deleteItem(props.item) | |
} | |
// Just another callback to todolist | |
function handleEdit() { | |
props.editItem(props.item) | |
} | |
function handleInPlaceChanges() { | |
console.log("Farooq 2.1 - handleInPlaceChanges") | |
// props.item.body = this.body_input | |
props.item.body = this. | |
console.log("Faroow 2.1.1 - " + props.item.body) | |
console.log("Faroow 2.1.2 - " + JSON.stringify(props.item, null, 2)) | |
console.log("Farooq 2.1.3 - " + JSON.stringify(this, null, 2)) | |
// props.changeItem(props.item) | |
console.log("Farooq 2.2 - handleInPlaceChanges") | |
} | |
return ( | |
// I just copied the delete button and changed the text to edit. | |
<Grid container spacing={0}> | |
<Grid item xs={1}></Grid> | |
<Grid item xs={10}> | |
<Paper elevation={10} className={classes.paper}> | |
<Typography variant="h4" className={classes.heading}> | |
{props.item.task} | |
</Typography> | |
<hr className={classes.divider} style={{ marginLeft: "37.5%" }} /> | |
<div className={classes.todo_budy}> | |
<Typography variant="body1"> | |
{props.item.body} | |
<Grid item xs={12}> | |
{/* <TextField | |
id="outlined-basic" | |
label={props.item.body} | |
variant="outlined" /> */} | |
<TextareaAutosize | |
id="body_input" | |
label="Task body label" | |
variant="outlined" | |
type="text" | |
// onChange={this.handleBodyChange} | |
// ref={this.textAreaRef} | |
// ref={(textarea) => { props.item.body = textarea }} | |
// onChange={handleBodyChange()} | |
// onSubmit={(event) => this.handleInPlaceChanges(event)} | |
// onChange={this.handleInPlaceChanges()} | |
// onChange = {this.setState({ value: props.item.body})} | |
// onChange = {this.formUpdate({value: props.item.body})} | |
// onChange = {props.item.body)} | |
// value={this.state.body} | |
// onChange={props.item.body = "xxx"} | |
style={{ width: "99%", borderRadius: "5px" }} | |
rowsMin={3} | |
placeholder={props.item.body} | |
name="newbody"> | |
</TextareaAutosize> | |
<TextField | |
id={props.item.id} | |
label={props.item.body} | |
variant="outlined" | |
style={{ width: "99%", borderRadius: "5px" }} | |
// onChange={this.handleInPlaceChanges} | |
/> | |
</Grid> | |
</Typography> | |
</div> | |
<hr className={classes.divider} /> | |
<Button | |
variant="contained" | |
color="secondary" | |
size="small" | |
startIcon={<DeleteIcon />} | |
onClick={handleDelete}> | |
Delete | |
</Button> | |
<Button | |
variant="contained" | |
color="default" | |
size="small" | |
startIcon={<DeleteIcon />} | |
onClick={handleEdit}> | |
Edit | |
</Button> | |
<Button | |
variant="contained" | |
color="primary" | |
size="small" | |
startIcon={<UpdateIcon />} | |
onClick={handleInPlaceChanges}> | |
In Place Changes | |
</Button> | |
</Paper> | |
</Grid> | |
</Grid> | |
) | |
} |
This file contains 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 characters
import React, { Component } from "react" | |
import TodoForm from "./TodoForm" | |
import TodoItem from "./TodoItem" | |
import Grid from "@material-ui/core/Grid" | |
const api_url = `http://localhost:3001/api/v1/todos` | |
// Create form actions to allow us to change | |
// the Add todo item text. | |
const form_actions = ["add", "edit"] | |
class TodoList extends Component { | |
constructor(props) { | |
super(props) | |
this.state = { | |
items: [], | |
form_task: "Default task", | |
form_body: "Default body", | |
// Set the default form action to "Add", for add new task. | |
form_action: form_actions[0] | |
} | |
this.updateTodoList = this.updateTodoList.bind(this); | |
this.deleteItem = this.deleteItem.bind(this); | |
// Edit item allows us to set the form's new state | |
// to be the clicked item's values. | |
this.editItem = this.editItem.bind(this); | |
// This is what actually updates our state with | |
// the new values | |
this.updateItem = this.updateItem.bind(this); | |
this.changeItem = this.changeItem.bind(this); | |
} | |
componentDidMount() { | |
this.getTasks(); | |
} | |
getTasks() { | |
console.log("Farooq 4 - getTasks") | |
fetch(api_url) | |
.then(response => response.json()) | |
.then(response_items => { | |
this.setState({ | |
items: response_items.reverse() | |
}) | |
}); | |
} | |
updateTodoList(item) { | |
console.log("Farooq 3 - updateTotoList") | |
let _items = this.state.items | |
_items.unshift(item) | |
this.setState({ | |
items: _items | |
}) | |
} | |
updateItem(item) { | |
// Gets the index of the item and stores it in index. | |
// Creates a copy of the items state array. | |
console.log("Farooq 2 - update item" + JSON.stringify(item, null, 2)) | |
let index = this.state.items.findIndex( | |
element => element.id === item.id); | |
let _items = [...this.state.items]; | |
_items[index] = item; | |
this.setState({ | |
items: _items | |
}) | |
} | |
changeItem(item) { | |
// Gets the index of the item and stores it in index. | |
// Creates a copy of the items state array. | |
console.log("Farooq 5 - CHANGE item - NEWLY IMPLEMENTED") | |
console.log("Farooq 5.1 - ID:" + item.id) | |
console.log("Farooq 5.2 - Task:" + item.task) | |
console.log("Farooq 5.3 - Body:" + item.body) | |
console.log("Farooq 5.4 - NewBody:" + JSON.stringify(item, null, 2)) | |
console.log("Farooq 5.END - CHANGE item - NEWLY IMPLEMENTED") | |
} | |
deleteItem(item) { | |
// delete the item remotely | |
// localhost:3001/api/v1/todos + /13 | |
var deleteURL = api_url + `/${item.id}` | |
fetch(deleteURL, { | |
method: "DELETE" | |
}).then(() => { | |
// Client side delete | |
var _items = [...this.state.items]; | |
var index = _items.indexOf(item) | |
_items.splice(index, 1); | |
this.setState({ | |
items: _items | |
}) | |
}) | |
} | |
// Allows us to set the state of the form to be | |
// the values of the clicked item. | |
editItem(item) { | |
console.log("Farooq 1 edit item ..." + JSON.stringify(item, null, 2)) | |
this.setState({ | |
form_task: item.task, | |
form_body: item.body, | |
form_id: item.id, | |
form_action: form_actions[1] | |
}) | |
} | |
render() { | |
return ( | |
<Grid container spacing={3}> | |
<Grid item xs={12}> | |
<TodoForm api_url={api_url} | |
updateTodoList={this.updateTodoList} | |
task={this.state.form_task} | |
body={this.state.form_body} | |
// Passing in the id so that rails knows | |
// whicch item we want to edit | |
id={this.state.form_id} | |
// Passing in our add or edit action | |
// Which will update the text. | |
action={this.state.form_action} | |
// Callback to our update item function | |
updateItem={this.updateItem} /> | |
</Grid> | |
<Grid item xs={12} id="todo_list"> | |
{this.state.items.map((item) => ( | |
<TodoItem | |
key={item.id} | |
item={item} | |
deleteItem={this.deleteItem} | |
// Callback to our edit item function | |
editItem={this.editItem} | |
changeItem={this.changeItem}/> | |
))} | |
</Grid> | |
</Grid> | |
) | |
} | |
} | |
export default TodoList; |
This file contains 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 characters
import React, { Component } from "react" | |
import TextField from '@material-ui/core/TextField' | |
import Button from '@material-ui/core/Button' | |
import Grid from "@material-ui/core/Grid" | |
import TextareaAutosize from "@material-ui/core/TextareaAutosize" | |
class TodoForm extends Component { | |
constructor(props) { | |
super(props) | |
// Overhauled this, defaults now come from todo list. | |
// The rest is pretty similar to what we did before. | |
this.state = { | |
api_url: props.api_url, | |
task: props.task, | |
body: props.body, | |
action: props.action, | |
id: props.id, | |
defaultTaskValue: props.task, | |
defaultBodyValue: props.body, | |
defaultActionValue: props.action | |
} | |
this.handleSubmit = this.handleSubmit.bind(this); | |
this.handleTaskChange = this.handleTaskChange.bind(this); | |
this.handleBodyChange = this.handleBodyChange.bind(this); | |
} | |
handleSubmit(event) { | |
event.preventDefault(); | |
// Perform a check on our action. | |
// Do what we did before if it's add | |
// Do the new edit stuff otherwise. | |
if (this.state.action === "add") { | |
this.formSubmit(event.target); | |
} else { | |
this.formUpdate(event.target); | |
} | |
} | |
// Old form submit action. It's the same | |
async formSubmit(formData) { | |
var data = new FormData(formData); | |
await fetch(this.state.api_url, { | |
method: "POST", | |
mode: "cors", | |
body: data | |
}).then(response => response.json()) | |
.then(response => this.props.updateTodoList(response)) | |
this.setState({ | |
task: this.state.defaultTaskValue, | |
body: this.state.defaultBodyValue, | |
action: this.state.defaultActionValue | |
}) | |
} | |
// New form update action. | |
async formUpdate(formData) { | |
var data = new FormData(formData); | |
// Appends an ID so that Rails knows which item to edit. | |
data.append("id", this.state.id) | |
await fetch(this.state.api_url + "/" + this.state.id, { | |
method: "PUT", | |
mode: "cors", | |
body: data | |
}).then(response => response.json()) | |
.then(response => this.props.updateItem(response)) | |
this.setState({ | |
task: this.state.defaultTaskValue, | |
body: this.state.defaultBodyValue, | |
// Don't forget to reset the state to add. | |
action: this.state.defaultActionValue | |
}) | |
} | |
handleTaskChange(event) { | |
this.setState({ | |
task: event.target.value | |
}) | |
} | |
handleBodyChange(event) { | |
this.setState({ | |
body: event.target.value | |
}) | |
} | |
componentWillReceiveProps(newProps) { | |
// This is how the form updates its state. | |
// Whenever the todo item calls the editItem function in todo list | |
// Todo List rerenders with new props for todo form. | |
// That causes this function to set new values for our form. | |
this.setState({ | |
task: newProps.task, | |
body: newProps.body, | |
action: newProps.action, | |
id: newProps.id | |
}); | |
} | |
render() { | |
// Just changing the text, self explanatory. | |
let action_text = ''; | |
if (this.state.action === "add") { | |
action_text = "Add Task" | |
} else { | |
action_text = "Edit Task" | |
} | |
return ( | |
<Grid container> | |
<Grid item xs></Grid> | |
<Grid item xs={10}> | |
<form | |
onSubmit={this.handleSubmit} | |
id="todo_form" | |
autoComplete="off"> | |
<Grid container> | |
<Grid item xs={12}> | |
<TextField | |
id="task_input" | |
label="Task Description" | |
variant="outlined" | |
type="text" | |
name="todo[task]" | |
value={this.state.task} | |
onChange={this.handleTaskChange} | |
fullWidth /> | |
</Grid> | |
<Grid item xs={12}> | |
<TextareaAutosize | |
id="body_input" | |
label="Task Body" | |
variant="outlined" | |
type="text" | |
value={this.state.body} | |
onChange={this.handleBodyChange} | |
style={{ width: "99%", borderRadius: "5px" }} | |
rowsMin={3} | |
placeholder="Describe your todo item..." | |
name="todo[body]"></TextareaAutosize> | |
</Grid> | |
<Grid item xs={2}> | |
<Button variant="contained" | |
color="primary" | |
type="submit" | |
style={{ height: "100%" }}>{action_text}</Button> | |
</Grid> | |
</Grid> | |
</form> | |
</Grid> | |
<Grid item xs></Grid> | |
</Grid> | |
) | |
} | |
} | |
export default TodoForm; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment