Skip to content

Commit d6da9c3

Browse files
committed
first commit
1 parent b4af9a6 commit d6da9c3

File tree

4 files changed

+363
-0
lines changed

4 files changed

+363
-0
lines changed

img/background_office.jpg

339 KB
Loading

index.html

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta2/css/all.min.css"
8+
integrity="sha512-YWzhKL2whUzgiheMoBFwW8CKV4qpHQAEuvilg9FAn5VJUDwKZZxkJNuGM4XkWuk94WCrrwslk8yWNGmY1EduTA=="
9+
crossorigin="anonymous" referrerpolicy="no-referrer" />
10+
<link rel="stylesheet" href="style.css">
11+
<title>Kanban desk</title>
12+
</head>
13+
14+
<body>
15+
<!-- <header>Stop starting, start finishing</header> -->
16+
<div class="container">
17+
<div class="column" id="todo">
18+
<div class="head">
19+
<h2>To do</h2>
20+
<button class="btn" id="todobtn">add task</button>
21+
</div>
22+
<div class="taskcontainer todoTask">
23+
<!-- <textarea class="newtask" name="" id=""></textarea> -->
24+
<!-- <div class="newtask"><input type="text"></div> -->
25+
</div>
26+
</div>
27+
<div class="column" id="inprogress">
28+
<div class="head">
29+
<h2>In progress</h2>
30+
<button class="btn" id="inprogressbtn">add task</button>
31+
</div>
32+
<div class="taskcontainer inprogressTask"></div>
33+
</div>
34+
<div class="column" id="done">
35+
<div class="head">
36+
<h2>Done</h2>
37+
<button class="btn" id="donebtn">clear</button>
38+
</div>
39+
<div class="taskcontainer doneTask"></div>
40+
</div>
41+
</div>
42+
<script src="script.js" defer></script>
43+
<!-- <script src="https://kit.fontawesome.com/a9858e9911.js" crossorigin="anonymous"></script> -->
44+
45+
</body>
46+
47+
</html>

