├── models ├── index.js └── todo.js ├── package.json ├── routes └── todos.js ├── index.js ├── views └── index.html ├── helpers └── todos.js └── public ├── app.css └── app.js /models/index.js: -------------------------------------------------------------------------------- 1 | var mongoose = require('mongoose'); 2 | mongoose.set('debug', true); 3 | mongoose.connect('mongodb://localhost/todo-api'); 4 | 5 | mongoose.Promise = Promise; 6 | 7 | module.exports.Todo = require("./todo"); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "todos_api", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "body-parser": "^1.17.2", 13 | "express": "^4.15.4", 14 | "mongoose": "^4.11.9" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /routes/todos.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var db = require("../models"); 4 | var helpers = require("../helpers/todos"); 5 | 6 | router.route('/') 7 | .get(helpers.getTodos) 8 | .post(helpers.createTodo) 9 | 10 | router.route('/:todoId') 11 | .get(helpers.getTodo) 12 | .put(helpers.updateTodo) 13 | .delete(helpers.deleteTodo) 14 | 15 | module.exports = router; -------------------------------------------------------------------------------- /models/todo.js: -------------------------------------------------------------------------------- 1 | var mongoose = require('mongoose'); 2 | 3 | var todoSchema = new mongoose.Schema({ 4 | name: { 5 | type: String, 6 | required: 'Name cannot be blank!' 7 | }, 8 | completed: { 9 | type: Boolean, 10 | default: false 11 | }, 12 | created_date: { 13 | type: Date, 14 | default: Date.now 15 | } 16 | }); 17 | 18 | var Todo = mongoose.model('Todo', todoSchema); 19 | 20 | module.exports = Todo; -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'), 2 | app = express(), 3 | port = process.env.PORT || 3000, 4 | bodyParser = require('body-parser'); 5 | 6 | var todoRoutes = require("./routes/todos"); 7 | 8 | app.use(bodyParser.json()); 9 | app.use(bodyParser.urlencoded({extended: true})); 10 | app.use(express.static(__dirname +'/public')); 11 | app.use(express.static(__dirname + '/views')); 12 | 13 | app.get('/', function(req, res){ 14 | res.sendFile("index.html"); 15 | }); 16 | 17 | app.use('/api/todos', todoRoutes); 18 | 19 | app.listen(port, function(){ 20 | console.log("APP IS RUNNING ON PORT " + process.env.PORT); 21 | }) 22 | 23 | -------------------------------------------------------------------------------- /views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 |
11 |

todolist

12 |

A simple todo list app built with node

