Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import express from 'express'
import pug from 'pug'
import favicon from 'serve-favicon'
import sassMiddleware from 'node-sass-middleware'
import routes from './src/app/routes'

const env = 'production',
port = process.env.PORT || 3000,
publicDir = `${__dirname}/public`,
viewDir = `${__dirname}/src/views`,
faviconDir = `${__dirname}/public/img/favicon.png`,
app = express()

app
.set( 'views', viewDir )
.set( 'view engine', 'pug' )
.set( 'port', port )
.set( 'env', env )

.use(sassMiddleware({
src: `${__dirname}/src/scss`,
dest: publicDir,
debug: false,
outputStyle: 'compressed'
}))
.use( express.static(publicDir) )
.use( favicon(faviconDir) )
.use( routes )

if ( app.get('env') === 'production' ) {
app.use((req, res, next) => {
let err = new Error('Not Found')
err.status = 404
next(err)
})

app.use((err, req, res, next) => {
res.status(err.status || 500)
res.render('error', { err: err })
})
}

export default app
210 changes: 210 additions & 0 deletions public/script.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions public/style.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions src/app/routes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import express from 'express'

const routes = express.Router()


routes
.get('/', (req, res, next)=>{
res.render('index',{
title: 'To Do List',
description: 'ToDo list isomorfico con Vanilla js'
})
})


export default routes
110 changes: 110 additions & 0 deletions src/js/ToDoList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { ENTER_KEY, c, d, j, ls } from './helpers'
import Task from './Task'

export default class ToDoList {
constructor(key) {
this.key = key

if (!ls.getItem(key))
ls.setItem(key, j.stringify([]))

this.addTask = this.addTask.bind(this)
this.editTask = this.editTask.bind(this)
this.removeTask = this.removeTask.bind(this)
}

addTask(e) {
//c(e)
if (!e.target.value)
alert('No puedes agregar una tarea vacia')

if (e.keyCode === ENTER_KEY) {
let newTask = new Task(e.target.value),
tasks = j.parse(ls.getItem(this.key))

tasks.push(newTask)
ls.setItem(this.key, j.stringify(tasks))
this.renderTask(newTask)
e.target.value = null
//c(newTask, tasks, ls)
}
}

editTask(e) {
if (e.target.localName === 'label') {
//alert('funciona')
let tasks = j.parse(ls.getItem(this.key)),
toEdit = tasks.findIndex(task => task.name === e.target.textContent),
label = d.querySelector(`[data-id="${tasks[toEdit].id}"]`)
//c(tasks, toEdit, tasks[toEdit])

const saveTask = e => {
e.target.textContent = e.target.textContent
tasks[toEdit].name = e.target.textContent
ls.setItem(this.key, j.stringify(tasks))
e.target.blur()
}

label.addEventListener('blur', e => saveTask(e)) //Cuando pierda el foco
label.addEventListener('keyup', e => (e.keyCode === ENTER_KEY) && saveTask(e))
}
}

removeTask(e) {
//Bind del metodo
c(e)
if (e.target.localName === 'a') {
//alert('eliminar')
let tasks = j.parse(ls.getItem(this.key)),
toRemove = tasks.findIndex(task => task.id.toString() === e.target.dataset.id)//Cuando el id de la tarea sea igual a ....
//Dataser es un arreglo que genera js
//Buena practica es no utilizar 2 iguales ya que solo comparamos valor. Lo mejor es === o !=

tasks.splice(toRemove, 1)
ls.setItem(this.key, j.stringify(tasks))
e.target.parentElement.remove()
}
}

renderTask(task) {
let templateTask = `
<li class="List-item ${task.isComplete ? 'complete' : ''}">
<input id="${task.id}" type="checkbox" class="List-checkbox" ${task.isComplete ? 'checked' : ''}>
<label data-id="${task.id}" class="List-label" contenteditable spellcheck>${task.name}</label>
<a href="#" data-id="${task.id}" class="List-removeLink">&#128465;</a>
</li>
`
list.insertAdjacentHTML('beforeend', templateTask)
}

render() {
let tasks = j.parse(ls.getItem(this.key)),
listTasks = list.children
//c(tasks, listTasks)

tasks.forEach(task => this.renderTask(task))

Array.from(listTasks).forEach(input => {
/*Aparentemente es un arreglo pero solo es uno o lista de nodos, o html collection.
por si solo, es por eso que se agrega un Array.from() -> Es un casting.*/
input.querySelector('input[type="checkbox"]').addEventListener('change', e => {
let task = tasks.filter(task => task.id == e.target.id)
//c(task)

if (e.target.checked) {
e.target.parentElement.classList.add('complete')
task[0].isComplete = true
} else {
e.target.parentElement.classList.remove('complete')
task[0].isComplete = false
}

ls.setItem(this.key, j.stringify(tasks))
})
})

task.addEventListener('keyup', this.addTask)
list.addEventListener('click', this.editTask)
list.addEventListener('click', this.removeTask)
}
}
17 changes: 17 additions & 0 deletions src/js/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//Filosofia de los modulos
//Los elementos del dom los voy a guardar y exportar