script.js

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
const todobtn = document.getElementById('todobtn')
2+
const inprogressbtn = document.getElementById('inprogressbtn')
3+
const donebtn = document.getElementById('donebtn')
4+
5+
const todo = document.querySelector('#todo .taskcontainer')
6+
const inprogress = document.querySelector('#inprogress .taskcontainer')
7+
const done = document.querySelector('#done .taskcontainer')
8+
let newTasks = document.querySelectorAll('.newtask')
9+
10+
let draggables = document.querySelectorAll('.draggable')
11+
const taskcontainers = document.querySelectorAll('.taskcontainer')
12+
let taskId = 0;
13+
14+
(function () { //get tasks from localstorage
15+
let tasksFromLS = []
16+
Object.keys(localStorage).forEach(task => tasksFromLS.
17+
push(JSON.parse(localStorage.getItem(task))))
18+
19+
if (localStorage.length > 0) {
20+
let ids = []
21+
tasksFromLS.forEach(task => ids.push(task.id))
22+
console.log(ids)
23+
taskId = Math.max.apply(Math, ids)
24+
}
25+
26+
let todoTasks = []
27+
let inprogressTasks = []
28+
let doneTasks = []
29+
30+
const tasksFromLSMapped = {
31+
todo: todoTasks,
32+
inprogress: inprogressTasks,
33+
done: doneTasks,
34+
}
35+
36+
tasksFromLS.forEach(task => {
37+
if (task === null) {
38+
console.log('no tasks')
39+
} else if (task.col === 'todoTask') {
40+
todoTasks.push(task)
41+
} else if (task.col === 'inprogressTask') {
42+
inprogressTasks.push(task)
43+
} else if (task.col === 'doneTask') {
44+
doneTasks.push(task)
45+
}
46+
})
47+
48+
49+
todoTasks.sort((a, b) => sortTasks(a, b))
50+
inprogressTasks.sort((a, b) => sortTasks(a, b))
51+
doneTasks.sort((a, b) => sortTasks(a, b))
52+
53+
function sortTasks(a, b) {
54+
if (a.order < b.order) {
55+
return -1
56+
}
57+
}
58+
59+
tasksFromLSMapped.todo.forEach(task => todo.
60+
appendChild(createTextArea(task)))
61+
tasksFromLSMapped.inprogress.forEach(task => inprogress.
62+
appendChild(createTextArea(task)))
63+
tasksFromLSMapped.done.forEach(task => done.
64+
appendChild(createTextArea(task)))
65+
66+
function createTextArea(task) {
67+
let textarea = document.createElement('textarea')
68+
textarea.classList.add('newtask', 'draggable', `${task.col}`)
69+
textarea.setAttribute('draggable', 'true')
70+
textarea.innerHTML += `${task.text}`
71+
textarea.id = task.id
72+
return textarea
73+
}
74+
renewTasksClasses()
75+
})();
76+
77+
console.log(taskId)
78+
79+
todobtn.addEventListener('click', () => {
80+
newTask(todo)
81+
renewTasksClasses()
82+
})
83+
84+
inprogressbtn.addEventListener('click', () => {
85+
newTask(inprogress)
86+
renewTasksClasses()
87+
})
88+
89+
donebtn.addEventListener('click', () => {
90+
document.querySelectorAll('.doneTask.draggable').forEach(el => {
91+
el.remove()
92+
localStorage.removeItem(`Task${el.id}`)
93+
})
94+
})
95+
96+
class Task {
97+
constructor(id, col, order, text) {
98+
this.id = id
99+
this.col = col
100+
this.order = order
101+
this.text = text
102+
}
103+
}
104+
105+
function newTask(col) {
106+
let textarea = document.createElement('textarea')
107+
const currClass = col.classList[1]
108+
textarea.classList.add('newtask', 'draggable', `${currClass}`)
109+
textarea.setAttribute('draggable', 'true')
110+
textarea.innerHTML += ``
111+
textarea.id = ++taskId
112+
col.appendChild(textarea)
113+
textarea.focus()
114+
}
115+
116+
117+
function getCurrOrder(task, currClass) {
118+
const taskAllCol = document.querySelectorAll(`.draggable.${currClass}`)
119+
let taskOrder = 1
120+
for (let i = 0; taskAllCol[i].id !== task.id; i++) {
121+
taskOrder += 1
122+
}
123+
return taskOrder
124+
}
125+
126+
function renewTasksClasses() {
127+
draggables = document.querySelectorAll('.draggable')
128+
newTasks = document.querySelectorAll('.newtask')
129+
newTasks.forEach((task) => {
130+
task.addEventListener('input', () => {
131+
const currClass = task.classList[2]
132+
const taskValue = task.value
133+
const taskOrder = getCurrOrder(task, currClass)
134+
const taskData = new Task(task.id, `${currClass}`, `${taskOrder}`, `${taskValue}`)
135+
console.log(taskData)
136+
localStorage.setItem(`Task${task.id}`, JSON.stringify(taskData))
137+
})
138+
139+
})
140+
draggables.forEach((draggable) => {
141+
draggable.addEventListener('dragstart', () => {
142+
draggable.classList.add('dragging')
143+
})
144+
draggable.addEventListener('dragend', () => {
145+
draggable.classList.remove('dragging')
146+
})
147+
})
148+
}
149+
150+
151+
taskcontainers.forEach((container) => { //dragover
152+
container.addEventListener('dragover', (e) => {
153+
e.preventDefault() //'e' is event in DOM
154+
const afterElement = getDragAfterElement(container, e.clientY)
155+
const draggable = document.querySelector('.dragging')
156+
draggable.classList.remove('todoTask', 'inprogressTask', 'doneTask')
157+
const currClass = container.classList[1] //get curr class
158+
if (afterElement == null) {
159+
container.appendChild(draggable)
160+
draggable.classList.add(`${currClass}`)
161+
defineTasksOrder(currClass)
162+
}
163+
else {
164+
container.insertBefore(draggable, afterElement)
165+
renewTasksClasses()
166+
draggable.classList.add(`${currClass}`)
167+
defineTasksOrder(currClass)
168+
}
169+
})
170+
})
171+
172+
function defineTasksOrder(currClass) { //define tasks order and write them in LS
173+
const taskAllCol = document.querySelectorAll(`.draggable.${currClass}`)
174+
let taskOrder = 0
175+
for (let i = 0; i <= (taskAllCol.length - 1); i++) {
176+
taskOrder += 1
177+
const task = new Task(`${taskAllCol[i].id}`, `${currClass}`,
178+
`${taskOrder}`, `${taskAllCol[i].value}`)
179+
localStorage.setItem(`Task${taskAllCol[i].id}`, JSON.stringify(task))
180+
}
181+
}
182+
183+
function getDragAfterElement(container, y) { //finds the position
184+
const draggableElements = [...container.querySelectorAll('.draggable:not(.dragging)')]
185+
return draggableElements.reduce((closest, child) => {
186+
const box = child.getBoundingClientRect() //returns size of element and his position
187+
const offset = y - box.top - box.height / 2
188+
if (offset < 0 && offset > closest.offset) {
189+
return { offset: offset, element: child }
190+
}
191+
else {
192+
return closest
193+
}
194+
}, { offset: Number.NEGATIVE_INFINITY }).element
195+
}

