├── .DS_Store ├── .vscode └── settings.json ├── assets ├── bg-desktop-dark.jpg ├── icon-check.svg ├── icon-cross.svg ├── icon-moon.svg └── icon-sun.svg ├── firebase.js ├── index.html ├── script.js └── style.css /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleverProgrammers/challenge-todo-list/6474bc8bf67103ae08d6facbca6df48aafbf0713/.DS_Store -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "liveServer.settings.port": 5501 3 | } -------------------------------------------------------------------------------- /assets/bg-desktop-dark.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleverProgrammers/challenge-todo-list/6474bc8bf67103ae08d6facbca6df48aafbf0713/assets/bg-desktop-dark.jpg -------------------------------------------------------------------------------- /assets/icon-check.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/icon-cross.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/icon-moon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/icon-sun.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /firebase.js: -------------------------------------------------------------------------------- 1 | var firebaseConfig = { 2 | apiKey: "AIzaSyAI1brKkR9XfOGErHdMQKyfj8GQbKR7tXA", 3 | authDomain: "to-do-list-519ae.firebaseapp.com", 4 | projectId: "to-do-list-519ae", 5 | storageBucket: "to-do-list-519ae.appspot.com", 6 | messagingSenderId: "897143349984", 7 | appId: "1:897143349984:web:e23f665d2848abc8fa2685", 8 | measurementId: "G-N6YDZCPM2S" 9 | }; 10 | 11 | firebase.initializeApp(firebaseConfig); 12 | firebase.analytics(); 13 | var db = firebase.firestore(); -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | To Do List App 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |
22 |
23 |
24 |
25 | TODO 26 |
27 |
28 | 29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | 39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | 48 |
49 |
50 |
51 | Cut the lawn 52 |
53 |
54 |
55 |
56 |
57 | 58 |
59 |
60 |
61 | Cut the lawn 62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | Cut the lawn 71 |
72 |
73 |
74 |
75 |
76 | 5 items left 77 |
78 |
79 | All 80 | Active 81 | Completed 82 |
83 |
84 | Clear Completed 85 |
86 |
87 |
88 |
89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | 2 | function getItems(){ 3 | db.collection("todo-items").onSnapshot((snapshot) => { 4 | let items = []; 5 | snapshot.docs.forEach((doc) => { 6 | items.push({ 7 | id: doc.id, 8 | ...doc.data() 9 | }) 10 | }) 11 | generateItems(items); 12 | }) 13 | } 14 | 15 | function generateItems(items){ 16 | let todoItems = [] 17 | items.forEach((item) => { 18 | let todoItem = document.createElement("div"); 19 | todoItem.classList.add("todo-item"); 20 | let checkContainer = document.createElement("div"); 21 | checkContainer.classList.add("check"); 22 | let checkMark = document.createElement("div"); 23 | checkMark.classList.add("check-mark"); 24 | checkMark.innerHTML = ''; 25 | checkMark.addEventListener("click", function(){ 26 | markCompleted(item.id); 27 | }) 28 | checkContainer.appendChild(checkMark); 29 | 30 | let todoText = document.createElement("div"); 31 | todoText.classList.add("todo-text"); 32 | todoText.innerText = item.text; 33 | 34 | if(item.status == "completed"){ 35 | checkMark.classList.add("checked"); 36 | todoText.classList.add("checked"); 37 | } 38 | todoItem.appendChild(checkContainer); 39 | todoItem.appendChild(todoText); 40 | todoItems.push(todoItem) 41 | }) 42 | document.querySelector(".todo-items").replaceChildren(...todoItems); 43 | } 44 | 45 | 46 | 47 | function addItem(event){ 48 | event.preventDefault(); 49 | let text = document.getElementById("todo-input"); 50 | let newItem = db.collection("todo-items").add({ 51 | text: text.value, 52 | status: "active" 53 | }) 54 | text.value = ""; 55 | } 56 | 57 | function markCompleted(id){ 58 | let item = db.collection("todo-items").doc(id); 59 | item.get().then(function(doc) { 60 | if (doc.exists) { 61 | if(doc.data().status == "active"){ 62 | item.update({ 63 | status: "completed" 64 | }) 65 | } else { 66 | item.update({ 67 | status: "active" 68 | }) 69 | } 70 | } 71 | }) 72 | } 73 | 74 | getItems(); -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0; 3 | margin: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | font-family: 'Josefin Sans', sans-serif; 9 | background-color: hsl(235, 21%, 11%); 10 | font-size: 18px; 11 | display: flex; 12 | justify-content: center; 13 | } 14 | 15 | .background-image { 16 | position: absolute; 17 | top: 0; 18 | left: 0; 19 | right: 0; 20 | max-height: 350px; 21 | z-index: -1; 22 | } 23 | 24 | .background-image img { 25 | width: 100%; 26 | object-fit: cover; 27 | min-height: 350px; 28 | object-position: left; 29 | } 30 | 31 | .container { 32 | width: 100%; 33 | max-width: 700px; 34 | margin: 0px 30px; 35 | margin-top: 100px; 36 | } 37 | 38 | .header { 39 | display: flex; 40 | justify-content: space-between; 41 | align-items: center; 42 | } 43 | 44 | .title { 45 | color: white; 46 | letter-spacing: 10px; 47 | font-size: 50px; 48 | font-weight: bold; 49 | } 50 | 51 | .new-todo { 52 | width: 100%; 53 | height: 70px; 54 | background-color: hsl(235, 24%, 19%); 55 | margin-top: 50px; 56 | border-radius: 6px; 57 | display: flex; 58 | } 59 | 60 | 61 | 62 | .check{ 63 | flex-basis: 90px; 64 | display: flex; 65 | justify-content: center; 66 | align-items: center; 67 | } 68 | 69 | .check-mark { 70 | width: 30px; 71 | height: 30px; 72 | border-radius: 50%; 73 | border: 2px solid hsl(237, 14%, 26%); 74 | transition: all 0.25s; 75 | display: flex; 76 | justify-content: center; 77 | align-items: center; 78 | } 79 | 80 | .check-mark img { 81 | visibility: hidden; 82 | } 83 | 84 | .check-mark.checked img, .check-mark:hover img { 85 | visibility: visible; 86 | } 87 | 88 | .check-mark:hover { 89 | border-color: linear-gradient(135deg, #55DDFF 0%, #C058F3 100%); 90 | background: linear-gradient(135deg, #55DDFF 0%, #C058F3 100%); 91 | } 92 | 93 | .check-mark.checked { 94 | background-color: pink; 95 | background: linear-gradient(135deg, #55DDFF 0%, #C058F3 100%); 96 | } 97 | 98 | .todo-text.checked { 99 | text-decoration: line-through; 100 | color: hsl(233, 14%, 35%); 101 | } 102 | 103 | .new-todo-input { 104 | flex-grow: 1; 105 | display: flex; 106 | align-items: center; 107 | } 108 | 109 | .new-todo-input input { 110 | width: 100%; 111 | padding: 10px 0px; 112 | font-size: 18px; 113 | background-color: transparent; 114 | border: none; 115 | outline: none; 116 | color: hsl(234, 39%, 85%); 117 | } 118 | 119 | .new-todo-input form { 120 | flex-grow: 1; 121 | display: flex; 122 | } 123 | 124 | .new-todo-input input::placeholder { 125 | color: hsl(233, 14%, 35%); 126 | } 127 | 128 | .todo-text { 129 | display: flex; 130 | align-items: center; 131 | font-size: 18px; 132 | color: hsl(234, 39%, 85%); 133 | } 134 | 135 | .todo-item { 136 | width: 100%; 137 | height: 70px; 138 | background-color: hsl(235, 24%, 19%); 139 | display: flex; 140 | border-bottom: 1px solid hsl(237, 14%, 26%); 141 | cursor: pointer; 142 | transition: all .25s ease; 143 | transition-property: box-shadow, transform, border-color; 144 | } 145 | 146 | .todo-items-wrapper { 147 | margin-top: 30px; 148 | border-radius: 6px; 149 | overflow: hidden; 150 | background-color: hsl(235, 24%, 19%); 151 | box-shadow: 0px 2px 30px 0px rgba(0,0,0,0.4); 152 | margin-bottom: 30px; 153 | } 154 | 155 | .todo-items-info { 156 | width: 100%; 157 | height: 70px; 158 | background-color: hsl(235, 24%, 19%); 159 | display: flex; 160 | align-items: center; 161 | color: hsl(233, 14%, 35%); 162 | padding-left: 30px; 163 | display: flex; 164 | justify-content: space-between; 165 | padding-right: 30px; 166 | } 167 | 168 | .items-statuses { 169 | display: flex; 170 | justify-content: center; 171 | } 172 | 173 | .items-statuses span { 174 | padding: 0 4px; 175 | cursor: pointer; 176 | } 177 | 178 | .items-clear { 179 | cursor: pointer; 180 | text-align: end; 181 | } 182 | 183 | .items-statuses span:hover, .items-clear:hover { 184 | color: hsl(220, 98%, 61%); 185 | } 186 | 187 | .items-statuses .active { 188 | color: hsl(220, 98%, 61%); 189 | } 190 | 191 | .todo-item:hover { 192 | transform: translateY(-2px); 193 | box-shadow: 0 0px 7px 0px hsl(235, 21%, 11%); 194 | border-color: hsl(235, 24%, 19%); 195 | } 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | --------------------------------------------------------------------------------