diff --git a/databases/userDatabase.js b/databases/userDatabase.js index c630c86..14f39bf 100644 --- a/databases/userDatabase.js +++ b/databases/userDatabase.js @@ -250,6 +250,7 @@ async function getStudentSessions(userId) { s.duration_minutes, s.status, p.status AS payment_status, + p.amount AS payment_amount, m.link AS meeting_link FROM sessions s LEFT JOIN payments p diff --git a/public/admin/dashboard_admin.html b/public/admin/dashboard_admin.html index e7ab943..0b055cf 100644 --- a/public/admin/dashboard_admin.html +++ b/public/admin/dashboard_admin.html @@ -4,17 +4,197 @@ Admin Dashboard + + -

Admin Dashboard

-

-
-

Pending Instructor Approvals

- +
+

Admin Dashboard

+

+ +
+

Pending Instructor Approvals

+ +
    + + +
    + + + diff --git a/public/admin/dashboard_admin.js b/public/admin/dashboard_admin.js index 0af5893..1854bd4 100644 --- a/public/admin/dashboard_admin.js +++ b/public/admin/dashboard_admin.js @@ -31,6 +31,18 @@ async function loadDashboard() { const pendingUl = document.getElementById('pendingInstructors'); pendingUl.innerHTML = ''; + /* ===================== ADDITION START ===================== */ + const pendingStatus = document.getElementById('pendingStatus'); + pendingStatus.style.display = "none"; + pendingStatus.textContent = ""; + + if (!pending || pending.length === 0) { + pendingStatus.textContent = "No pending instructors at the moment."; + pendingStatus.style.display = "block"; + return; + } + /* ====================== ADDITION END ====================== */ + pending.forEach(inst => { const li = document.createElement('li'); li.innerHTML = ` @@ -52,7 +64,7 @@ async function loadDashboard() { }); const result = await res.json(); alert(result.message); - loadDashboard(); // refresh list + loadDashboard(); }); }); @@ -65,7 +77,7 @@ async function loadDashboard() { }); const result = await res.json(); alert(result.message); - loadDashboard(); // refresh list + loadDashboard(); }); }); diff --git a/public/index.html b/public/index.html index d36016f..ca32381 100644 --- a/public/index.html +++ b/public/index.html @@ -4,12 +4,86 @@ LearnSync + -

    LearnSync CMS

    - - +
    +

    LearnSync

    + + +
    diff --git a/public/instructor/dashboard_instructor.html b/public/instructor/dashboard_instructor.html index 2f695e1..031f58b 100644 --- a/public/instructor/dashboard_instructor.html +++ b/public/instructor/dashboard_instructor.html @@ -4,6 +4,188 @@ Instructor Dashboard + @@ -17,21 +199,10 @@

    Instructor Dashboard

    Pending Approvals (student requests)

    +

    Scheduled sessions

    + -

    Approved Sessions / Schedule

    - - - - - - - - - - -
    StudentCourse / TopicDate & TimeStatus
    - -

    ALL SESSIONS

    +

    ALL SESSIONS

    @@ -39,24 +210,31 @@

    ALL SESSIONS

    + + diff --git a/public/instructor/dashboard_instructor.js b/public/instructor/dashboard_instructor.js index feff23c..cdd1253 100644 --- a/public/instructor/dashboard_instructor.js +++ b/public/instructor/dashboard_instructor.js @@ -22,6 +22,8 @@ async function viewAllSessions(token) { // Render sessions function renderSessions(sessions) { const allUl = document.getElementById("allSessions"); + const scheduledSessionsUl = document.getElementById("scheduledSessions"); + scheduledSessionsUl.innerHTML = ""; allUl.innerHTML = ""; if (!sessions.length) { @@ -44,7 +46,7 @@ function renderSessions(sessions) { // Base text li.textContent = `${s.description} | ${s.status} | Payment: ${paymentText}`; - li.textContent += ` | Scheduled at: ${formatLocalTime(s.local_start_time)}`; + li.textContent += ` | Scheduled at: ${formatLocalTime(s.local_start_time)} | Duration: ${s.duration_minutes} mins`; // Handle meeting link visibility if (s.meeting_scheduled && s.meeting_link) { @@ -60,7 +62,19 @@ function renderSessions(sessions) { } allUl.appendChild(li); + if (s.status === "scheduled" && !s.meetingCompleted) { + const scheduledLi = li.cloneNode(true); // clone the same li + scheduledSessionsUl.appendChild(scheduledLi); + } }); + if (!scheduledSessionsUl || scheduledSessionsUl.children.length === 0) { + scheduledSessionsUl.textContent = "No scheduled sessions at the moment."; + scheduledSessionsUl.style.display = "block"; + } + if (!allUl || allUl.children.length === 0) { + allUl.textContent = "No sessions found."; + allUl.style.display = "block"; + } } @@ -79,15 +93,21 @@ async function loadPendingApprovals(token) { const ul = document.getElementById("pendingApprovals"); ul.innerHTML = ""; + if (!pending.length) { + ul.innerHTML = "
  • No pending approvals at the moment.
  • "; + return; + } + pending.forEach(s => { const li = document.createElement("li"); li.innerHTML = ` Student: ${s.student_id || s.student_user_id} | ${s.description} | - ${formatLocalTime(s.local_start_time)} + ${formatLocalTime(s.local_start_time)} | + ${s.duration_minutes} mins
    - Amount: + Amount:
    @@ -170,7 +190,6 @@ async function loadInstructorDashboard() { } viewAllSessions(token); - } catch (err) { console.error("Error loading dashboard:", err); } diff --git a/public/shared/login.html b/public/shared/login.html index f92b3d9..7d0cae6 100644 --- a/public/shared/login.html +++ b/public/shared/login.html @@ -1,23 +1,121 @@ + LearnSync Login + + -

    Login to LearnSync

    -
    -

    - -
    -

    - +

    Login to LearnSync

    + + + + + + + -
    -

    +

    + - + + \ No newline at end of file diff --git a/public/shared/signup.html b/public/shared/signup.html index 4897dbc..29b19b3 100644 --- a/public/shared/signup.html +++ b/public/shared/signup.html @@ -1,42 +1,143 @@ - + + LearnSync Signup - - + + + + + +

    Create a LearnSync Account

    - -
    -

    - -
    -

    - -
    -

    - -
    -

    - -
    - + + + + + + + + + + + + -

    - -
    -
    Password must contain at least 1 uppercase letter, 1 lowercase letter, and 1 digit mwith minimum length of 8 characters.
    -

    +
    Password must contain at least 1 uppercase letter, 1 lowercase letter, and 1 digit with minimum length of 8 + characters.
    + +

    + + + + - - - + \ No newline at end of file diff --git a/public/student/book_session.html b/public/student/book_session.html index c9e2b01..cd4f4d4 100644 --- a/public/student/book_session.html +++ b/public/student/book_session.html @@ -5,11 +5,97 @@ Create Session -

    Create Session

    +

    Create Session

    -
    -

    + + -
    -

    + + -
    -

    + + -
    -

    + +

    Filter Instructors (Leave empty for no filters)

    -
    -

    + + +

    +

    Matching Instructors

    -

    diff --git a/public/student/dashboard_student.html b/public/student/dashboard_student.html index 0a915a2..ec67ea9 100644 --- a/public/student/dashboard_student.html +++ b/public/student/dashboard_student.html @@ -2,8 +2,181 @@ - + Student Dashboard + + @@ -17,6 +190,9 @@

    Student Dashboard

    Sessions Pending Payment

    +

    Scheduled sessions

    + +

    All Sessions

    @@ -24,18 +200,29 @@

    All Sessions

    + + diff --git a/public/student/dashboard_student.js b/public/student/dashboard_student.js index 3da8d61..660eb70 100644 --- a/public/student/dashboard_student.js +++ b/public/student/dashboard_student.js @@ -76,6 +76,10 @@ async function viewAllSessions(token) { function renderSessions(sessions) { const allUl = document.getElementById("allSessions"); allUl.innerHTML = ""; + const scheduledSessionsUl = document.getElementById("scheduledSessions"); + scheduledSessionsUl.innerHTML = ""; + const pendingUl = document.getElementById("pendingPaymentSessions"); + pendingUl.innerHTML = ""; if (!sessions.length) { allUl.innerHTML = "
  • No sessions found.
  • "; @@ -97,18 +101,24 @@ function renderSessions(sessions) { // Base text li.textContent = `${s.description} | ${s.status} | Payment: ${paymentText}`; - li.textContent += ` | Scheduled at: ${formatLocalTime(s.local_start_time)}`; + li.textContent += ` | Scheduled at: ${formatLocalTime(s.local_start_time)} | Duration: ${s.duration_minutes} mins`; // Show Pay Now button if eligible if ( s.status === "accepted" && (!s.payment_status || ["pending", "failed"].includes(s.payment_status.toLowerCase())) ) { + pendingUl.textContent = `${s.description} | ${s.status} | Payment: ${paymentText}`; + pendingUl.textContent += ` | Scheduled at: ${formatLocalTime(s.local_start_time)} | Duration: ${s.duration_minutes} mins`; + pendingUl.textContent += '| Payment amount: $' + s.payment_amount; + li.textContent += "| Payment amount: $" + s.payment_amount; const btn = document.createElement("button"); btn.textContent = "Pay Now"; btn.addEventListener("click", () => handlePayNow(s.session_id, btn)); li.appendChild(document.createTextNode(" ")); li.appendChild(btn); + pendingUl.appendChild(document.createTextNode(" ")); + pendingUl.appendChild(btn); } // Handle meeting link visibility @@ -126,7 +136,25 @@ function renderSessions(sessions) { } allUl.appendChild(li); - }); + + if (s.status === "scheduled" && !s.meetingCompleted) { + const scheduledLi = li.cloneNode(true); // clone the same li + scheduledSessionsUl.appendChild(scheduledLi); + } + + }) + if (!pendingUl || pendingUl.children.length === 0) { + pendingUl.textContent = "No pending payment at the moment."; + pendingUl.style.display = "block"; + } + if (!scheduledSessionsUl || scheduledSessionsUl.children.length === 0) { + scheduledSessionsUl.textContent = "No scheduled sessions at the moment."; + scheduledSessionsUl.style.display = "block"; + } + if (!allUl || allUl.children.length === 0) { + allUl.textContent = "No sessions found."; + allUl.style.display = "block"; + }; } // Handle Pay Now click diff --git a/services/instructorService.js b/services/instructorService.js index 7517ed6..d0a3580 100644 --- a/services/instructorService.js +++ b/services/instructorService.js @@ -82,7 +82,7 @@ export async function getInstructorSessionsService(instructorId, userTimeZone) { // Initialize meeting info let meetingLink = s.meeting_link || null; let meetingScheduled = !!meetingLink; - + let meetingCompleted = false; if (meetingLink) { const endDtUtc = dtUtc.plus({ minutes: Number(s.duration_minutes) }); // Session end in UTC @@ -90,6 +90,7 @@ export async function getInstructorSessionsService(instructorId, userTimeZone) { // Session completely finished meetingLink = null; meetingScheduled = false; + meetingCompleted = true; } else if (dtUtc.diff(nowUtc, 'minutes').minutes > 2) { // Session in future (>2 min away), hide link meetingLink = null; @@ -103,6 +104,7 @@ export async function getInstructorSessionsService(instructorId, userTimeZone) { return { ...s, local_start_time: localTime, + meetingCompleted: meetingCompleted, payment_status: s.payment_status || null, meeting_link: meetingLink, meeting_scheduled: meetingScheduled diff --git a/services/studentService.js b/services/studentService.js index 5930b51..bc0ed88 100644 --- a/services/studentService.js +++ b/services/studentService.js @@ -63,6 +63,7 @@ export async function getStudentSessionsService(studentId, userTimeZone) { // Initialize meeting info let meetingLink = s.meeting_link || null; let meetingScheduled = !!meetingLink; + let meetingCompleted = false; if (meetingLink) { const endDtUtc = dtUtc.plus({ minutes: Number(s.duration_minutes) }); // Session end in UTC @@ -71,6 +72,8 @@ export async function getStudentSessionsService(studentId, userTimeZone) { // Session completely finished meetingLink = null; meetingScheduled = false; + meetingCompleted = true; + } else if (dtUtc.diff(nowUtc, 'minutes').minutes > 2) { // Session in future (>2 min away), hide link meetingLink = null; @@ -84,7 +87,9 @@ export async function getStudentSessionsService(studentId, userTimeZone) { return { ...s, local_start_time: localTime, + meetingCompleted: meetingCompleted, payment_status: s.payment_status || null, + payment_amount: s.payment_amount || null, meeting_link: meetingLink, meeting_scheduled: meetingScheduled };