Skip to content

Latest commit

 

History

History
380 lines (316 loc) · 7.98 KB

proyecto-todo.md

File metadata and controls

380 lines (316 loc) · 7.98 KB

Proyecto

TODO APP

Pendiente

Solo hice cambie/cree los siguuientes de un proyecto en blanco de React.js

App.js

import './App.scss';
import Container from './components/Container'

function App() {
  return (
    <div className="App">
      <Container/>
    </div>
  );
}

export default App;

/components/Checkbox.jsx

import React, { Fragment } from "react";

const Checkbox = props => {

    const {
        onChange,
        data: {id, description, done}
    } = props; 

    return (<Fragment>

        <svg viewBox="0 0 0 0" 
            style={{
                position: "absolute",
                zIndex: -1,
                opacity: 0
            }}>
            <defs>
                <path id="todo_line" d="M21 12.3h168v0.1z"/>
                <path id="todo_box" d="M21 12.7v5c0 1.3-1 2.3-2.3 2.3H8.3C7 20 6 19 6 17.7V7.3C6 6 7 5 8.3 5h10.4C20 5 21 6 21 7.3v5.4"/>
                <path id="todo_check" d="M10 13l2 2 5-5" />
                <circle id="todo_circle" cx="13.5" cy="12.5" r="10"/>
            </defs>
        </svg>

        <label className="todo new-item">
            <input
                className="todo_state"
                name={id}
                type="checkbox"
                defaultChecked={done}
                onChange={onChange}
            />

            <svg 
                xmlns="http://www.w3.org/2000/svg" 
                xmlnsXlink="http://www.w3.org/1999/xlink" 
                viewBox="0 0 200 25" 
                className="todo_icon">
                    <use xlinkHref="#todo_line"  className="todo_line" />
                    <use xlinkHref="#todo_box"  className="todo_box" />
                    <use xlinkHref="#todo_check"  className="todo_check" />
                    <use xlinkHref="#todo_circle"  className="todo_circle" />
            </svg>

            <div className="todo_text">{description}</div>
        </label>
    </Fragment>);
}

export default Checkbox;

/components/Container.jsx

import React, { useState } from "react";
import FormTodo from './FormTodo';
import TaskList from './TaskList';

const Container = () => {
    const [list, setList] = useState([]);

    const addItem = addItem => {
        setList([...list, addItem])
    };

    return (
        <div>
            <FormTodo addItem={addItem}/>
            <TaskList list={list} setList={setList}/>
        </div>
    );
}

export default Container

/components/FormTodo.jsx

import React, { useState } from "react";

const FormTodo = props => {
    const [description, setDescription] = useState("");
    const {addItem} = props;

    const handleSubmit = e =>  {
        e.preventDefault();
        console.log(description)
        
        addItem({
            done: false,
            id: (new Date()).toString(),
            description
        });

        setDescription("");
    }

    return (
        <form onSubmit={handleSubmit}>
            <div className="todo-list">
                <div className="file-input">
                    <input
                        type="text"
                        className="text"
                        value={description}
                        onChange={e => setDescription(e.target.value)}
                    />
                    <button
                        className="button pink"
                        disabled={description ? "" : "disabled"}
                    /*
                    Lo mismo:
                    if (Descripcion == "") {
                        disabled="disabled"
                    } else {
                        disabled=""
                    }
                    */
                    >
                        Agregar tarea
                    </button>
                </div>
            </div>
        </form>
    );
}

export default FormTodo;

/components/TaskList.jsx

import React from "react";
import Checkbox from "./Checkbox";

const TaskList = props => {
    const {list, setList} = props;

    const onChangeStatus = e => {
        const {name, checked} = e.target;
        const updateList = list.map(item => ({
            ...item,
            done: item.id === name ? checked : item.done
        }));
        setList(updateList);
    };
    
    const onClickRemoveItem = e =>  {
        const updateList = list.filter(item => !item.done);
        setList(updateList)
    };

    const checkbox = list.map(item => (
        <Checkbox key={item.id} data={item} onChange={onChangeStatus} />
    ));

    return (
        <div className="todo-list">
            {list.length ? checkbox : "No hay tareas"}
            {list.length ? (
                <p>
                    <button className="button pink" onClick={onClickRemoveItem}> Delete</button>
                </p>
            ) : null}
        </div>
    )
}

