Skip to content

Instantly share code, notes, and snippets.

@myraft
Created May 19, 2020 22:01
Show Gist options
  • Save myraft/2c8de889438a58d0e5d2bf24d03d3650 to your computer and use it in GitHub Desktop.
Save myraft/2c8de889438a58d0e5d2bf24d03d3650 to your computer and use it in GitHub Desktop.
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>
)
}
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;
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