style.css

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
2+
3+
* {
4+
box-sizing: border-box;
5+
}
6+
7+
body {
8+
font-family: 'Roboto', sans-serif;
9+
align-items: center;
10+
font-size: 20px;
11+
height: 100%;
12+
margin: 0;
13+
background-color: rgb(235, 206, 196);
14+
background-image: url(./img/background_office.jpg);
15+
background-size: 150vh;
16+
}
17+
18+
header {
19+
text-align: center;
20+
font-family: 'Roboto';
21+
color: rgb(22, 22, 22);
22+
margin-top: 10px;
23+
opacity: 0.6;
24+
}
25+
26+
.container {
27+
display: flex;
28+
}
29+
30+
.column {
31+
height: 80vh;
32+
flex: 1;
33+
display: flex;
34+
flex-direction: column;
35+
}
36+
37+
.head {
38+
display: flex;
39+
flex-direction: column;
40+
justify-content: center;
41+
align-items: center;
42+
background-color: rgb(240, 219, 212);
43+
color: rgb(91, 143, 143);
44+
}
45+
46+
.column,
47+
.head,
48+
.taskcontainer {
49+
border-radius: 10px;
50+
padding: 5px;
51+
margin: 5px;
52+
}
53+
54+
.btn {
55+
width: 100px;
56+
height: 20px;
57+
border-radius: 5px;
58+
border: none;
59+
color: inherit;
60+
background: none;
61+
cursor: pointer;
62+
}
63+
64+
.btn:hover {
65+
color: rgb(170, 184, 184);
66+
}
67+
68+
h2 {
69+
margin: 5px;
70+
}
71+
72+
.taskcontainer {
73+
flex: 2;
74+
flex-direction: column;
75+
justify-content: center;
76+
}
77+
78+
.newtask {
79+
color: rgb(22, 22, 22);
80+
height: 100px;
81+
width: 29vw;
82+
border-radius: 10px;
83+
opacity: 0.7;
84+
text-align: center;
85+
margin: 5px;
86+
resize: none;
87+
overflow: auto;
88+
background-color: rgb(137, 151, 139);
89+
border: 1px solid #999;
90+
font-size: 12pt;
91+
92+
}
93+
94+
.draggable {
95+
padding: 1rem;
96+
cursor: grab;
97+
}
98+
99+
.draggable.dragging {
100+
opacity: 0.2;
101+
cursor: grabbing;
102+
}
103+
104+
textarea:active {
105+
outline-style: double;
106+
outline-color: rgb(240, 219, 212);
107+
}
108+
109+
textarea:hover {
110+
box-shadow: 0 0 30px rgb(240, 219, 212);
111+
transition: 0.3s ease-in-out;
112+
}
113+
114+
textarea:focus {
115+
outline-style: double;
116+
outline-color: rgb(240, 219, 212);
117+
box-shadow: 0 0 30px rgb(240, 219, 212);
118+
background-color: rgb(137, 155, 139);
119+
transition: 0.4s ease-in;
120+
cursor: text
121+
}

0 commit comments

Comments
 (0)