export default TaskList;
html {
  background: #ddd;
  height: 100%;
  display: flex;
}
body {
  width: 100%;
  margin: auto;
}

.App {
  font-family: sans-serif;
  text-align: center;
}

.todo-list {
  background: #fff;
  font-size: 18px;
  max-width: 300px;
  margin: auto;
  margin-bottom: 24px;
  padding: 8px 16px;
  box-shadow: 0 5px 30px rgba(0,0,0,0.2);
}

$colorRosa: #C2185B;
$colorRosaHover: #E91E63;

$colorAzul: #1976D2;
$colorAzulHover: #03A9F4;

@mixin button($class, $color, $colorHover) {
  .button.#{$class}{background: $color;}
  .button.#{$class}:hover{background: $colorHover;}
  .button.#{$class}:active{background: $color;}
}

.button {
  outline: none;
  padding: 8px;
  border: 1px solid white;
  border-radius: 15px;
  color: white;
}

@include button ('pink', $colorRosa, $colorRosaHover);
@include button ('blue', $colorAzul, $colorAzulHover);

.file_input {
  padding: 2px;
  background: #f8f8f8;
}

.file_input > .text {
  outline: none;
  padding: 0px, 10px;
  font-size: 18px;
  width: 230px;
  height: 43;
  background: transparent;
  border: 0px solid;
}

$duracion: 0.4s;
$stroke: #34eb9f;
$colorText: #222222;
$colorTextChecked: #85e6e4;

.todo {
  display: block;
  position: relative;
  padding: 1em 1em 1em 16%;
  margin: 0 auto;
  cursor: pointer;
  border-bottom: solid 1px #ddd;
  &:last-child {border-bottom: none;}
}

.todo.new-item {
  opacity: 0;
  transform: translateX(100px);
  animation: fadeIn .3s linear forwards;
}

@keyframes fadeIn {
  to {
    transform: translateX(0px);
    opacity: 1;
  }
}

.todo_state {
  position: absolute;
  top: 0;
  left: 0;
  opacity: 0;
}

.todo_text {
  color: $colorText;
  text-align: right;
  transition: all $duracion/2 linear $duracion/2;
}

.todo_icon {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 100%;
  height: auto;
  margin: auto;

  fill: none;
  stroke: $stroke;
  stroke-width: 2;
  stroke-linejoin: round;
  stroke-linecap: round;
}

.todo_line, .todo_box, .todo_check {
  transition: stroke-dashoffset $duracion cubic-bezier(0.075, 0.82, 0.165, 1)
}

.todo_circle {
  stroke: $stroke;
  stroke-dasharray: 1 6;
  stroke-width: 0;

  transform-origin: 13.5px 12.5px;
  transform: scale(0.4) rotate(0deg);
  animation: none $duracion linear;

  @keyframes explode {
    30% {
      stroke-width: 3;
      stroke-opacity: 1;
      transform: scale(0.8) rotate(40deg);
    }

    100% {
      stroke-width: 0;
      stroke-opacity: 0;
      transform: scale(1.1) rotate(60deg);
    }
  }

}

.todo_box {
  stroke-dasharray: 56, 56;
  stroke-dashoffset: 0;
  transition-delay: $duracion * 0.2;
}

.todo_check {
  stroke: $stroke;
  stroke-dasharray: 9.8 9.8;
  stroke-dashoffset: 9;
  transition-delay: $duracion * 0.4;
}

.todo_line {
  stroke-dasharray: 168, 168;
  stroke-dashoffset: 168;
}

.todo_circle {
  animation-delay: $duracion * 0.7;
  animation-duration: $duracion * 0.7;
}

.todo_state:checked {
  ~ .todo_text { transition-delay: 0s; color: $colorTextChecked; opacity: 0.6;}
  ~ .todo_icon .todo_box { stroke-dashoffset: 56; transition-delay: 0s; }
  ~ .todo_icon .todo_line { stroke-dashoffset: -8; }
  ~  .todo_icon .todo_check { stroke-dashoffset: 0; transition-delay: $duracion * 0.6; }
  ~ .todo_icon .todo_circle { animation-name: explode;}
}