├── db
└── db.json
├── index.html
└── src
├── css
└── style.css
└── js
└── index.js
/db/db.json:
--------------------------------------------------------------------------------
1 | {
2 | "todos": [
3 | {
4 | "title": "sd",
5 | "completed": false,
6 | "id": 1
7 | },
8 | {
9 | "completed": true,
10 | "id": 2,
11 | "title": "ff"
12 | },
13 | {
14 | "completed": true,
15 | "id": 3,
16 | "title": "ff"
17 | },
18 | {
19 | "completed": true,
20 | "id": 4,
21 | "title": "ggg"
22 | },
23 | {
24 | "title": "s",
25 | "completed": false,
26 | "id": 5
27 | }
28 | ]
29 | }
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 | HW23-js-jquery-part2
9 |
10 |
11 |
12 |
13 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/css/style.css:
--------------------------------------------------------------------------------
1 | html,
2 | body {
3 | margin: 0;
4 | padding: 0;
5 | }
6 |
7 | body {
8 | height: 100vh;
9 | font: 22px 'Helvetica Neue', Helvetica, Arial, sans-serif;
10 | line-height: 1.2em;
11 | background: linear-gradient(to right, #4e65d4 0%, #293dcb 19%, #4246a5 60%, #505ac2 100%);
12 | display: flex;
13 | align-items: center;
14 | justify-content: center;
15 | color: #fff;
16 | }
17 |
18 | ul {
19 | list-style-type: none;
20 | -webkit-padding-start: 0;
21 | }
22 |
23 | .btn {
24 | cursor: pointer;
25 | font-size: 15px;
26 | padding: 10px 20px;
27 | border-radius: 2em;
28 | background: none;
29 | border: 1px solid #fff;
30 | transition: 250ms ease-out;
31 | }
32 |
33 | .btn-danger:hover {
34 | color: #fff;
35 | background: #e74c3c;
36 | }
37 |
38 | .btn-success:hover {
39 | color: #fff;
40 | background: #05b437;
41 | }
42 |
43 | .btn:focus {
44 | color: #fff;
45 | outline: none;
46 | }
47 |
48 | .container {
49 | width: 400px;
50 | min-height: 500px;
51 | box-shadow: 0 20px 80px rgba(0,0,0,0.6);
52 | position: relative;
53 | border-radius: 1em;
54 | padding: 15px;
55 | display: flex;
56 | flex-direction: column;
57 | justify-content: space-between;
58 | }
59 |
60 | .header {
61 | display: flex;
62 | justify-content: space-around;
63 | }
64 | .header h2 {
65 | margin: 0;
66 | }
67 |
68 | .task-count {
69 | align-self: center;
70 | }
71 |
72 | .todo-list:first-of-type {
73 | border-top: 1px solid #f5f4f4;
74 | }
75 |
76 | .list-item-view {
77 | padding-top: 12px;
78 | padding-bottom: 12px;
79 | display: flex;
80 | align-items: center;
81 | justify-content: space-between;
82 | }
83 |
84 | .form {
85 | margin-bottom: 10px;
86 | display: flex;
87 | justify-content: center;
88 | }
89 |
90 | .input-text {
91 | height: 40px;
92 | font-size: 15px;
93 | border: 1px solid #dce4ec;
94 | width: 100%;
95 | margin-right: 15px;
96 | border-radius: 2em;
97 | padding: 5px 10px;
98 | transition: border 250ms ease-out;
99 | }
100 |
101 | .input-text:focus {
102 | border: 1px solid;
103 | outline: none;
104 | }
105 |
106 |
107 | .completed {
108 | text-decoration: line-through;
109 | }
110 |
111 | input[type="checkbox"] {
112 | display: none;
113 | }
114 |
115 | .list-item-view label:hover {
116 | cursor: pointer;
117 | }
118 | .list-item-view label {
119 | color: #e6ff01;
120 | }
121 | .list-item-view label.completed {
122 | color: #00f204;
123 | }
124 |
125 | #todos {
126 | max-height: 500px;
127 | overflow: auto;
128 | }
129 |
--------------------------------------------------------------------------------
/src/js/index.js:
--------------------------------------------------------------------------------
1 | const resource = 'http://localhost:3000'
2 | const $todosSection = $('#todos')
3 | const $formAddTask = $('#addTask')
4 | let todos = []
5 |
6 | async function deleteTask(id) {
7 | return await $.ajax({
8 | url: `${resource}/todos/${id}`,
9 | method: 'DELETE'
10 | })
11 | }
12 |
13 | async function addTask(data) {
14 | return await $.ajax({
15 | url: `${resource}/todos`,
16 | method: 'POST',
17 | headers: {
18 | 'Content-Type': 'application/json'
19 | },
20 | data: JSON.stringify(data)
21 | })
22 | }
23 |
24 | async function changeTask(data) {
25 | return await $.ajax({
26 | url: `${resource}/todos/${data.id}`,
27 | method: 'PUT',
28 | headers: {
29 | 'Content-Type': 'application/json'
30 | },
31 | data: JSON.stringify(data)
32 | })
33 | }
34 |
35 | function draw(whereDraw) {
36 | let todosContainer = ''
37 | todos.forEach(todo => {
38 | todosContainer += templateTodo(todo)
39 | })
40 | whereDraw.html(todosContainer)
41 | }
42 | function templateTodo(data) {
43 | return `
44 |
45 |
48 |
49 |
50 | `
51 | }
52 |
53 | $.ajax({
54 | url: `${resource}/todos`
55 | })
56 | .then((res) => {
57 | todos = res
58 | draw($todosSection)
59 | })
60 |
61 | async function handlerDeleteTask(event) {
62 | const $parentEl = $(event.target).closest('.todo-list')
63 | const id = $parentEl.data('id')
64 | await deleteTask(id)
65 | $parentEl.remove()
66 | }
67 |
68 | async function handlerMarkedTask(event) {
69 | const $parentEl = $(event.target).closest('.todo-list')
70 | const id = $parentEl.data('id')
71 | const status = $parentEl.data('completed')
72 | const title = $parentEl.data('title')
73 | let newStatus = !Boolean(+status)
74 |
75 | await changeTask({
76 | completed: newStatus,
77 | id,
78 | title
79 | })
80 | $parentEl.data('completed', newStatus ? '1' : '0')
81 | const $label = $(event.target).closest('label')
82 | if (newStatus) {
83 | $label.addClass('completed')
84 | } else {
85 | $label.removeClass('completed')
86 | }
87 | }
88 |
89 |
90 | $formAddTask.submit((event) => handlerAddTask(event))
91 |
92 | async function handlerAddTask(event) {
93 | const $input = $(event.target).children('input')
94 | event.preventDefault()
95 | const res = await addTask({
96 | title: $input.val(),
97 | completed: false
98 | })
99 | const el = templateTodo(res)
100 | $todosSection.append(el)
101 | $input.val('')
102 | }
103 |
104 | $todosSection.click((event) => {
105 | switch (event.target.tagName) {
106 | case 'LABEL':
107 | handlerMarkedTask(event)
108 | break;
109 | case 'BUTTON':
110 | handlerDeleteTask(event)
111 | break;
112 | }
113 | })
114 |
115 |
--------------------------------------------------------------------------------