Skip to content

feat: update pages according to old website color scheme and design#19

Open
ghanshyam2005singh wants to merge 5 commits intoalphaonelabs:mainfrom
ghanshyam2005singh:feature/pages-redesign
Open

feat: update pages according to old website color scheme and design#19
ghanshyam2005singh wants to merge 5 commits intoalphaonelabs:mainfrom
ghanshyam2005singh:feature/pages-redesign

Conversation

@ghanshyam2005singh
Copy link
Copy Markdown

@ghanshyam2005singh ghanshyam2005singh commented Mar 25, 2026

Changes Made

Landing Page (index.html)

  • ✅ Color scheme updated from blue to teal (#0D9488)
  • ✅ Hero gradient refined with teal variants
  • ✅ Navbar profile dropdown added (logged-in users)
  • ✅ Footer expanded with 4-column layout
  • ✅ 7 social media links integrated
  • ✅ OSL affiliate logo added

New Profile Page (profile.html)

  • ✅ Complete user profile display
  • ✅ Account details card with encryption info
  • ✅ Privacy & encryption breakdown
  • ✅ Activity stats and listings
  • ✅ Data encryption transparency badges

Navbar Enhancements

  • ✅ Auth state detection from localStorage
  • ✅ Dynamic profile button (shows initials)
  • ✅ Dropdown menu: Profile → Dashboard → Sign Out
  • ✅ Auto-hide on click outside

Dashboard and Teach Page

  • ✅ Color scheme updated from blue to teal (#0D9488)
  • ✅ Footer Updated
  • ✅ Complete user profile activity
  • ✅ Activity stats and listings

Screenshots:

Screencast.from.2026-03-25.23-35-13.mp4

Purpose

Redesign public-facing pages to the project's teal branding (#0D9488), replace Tailwind-driven layouts with bespoke CSS, and add an auth-aware profile/dashboard experience with client-side fetching and improved navbar behavior.

Key modifications

  • Design & assets
    • Replaced Tailwind utilities with extensive inline/custom CSS variables and component styles across index.html, dashboard.html, teach.html, and added profile.html.
    • Added Google Fonts (Syne, DM Sans) and Font Awesome; hero visuals refined with teal gradients/mesh; multi-column footer and new social/affiliate elements present in the updated designs.
  • Navigation & authentication
    • Navbar uses localStorage (edu_token / edu_user) to detect auth state and renders either auth links or a dynamic profile button showing user initials.
    • Profile dropdown added (Profile → Dashboard → Sign Out), mobile menu introduced, dropdown/mobile menus auto-close on outside click, and navbar gains a scroll-driven "scrolled" visual state.
    • logout() now clears specific auth keys (edu_token, edu_user) and reloads/redirects rather than wiping all localStorage.
  • Pages added/updated
    • index.html (Landing): rebuilt layout, hero, activity-browser UI (search, filters, tag chips wired via addEventListener), and updated footer.
    • profile.html (New): full profile/dashboard page — displays account/encryption info, privacy breakdown, hosted/joined activity lists and stats, data-encryption badges, IntersectionObserver reveals, and bearer-auth dashboard fetch (401 triggers logout).
    • dashboard.html: migrated to custom CSS, reworked stat rendering, hosted/joined activity grids/cards, empty states, and inline fetch error UI.
    • teach.html: migrated to custom styling, updated host UI, alert behavior (alert.show), activity row markup, and footer.
  • Client-side behavior & robustness
    • New/updated global helpers and UI controllers: updateNav, toggleMobileMenu, toggleDD/toggleDropdown, toggleTag, logout, esc, and various rendering helpers (actRow, stat rendering).
    • Activity rendering/filtering hardened for missing fields (uses safe checks like (a.description || '')), tag cloud wired via data + event listeners, and visibility toggles moved from Tailwind utilities to explicit class/style manipulation.

Impact

  • UX: Consistent teal branding, richer hero and profile experiences, clearer auth flows, and redesigned activity cards and footer.
  • Functionality: New client-side profile/dashboard flows and auth-aware nav; activity search/filter behavior and error/empty states changed.
  • Developer/maintenance: Large increase in custom CSS and page-level JS globals (higher review/maintenance cost). Reviewers should verify auth token handling and 401 flows, dropdown/mobile accessibility (keyboard and ARIA), consistent state cleanup on logout, and cross-page styling/behavior consistency.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 25, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Replaces Tailwind-based styling with large inline custom CSS across public pages, redesigns UI (fonts, icons, layout), refactors client-side nav/auth and activity rendering, adds a new auth-aware profile page that fetches dashboard data and renders hosted/joined activities.

Changes

Cohort / File(s) Summary
Index & landing
public/index.html
Rebuilt layout and styles (fonts, icons, hero, stats, filters, tag cloud, grid), added mobile menu, profile dropdown, scroll-driven navbar scrolled state, new activity-grid/card markup, tag button wiring via event listeners, search/filter refactor, and new global helpers (toggleMobileMenu, toggleDD, toggleTag, esc).
Dashboard page
public/dashboard.html
Replaced Tailwind with inline theme CSS, rebuilt navbar/hero/stats/activity cards and footer, changed statCard signature (removed color), adjusted hosted/joined rendering and empty-state toggles, added scroll listener and mobile/profile menu handling, and updated error UI.
Teach page
public/teach.html
Removed Tailwind utilities, added inline styles and fonts, rewired auth/nav to updateNav/init flow, moved visibility control from Tailwind classes to style.display and .alert.show, updated hosted activity rows and action buttons, changed fetch targets to ${API}/api/... and token handling.
New profile page
public/profile.html
Added new page implementing auth-aware profile UI, loadProfile() fetch to ${API}/api/dashboard with Bearer token, profile hydration, hosted/joined rendering (actRow), reveal IntersectionObserver, 401 handling that triggers logout, and navbar integration.
Shared auth/nav logic
public/index.html, public/dashboard.html, public/teach.html, public/profile.html
Introduced updateNav() rendering profile dropdown or login links, toggleDD() and global click-outside closing, toggleMobileMenu(), altered logout() to remove only edu_token/edu_user and reload, added esc() helper and ddOpen state.
Activity rendering & UX fixes
public/index.html, public/dashboard.html, public/profile.html, public/teach.html
Unified activity card/row/grid markup, changed metadata presentation (host/role/status mapping), removed inline onclicks for tags in favor of dataset + listeners, improved search safety using `(a.description

Sequence Diagram(s)

sequenceDiagram
    participant Browser
    participant LocalStorage
    participant DOM
    participant API

    Browser->>LocalStorage: read edu_token & edu_user
    alt token present
        LocalStorage-->>Browser: user + token
        Browser->>DOM: updateNav() -> render avatar & profile dropdown
        Browser->>DOM: show profile/dashboard UI
        Browser->>API: GET /api/dashboard (Authorization: Bearer token)
        alt 200 OK
            API-->>Browser: dashboard data
            Browser->>DOM: render hosted/joined lists and stats
            Browser->>Browser: start IntersectionObserver reveals
        else 401 Unauthorized
            API-->>Browser: 401
            Browser->>LocalStorage: clear edu_token & edu_user
            Browser->>DOM: updateNav() -> show logged-out state / redirect
        else error
            API-->>Browser: error
            Browser->>DOM: show empty-state / error UI
        end
    else no token
        LocalStorage-->>Browser: null
        Browser->>DOM: render logged-out navbar and not-logged-in view
    end
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the primary change: a comprehensive redesign of multiple HTML pages with a new color scheme (teal) and design system, replacing Tailwind with custom CSS.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
public/dashboard.html (2)

248-251: ⚠️ Potential issue | 🟠 Major

Handle non-2xx dashboard responses before rendering.

A 401/500 response currently falls through to renderDashboard(data), which turns auth or API failures into a fake empty dashboard. Check res.ok, log out on 401, and raise an error for other statuses before calling renderDashboard.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/dashboard.html` around lines 248 - 251, In loadDashboard, check the
fetch response status before calling renderDashboard: inspect res.ok and if
false handle special cases—if res.status === 401 trigger the logout flow (clear
token/session and redirect to login) and return, otherwise log or throw an error
for non-2xx statuses (include res.status and res.statusText) so renderDashboard
is only called with valid data; update loadDashboard and any token usage to
avoid rendering on error.

236-246: ⚠️ Potential issue | 🟠 Major

Guard the rest of the script after redirecting unauthenticated users.

Line 238 changes window.location.href, but execution continues and Line 246 still reads user.username. When edu_user is missing, that throws before navigation completes. Wrap the authenticated initialization in an else block or otherwise stop execution on the redirect path.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/dashboard.html` around lines 236 - 246, The code currently sets
window.location.href when token or user is missing but continues executing and
then accesses user.username (document.getElementById('nav-user').textContent),
which can throw; fix by short-circuiting after redirect—either wrap the
authenticated initialization (the logout function,
typeIcon/typeColor/fmtLabel/schedLabel declarations, and the
document.getElementById('nav-user') assignment) in an else block or immediately
return after setting window.location.href when (!token || !user) to prevent
further execution. Ensure the guard uses the existing symbols token, user,
window.location.href, logout and the DOM update for nav-user.
public/teach.html (1)

435-472: ⚠️ Potential issue | 🟠 Major

Surface dashboard-loading failures instead of collapsing to an empty host list.

loadHostedActivities() assumes /api/dashboard always succeeds. On 401/500 or a rejected fetch, the session selector never populates and the page can stay stuck in a loading/empty state. Check res.ok, log out on 401, and render an explicit error state in a catch.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/teach.html` around lines 435 - 472, loadHostedActivities currently
assumes fetch('/api/dashboard') always succeeds, causing the selector (sel),
hostedActivities and list to stay empty on 401/500 or network errors; update
loadHostedActivities to check res.ok after the fetch, if res.status === 401
trigger the existing logout flow (or redirect to login) and return, for other
non-ok responses treat as failure (set hostedActivities = [], update
'hosted-count', populate sel with a single disabled error option and render a
clear error message into list), and wrap the await fetch/res.json in try/catch
to log the error and render the same error state so the page doesn't silently
collapse into an empty host list.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@public/dashboard.html`:
- Around line 216-220: The anchor in the empty-state block has duplicated id
attributes ("empty-action-link" and "empty-action-text"); remove one of them so
the element has a single id (e.g., keep id="empty-action-link") and, if needed,
convert the other identifier to a class or update references elsewhere to use
the remaining id; look for the anchor with id values empty-action-link /
empty-action-text to update the markup and any JS/CSS that targets the removed
id.

In `@public/index.html`:
- Around line 467-482: The search input and filter selects (elements with IDs
"search", "filter-type", and "filter-format") lack accessible names; add either
visible <label> elements that use for="search" / for="filter-type" /
for="filter-format" with clear text (e.g., "Search activities", "Type",
"Format") or add aria-label attributes on each element with the same descriptive
text, and ensure labels are readable and associated with the correct ID so
screen readers can announce them.
- Around line 56-71: The profile dropdown is only visually hidden so its
interactive elements remain keyboard-focusable; update the toggle logic to
remove it from the accessibility tree and tab order when closed and keep the
trigger's ARIA state in sync: when `#profile-dropdown` does NOT have the .open
class set aria-hidden="true" and add inert (or set all descendant focusable
elements tabindex="-1"), and when .open set aria-hidden="false" (or remove inert
/ restore tabindex) and update the trigger element (e.g., `#profile-button`) to
set aria-expanded="true" when opening and "false" when closing; ensure this same
pattern is applied wherever the same dropdown markup appears.
- Around line 674-676: The esc() helper only HTML-escapes and is being used to
interpolate user-controlled tag names into an inline onclick handler which
breaks on quotes and enables XSS; instead stop inserting name into inline
JS—render the tag into a safe HTML attribute (e.g. data-name="<escaped via
esc()>") and remove the onclick="…" interpolation, then attach the click handler
in external JS (use element.addEventListener('click', handler) and read the
value with element.dataset.name). Update the code that currently uses esc(name)
inside the onclick string to write the escaped name to a data-* attribute and
modify the event-binding code to use addEventListener and dataset access; keep
using esc() only for HTML attribute values, not for producing JS code.

In `@public/profile.html`:
- Around line 52-64: The CSS-only hiding of `#profile-dropdown` (using
opacity/pointer-events) leaves controls in the accessibility tree and tab order;
update the toggle logic that adds/removes the .open class so it also sets a
semantic hidden state (add/remove the hidden attribute or inert, or toggle
display:none) on the `#profile-dropdown` element and update the trigger element to
keep aria-expanded and aria-controls in sync with the dropdown state; ensure the
JS that currently toggles "#profile-dropdown.open" manages attributes
(hidden/inert or style.display) and updates the trigger's aria-expanded and
aria-controls accordingly for the other affected dropdowns (230-250, 500-502,
515-516).
- Around line 323-327: The "Member Since" field (element id prof-joined and the
surrounding label "Member Since") is using the earliest hosted/joined activity
timestamp (via fmtDate) instead of the account creation date; update the code
that populates prof-joined to use the user's account-created timestamp (e.g.,
user.created_at or profile.createdAt) and call fmtDate(created_at) so it shows
signup date, or alternatively change the label text to "First Activity" if you
intend to keep the activity timestamp; apply the same fix to the other identical
block referenced (the second profile date block that also uses fmtDate(null)).
- Around line 120-121: The CSS rule .s-label is being reused for both decorative
section headings and the smaller stat captions, causing the stat labels
(Hosted/Joined/Total) to inherit the hero styling; create two distinct classes
(e.g., .section-label for the large decorative header and .stat-label for the
small stat captions), update the CSS by renaming the stat-related .s-label
selector to .stat-label (leave the section heading selector as .section-label or
.s-label if you prefer) and then update the corresponding HTML elements that
render the stats to use .stat-label instead of .s-label; repeat this change for
the other occurrences mentioned so only the section header uses the decorative
class while the stats use the compact .stat-label styling.

In `@public/teach.html`:
- Around line 213-255: Update each label to include a matching for attribute
that references the control id so they are programmatically associated (e.g.,
change the title label to for="a-title", description label to for="a-desc",
type/format/schedule labels to for="a-type"/"a-format"/"a-schedule", tags label
to for="a-tags", and apply the same pattern to other templates mentioned like
s-title and s-start); ensure every <label> in this form and the areas noted
(lines ~271-302) uses the exact id of its corresponding input/textarea/select so
screen readers can link them correctly.
- Line 11: The Font Awesome version referenced (link tag) is 6.0.0-beta3 which
does not include the fa-x-twitter icon; update the markup to use the existing
fa-twitter class (replace usages of "fa-x-twitter" with "fa-twitter") or upgrade
the CDN href to a Font Awesome 6.4.2+ release so "fa-x-twitter" is available;
alternatively, follow the existing image-fallback pattern (like the logo-osl.svg
usage) and add an <img> fallback for the X logo where the icon is used to ensure
it displays when the library lacks that glyph.

---

Outside diff comments:
In `@public/dashboard.html`:
- Around line 248-251: In loadDashboard, check the fetch response status before
calling renderDashboard: inspect res.ok and if false handle special cases—if
res.status === 401 trigger the logout flow (clear token/session and redirect to
login) and return, otherwise log or throw an error for non-2xx statuses (include
res.status and res.statusText) so renderDashboard is only called with valid
data; update loadDashboard and any token usage to avoid rendering on error.
- Around line 236-246: The code currently sets window.location.href when token
or user is missing but continues executing and then accesses user.username
(document.getElementById('nav-user').textContent), which can throw; fix by
short-circuiting after redirect—either wrap the authenticated initialization
(the logout function, typeIcon/typeColor/fmtLabel/schedLabel declarations, and
the document.getElementById('nav-user') assignment) in an else block or
immediately return after setting window.location.href when (!token || !user) to
prevent further execution. Ensure the guard uses the existing symbols token,
user, window.location.href, logout and the DOM update for nav-user.

In `@public/teach.html`:
- Around line 435-472: loadHostedActivities currently assumes
fetch('/api/dashboard') always succeeds, causing the selector (sel),
hostedActivities and list to stay empty on 401/500 or network errors; update
loadHostedActivities to check res.ok after the fetch, if res.status === 401
trigger the existing logout flow (or redirect to login) and return, for other
non-ok responses treat as failure (set hostedActivities = [], update
'hosted-count', populate sel with a single disabled error option and render a
clear error message into list), and wrap the await fetch/res.json in try/catch
to log the error and render the same error state so the page doesn't silently
collapse into an empty host list.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: alphaonelabs/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e9a41961-23b4-4f0e-9307-062c6c4209c3

📥 Commits

Reviewing files that changed from the base of the PR and between a08bafc and 85e5cfa.

⛔ Files ignored due to path filters (1)
  • public/images/logo-osl.svg is excluded by !**/*.svg
📒 Files selected for processing (4)
  • public/dashboard.html
  • public/index.html
  • public/profile.html
  • public/teach.html

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
public/index.html (2)

468-482: ⚠️ Potential issue | 🟠 Major

Add accessible names for search and filter controls.

#search, #filter-type, and #filter-format still lack explicit labels/accessible names.

Suggested patch
-<input id="search" type="text" placeholder="Search activities…" class="filter-input" style="min-width:220px;" />
-<select id="filter-type" class="filter-input">
+<input id="search" type="text" aria-label="Search activities" placeholder="Search activities…" class="filter-input" style="min-width:220px;" />
+<select id="filter-type" aria-label="Filter by type" class="filter-input">
@@
-<select id="filter-format" class="filter-input">
+<select id="filter-format" aria-label="Filter by format" class="filter-input">

As per coding guidelines, **/*.html: Review HTML templates for accessibility (ARIA attributes, semantic elements).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/index.html` around lines 468 - 482, The search and filter controls
(`#search`, `#filter-type`, `#filter-format`) lack accessible names; add explicit
labels or ARIA names for each control by either adding a <label
for="search">Search</label> (and similar labels for filter-type and
filter-format) or adding aria-label/aria-labelledby attributes that provide
concise descriptive text; ensure the label text is programmatic and visible or
referenced by id so screen readers announce the control names and update any CSS
to keep layout intact.

637-663: ⚠️ Potential issue | 🟠 Major

Keep the profile dropdown out of tab order when closed and sync ARIA state.

This is still reachable by keyboard when visually closed, and the trigger does not expose expanded/collapsed state. Please apply the same fix pattern already discussed earlier (aria-expanded, aria-hidden, and inert/focus management).

Suggested patch
-<div id="profile-dropdown">
+<div id="profile-dropdown" aria-hidden="true" inert>
@@
-        <button id="profile-btn" onclick="toggleDropdown(event)" style="...">${esc(initials)}</button>`;
+        <button id="profile-btn" onclick="toggleDropdown(event)" aria-haspopup="menu" aria-controls="profile-dropdown" aria-expanded="false" style="...">${esc(initials)}</button>`;
@@
-  function toggleDropdown(e) {
+  function setDropdownOpen(open) {
+    const dd = document.getElementById('profile-dropdown');
+    const btn = document.getElementById('profile-btn');
+    dropdownOpen = open;
+    dd.classList.toggle('open', open);
+    dd.setAttribute('aria-hidden', open ? 'false' : 'true');
+    if (open) dd.removeAttribute('inert'); else dd.setAttribute('inert', '');
+    if (btn) btn.setAttribute('aria-expanded', open ? 'true' : 'false');
+  }
+  function toggleDropdown(e) {
     e.stopPropagation();
-    dropdownOpen = !dropdownOpen;
-    document.getElementById('profile-dropdown').classList.toggle('open', dropdownOpen);
+    setDropdownOpen(!dropdownOpen);
   }
   document.addEventListener('click', () => {
-    if (dropdownOpen) {
-      dropdownOpen = false;
-      const dd = document.getElementById('profile-dropdown');
-      if (dd) dd.classList.remove('open');
-    }
+    if (dropdownOpen) setDropdownOpen(false);
   });

As per coding guidelines, **/*.html: Review HTML templates for accessibility (ARIA attributes, semantic elements).

Also applies to: 687-717

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/index.html` around lines 637 - 663, The profile dropdown (element
id="profile-dropdown" and its interactive children like the links and the Sign
Out button that calls logout()) must be removed from tab order and have its ARIA
state synced when closed: add aria-hidden="true" to `#profile-dropdown` and mark
all interactive descendants (anchors and the button invoking logout()) with
tabindex="-1" or set the container inert when closed; ensure the dropdown
trigger element (the button that toggles this menu) exposes
aria-expanded="true"/"false" and that your toggle logic updates
aria-hidden/inert and the descendants' tabindex accordingly when opening/closing
so keyboard users cannot reach the closed menu and the ARIA expanded state stays
in sync.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@public/index.html`:
- Around line 598-622: Multiple footer anchor elements (anchors with class
"fc-link" that use target=\"_blank\") lack rel attributes; update each <a ...
class=\"fc-link\" target=\"_blank\"> element (e.g., the links under the Courses,
Community, and About columns) to include rel=\"noopener noreferrer\" to prevent
window.opener exposure and privacy leaks, and ensure you apply the same change
to the other footer anchors referenced in the diff that open in a new tab.
- Line 658: The Sign Out button that calls logout() should explicitly include
type="button" to prevent it from acting as a submit button if placed inside a
form; update the button element (the one with onclick="logout()") to add
type="button" while preserving its existing attributes and event handlers.

---

Duplicate comments:
In `@public/index.html`:
- Around line 468-482: The search and filter controls (`#search`, `#filter-type`,
`#filter-format`) lack accessible names; add explicit labels or ARIA names for
each control by either adding a <label for="search">Search</label> (and similar
labels for filter-type and filter-format) or adding aria-label/aria-labelledby
attributes that provide concise descriptive text; ensure the label text is
programmatic and visible or referenced by id so screen readers announce the
control names and update any CSS to keep layout intact.
- Around line 637-663: The profile dropdown (element id="profile-dropdown" and
its interactive children like the links and the Sign Out button that calls
logout()) must be removed from tab order and have its ARIA state synced when
closed: add aria-hidden="true" to `#profile-dropdown` and mark all interactive
descendants (anchors and the button invoking logout()) with tabindex="-1" or set
the container inert when closed; ensure the dropdown trigger element (the button
that toggles this menu) exposes aria-expanded="true"/"false" and that your
toggle logic updates aria-hidden/inert and the descendants' tabindex accordingly
when opening/closing so keyboard users cannot reach the closed menu and the ARIA
expanded state stays in sync.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: alphaonelabs/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7e9f46c3-9a25-4c33-b2f1-6a5cbb1f724c

📥 Commits

Reviewing files that changed from the base of the PR and between 85e5cfa and 4f49ff4.

📒 Files selected for processing (1)
  • public/index.html

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (6)
public/index.html (2)

607-637: ⚠️ Potential issue | 🟡 Minor

Add rel="noopener noreferrer" to footer links opening in new tabs.

Several footer links use target="_blank" without a rel attribute (e.g., lines 613-616, 621-626, 631-637). This leaves a minor security gap where the opened page could access window.opener. The social icons correctly use rel="noopener", so applying the same pattern here would be consistent.

🔧 Example fix for one link
-      <a href="https://alphaonelabs.com/en/courses/search/" target="_blank" class="fc-link">All Courses</a>
+      <a href="https://alphaonelabs.com/en/courses/search/" target="_blank" rel="noopener noreferrer" class="fc-link">All Courses</a>

Apply this pattern to all fc-link elements with target="_blank".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/index.html` around lines 607 - 637, Footer anchor elements with class
"fc-link" that open in new tabs (target="_blank") lack rel attributes and should
be hardened; update every <a ... class="fc-link" target="_blank"> in the
Learning, Community, and About columns to include rel="noopener noreferrer"
(i.e., add rel="noopener noreferrer" to the anchors linking to external sites
such as the Courses/Subjects/Study Groups, Forum/Blog/etc., and About links) so
they match the security pattern used by the social icons.

672-677: ⚠️ Potential issue | 🟡 Minor

Add type="button" to the Sign Out button.

This button still needs an explicit type="button" attribute to prevent it from acting as a submit button if placed inside a form.

🔧 Suggested fix
-    <button onclick="logout()" style="display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;background:transparent;border:none;cursor:pointer;color:`#e53e3e`;font-size:.85rem;font-weight:500;width:100%;text-align:left;transition:background .15s;" onmouseover="this.style.background='#fff5f5'" onmouseout="this.style.background='transparent'">
+    <button type="button" onclick="logout()" style="display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;background:transparent;border:none;cursor:pointer;color:`#e53e3e`;font-size:.85rem;font-weight:500;width:100%;text-align:left;transition:background .15s;" onmouseover="this.style.background='#fff5f5'" onmouseout="this.style.background='transparent'">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/index.html` around lines 672 - 677, The Sign Out button lacks an
explicit type which can make it act as a submit button inside a form; update the
button element that calls logout() (the "Sign Out" button with
onclick="logout()") to include type="button" so it will not trigger form
submission when nested in a form.
public/teach.html (2)

268-300: ⚠️ Potential issue | 🟠 Major

Session form labels still need for attributes.

While the activity form labels are now properly associated, the session form labels (lines 270, 277, 283, 287, 293, 298) are still missing for attributes. Screen readers won't be able to programmatically link these labels to their corresponding inputs.

As per coding guidelines, **/*.html: Review HTML templates for accessibility (ARIA attributes, semantic elements).

🔧 Add for attributes to session form labels
             <div class="form-group">
-              <label class="form-label">Activity *</label>
+              <label for="s-activity" class="form-label">Activity *</label>
               <select id="s-activity" class="form-select">

             <div class="form-group">
-              <label class="form-label">Session Title *</label>
+              <label for="s-title" class="form-label">Session Title *</label>
               <input id="s-title" type="text" required class="form-input" placeholder="e.g. Week 1 - Introduction" />

             <div class="form-group" style="margin-bottom:0;">
-                <label class="form-label">Start Time</label>
+                <label for="s-start" class="form-label">Start Time</label>
                 <input id="s-start" type="datetime-local" class="form-input" />

             <div class="form-group" style="margin-bottom:0;">
-                <label class="form-label">End Time</label>
+                <label for="s-end" class="form-label">End Time</label>
                 <input id="s-end" type="datetime-local" class="form-input" />

             <div class="form-group">
-              <label class="form-label">Location (encrypted)</label>
+              <label for="s-location" class="form-label">Location (encrypted)</label>
               <input id="s-location" type="text" class="form-input" placeholder="e.g. Room 101 or Zoom link" />

             <div class="form-group">
-              <label class="form-label">Description (encrypted)</label>
+              <label for="s-desc" class="form-label">Description (encrypted)</label>
               <textarea id="s-desc" class="form-textarea" placeholder="What will be covered?"></textarea>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/teach.html` around lines 268 - 300, The session form labels in the
form with id "form-session" are missing associated for attributes; update each
label to include for="s-activity", for="s-title", for="s-start", for="s-end",
for="s-location", and for="s-desc" respectively so they correctly reference the
inputs with ids s-activity, s-title, s-start, s-end, s-location, and s-desc to
restore proper label-control association for screen readers and accessibility
tools.

340-342: ⚠️ Potential issue | 🟡 Minor

The fa-x-twitter icon won't render in Font Awesome 6.0.0-beta3.

This icon was introduced in Font Awesome 6.4.2. The current version (6.0.0-beta3) doesn't include it, so users will see a blank space. Consider either:

  1. Using fa-twitter (the original bird icon, available in 6.0.0-beta3), or
  2. Using the same image-with-fallback approach that index.html uses for the X logo
🔧 Option: Use image fallback like index.html
         <a href="https://twitter.com/alphaonelabs" target="_blank" rel="noopener" class="f-social" title="X / Twitter">
-          <i class="fab fa-x-twitter"></i>
+          <img src="https://alphaonelabs.com/static/images/x-logo.svg" alt="X" style="width:14px;height:14px;filter:invert(1);opacity:.55;" onerror="this.parentElement.innerHTML='<svg width=\'14\' height=\'14\' viewBox=\'0 0 24 24\' fill=\'currentColor\'><path d=\'M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.747l7.73-8.835L1.254 2.25H8.08l4.254 5.622 5.91-5.622Zm-1.161 17.52h1.833L7.084 4.126H5.117z\'/></svg>'">
         </a>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/teach.html` around lines 340 - 342, The X/Twitter icon class used
inside the anchor with class "f-social" (<i class="fab fa-x-twitter"></i>) won't
render on Font Awesome 6.0.0-beta3; either swap the icon to the legacy bird
class by replacing "fa-x-twitter" with "fa-twitter" or implement the same
image-with-fallback pattern used in index.html for the X logo (keep the
surrounding <a class="f-social" ...> intact and add an <img> fallback and
appropriate aria-label/title). Ensure the anchor still targets the external URL
and preserves rel/target attributes.
public/profile.html (2)

369-382: ⚠️ Potential issue | 🟡 Minor

Stat labels are using the wrong CSS class.

The stat cards use class="s-label" (lines 372, 376, 380), but .s-label includes the decorative ::before pseudo-element with a teal bar (defined at lines 192-199). This causes the "Hosted", "Joined", and "Total" labels to display with an unwanted decorative bar.

You've already defined .stat-label at line 123 for this purpose—just update the stat card HTML to use it.

🔧 Suggested fix
         <div class="stat-card">
           <p class="s-num" id="stat-hosted" style="color:var(--teal);">0</p>
-          <p class="s-label">Hosted</p>
+          <p class="stat-label">Hosted</p>
         </div>
         <div class="stat-card">
           <p class="s-num" id="stat-joined" style="color:var(--accent);">0</p>
-          <p class="s-label">Joined</p>
+          <p class="stat-label">Joined</p>
         </div>
         <div class="stat-card">
           <p class="s-num" id="stat-total" style="color:var(--jade);">0</p>
-          <p class="s-label">Total</p>
+          <p class="stat-label">Total</p>
         </div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/profile.html` around lines 369 - 382, The stat label elements are
using the wrong CSS class: replace class="s-label" on the three <p> elements
with the correct class "stat-label" so the labels (IDs stat-hosted, stat-joined,
stat-total) use the intended styling (avoid the s-label ::before decorative
bar); update the three <p> elements that currently read class="s-label" to
class="stat-label" in the stat-card blocks.

505-529: ⚠️ Potential issue | 🟠 Major

Profile dropdown trigger should manage aria-expanded and aria-controls.

The toggleDD() function toggles the dropdown visibility but doesn't update accessibility attributes. Unlike index.html (which now properly manages these), the profile button here lacks aria-expanded and aria-controls.

🔧 Suggested improvement
 function updateNav(){
   // ...
   if(token&&user){
     const ini=(user.name||user.username||'?').slice(0,2).toUpperCase();
     nav.innerHTML=`
       <a href="/dashboard.html" style="...">Dashboard</a>
-      <button onclick="toggleDD(event)" style="width:36px;height:36px;...">${esc(ini)}</button>`;
+      <button id="profile-btn" onclick="toggleDD(event)" aria-expanded="false" aria-controls="profile-dropdown" style="width:36px;height:36px;...">${esc(ini)}</button>`;
     // ...
   }
 }

-function toggleDD(e){e.stopPropagation();ddOpen=!ddOpen;document.getElementById('profile-dropdown').classList.toggle('open',ddOpen);}
+function toggleDD(e){
+  e.stopPropagation();
+  ddOpen=!ddOpen;
+  const btn=document.getElementById('profile-btn');
+  if(btn) btn.setAttribute('aria-expanded',ddOpen);
+  document.getElementById('profile-dropdown').classList.toggle('open',ddOpen);
+}

As per coding guidelines, **/*.html: Review HTML templates for accessibility (ARIA attributes, semantic elements).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/profile.html` around lines 505 - 529, The profile dropdown toggle
lacks ARIA state and control references; update the button created in updateNav
(the button that calls toggleDD and the element with id
'dd-avatar'/'profile-dropdown') to include aria-controls="profile-dropdown" and
aria-expanded="false" when rendering, and modify toggleDD(e) to set the button's
aria-expanded to the new ddOpen value (and when closing via the document click
handler also set aria-expanded="false"). Ensure the `#profile-dropdown` element
keeps the id "profile-dropdown" to match aria-controls and use
document.getElementById to find the toggle button (by id or a stable selector)
when updating attributes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@public/dashboard.html`:
- Around line 176-177: The logout button lacks an explicit type and will default
to type="submit" inside a form; update the button element (the one with
onclick="logout()") to include type="button" so clicking it won't trigger form
submission—modify the <button ... onclick="logout()"> element to add
type="button" while keeping its existing attributes and event handlers intact.

In `@public/index.html`:
- Around line 464-499: The outer wrapper <div> that contains the filter controls
(which encloses the labeled inputs with ids "search", "filter-type", and
"filter-format") is missing its closing </div>, breaking the DOM; fix by adding
the missing closing tag to close that wrapper div after the last select block
(i.e., after the block containing the element with id "filter-format") so the
structure properly nests and the layout is restored.

In `@public/profile.html`:
- Around line 255-258: The Sign Out button lacks an explicit type which can
cause it to act as a submit button inside forms; update the button element that
calls logout() (the <button ... onclick="logout()"> in the profile dropdown) to
include type="button" so it won't trigger form submission and will only invoke
the logout() handler.

In `@public/teach.html`:
- Around line 186-187: The Logout button element is missing an explicit type so
it defaults to type="submit" and can unintentionally submit forms; update the
button tag that calls logout() to include type="button" (e.g., the <button ...
onclick="logout()"> element) to prevent form submission and preserve the
intended click behavior.

---

Duplicate comments:
In `@public/index.html`:
- Around line 607-637: Footer anchor elements with class "fc-link" that open in
new tabs (target="_blank") lack rel attributes and should be hardened; update
every <a ... class="fc-link" target="_blank"> in the Learning, Community, and
About columns to include rel="noopener noreferrer" (i.e., add rel="noopener
noreferrer" to the anchors linking to external sites such as the
Courses/Subjects/Study Groups, Forum/Blog/etc., and About links) so they match
the security pattern used by the social icons.
- Around line 672-677: The Sign Out button lacks an explicit type which can make
it act as a submit button inside a form; update the button element that calls
logout() (the "Sign Out" button with onclick="logout()") to include
type="button" so it will not trigger form submission when nested in a form.

In `@public/profile.html`:
- Around line 369-382: The stat label elements are using the wrong CSS class:
replace class="s-label" on the three <p> elements with the correct class
"stat-label" so the labels (IDs stat-hosted, stat-joined, stat-total) use the
intended styling (avoid the s-label ::before decorative bar); update the three
<p> elements that currently read class="s-label" to class="stat-label" in the
stat-card blocks.
- Around line 505-529: The profile dropdown toggle lacks ARIA state and control
references; update the button created in updateNav (the button that calls
toggleDD and the element with id 'dd-avatar'/'profile-dropdown') to include
aria-controls="profile-dropdown" and aria-expanded="false" when rendering, and
modify toggleDD(e) to set the button's aria-expanded to the new ddOpen value
(and when closing via the document click handler also set
aria-expanded="false"). Ensure the `#profile-dropdown` element keeps the id
"profile-dropdown" to match aria-controls and use document.getElementById to
find the toggle button (by id or a stable selector) when updating attributes.

In `@public/teach.html`:
- Around line 268-300: The session form labels in the form with id
"form-session" are missing associated for attributes; update each label to
include for="s-activity", for="s-title", for="s-start", for="s-end",
for="s-location", and for="s-desc" respectively so they correctly reference the
inputs with ids s-activity, s-title, s-start, s-end, s-location, and s-desc to
restore proper label-control association for screen readers and accessibility
tools.
- Around line 340-342: The X/Twitter icon class used inside the anchor with
class "f-social" (<i class="fab fa-x-twitter"></i>) won't render on Font Awesome
6.0.0-beta3; either swap the icon to the legacy bird class by replacing
"fa-x-twitter" with "fa-twitter" or implement the same image-with-fallback
pattern used in index.html for the X logo (keep the surrounding <a
class="f-social" ...> intact and add an <img> fallback and appropriate
aria-label/title). Ensure the anchor still targets the external URL and
preserves rel/target attributes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: alphaonelabs/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b9dc50cd-e385-45de-b17e-034a6835aa2f

📥 Commits

Reviewing files that changed from the base of the PR and between 4f49ff4 and f6c8e9a.

📒 Files selected for processing (4)
  • public/dashboard.html
  • public/index.html
  • public/profile.html
  • public/teach.html

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (5)
public/teach.html (2)

340-342: ⚠️ Potential issue | 🟡 Minor

The fa-x-twitter icon won't render with Font Awesome 6.0.0-beta3.

This icon was introduced in Font Awesome 6.4.2, so it will appear blank with the current CDN version (6.0.0-beta3). Consider either:

  1. Upgrade Font Awesome to 6.4.2+ across all pages, or
  2. Use fa-twitter (the original bird icon available in 6.0.0-beta3), or
  3. Use an image/SVG fallback like public/profile.html does (Line 427 in that file shows the pattern)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/teach.html` around lines 340 - 342, The X/Twitter icon uses the class
fa-x-twitter which is not present in the loaded Font Awesome 6.0.0-beta3 and
will render blank; update the markup in public/teach.html by either (A) updating
the Font Awesome CDN to 6.4.2+ in the shared head include so fa-x-twitter is
available across pages, or (B) replace the icon class fa-x-twitter with the
older fa-twitter class (or implement the SVG/image fallback pattern used in
public/profile.html) to restore a visible icon; adjust the <a> with class
f-social and the inner <i> accordingly so styling remains consistent.

268-305: ⚠️ Potential issue | 🟠 Major

Associate session form labels with their controls.

The session form labels are missing for attributes, so they're not programmatically linked to their corresponding inputs. This makes the form harder to use for screen reader users and reduces click-target areas (clicking a label won't focus its input).

As per coding guidelines, **/*.html: Review HTML templates for accessibility (ARIA attributes, semantic elements).

♿ Proposed fix — add for attributes to session form labels
             <div class="form-group">
-              <label class="form-label">Activity *</label>
+              <label for="s-activity" class="form-label">Activity *</label>
               <select id="s-activity" class="form-select">
                 <option value="">Select an activity...</option>
               </select>
             </div>

             <div class="form-group">
-              <label class="form-label">Session Title *</label>
+              <label for="s-title" class="form-label">Session Title *</label>
               <input id="s-title" type="text" required class="form-input" placeholder="e.g. Week 1 - Introduction" />
             </div>

             <div style="display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1rem;">
               <div class="form-group" style="margin-bottom:0;">
-                <label class="form-label">Start Time</label>
+                <label for="s-start" class="form-label">Start Time</label>
                 <input id="s-start" type="datetime-local" class="form-input" />
               </div>
               <div class="form-group" style="margin-bottom:0;">
-                <label class="form-label">End Time</label>
+                <label for="s-end" class="form-label">End Time</label>
                 <input id="s-end" type="datetime-local" class="form-input" />
               </div>
             </div>

             <div class="form-group">
-              <label class="form-label">Location (encrypted)</label>
+              <label for="s-location" class="form-label">Location (encrypted)</label>
               <input id="s-location" type="text" class="form-input" placeholder="e.g. Room 101 or Zoom link" />
             </div>

             <div class="form-group">
-              <label class="form-label">Description (encrypted)</label>
+              <label for="s-desc" class="form-label">Description (encrypted)</label>
               <textarea id="s-desc" class="form-textarea" placeholder="What will be covered?"></textarea>
             </div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/teach.html` around lines 268 - 305, Labels in the session form are not
programmatically associated with their controls; add matching for attributes to
each label so clicking/focusing the label focuses the corresponding control.
Specifically, update the label elements to use for="s-activity", for="s-title",
for="s-start", for="s-end", for="s-location", and for="s-desc" to match the
select/input/textarea ids (ensure the ids remain unique and unchanged), and
leave the error/success paragraphs as-is (they are not form controls).
public/index.html (2)

673-678: ⚠️ Potential issue | 🟡 Minor

Add type="button" to the Sign Out button.

The logout button (Line 674) is missing an explicit type attribute. Without it, the button defaults to type="submit", which could cause unexpected form submission behavior if this dropdown is ever nested inside a form.

🔧 Proposed fix
   <div style="padding:8px;border-top:1px solid rgba(13,13,20,.07);">
-    <button onclick="logout()" style="display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;background:transparent;border:none;cursor:pointer;color:`#e53e3e`;font-size:.85rem;font-weight:500;width:100%;text-align:left;transition:background .15s;" onmouseover="this.style.background='#fff5f5'" onmouseout="this.style.background='transparent'">
+    <button type="button" onclick="logout()" style="display:flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;background:transparent;border:none;cursor:pointer;color:`#e53e3e`;font-size:.85rem;font-weight:500;width:100%;text-align:left;transition:background .15s;" onmouseover="this.style.background='#fff5f5'" onmouseout="this.style.background='transparent'">
       <svg width="16" height="16" viewBox="0 0 16 16" fill="none">...</svg>
       Sign Out
     </button>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/index.html` around lines 673 - 678, The Sign Out button lacks an
explicit type and therefore defaults to type="submit", which can cause
accidental form submissions; update the button element that calls logout() (the
<button onclick="logout()"> for "Sign Out") to include type="button" so it will
not submit any enclosing form when clicked.

614-637: ⚠️ Potential issue | 🟡 Minor

Add rel="noopener noreferrer" to external links opening in new tabs.

Several footer links use target="_blank" without rel="noopener noreferrer". This leaves a small security/privacy gap where the opened page can access window.opener. The social links (Lines 584-604) correctly include rel="noopener", so this should be applied consistently.

🔒 Proposed fix — add rel attributes
-      <a href="https://alphaonelabs.com/en/courses/search/" target="_blank" class="fc-link">All Courses</a>
-      <a href="https://alphaonelabs.com/en/subjects/" target="_blank" class="fc-link">Subjects</a>
-      <a href="https://alphaonelabs.com/en/study-groups/" target="_blank" class="fc-link">Study Groups</a>
+      <a href="https://alphaonelabs.com/en/courses/search/" target="_blank" rel="noopener noreferrer" class="fc-link">All Courses</a>
+      <a href="https://alphaonelabs.com/en/subjects/" target="_blank" rel="noopener noreferrer" class="fc-link">Subjects</a>
+      <a href="https://alphaonelabs.com/en/study-groups/" target="_blank" rel="noopener noreferrer" class="fc-link">Study Groups</a>

Apply the same pattern to all target="_blank" links in the footer columns (Community and About sections).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/index.html` around lines 614 - 637, The footer's external anchor
elements in the "Community" and "About" columns (the <a> tags with class
"fc-link" that use target="_blank") need rel="noopener noreferrer" added to each
to prevent window.opener access; update all those anchor tags (e.g., Forum,
Blog, Success Stories, Waiting Rooms, GSoC '26, Our Mission, GitHub Repo,
Status, Feedback, Privacy Policy, Terms) to include rel="noopener noreferrer"
alongside their existing target attributes.
public/profile.html (1)

513-529: ⚠️ Potential issue | 🟡 Minor

Add aria-expanded to the profile dropdown trigger.

While visibility: hidden now properly removes the closed dropdown from the tab order (good improvement!), the trigger button should communicate its expanded state to assistive technologies. Without aria-expanded, screen reader users won't know if the menu is open or closed.

As per coding guidelines, **/*.html: Review HTML templates for accessibility (ARIA attributes, semantic elements).

♿ Proposed fix

Update the button template in updateNav() and modify toggleDD():

       nav.innerHTML=`
         <a href="/dashboard.html" style="...">Dashboard</a>
-        <button onclick="toggleDD(event)" style="...">
+        <button id="profile-trigger" aria-expanded="false" aria-controls="profile-dropdown" onclick="toggleDD(event)" style="...">
           ${esc(ini)}
         </button>`;
 function toggleDD(e){
   e.stopPropagation();
   ddOpen=!ddOpen;
+  const trigger = document.getElementById('profile-trigger');
+  if (trigger) trigger.setAttribute('aria-expanded', ddOpen);
   document.getElementById('profile-dropdown').classList.toggle('open',ddOpen);
 }
 document.addEventListener('click',()=>{
   if(ddOpen){
     ddOpen=false;
+    const trigger = document.getElementById('profile-trigger');
+    if (trigger) trigger.setAttribute('aria-expanded', 'false');
     document.getElementById('profile-dropdown').classList.remove('open');
   }
 });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/profile.html` around lines 513 - 529, The profile dropdown trigger
button (rendered in updateNav()) lacks an aria-expanded attribute so assistive
tech can't detect open/closed state; update the button markup created in
updateNav() to include aria-expanded="false" initially (on the same element that
uses onclick="toggleDD(event)" and contains ${esc(ini)}), and then modify
toggleDD(e) to set document.getElementById('profile-dropdown-trigger') or the
same button element's aria-expanded to String(ddOpen) whenever ddOpen toggles
(also ensure the trigger has a stable id or use a querySelector to find it), and
keep updating the 'profile-dropdown' class as now.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@public/dashboard.html`:
- Around line 336-339: The error message is injected directly into innerHTML in
the loadDashboard().catch handler using e.message and can lead to XSS; change
the handler to avoid innerHTML by locating the element with id 'activities-list'
and set its textContent (or create a text node) with a safe, escaped version of
e.message, and apply styling via element.className or element.style instead of
embedding HTML; update the anonymous catch callback that currently uses
innerHTML to use safe text insertion of e.message.

In `@public/profile.html`:
- Around line 192-199: The .s-label selector currently defines a decorative
::before bar and section-heading styles but is being reused on stat captions
(symbols: .s-label applied to the stat card captions 'Hosted', 'Joined',
'Total'), causing unwanted teal bars; update the stat markup to use the distinct
.stat-label class (symbol: .stat-label) instead of .s-label for those stat
captions so the decorative ::before on .s-label only affects section headings,
and verify .stat-label has the intended styles for the stat captions.

---

Duplicate comments:
In `@public/index.html`:
- Around line 673-678: The Sign Out button lacks an explicit type and therefore
defaults to type="submit", which can cause accidental form submissions; update
the button element that calls logout() (the <button onclick="logout()"> for
"Sign Out") to include type="button" so it will not submit any enclosing form
when clicked.
- Around line 614-637: The footer's external anchor elements in the "Community"
and "About" columns (the <a> tags with class "fc-link" that use target="_blank")
need rel="noopener noreferrer" added to each to prevent window.opener access;
update all those anchor tags (e.g., Forum, Blog, Success Stories, Waiting Rooms,
GSoC '26, Our Mission, GitHub Repo, Status, Feedback, Privacy Policy, Terms) to
include rel="noopener noreferrer" alongside their existing target attributes.

In `@public/profile.html`:
- Around line 513-529: The profile dropdown trigger button (rendered in
updateNav()) lacks an aria-expanded attribute so assistive tech can't detect
open/closed state; update the button markup created in updateNav() to include
aria-expanded="false" initially (on the same element that uses
onclick="toggleDD(event)" and contains ${esc(ini)}), and then modify toggleDD(e)
to set document.getElementById('profile-dropdown-trigger') or the same button
element's aria-expanded to String(ddOpen) whenever ddOpen toggles (also ensure
the trigger has a stable id or use a querySelector to find it), and keep
updating the 'profile-dropdown' class as now.

In `@public/teach.html`:
- Around line 340-342: The X/Twitter icon uses the class fa-x-twitter which is
not present in the loaded Font Awesome 6.0.0-beta3 and will render blank; update
the markup in public/teach.html by either (A) updating the Font Awesome CDN to
6.4.2+ in the shared head include so fa-x-twitter is available across pages, or
(B) replace the icon class fa-x-twitter with the older fa-twitter class (or
implement the SVG/image fallback pattern used in public/profile.html) to restore
a visible icon; adjust the <a> with class f-social and the inner <i> accordingly
so styling remains consistent.
- Around line 268-305: Labels in the session form are not programmatically
associated with their controls; add matching for attributes to each label so
clicking/focusing the label focuses the corresponding control. Specifically,
update the label elements to use for="s-activity", for="s-title", for="s-start",
for="s-end", for="s-location", and for="s-desc" to match the
select/input/textarea ids (ensure the ids remain unique and unchanged), and
leave the error/success paragraphs as-is (they are not form controls).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: alphaonelabs/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: cc22d746-6e4c-4782-83a1-0c1c7575cac3

📥 Commits

Reviewing files that changed from the base of the PR and between f6c8e9a and 9360bf5.

📒 Files selected for processing (4)
  • public/dashboard.html
  • public/index.html
  • public/profile.html
  • public/teach.html

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@public/dashboard.html`:
- Line 253: The mobile menu toggle button currently lacks an explicit type and
will default to type="submit"; update the <button class="nav-toggle" ...>
element that calls toggleMobileMenu() to include type="button" so it no longer
triggers form submission if placed inside a form; locate the button by its class
"nav-toggle" or its onclick calling toggleMobileMenu and add the type attribute.
- Around line 474-476: The statCard function currently renders the visible value
directly (function statCard) and using a lock emoji for the "Data Encrypted"
card can confuse screen readers; update the place where statCard is called for
"Data Encrypted" to use a descriptive textual value (e.g., "Yes" or "100%")
instead of the emoji and/or enhance the generated HTML in statCard to include an
aria-label on the value element (for example set aria-label="Data encrypted:
Yes" on the <p class="stat-value">) so assistive tech receives a clear, semantic
description while keeping the visual icon if desired.
- Around line 556-560: The loadDashboard() function currently calls res.json()
and renderDashboard(data) without checking the HTTP status; update loadDashboard
to check res.ok (or res.status) after the fetch, handle non-2xx responses by
parsing the error body (or using res.statusText) and surface an error (e.g.,
show an error UI message, log to console, or early-return) instead of calling
renderDashboard; in short, inside loadDashboard() guard the
res.json()/renderDashboard(data) path behind a res.ok check and handle/propagate
the error when res.ok is false.

In `@public/index.html`:
- Line 547: The mobile menu toggle button lacks an explicit type and may default
to type="submit" inside forms; update the button element that calls
toggleMobileMenu() (the button with class "nav-toggle" and
onclick="toggleMobileMenu()") to include an explicit type attribute
(type="button") so it does not submit forms when clicked.
- Around line 563-566: The accordion toggle button with class "accordion-btn"
(onclick="toggleAccordion('auth-accordion')" and icon id "auth-accordion-icon")
is missing an explicit type and may trigger form submit; update the button
element to include type="button" so it acts as a non-submitting control and
prevents default submit behavior.
- Around line 1071-1079: The dynamically created profile avatar button in
updateNav() (the button in nav.innerHTML that calls toggleDD(event)) lacks an
explicit type, which can cause it to act as a submit button inside forms; update
the template for nav.innerHTML so the avatar button includes type="button"
(i.e., add the type attribute to the button element that renders ${esc(ini)}) to
ensure it does not trigger form submission.

In `@public/profile.html`:
- Line 286: The mobile menu toggle button (class "nav-toggle", onclick calling
toggleMobileMenu()) lacks an explicit type and may act as a submit button in
form contexts; update the <button class="nav-toggle"
onclick="toggleMobileMenu()"> element to include type="button" so it will not
submit forms accidentally.
- Around line 586-589: The avatar button inserted via nav.innerHTML in
updateNav() lacks an explicit type, causing it to act as a submit button in
forms; update the generated button element (the one with
onclick="toggleDD(event)" and text ${esc(ini)}) to include type="button" so it
won't trigger form submissions, leaving the rest of the markup and the
document.getElementById('dd-avatar') assignment unchanged.

In `@public/teach.html`:
- Line 251: The mobile menu toggle button lacks an explicit type and will
default to type="submit", causing unintended form submissions; update the button
element that calls toggleMobileMenu() (the element with class "nav-toggle" and
onclick="toggleMobileMenu()") to include type="button" so it does not submit
forms when clicked.
- Around line 346-377: The form labels in the session block are not linked to
their inputs; update each <label> to include a matching for attribute that
equals the corresponding control id (s-activity, s-title, s-start, s-end,
s-location, s-desc) so the Activity select, Session Title input, Start/End
datetime inputs, Location input, and Description textarea are programmatically
associated with their labels for accessibility.
- Around line 533-541: The dynamically generated avatar button inside updateNav
(the block that sets nav.innerHTML with the <button onclick="toggleDD(event)">)
is missing an explicit type, causing it to act as a submit button in forms;
update the generated HTML for that button to include type="button" (i.e., add
the type attribute to the button in the nav.innerHTML string) so it no longer
triggers form submission when clicked.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: alphaonelabs/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: c40a3242-cbcb-4a60-bf04-f6f1caa7d558

📥 Commits

Reviewing files that changed from the base of the PR and between 9360bf5 and 1c3dfc2.

📒 Files selected for processing (4)
  • public/dashboard.html
  • public/index.html
  • public/profile.html
  • public/teach.html

<a href="/teach.html" class="nav-link">Host</a>
</div>
<div id="nav-auth"></div>
<button class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add type="button" to the mobile menu toggle button.

This button lacks an explicit type attribute, which defaults to type="submit". If this markup is ever placed inside a form, it could cause unexpected form submission.

🔧 Suggested fix
-    <button class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
+    <button type="button" class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
🧰 Tools
🪛 HTMLHint (1.9.2)

[warning] 253-253: The type attribute must be present on elements.

(button-type-require)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/dashboard.html` at line 253, The mobile menu toggle button currently
lacks an explicit type and will default to type="submit"; update the <button
class="nav-toggle" ...> element that calls toggleMobileMenu() to include
type="button" so it no longer triggers form submission if placed inside a form;
locate the button by its class "nav-toggle" or its onclick calling
toggleMobileMenu and add the type attribute.

Comment on lines +474 to 476
function statCard(value, label) {
return '<div class="stat-card"><p class="stat-value" style="color:var(--teal);">' + value + '</p><p class="stat-label">' + label + '</p></div>';
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Stat card with emoji as value may confuse assistive technologies.

The "Data Encrypted" stat card uses a lock emoji (🔒) as the numeric value. Screen readers will announce this differently across platforms, and it doesn't convey meaningful quantitative information like the other stat cards. Consider using text like "Yes" or "100%" with an accompanying icon, or add an aria-label for clarity.

💡 Alternative approach
-      statCard('🔒',           'Data Encrypted');
+      statCard('✓',            'Data Encrypted');

Or provide a more descriptive value:

statCard('100%', 'Data Encrypted');
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/dashboard.html` around lines 474 - 476, The statCard function
currently renders the visible value directly (function statCard) and using a
lock emoji for the "Data Encrypted" card can confuse screen readers; update the
place where statCard is called for "Data Encrypted" to use a descriptive textual
value (e.g., "Yes" or "100%") instead of the emoji and/or enhance the generated
HTML in statCard to include an aria-label on the value element (for example set
aria-label="Data encrypted: Yes" on the <p class="stat-value">) so assistive
tech receives a clear, semantic description while keeping the visual icon if
desired.

Comment on lines +556 to +560
async function loadDashboard() {
const res = await fetch('/api/dashboard', { headers:{ Authorization: 'Bearer ' + token } });
const data = await res.json();
renderDashboard(data);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Consider adding error handling for non-OK responses in loadDashboard().

The loadDashboard() function calls res.json() but doesn't check res.ok before processing. If the API returns a non-2xx status, the code will still attempt to render the response as dashboard data, potentially causing confusing UI states.

🛡️ Proposed fix
   async function loadDashboard() {
     const res  = await fetch('/api/dashboard', { headers:{ Authorization: 'Bearer ' + token } });
+    if (!res.ok) {
+      const err = await res.json().catch(() => ({}));
+      throw new Error(err.error || 'Failed to load dashboard');
+    }
     const data = await res.json();
     renderDashboard(data);
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function loadDashboard() {
const res = await fetch('/api/dashboard', { headers:{ Authorization: 'Bearer ' + token } });
const data = await res.json();
renderDashboard(data);
}
async function loadDashboard() {
const res = await fetch('/api/dashboard', { headers:{ Authorization: 'Bearer ' + token } });
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(err.error || 'Failed to load dashboard');
}
const data = await res.json();
renderDashboard(data);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/dashboard.html` around lines 556 - 560, The loadDashboard() function
currently calls res.json() and renderDashboard(data) without checking the HTTP
status; update loadDashboard to check res.ok (or res.status) after the fetch,
handle non-2xx responses by parsing the error body (or using res.statusText) and
surface an error (e.g., show an error UI message, log to console, or
early-return) instead of calling renderDashboard; in short, inside
loadDashboard() guard the res.json()/renderDashboard(data) path behind a res.ok
check and handle/propagate the error when res.ok is false.

</div>
<div id="nav-auth" class="flex items-center gap-3"></div>
<div id="nav-auth"></div>
<button class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add type="button" to the mobile menu toggle button.

This button lacks an explicit type attribute. Without it, the default is type="submit", which could cause unexpected behavior if placed inside a form.

🔧 Suggested fix
-    <button class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
+    <button type="button" class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
<button type="button" class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
🧰 Tools
🪛 HTMLHint (1.9.2)

[warning] 547-547: The type attribute must be present on elements.

(button-type-require)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/index.html` at line 547, The mobile menu toggle button lacks an
explicit type and may default to type="submit" inside forms; update the button
element that calls toggleMobileMenu() (the button with class "nav-toggle" and
onclick="toggleMobileMenu()") to include an explicit type attribute
(type="button") so it does not submit forms when clicked.

Comment on lines +563 to +566
<button class="accordion-btn" onclick="toggleAccordion('auth-accordion')">
<span><i class="fas fa-user"></i>Auth</span>
<i class="fas fa-chevron-down" id="auth-accordion-icon"></i>
</button>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add type="button" to the accordion toggle button.

The accordion button in the mobile menu is missing an explicit type attribute. Add type="button" to prevent default submit behavior.

🔧 Suggested fix
-      <button class="accordion-btn" onclick="toggleAccordion('auth-accordion')">
+      <button type="button" class="accordion-btn" onclick="toggleAccordion('auth-accordion')">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button class="accordion-btn" onclick="toggleAccordion('auth-accordion')">
<span><i class="fas fa-user"></i>Auth</span>
<i class="fas fa-chevron-down" id="auth-accordion-icon"></i>
</button>
<button type="button" class="accordion-btn" onclick="toggleAccordion('auth-accordion')">
<span><i class="fas fa-user"></i>Auth</span>
<i class="fas fa-chevron-down" id="auth-accordion-icon"></i>
</button>
🧰 Tools
🪛 HTMLHint (1.9.2)

[warning] 563-563: The type attribute must be present on elements.

(button-type-require)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/index.html` around lines 563 - 566, The accordion toggle button with
class "accordion-btn" (onclick="toggleAccordion('auth-accordion')" and icon id
"auth-accordion-icon") is missing an explicit type and may trigger form submit;
update the button element to include type="button" so it acts as a
non-submitting control and prevents default submit behavior.

<a href="/teach.html" class="nav-link">Host</a>
</div>
<div id="nav-auth"></div>
<button class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add type="button" to the mobile menu toggle button.

This button is missing an explicit type attribute. Adding type="button" ensures it won't accidentally submit a form if the markup context changes.

🔧 Suggested fix
-    <button class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
+    <button type="button" class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
<button type="button" class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
🧰 Tools
🪛 HTMLHint (1.9.2)

[warning] 286-286: The type attribute must be present on elements.

(button-type-require)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/profile.html` at line 286, The mobile menu toggle button (class
"nav-toggle", onclick calling toggleMobileMenu()) lacks an explicit type and may
act as a submit button in form contexts; update the <button class="nav-toggle"
onclick="toggleMobileMenu()"> element to include type="button" so it will not
submit forms accidentally.

Comment on lines +586 to +589
nav.innerHTML=`
<a href="/dashboard.html" class="nav-link">Dashboard</a>
<button onclick="toggleDD(event)" style="width:36px;height:36px;background:rgba(255,255,255,.2);border-radius:9px;border:none;cursor:pointer;font-family:'Syne',sans-serif;font-weight:800;font-size:.8rem;color:#fff;display:flex;align-items:center;justify-content:center;">${esc(ini)}</button>`;
document.getElementById('dd-avatar').textContent=ini;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add type="button" to the dynamically generated profile avatar button.

The profile avatar button created in updateNav() is missing an explicit type attribute. Since this button is generated via innerHTML, it should include type="button" to prevent default submit behavior.

🔧 Suggested fix
       nav.innerHTML=`
         <a href="/dashboard.html" class="nav-link">Dashboard</a>
-        <button onclick="toggleDD(event)" style="width:36px;height:36px;background:rgba(255,255,255,.2);border-radius:9px;border:none;cursor:pointer;font-family:'Syne',sans-serif;font-weight:800;font-size:.8rem;color:`#fff`;display:flex;align-items:center;justify-content:center;">${esc(ini)}</button>`;
+        <button type="button" onclick="toggleDD(event)" style="width:36px;height:36px;background:rgba(255,255,255,.2);border-radius:9px;border:none;cursor:pointer;font-family:'Syne',sans-serif;font-weight:800;font-size:.8rem;color:`#fff`;display:flex;align-items:center;justify-content:center;">${esc(ini)}</button>`;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
nav.innerHTML=`
<a href="/dashboard.html" class="nav-link">Dashboard</a>
<button onclick="toggleDD(event)" style="width:36px;height:36px;background:rgba(255,255,255,.2);border-radius:9px;border:none;cursor:pointer;font-family:'Syne',sans-serif;font-weight:800;font-size:.8rem;color:#fff;display:flex;align-items:center;justify-content:center;">${esc(ini)}</button>`;
document.getElementById('dd-avatar').textContent=ini;
nav.innerHTML=`
<a href="/dashboard.html" class="nav-link">Dashboard</a>
<button type="button" onclick="toggleDD(event)" style="width:36px;height:36px;background:rgba(255,255,255,.2);border-radius:9px;border:none;cursor:pointer;font-family:'Syne',sans-serif;font-weight:800;font-size:.8rem;color:`#fff`;display:flex;align-items:center;justify-content:center;">${esc(ini)}</button>`;
document.getElementById('dd-avatar').textContent=ini;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/profile.html` around lines 586 - 589, The avatar button inserted via
nav.innerHTML in updateNav() lacks an explicit type, causing it to act as a
submit button in forms; update the generated button element (the one with
onclick="toggleDD(event)" and text ${esc(ini)}) to include type="button" so it
won't trigger form submissions, leaving the rest of the markup and the
document.getElementById('dd-avatar') assignment unchanged.

<a href="/teach.html" class="nav-link active">Host</a>
</div>
<div id="nav-auth"></div>
<button class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add type="button" to the mobile menu toggle button.

This button is missing an explicit type attribute, which defaults to type="submit".

🔧 Suggested fix
-    <button class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
+    <button type="button" class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
<button type="button" class="nav-toggle" onclick="toggleMobileMenu()"><i class="fas fa-bars"></i></button>
🧰 Tools
🪛 HTMLHint (1.9.2)

[warning] 251-251: The type attribute must be present on elements.

(button-type-require)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/teach.html` at line 251, The mobile menu toggle button lacks an
explicit type and will default to type="submit", causing unintended form
submissions; update the button element that calls toggleMobileMenu() (the
element with class "nav-toggle" and onclick="toggleMobileMenu()") to include
type="button" so it does not submit forms when clicked.

Comment on lines +346 to 377
<div class="form-group">
<label class="form-label">Activity *</label>
<select id="s-activity" class="form-select">
<option value="">Select an activity...</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-slate-700 mb-1">Session Title *</label>
<input id="s-title" type="text" required
class="w-full px-4 py-2.5 rounded-xl border border-slate-200 focus:outline-none focus:ring-2 focus:ring-brand/40 text-sm" placeholder="e.g. Week 1 - Introduction" />

<div class="form-group">
<label class="form-label">Session Title *</label>
<input id="s-title" type="text" required class="form-input" placeholder="e.g. Week 1 - Introduction" />
</div>
<div class="grid grid-cols-2 gap-3">
<div>
<label class="block text-sm font-medium text-slate-700 mb-1">Start Time</label>
<input id="s-start" type="datetime-local"
class="w-full px-3 py-2.5 rounded-xl border border-slate-200 focus:outline-none focus:ring-2 focus:ring-brand/40 text-sm" />

<div style="display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1rem;">
<div class="form-group" style="margin-bottom:0;">
<label class="form-label">Start Time</label>
<input id="s-start" type="datetime-local" class="form-input" />
</div>
<div>
<label class="block text-sm font-medium text-slate-700 mb-1">End Time</label>
<input id="s-end" type="datetime-local"
class="w-full px-3 py-2.5 rounded-xl border border-slate-200 focus:outline-none focus:ring-2 focus:ring-brand/40 text-sm" />
<div class="form-group" style="margin-bottom:0;">
<label class="form-label">End Time</label>
<input id="s-end" type="datetime-local" class="form-input" />
</div>
</div>
<div>
<label class="block text-sm font-medium text-slate-700 mb-1">Location (encrypted)</label>
<input id="s-location" type="text"
class="w-full px-4 py-2.5 rounded-xl border border-slate-200 focus:outline-none focus:ring-2 focus:ring-brand/40 text-sm" placeholder="e.g. Room 101 or Zoom link" />

<div class="form-group">
<label class="form-label">Location (encrypted)</label>
<input id="s-location" type="text" class="form-input" placeholder="e.g. Room 101 or Zoom link" />
</div>
<div>
<label class="block text-sm font-medium text-slate-700 mb-1">Description (encrypted)</label>
<textarea id="s-desc" rows="2"
class="w-full px-4 py-2.5 rounded-xl border border-slate-200 focus:outline-none focus:ring-2 focus:ring-brand/40 text-sm resize-none" placeholder="What will be covered in this session?"></textarea>

<div class="form-group">
<label class="form-label">Description (encrypted)</label>
<textarea id="s-desc" class="form-textarea" placeholder="What will be covered?"></textarea>
</div>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Associate session form labels with their controls using for attributes.

The session form has several labels that are not programmatically linked to their inputs. While the activity form labels were properly fixed to include for attributes, the session form labels are still missing them. This affects accessibility for screen reader users.

As per coding guidelines, **/*.html: Review HTML templates for accessibility (ARIA attributes, semantic elements).

🔧 Suggested fix
             <div class="form-group">
-              <label class="form-label">Activity *</label>
+              <label for="s-activity" class="form-label">Activity *</label>
               <select id="s-activity" class="form-select">

             <div class="form-group">
-              <label class="form-label">Session Title *</label>
+              <label for="s-title" class="form-label">Session Title *</label>
               <input id="s-title" type="text" required class="form-input" placeholder="e.g. Week 1 - Introduction" />

               <div class="form-group" style="margin-bottom:0;">
-                <label class="form-label">Start Time</label>
+                <label for="s-start" class="form-label">Start Time</label>
                 <input id="s-start" type="datetime-local" class="form-input" />
               </div>
               <div class="form-group" style="margin-bottom:0;">
-                <label class="form-label">End Time</label>
+                <label for="s-end" class="form-label">End Time</label>
                 <input id="s-end" type="datetime-local" class="form-input" />

             <div class="form-group">
-              <label class="form-label">Location (encrypted)</label>
+              <label for="s-location" class="form-label">Location (encrypted)</label>
               <input id="s-location" type="text" class="form-input" placeholder="e.g. Room 101 or Zoom link" />

             <div class="form-group">
-              <label class="form-label">Description (encrypted)</label>
+              <label for="s-desc" class="form-label">Description (encrypted)</label>
               <textarea id="s-desc" class="form-textarea" placeholder="What will be covered?"></textarea>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div class="form-group">
<label class="form-label">Activity *</label>
<select id="s-activity" class="form-select">
<option value="">Select an activity...</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-slate-700 mb-1">Session Title *</label>
<input id="s-title" type="text" required
class="w-full px-4 py-2.5 rounded-xl border border-slate-200 focus:outline-none focus:ring-2 focus:ring-brand/40 text-sm" placeholder="e.g. Week 1 - Introduction" />
<div class="form-group">
<label class="form-label">Session Title *</label>
<input id="s-title" type="text" required class="form-input" placeholder="e.g. Week 1 - Introduction" />
</div>
<div class="grid grid-cols-2 gap-3">
<div>
<label class="block text-sm font-medium text-slate-700 mb-1">Start Time</label>
<input id="s-start" type="datetime-local"
class="w-full px-3 py-2.5 rounded-xl border border-slate-200 focus:outline-none focus:ring-2 focus:ring-brand/40 text-sm" />
<div style="display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1rem;">
<div class="form-group" style="margin-bottom:0;">
<label class="form-label">Start Time</label>
<input id="s-start" type="datetime-local" class="form-input" />
</div>
<div>
<label class="block text-sm font-medium text-slate-700 mb-1">End Time</label>
<input id="s-end" type="datetime-local"
class="w-full px-3 py-2.5 rounded-xl border border-slate-200 focus:outline-none focus:ring-2 focus:ring-brand/40 text-sm" />
<div class="form-group" style="margin-bottom:0;">
<label class="form-label">End Time</label>
<input id="s-end" type="datetime-local" class="form-input" />
</div>
</div>
<div>
<label class="block text-sm font-medium text-slate-700 mb-1">Location (encrypted)</label>
<input id="s-location" type="text"
class="w-full px-4 py-2.5 rounded-xl border border-slate-200 focus:outline-none focus:ring-2 focus:ring-brand/40 text-sm" placeholder="e.g. Room 101 or Zoom link" />
<div class="form-group">
<label class="form-label">Location (encrypted)</label>
<input id="s-location" type="text" class="form-input" placeholder="e.g. Room 101 or Zoom link" />
</div>
<div>
<label class="block text-sm font-medium text-slate-700 mb-1">Description (encrypted)</label>
<textarea id="s-desc" rows="2"
class="w-full px-4 py-2.5 rounded-xl border border-slate-200 focus:outline-none focus:ring-2 focus:ring-brand/40 text-sm resize-none" placeholder="What will be covered in this session?"></textarea>
<div class="form-group">
<label class="form-label">Description (encrypted)</label>
<textarea id="s-desc" class="form-textarea" placeholder="What will be covered?"></textarea>
</div>
<div class="form-group">
<label for="s-activity" class="form-label">Activity *</label>
<select id="s-activity" class="form-select">
<option value="">Select an activity...</option>
</select>
</div>
<div class="form-group">
<label for="s-title" class="form-label">Session Title *</label>
<input id="s-title" type="text" required class="form-input" placeholder="e.g. Week 1 - Introduction" />
</div>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1rem;">
<div class="form-group" style="margin-bottom:0;">
<label for="s-start" class="form-label">Start Time</label>
<input id="s-start" type="datetime-local" class="form-input" />
</div>
<div class="form-group" style="margin-bottom:0;">
<label for="s-end" class="form-label">End Time</label>
<input id="s-end" type="datetime-local" class="form-input" />
</div>
</div>
<div class="form-group">
<label for="s-location" class="form-label">Location (encrypted)</label>
<input id="s-location" type="text" class="form-input" placeholder="e.g. Room 101 or Zoom link" />
</div>
<div class="form-group">
<label for="s-desc" class="form-label">Description (encrypted)</label>
<textarea id="s-desc" class="form-textarea" placeholder="What will be covered?"></textarea>
</div>
🧰 Tools
🪛 HTMLHint (1.9.2)

[warning] 355-355: No matching [ label ] tag found.

(input-requires-label)


[warning] 361-361: No matching [ label ] tag found.

(input-requires-label)


[warning] 365-365: No matching [ label ] tag found.

(input-requires-label)


[warning] 371-371: No matching [ label ] tag found.

(input-requires-label)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/teach.html` around lines 346 - 377, The form labels in the session
block are not linked to their inputs; update each <label> to include a matching
for attribute that equals the corresponding control id (s-activity, s-title,
s-start, s-end, s-location, s-desc) so the Activity select, Session Title input,
Start/End datetime inputs, Location input, and Description textarea are
programmatically associated with their labels for accessibility.

Comment on lines +533 to +541
if(token&&user){
const ini=(user.name||user.username||'?').slice(0,2).toUpperCase();
nav.innerHTML=`
<a href="/dashboard.html" class="nav-link">Dashboard</a>
<button onclick="toggleDD(event)" style="width:36px;height:36px;background:rgba(255,255,255,.2);border-radius:9px;border:none;cursor:pointer;font-family:'Syne',sans-serif;font-weight:800;font-size:.8rem;color:#fff;display:flex;align-items:center;justify-content:center;">${esc(ini)}</button>`;
document.getElementById('dd-avatar').textContent=ini;
document.getElementById('dd-name').textContent=user.name||user.username;
document.getElementById('dd-role').textContent=user.role||'member';
nav.appendChild(dd);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add type="button" to the dynamically generated profile avatar button.

The profile avatar button created in updateNav() is missing an explicit type attribute, which should be included to prevent default submit behavior.

🔧 Suggested fix
       nav.innerHTML=`
         <a href="/dashboard.html" class="nav-link">Dashboard</a>
-        <button onclick="toggleDD(event)" style="width:36px;height:36px;background:rgba(255,255,255,.2);border-radius:9px;border:none;cursor:pointer;font-family:'Syne',sans-serif;font-weight:800;font-size:.8rem;color:`#fff`;display:flex;align-items:center;justify-content:center;">${esc(ini)}</button>`;
+        <button type="button" onclick="toggleDD(event)" style="width:36px;height:36px;background:rgba(255,255,255,.2);border-radius:9px;border:none;cursor:pointer;font-family:'Syne',sans-serif;font-weight:800;font-size:.8rem;color:`#fff`;display:flex;align-items:center;justify-content:center;">${esc(ini)}</button>`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@public/teach.html` around lines 533 - 541, The dynamically generated avatar
button inside updateNav (the block that sets nav.innerHTML with the <button
onclick="toggleDD(event)">) is missing an explicit type, causing it to act as a
submit button in forms; update the generated HTML for that button to include
type="button" (i.e., add the type attribute to the button in the nav.innerHTML
string) so it no longer triggers form submission when clicked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant