소프트웨어 이론교육/웹 서비스 프론트엔드 개발

React (6) - TodoList 구현

마루설아 2022. 8. 5. 12:10

App.js

import { Container, List, Paper } from "@mui/material";
import { useState } from "react";
import Todo from "./Todo";
import AddTodo from "./AddTodo";


function ItmeListComp({items}) {
  return (<Paper>
    <List>
    {
      items.map((item)=>(<Todo item={item} key={item.id}/>))
    }
    </List>
  </Paper>);
}

function App() {
  const [items, setItems] = useState([
    {id:"0", title:"Hello World 1", done:true},
    {id:"1", title:"Hello World 2", done:false},
    {id:"2", title:"Hello World 3", done:true},
  ]);

  function onAddItem(newItem){
    const currItems = [...items, newItem];
    setItems(currItems);
  }

  function onDeleteItem(delItem){
    const index = items.findIndex((item)=>{
      return item.id === delItem.id;
    });

    const currItems = [...items];
    currItems.splice(index, 1);
    setItems(currItems);
  }

  function updateItem(newItem){
    const index = items.findIndex((item)=>{
      return item.id === newItem.id;
    });

    const currItems = [...items];
    currItems[index] = newItem;
    setItems(currItems);
  }

  const itemListTemp = items.length>0 && (<Paper>
    <List>
    {
      items.map((item)=>(<Todo onDeleteItem={onDeleteItem} updateItem={updateItem} item={item} key={item.id}/>))
    }
    </List>
  </Paper>);
  return (
    <div>
      <Container maxWidth="md">
        <AddTodo onAddItem={onAddItem} />
        <div className="todoList">
          {itemListTemp}
        </div>
      </Container>
    </div>
  );
}

export default App;

 

 

AddTodo.js

import { Button, Grid, Paper, TextField } from "@mui/material";
import { useState } from "react";

class ItemObject {
    constructor(id, title, done){
        this.id = "";
        this.title = "";
        this.done = false;
    }
}

function AddTodo({onAddItem}) {
    const [item, setItem] = useState(new ItemObject("", "", false));

    const onButtonClick = (e)=>{
        onAddItem(item);
        setItem(new ItemObject("", "", false));
    }

    const onEnterKeyPress = (e)=>{
        if(e.key == 'Enter'){
            onButtonClick(e);
            setItem({id:"", title: "", done:false});
        }
    }
  
    return (<Paper style={{margin: "16px 0px", padding: "16px"}}>
      <Grid container>
        <Grid xs={11} md={11} item style={{paddingRight: "16px"}}>
          <TextField fullWidth placeholder="할 일 입력" 
          value={item.title} 
          onChange={(e)=>{
            let currItem = {...item};
            currItem.title = e.currentTarget.value;
            setItem(currItem);
          }} 
          onKeyPress={onEnterKeyPress}
          />
        </Grid>
        <Grid xs={1} md={1}>
            <Button onClick={onButtonClick}>추가</Button>
        </Grid>
      </Grid>
    </Paper>);
}

export default AddTodo;

 

 

Todo.js

import { Favorite, FavoriteBorder } from "@mui/icons-material"
import { Checkbox, IconButton, InputBase, ListItem, ListItemSecondaryAction, ListItemText } from "@mui/material"
import { useState } from "react";
import DeleteOutline from "@mui/icons-material/DeleteOutline";

function Todo({item, onDeleteItem, updateItem}) {
    const [readOnly, setReadOnly] = useState(true);
    const [titleData, setTitleData] = useState(item.title);

    const deleteItemHandler = (e)=>{
        onDeleteItem(item);
    }

    const onUpdateItem = (cmd)=>{
        setReadOnly(true);
        const currItem = {...item};
        currItem.title = titleData;
        if(cmd === 'toggleChk') currItem.done = !currItem.done;
        updateItem(currItem);
    }

    return (<>
        <ListItem>
            <Checkbox onClick={(e)=>{
                onUpdateItem('toggleChk');
            }}
            checked={item.done} icon={<FavoriteBorder />} checkedIcon={<Favorite />} />
            <ListItemText>
                <InputBase
                    type="text" 
                    inputProps={{"arial=label": "naked", readOnly: readOnly}} 
                    id={item.id} 
                    name={item.id}
                    multiline={true} 
                    fullWidth={true} 
                    onChange={(e)=>{setTitleData(e.target.value)}}
                    onClick={(e)=>{setReadOnly(false)}}
                    onKeyPress={(e)=>{
                        if(e.key === 'Enter') {
                            onUpdateItem();
                        }
                    }}
                    value={titleData}>
                </InputBase>
            </ListItemText>
            <ListItemSecondaryAction>
                <IconButton aria-label="Deleete Todo" onClick={deleteItemHandler}>
                    <DeleteOutline />
                </IconButton>
            </ListItemSecondaryAction>
        </ListItem>
    </>);
}

export default Todo;