const ENTER_KEY = 13,
c = console.log,
d = document,
j = JSON,
ls = localStorage

// Destructuración
export{
ENTER_KEY,
c,
d,
j,
ls
}
9 changes: 9 additions & 0 deletions src/js/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//Llamando al modulo por destructuración
import {d} from './helpers'
import ToDoList from './ToDoList'

const task = d.querySelector('#task'),
list = d.querySelector('#list'),
todo = new ToDoList('edList') //Todo lo que guarde en la edList se guardare en el localStorage

todo.render()
8 changes: 8 additions & 0 deletions src/js/task.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default class Task{
constructor(name){
this.id = new Date().getTime()
this.name = name
this.isComplete = false
return this
}
}
87 changes: 82 additions & 5 deletions src/scss/style.scss
Original file line number Diff line number Diff line change
@@ -1,10 +1,87 @@
$bg-color: steelblue;

html {
box-sizing: border-box;
font: {
family: sanserif;
size: 16px;
family: sans-serif;
}
}

*,
*:after,
*:before {
box-sizing: inherit;
margin: 0;
padding: 0;
}

.ToDo {
margin: 2rem auto;
width: 80%;
max-width: 768px;
background-color: steelblue;
color: white;
}

.Task {
display: block;
padding: .5rem;
width: 100%;
line-height: 2rem;
font-size: 1.5rem;
color: steelblue;
}

.List {
display: flex;
flex-direction: column;
list-style: none;
margin-top: 1rem;
&-item {
display: flex;
align-items: center;
line-height: 2;
font-size: 1.25rem;
background-color: steelblue;
}
&-item:hover {
background-color: deepskyblue;
transition: all .3s ease-in;
}
&-checkbox {
width: 10%;
cursor: pointer;
transform: scale(1.5);
}
&-label {
width: calc(90% - 2.5rem);
cursor: pointer;
}
&-label:focus {
border: thin solid white;
outline: thin solid white;
}
&-removeLink {
width: 2.5rem;
height: 2.5rem;
font-weight: bold;
text-align: center;
background-color: white;
border-radius: 100%;
color: firebrick;
text-decoration: none;
transform: scale(.75);
transition: all .3s ease-in;
}
&-removeLink:hover {
background-color: firebrick;
color: white;
}
}

.complete {
order: 1;
background-color: lightsteelblue;
& label {
text-decoration: line-through;
}
background-color: $bg-color;
display: grid;
}
8 changes: 4 additions & 4 deletions src/views/index.pug
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ block metatags
title= title
meta(name="description", content=description)
block content
main.App
h1= title
p= description
img(src="./img/edteam-logo.png")
main.ToDo
input#task.Task(type="text", placeholder= "Tarea...", spellcheck)
ul#list.List