├── .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 |
31 |
42 |
43 |
44 |
45 |
46 |
47 |

48 |
49 |
50 |
51 | Cut the lawn
52 |
53 |
54 |
55 |
60 |
61 | Cut the lawn
62 |
63 |
64 |
65 |
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 |
--------------------------------------------------------------------------------