diff --git a/src/assets/js/progressBar.js b/src/assets/js/progressBar.js new file mode 100644 index 0000000..7093515 --- /dev/null +++ b/src/assets/js/progressBar.js @@ -0,0 +1,29 @@ +const innerMeter = document.querySelector('.meter-inner'); +const checkboxes = document.querySelectorAll('.watched'); +let completed = Number(innerMeter.innerText); + +if (checkboxes) { + for (const checkbox of checkboxes) { + checkbox.addEventListener('change', updateProgress); + } +} + +function updateWidth() { + innerMeter.style.width = `${completed / checkboxes.length * 100}%`; + innerMeter.innerText = `${completed} / ${checkboxes.length} `; + if (completed === checkboxes.length) { + innerMeter.innerText = "You are a software engineer."; + } +} + +function updateProgress(e) { + if (e.target.checked) { + completed += 1; + } else { + completed -= 1; + } + updateWidth(); +} + +// Set the progress bar width on page load +updateWidth(); diff --git a/src/controllers/homework.js b/src/controllers/homework.js index 5a09833..fff3ab8 100644 --- a/src/controllers/homework.js +++ b/src/controllers/homework.js @@ -40,7 +40,7 @@ export const addEditHomework = async (req, res) => { class: hwClass[i], due: req.body.due, description: hwDesc[i], - required: hwRequired[i] === "true" ? true : false, + required: hwRequired[i] === "true", }; const hwItem = await HomeworkItem.findByIdAndUpdate(hwId[i] || mongoose.Types.ObjectId(), item, {upsert: true, new: true}); items.push(hwItem._id); @@ -113,7 +113,7 @@ export const showHomework = async (req, res) => { }; export const importData = async (req, res) => { - if (!req.isAuthenticated()) return notLoggedIn(req, res);; + if (!req.isAuthenticated()) return notLoggedIn(req, res); try { const data = JSON.parse(JSON.parse(req.body.import).CBState); const submitData = []; diff --git a/src/controllers/lessons.js b/src/controllers/lessons.js index f37ab42..ecc9768 100644 --- a/src/controllers/lessons.js +++ b/src/controllers/lessons.js @@ -104,10 +104,15 @@ export const getAllLessonsProgress = async (userId, lessons) => { export const allLessons = async (req, res) => { let lessons = await Lesson.find().lean().sort({ _id: 1 }); + let completedCount = 0 if (req.isAuthenticated()) { lessons = await getAllLessonsProgress(req.user.id, lessons); + completedCount = await LessonProgress.countDocuments({ + user: req.user.id, + watched: true, + }); } - res.render("allLessons", { lessons }); + res.render("allLessons", { lessons, completedCount }); }; export const getLessonProgress = async (userId, lesson) => { diff --git a/src/controllers/pages.js b/src/controllers/pages.js index e79f3f4..2a2e0ff 100644 --- a/src/controllers/pages.js +++ b/src/controllers/pages.js @@ -23,7 +23,13 @@ export const dashboard = async (req, res) => { currentLesson = await Lesson.findById(req.user.currentClass); currentLesson = await getLessonProgress(req.user.id, currentLesson); } - res.render("dashboard", { lesson: currentLesson }); + + const totalCount = await LessonProgress.countDocuments(); + const completedCount = await LessonProgress.countDocuments({ + user: req.user.id, + watched: true, + }); + res.render("dashboard", { lesson: currentLesson, completedCount, totalCount }); }; export const account = (req, res) => { diff --git a/src/tailwind.css b/src/tailwind.css index 72f6497..8665f77 100644 --- a/src/tailwind.css +++ b/src/tailwind.css @@ -191,6 +191,14 @@ @apply shadow-[0_2px_10px_0_rgba(0,0,0,0.1)]; } + /*** PROGRESS METER ***/ + .meter-inner { + @apply transition-all duration-500 ease-in-out; + } + .meter { + @apply overflow-hidden; + } + /********* temporary ************/ #video { max-width: 960px; diff --git a/src/views/allLessons.pug b/src/views/allLessons.pug index 42b783e..eecae94 100644 --- a/src/views/allLessons.pug +++ b/src/views/allLessons.pug @@ -1,5 +1,6 @@ extends layouts/default.pug include ./mixins/lessonCard.pug +include ./mixins/progressBar.pug block variables - title = "Classes" @@ -11,6 +12,9 @@ block content h1.mb-4 All Classes + if loggedIn + +progressBar(completedCount) + #lessons.grid.gap-y-12.gap-x-16(class="sm:gap-y-24 grid-cols-[repeat(auto-fill,_minmax(285px,_1fr))]") each lesson in lessons +lessonCard(lesson) @@ -21,3 +25,4 @@ append scripts if loggedIn script(src="/js/lessonProgress.js") script(src="/js/lessonDone.js") + script(src="/js/progressBar.js") diff --git a/src/views/dashboard.pug b/src/views/dashboard.pug index c300a19..75d2399 100644 --- a/src/views/dashboard.pug +++ b/src/views/dashboard.pug @@ -1,5 +1,6 @@ extends layouts/default.pug include ./mixins/lessonCard.pug +include ./mixins/progressBar.pug block variables - title = "Dashboard" @@ -11,6 +12,10 @@ block content .flex.justify-center.items-baseline.flex-wrap.flex-wrap-reverse h1.mb-6.mr-auto Your Progress h3.mb-6.text-xl.text-twilight-900.font-medium #{user.username} + + if loggedIn + +progressBar(completedCount, totalCount) + h2.mb-3 Next Class #next-lesson.w-full.max-w-80 if lesson diff --git a/src/views/mixins/progressBar.pug b/src/views/mixins/progressBar.pug new file mode 100644 index 0000000..f95fb6a --- /dev/null +++ b/src/views/mixins/progressBar.pug @@ -0,0 +1,6 @@ +mixin progressBar(completedCount, totalCount) + div.meter.w-full.h-8.rounded.mb-6.bg-twilight-50.border + if totalCount + div.meter-inner.text-center.text-lg.font-medium.h-8.text-twilight-50.bg-pink-800(style=`width: ${completedCount / totalCount * 100}%`) #{completedCount} / #{totalCount} + else + div.meter-inner.text-center.text-lg.font-medium.h-8.text-twilight-50.bg-pink-800 #{completedCount}