# ToDo Vue

Práctica de ToDo con Vue + Composition API

# Apoya el Directo 😃

Suscríbete al canal de Youtube

¡GRATIS! 😍 Solo tienes que suscribirte para apoyar el canal, click aquí

CURSO EN UDEMY OFERTA!

Aprende desde cero a trabajar con Vue.js y Firebase aquí: http://curso-vue-js-udemy.bluuweb.cl Nos vemos en clases!

CURSO EN UDEMY OFERTA!

Aprende desde cero a trabajar con React.js y Firebase aquí: http://curso-react-js-udemy.bluuweb.cl Nos vemos en clases!

CURSO EN UDEMY OFERTA!

Aprende desde cero a trabajar con Bootstrap 4! aquí: http://curso-bootstrap-4-udemy.bluuweb.cl Nos vemos en clases!

# Preguntas y Respuestas

# ¿Qué vamos a realizar?

# Recursos

# App.vue

<template>
  <div class="container">
    <todo-app />
  </div>
</template>

<script>
import TodoApp from "./components/TodoApp.vue"


export default {
  name: 'App',
  components: { TodoApp },
}
</script>

# TodoApp.vue

<template>
  <h1 class="my-5">TODO</h1>
  <todo-form />
  <todo-list />
</template>

<script>
import { provide, ref, watchEffect } from 'vue'
import TodoForm from './TodoForm.vue'
import TodoList from './TodoList.vue'
export default {
  components: { TodoForm, TodoList },
  setup(){
    const todos = ref([])
    provide('todos', todos)
    
    if(localStorage.getItem('todos')){
        todos.value = JSON.parse(localStorage.getItem('todos'))
    }

    watchEffect(() => {
        localStorage.setItem('todos', JSON.stringify(todos.value))
        // console.log('desde app', todos.value.length)
        // console.log('desde app', todos.value)
    })

  }
}
</script>

# TodoForm.vue

<template>
  <form @submit.prevent="agregarTodo">
    <input 
        type="text"
        placeholder="Create a new todo..."
        class="form-control my-3"
        v-model.trim="texto"
    >
  </form>
</template>

<script>
import { inject, ref, toRef } from 'vue'
export default {
    setup(){

        const todos = inject('todos')

        const texto = ref('')
        
        const agregarTodo = () => {
            if(texto.value === ''){
                console.log('texto vacio')
                return
            }
            const todo = {
                id: Date.now(),
                texto: texto.value,
                estado: false
            }
            
            texto.value = ''

            todos.value.push(todo)
            // console.log(todos.value)
        }
        return {
            texto,
            agregarTodo
        }
    }
}
</script>

# TodoList.vue

<template>
  <ul class="list-group">
    <todo-item v-for="todo in todos" :key="todo.id" :todo="todo" />

    <todo-footer v-if="todos.length" />

    <li v-if="todos.length === 0" class="list-group-item">Sin ToDos...</li>
  </ul>
  <todo-filter />
  
</template>

<script>
import { computed, inject, provide, ref } from "vue";
import TodoItem from "./TodoItem.vue";
import TodoFooter from "./TodoFooter.vue";
import TodoFilter from "./TodoFilter.vue";
export default {
  components: { TodoItem, TodoFooter, TodoFilter },
  setup() {
    const todosApp = inject("todos");
    const estado = ref('all')

    const todos = computed(() => {
      if(estado.value === 'all'){
        return todosApp.value
      }
      if(estado.value === 'active'){
        return todosApp.value.filter(item => item.estado === false)
      }
      if(estado.value === 'complete'){
        return todosApp.value.filter(item => item.estado === true)
      }
    })

    provide('estado', estado)

    return {
      todos
    };
  },
};
</script>

# TodoItem.vue

<template>
  <li class="list-group-item d-flex justify-content-between align-items-center">
    <span 
        role="button"
        :class="{completada: todo.estado}"
        @click="complete(todo.id)"
    >
        {{todo.texto}}
    </span>
    <i class="fas fa-times" role="button" @click="eliminar(todo.id)"></i>
  </li>
</template>

<script>
import { inject, toRef } from 'vue';
export default {
    props: {
        todo: {
            type: Object,
            required: true
        }
    },
    setup(){
        const todos = inject('todos')
        
        const complete = id => {
            todos.value = todos.value.map(item => {
                if(item.id === id){
                    item.estado = !item.estado
                }
                return item
            })
        }

        const eliminar = id => {
            todos.value = todos.value.filter(item => item.id !== id)
        }

        return {
            complete,
            eliminar
        }
    }
};
</script>

<style scoped>
.completada {
    text-decoration: line-through;
}
</style>

# TodoFooter.vue

<template>
  <li class="list-group-item d-flex justify-content-between align-items-center">
    <span>
        {{active.length}} items actives
    </span>
    <span
        role="button"
        @click="eliminarCompletados"
    >
        Eliminar Completados
    </span>
  </li>
</template>

<script>
import { computed, inject} from 'vue'
export default {
    setup(){
        const todos = inject('todos')
        
        const active = computed(() => {
            return todos.value.filter(item => item.estado === false)
        })

        const eliminarCompletados = () => {
            todos.value = todos.value.filter(item => !item.estado)
        }

        return {active, eliminarCompletados}
    }
}
</script>

# TodoFilter.vue

<template>
  <div class="btn-group mt-3 d-flex" role="group" aria-label="Basic example">
    <button 
      type="button" 
      class="btn btn-dark-dos w-100"
      @click="filtro('active')"
      :class="{'text-info': estado === 'active'}"
    >Actives</button>
    <button 
      type="button" 
      class="btn btn-dark-dos w-100"
      @click="filtro('all')"
      :class="{'text-info': estado === 'all'}"
    >All</button>
    <button 
      type="button" 
      class="btn btn-dark-dos w-100"
      @click="filtro('complete')"
      :class="{'text-info': estado === 'complete'}"
    >Complete</button>
  </div>
</template>

<script>
import { computed, inject } from "vue";
export default {
  setup() {
    const estado = inject("estado");
    const filtro = (valor) => {
      estado.value = valor;
    };
    return { filtro, estado };
  },
};
</script>