13 |
14 | 15 |
16 | 17 |
18 | 19 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /helpers/todos.js: -------------------------------------------------------------------------------- 1 | var db = require('../models'); 2 | 3 | exports.getTodos = function(req, res){ 4 | db.Todo.find() 5 | .then(function(todos){ 6 | res.json(todos); 7 | }) 8 | .catch(function(err){ 9 | res.send(err); 10 | }) 11 | } 12 | 13 | exports.createTodo = function(req, res){ 14 | db.Todo.create(req.body) 15 | .then(function(newTodo){ 16 | res.status(201).json(newTodo); 17 | }) 18 | .catch(function(err){ 19 | res.send(err); 20 | }) 21 | } 22 | 23 | exports.getTodo = function(req, res){ 24 | db.Todo.findById(req.params.todoId) 25 | .then(function(foundTodo){ 26 | res.json(foundTodo); 27 | }) 28 | .catch(function(err){ 29 | res.send(err); 30 | }) 31 | } 32 | 33 | exports.updateTodo = function(req, res){ 34 | db.Todo.findOneAndUpdate({_id: req.params.todoId}, req.body, {new: true}) 35 | .then(function(todo){ 36 | res.json(todo); 37 | }) 38 | .catch(function(err){ 39 | res.send(err); 40 | }) 41 | } 42 | 43 | exports.deleteTodo = function(req, res){ 44 | db.Todo.remove({_id: req.params.todoId}) 45 | .then(function(){ 46 | res.json({message: 'We deleted it!'}); 47 | }) 48 | .catch(function(err){ 49 | res.send(err); 50 | }) 51 | } 52 | 53 | module.exports = exports; -------------------------------------------------------------------------------- /public/app.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Montserrat:300,400,700'); 2 | 3 | body { 4 | font-family: 'Montserrat', sans-serif; 5 | background: #ecf0f1; 6 | } 7 | 8 | /*****************************HEADER STYLES*****************************/ 9 | header { 10 | text-align: center; 11 | } 12 | header h1 { 13 | font-size: 64px; 14 | font-weight: 300; 15 | margin: 80px 0 25px; 16 | color: #2c3e50; 17 | } 18 | header h1 span { 19 | font-weight: 700; 20 | } 21 | header h2 { 22 | color: #bdc3c7; 23 | font-weight:300; 24 | } 25 | /*****************************FORM STYLES*****************************/ 26 | 27 | .form { 28 | width: 800px; 29 | margin: 50px auto 20px; 30 | } 31 | 32 | #todoInput { 33 | width: 100%; 34 | height: 60px; 35 | background: none; 36 | border: none; 37 | border-bottom: 1px solid #34495e; 38 | outline: none; 39 | font: 300 28px 'Ubuntu', sans-serif; 40 | padding: 20px; 41 | color: #34495e; 42 | } 43 | 44 | /*****************************LIST STYLES*****************************/ 45 | .list { 46 | width: 800px; 47 | margin: 0 auto; 48 | } 49 | .task { 50 | width: 100%; 51 | height: 60px; 52 | line-height: 60px; 53 | font-size: 20px; 54 | padding: 0 20px; 55 | color: #34495e; 56 | transition: all .3s ease; 57 | } 58 | .task:hover { 59 | background: rgba(0, 0, 0, .02); 60 | cursor: pointer; 61 | } 62 | 63 | .task:hover span{ 64 | opacity: 1; 65 | } 66 | 67 | .done { 68 | text-decoration: line-through; 69 | color: #bdc3c7; 70 | } 71 | 72 | li span { 73 | float: right; 74 | color: #c0392b; 75 | transition: all 0.3s; 76 | opacity: 0; 77 | } 78 | 79 | li span:hover { 80 | color: #e74c3c 81 | } -------------------------------------------------------------------------------- /public/app.js: -------------------------------------------------------------------------------- 1 | /* global $ */ 2 | $(document).ready(function(){ 3 | $.getJSON("/api/todos") 4 | .then(addTodos) 5 | 6 | $('#todoInput').keypress(function(event){ 7 | if(event.which == 13) { 8 | createTodo(); 9 | } 10 | }); 11 | 12 | $('.list').on('click', 'li', function(){ 13 | updateTodo($(this)); 14 | }) 15 | 16 | $('.list').on('click', 'span', function(e){ 17 | e.stopPropagation(); 18 | removeTodo($(this).parent()); 19 | }) 20 | }); 21 | 22 | function addTodos(todos) { 23 | //add todos to page here 24 | todos.forEach(function(todo){ 25 | addTodo(todo); 26 | }); 27 | } 28 | 29 | function addTodo(todo){ 30 | var newTodo = $('
  • '+todo.name +' X
  • '); 31 | newTodo.data('id', todo._id); 32 | newTodo.data('completed', todo.completed); 33 | if(todo.completed){ 34 | newTodo.addClass("done"); 35 | } 36 | $('.list').append(newTodo); 37 | } 38 | 39 | function createTodo(){ 40 | //send request to create new todo 41 | var usrInput = $('#todoInput').val(); 42 | $.post('/api/todos',{name: usrInput}) 43 | .then(function(newTodo){ 44 | $('#todoInput').val(''); 45 | addTodo(newTodo); 46 | }) 47 | .catch(function(err){ 48 | console.log(err); 49 | }) 50 | } 51 | 52 | function removeTodo(todo){ 53 | var clickedId = todo.data('id'); 54 | var deleteUrl = '/api/todos/' + clickedId; 55 | $.ajax({ 56 | method: 'DELETE', 57 | url: deleteUrl 58 | }) 59 | .then(function(data){ 60 | todo.remove(); 61 | }) 62 | .catch(function(err){ 63 | console.log(err); 64 | }) 65 | } 66 | 67 | function updateTodo(todo){ 68 | var updateUrl = '/api/todos/' + todo.data('id'); 69 | var isDone = !todo.data('completed'); 70 | var updateData = {completed: isDone} 71 | $.ajax({ 72 | method: 'PUT', 73 | url: updateUrl, 74 | data: updateData 75 | }) 76 | .then(function(updatedTodo){ 77 | todo.toggleClass("done"); 78 | todo.data('completed', isDone); 79 | }) 80 | } --------------------------------------------------------------------------------