\ No newline at end of file
diff --git a/dist/editor/js/editor.js b/dist/editor/js/editor.js
index 681c1bf..d25d547 100644
--- a/dist/editor/js/editor.js
+++ b/dist/editor/js/editor.js
@@ -1 +1 @@
-document.addEventListener("DOMContentLoaded",(e=>{})),document.querySelector("#navOpen").addEventListener("click",(e=>{document.querySelector("nav.sideNav").style.removeProperty("width"),document.querySelector("main.editor").style.removeProperty("margin-left"),e.target.style.removeProperty("visibility")})),document.querySelector("#navClose").addEventListener("click",(e=>{document.querySelector("nav.sideNav").style.width="0",document.querySelector("main.editor").style.marginLeft="0",document.querySelector("#navOpen").style.visibility="visible"}));
\ No newline at end of file
+let dateOptions={month:"short",year:"numeric"};function edit(e){document.querySelector("#timelineItem"+e).classList.toggle("editing"),document.querySelector("#grade"+e).removeAttribute("disabled"),document.querySelector("#course"+e).removeAttribute("disabled")}function updateItem(e,t){t.preventDefault();let n=new FormData;n.append("dateFrom",document.querySelector("#dateFrom"+e).value),n.append("dateTo",document.querySelector("#dateTo"+e).value),n.append("grade",document.querySelector("#grade"+e).value),n.append("course",document.querySelector("#course"+e).value),fetch("/api/timelineData/edu/"+e,{method:"PUT",body:n,headers:{Authorization:"Bearer "+localStorage.getItem("token")}}).then((t=>{if(t.ok)return document.querySelector("#timelineItem"+e).classList.toggle("editing"),document.querySelector("#grade"+e).setAttribute("disabled",""),void document.querySelector("#course"+e).setAttribute("disabled","");t.json().then((e=>{alert(e.message)}))}))}document.addEventListener("DOMContentLoaded",(()=>{document.querySelector("#dateFrom").max=(new Date).toISOString().split("T")[0],fetch("/api/timelineData/edu").then((e=>{e.json().then((t=>{if(e.ok)for(let e=0;eupdateItem(e,t),n.innerHTML=`\n
\n\t\t\t\t\t\n\t\t\t\t`,document.getElementById("edu").appendChild(n)}else document.querySelector("#edu").innerHTML="No education data found"}))}))})),document.querySelector("#navOpen").addEventListener("click",(e=>{document.querySelector("nav.sideNav").style.removeProperty("width"),document.querySelector("main.editor").style.removeProperty("margin-left"),e.target.style.removeProperty("visibility")})),document.querySelector("#navClose").addEventListener("click",(()=>{document.querySelector("nav.sideNav").style.width="0",document.querySelector("main.editor").style.marginLeft="0",document.querySelector("#navOpen").style.visibility="visible"}));
\ No newline at end of file
diff --git a/dist/editor/js/index.js b/dist/editor/js/index.js
index 63c633c..6a51c04 100644
--- a/dist/editor/js/index.js
+++ b/dist/editor/js/index.js
@@ -1 +1 @@
-function showErrorMessage(e,t){document.querySelector(`#${t}Error`).classList.remove("hidden"),document.querySelector(`#${t}Error div`).innerText=e}function switchView(e,t){document.querySelector(e).classList.toggle("shown"),setTimeout((()=>document.querySelector(e).style.transform="translateX(150vw)"),500),setTimeout((()=>document.querySelector(e).style.display="none"),500),setTimeout((()=>document.querySelector(t).style.removeProperty("display")),200),setTimeout((()=>document.querySelector(t).classList.toggle("shown")),300),setTimeout((()=>document.querySelector(t).style.removeProperty("transform")),400)}document.addEventListener("DOMContentLoaded",(e=>{fetch("/api/user/isLoggedIn").then((e=>{e.ok&&(window.location.href="./editor.html")}))})),document.querySelector("#login form").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;if(e.target.username.value.length>0&&e.target.password.value.length>0)return t.append("username",e.target.username.value),t.append("password",e.target.password.value),void fetch("/api/user/login",{method:"POST",body:t}).then((e=>{e.ok?window.location.href="./editor.html":400!==e.status?showErrorMessage("Invalid username or password.","login"):showErrorMessage("Please type in a username and password.","login")}));showErrorMessage("Please type in a username and password.","login")})),document.querySelector("#loginError .close").addEventListener("click",(()=>document.querySelector("#loginError").classList.toggle("hidden"))),document.querySelector("#resetError .close").addEventListener("click",(()=>document.querySelector("#resetError").classList.toggle("hidden"))),document.querySelector("#changeError .close").addEventListener("click",(()=>document.querySelector("#changeError").classList.toggle("hidden"))),document.querySelectorAll("form i.fa-eye").forEach((e=>{e.addEventListener("click",(e=>{if("password"===e.target.previousElementSibling.type)return e.target.previousElementSibling.type="text",e.target.classList.remove("fa-eye"),void e.target.classList.add("fa-eye-slash");e.target.previousElementSibling.type="password",e.target.classList.remove("fa-eye-slash"),e.target.classList.add("fa-eye")}))})),document.querySelector("#resetPwd").addEventListener("click",(()=>{switchView("#login","#resetPassword")})),document.querySelector("#loginBtn").addEventListener("click",(()=>{switchView("#resetPassword","#login")})),document.querySelector("#resetPassword form").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;""!==e.target.email?(window.email=e.target.email.value,t.append("email",e.target.email.value),fetch(`/api/user/checkResetEmail/${e.target.email.value}`).then((e=>{e.ok&&switchView("#resetPassword","#checkResetCode"),showErrorMessage("Invalid email.","reset")}))):showErrorMessage("Please type in your email.","reset")})),document.querySelector("#checkResetCode form").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;""!==e.target.code.value?(t.append("code",e.target.code.value),fetch(`/api/user/checkResetCode/${e.target.code.value}`).then((e=>{e.ok&&switchView("#checkResetCode","#changePassword"),showErrorMessage("Invalid code.","resetCode")}))):showErrorMessage("Please type in your reset code.","check")})),document.querySelector("#changePassword form").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;""!==e.target.pass.value||""!==e.target.rePass.value?e.target.pass.value===e.target.rePass.value?(t.append("password",e.target.pass.value),fetch("/api/user/changePassword",{method:"POST",body:t}).then((e=>{e.ok&&switchView("#changePassword","#login"),showErrorMessage("Something went wrong.","change")}))):showErrorMessage("Passwords do not match.","change"):showErrorMessage("Please type in a new password.","change")}));
\ No newline at end of file
+function showErrorMessage(e,t){document.querySelector(`#${t}Error`).classList.remove("hidden"),document.querySelector(`#${t}Error div`).innerText=e}function switchView(e,t){document.querySelector(e).classList.toggle("shown"),setTimeout((()=>document.querySelector(e).style.transform="translateX(150vw)"),500),setTimeout((()=>document.querySelector(e).style.display="none"),500),setTimeout((()=>document.querySelector(t).style.removeProperty("display")),200),setTimeout((()=>document.querySelector(t).classList.toggle("shown")),300),setTimeout((()=>document.querySelector(t).style.removeProperty("transform")),400)}document.addEventListener("DOMContentLoaded",(e=>{fetch("/api/user/isLoggedIn").then((e=>{e.ok&&(window.location.href="./editor.html")}))})),document.querySelector("#login form").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;if(e.target.username.value.length>0&&e.target.password.value.length>0)return t.append("username",e.target.username.value),t.append("password",e.target.password.value),void fetch("/api/user/login",{method:"POST",body:t}).then((e=>e.json())).then((e=>{if(res.ok)return localStorage.setItem("token",e.token),void(window.location.href="./editor.html");400!==res.status?showErrorMessage("Invalid username or password.","login"):showErrorMessage("Please type in a username and password.","login")}));showErrorMessage("Please type in a username and password.","login")})),document.querySelector("#loginError .close").addEventListener("click",(()=>document.querySelector("#loginError").classList.toggle("hidden"))),document.querySelector("#resetError .close").addEventListener("click",(()=>document.querySelector("#resetError").classList.toggle("hidden"))),document.querySelector("#changeError .close").addEventListener("click",(()=>document.querySelector("#changeError").classList.toggle("hidden"))),document.querySelectorAll("form i.fa-eye").forEach((e=>{e.addEventListener("click",(e=>{if("password"===e.target.previousElementSibling.type)return e.target.previousElementSibling.type="text",e.target.classList.remove("fa-eye"),void e.target.classList.add("fa-eye-slash");e.target.previousElementSibling.type="password",e.target.classList.remove("fa-eye-slash"),e.target.classList.add("fa-eye")}))})),document.querySelector("#resetPwd").addEventListener("click",(()=>{switchView("#login","#resetPassword")})),document.querySelector("#loginBtn").addEventListener("click",(()=>{switchView("#resetPassword","#login")})),document.querySelector("#resetPassword form").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;""!==e.target.email?(window.email=e.target.email.value,t.append("email",e.target.email.value),fetch(`/api/user/checkResetEmail/${e.target.email.value}`).then((e=>{e.ok&&switchView("#resetPassword","#checkResetCode"),showErrorMessage("Invalid email.","reset")}))):showErrorMessage("Please type in your email.","reset")})),document.querySelector("#checkResetCode form").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;""!==e.target.code.value?(t.append("code",e.target.code.value),fetch(`/api/user/checkResetCode/${e.target.code.value}`).then((e=>{e.ok&&switchView("#checkResetCode","#changePassword"),showErrorMessage("Invalid code.","resetCode")}))):showErrorMessage("Please type in your reset code.","check")})),document.querySelector("#changePassword form").addEventListener("submit",(e=>{e.preventDefault();let t=new FormData;""!==e.target.pass.value||""!==e.target.rePass.value?e.target.pass.value===e.target.rePass.value?(t.append("password",e.target.pass.value),fetch("/api/user/changePassword",{method:"POST",body:t}).then((e=>{e.ok&&switchView("#changePassword","#login"),showErrorMessage("Something went wrong.","change")}))):showErrorMessage("Passwords do not match.","change"):showErrorMessage("Please type in a new password.","change")}));
\ No newline at end of file
diff --git a/dist/js/main.js b/dist/js/main.js
index 721a832..5936e6f 100644
--- a/dist/js/main.js
+++ b/dist/js/main.js
@@ -1 +1 @@
-const scrollLimit=150;var dataText=["full stack developer","web designer","student","gamer","drummer"];function typeWriter(t,e,n){e_',setTimeout((function(){typeWriter(t,e+1,n)}),100)):"function"==typeof n&&setTimeout(n,700)}function StartTextAnimation(t){void 0===dataText[t]?setTimeout((function(){StartTextAnimation(0)}),1500):t{t.json().then((e=>{t.ok&&e.forEach((t=>{let e=document.createElement("div");e.classList.add("timelineItem"),e.innerHTML=`\n\t\t\t\t\t
\n `}))}))}))}window.onscroll=()=>{document.body.scrollTop>=150||document.documentElement.scrollTop>=150?document.querySelector("nav").classList.add("scrolled"):document.querySelector("nav").classList.remove("scrolled");let t="";document.querySelectorAll("section").forEach((e=>{const n=e.offsetTop;window.pageYOffset>=n-60&&(t=e.getAttribute("id"))})),document.querySelectorAll("nav ul li a").forEach((e=>{e.classList.remove("active"),e.href.includes(t)&&""!==t?e.classList.add("active"):""===t&&document.querySelector("nav ul li a").classList.add("active")}))},document.addEventListener("DOMContentLoaded",(()=>{StartTextAnimation(0),getTimelineData(),getProjectData()})),document.querySelector("#contactError .close").addEventListener("click",(()=>document.querySelector("#contactError").classList.toggle("hidden"))),document.querySelector("#goBackToTop").addEventListener("click",(()=>{window.scrollTo(0,0)})),document.querySelector("#contactForm").addEventListener("submit",(t=>{t.preventDefault();let e=new FormData;e.append("fName",document.querySelector("#fName").value),e.append("lName",document.querySelector("#lName").value),e.append("email",document.querySelector("#email").value),e.append("subject",document.querySelector("#subject").value),e.append("message",document.querySelector("#message").value);let n=!1;if(["#fName","#lName","#email","#subject","#message"].forEach((t=>{const e=document.querySelector(t);0===e.value.length?(e.classList.add("invalid"),n=!0):(e.classList.remove("invalid"),document.querySelector("#contactError").classList.remove("error"))})),n)return document.querySelector("#contactError").classList.add("error"),document.querySelector("#contactError").classList.remove("hidden"),void(document.querySelector("#contactError div").innerText="Please fill out all fields.");fetch("/api/contact",{method:"POST",body:e}).then((t=>{t.ok&&(document.querySelector("#contactError").classList.remove("hidden"),document.querySelector("#contactError div").innerText="Thanks for contacting me, I will get back to you as soon as possible.")}))}));
\ No newline at end of file
+const scrollLimit=150;var dataText=["full stack developer","web designer","student","gamer","drummer"];function typeWriter(t,e,n){e_',setTimeout((function(){typeWriter(t,e+1,n)}),100)):"function"==typeof n&&setTimeout(n,700)}function StartTextAnimation(t){void 0===dataText[t]?setTimeout((function(){StartTextAnimation(0)}),1500):t{e.json().then((n=>{e.ok&&n.forEach((e=>{let n=document.createElement("div");n.classList.add("timelineItem"),n.innerHTML=`\n\t\t\t\t\t