← Back to Home

📊 Feedback System — Project Report

Student, Teacher & Admin Portal · Built by P Vishnuvardhan Reddy
HTML / CSS / JS Firebase Firestore Chart.js 5,434 Lines of Code
📋 Project Overview
📦 RepositoryVishnumgit/feedback
📝 DescriptionA multi-role feedback collection and analytics system for educational institutions with Student, Teacher, and Admin portals
👤 AuthorP Vishnuvardhan Reddy (Vishnumgit)
🏫 InstitutionMGIT — Mahatma Gandhi Institute of Technology
📅 Created12 March 2026
🌐 VisibilityPublic
🗃 Total Size137 KB (15 files + 2 folders)
💻 LanguageHTML, CSS, JavaScript (Vanilla — No frameworks)
🗄 DatabaseFirebase Firestore (Cloud) + localStorage (Offline)
📊 ChartsChart.js 4.4.0 (Radar, Bar, Doughnut, Trend)
📈 Project Statistics
5,434
Lines of Code
15
Source Files
20
Git Commits
3
User Roles
7
Admin Tabs
6
Teacher Views
7
Firestore Collections
2
Report Generators
🏗 System Architecture
👤 Student Portal
📝 Feedback Form
🗄 localStorage
🔥 Firebase Firestore
👨‍🏫 Teacher Dashboard
📊 Analytics Engine
🗄 data.js
📄 HTML Report
🔑 Admin Panel
👥 User Mgmt
+
📋 Assignments
+
📊 Reports

🖥 Frontend

  • Vanilla HTML/CSS/JS
  • Dark theme UI (CSS vars)
  • Chart.js 4.4.0
  • Responsive sidebar layout
  • SVG inline charts for reports
  • Inter font (Google Fonts)

🗄 Data Layer

  • localStorage primary store
  • Firebase Firestore cloud sync
  • Background non-blocking sync
  • Auto-seed on first visit
  • Offline-first architecture
  • 7 data collections

🔒 Auth System

  • Role-based (Admin/Teacher/Student)
  • Session via localStorage
  • Login page per role
  • Protected dashboard routes
  • Email domain validation
  • Password-based login
🔥 Firebase Firestore Schema
CollectionlocalStorage KeyPurpose
userssfft_usersAll student, teacher, admin accounts
subjectssfft_subjectsAcademic subjects (Math, Physics, etc.)
questionnairessfft_questionnairesSubject-specific feedback question sets
enrollmentssfft_enrollmentsStudent-teacher assignment mappings
responsessfft_responsesSubmitted feedback with scores & comments
attendancesfft_attendanceStudent attendance records per section
settingssfft_settingsCollege name, domain, min threshold
📁 File Structure
FileLinesSizePurpose
admin-dashboard.html1,968104 KBFull admin panel (7 tabs, reports, user mgmt)
teacher-dashboard.html87749 KBTeacher portal (analytics, charts, report gen)
student-dashboard.html48925 KBStudent portal (profile, feedback status)
feedback-form.html26112 KBFeedback submission form
style.css52324 KBGlobal dark theme styles
data.js30917 KBlocalStorage data layer (CRUD, analytics)
firebase-sync.js23710 KBFirestore background sync
charts.js1254 KBChart.js rendering helpers
auth.js763 KBAuthentication & session management
firebase-config.js18646 BFirebase initialization
fix_emojis.js993 KBEmoji compatibility fixes
index.html633 KBLanding page / role selection
admin-login.html1276 KBAdmin login page
teacher-login.html1256 KBTeacher login page
student-login.html1376 KBStudent login page
🚀 Features by Portal

🔑 Admin Panel (7 Tabs)

👥 User Management

Create, edit, delete students/teachers. Bulk CSV import. Select All + Delete Selected with Firestore sync.

CRUDBulk Import

📚 Subjects & Questionnaires

Add/remove subjects. Build multi-section feedback questionnaires per subject.

Dynamic FormsMulti-Section

👥 Teacher Assignment

Assign students to teachers with visual checklist cards. Roll No display. Section grouping.

Visual CardsRoll No

💬 Feedback Oversight

View all submissions with filters. Select All checkbox. Delete Selected + Clear All with Firestore sync.

FiltersFirestore Delete

📊 Reports & Analytics

Institution-wide charts. Per-teacher breakdown. Downloadable HTML report with SVG charts.

ChartsDownload Report

📋 Attendance + ⚙ Settings

Upload CSV attendance. 75% threshold gate. College name, domain, min threshold config.

CSV UploadConfig

👨‍🏫 Teacher Dashboard

📊 Performance Overview

Score cards, radar chart, bar chart, trend line. Status banner. Category breakdown.

📄 Report Generator

Beautiful HTML report with SVG charts, summary cards, data table, comments. Print/PDF.

🎓 Student Portal

📝 Feedback Submission

Multi-section questionnaire with 1-5 star ratings. Anonymous option. Attendance-gated.

👤 Student Dashboard

Profile with Roll No. Assigned teachers list. Submission status per teacher.

🔧 Development History
Show Roll No in student dashboard profileFEAT
Add Roll No to user modal + Delete Selected usersFEAT
Normalize CSV column names for bulk importFIX
Unique user IDs to prevent overwritesFIX
Batch insert for bulk import — single writeFIX
Batch delete users + clean all related Firestore dataFIX
Enhanced CSV export with section scores & summary rowFEAT
Clear All Enrollments + Clear All Attendance buttonsFEAT
Feedback clear buttons + checkboxes + Firestore syncFEAT
Rich HTML reports with SVG charts (Teacher + Admin)FEAT
Roll No in Teacher Assignment student cardsFEAT
🛠 Technology Stack

Frontend

  • HTML5 (Semantic)
  • CSS3 (Custom Properties)
  • Vanilla JavaScript (ES6+)
  • Chart.js 4.4.0
  • SVG (Inline Charts)
  • Google Fonts (Inter)

Backend / Database

  • Firebase Firestore (NoSQL)
  • Firebase Compat SDK
  • localStorage (Offline)
  • Background Sync Pattern
  • Batch Write Operations
  • Auto-seed on First Run

DevOps / Tools

  • GitHub (Version Control)
  • CodeWords (AI Automation)
  • Pipedream (GitHub API)
  • 20 Commits in 1 Day
  • Zero-framework approach
  • No build step needed
🔍 Detailed File Analysis — Line by Line
js/data.js 309 lines · 17 KB · localStorage Data Layer
1–13
DB key constants — Defines the DB object mapping 7 collection names (USERS, SUBJECTS, QUESTIONNAIRES, ENROLLMENTS, RESPONSES, ATTENDANCE, SETTINGS) to their sfft_* localStorage keys. Centralises all key strings to prevent typos across the codebase.
15–21
CRUD helpers — Four tiny arrow functions: get()/set() parse/stringify JSON arrays, getObj()/setObj() do the same for plain objects. Used by every higher-level function to read/write localStorage.
24–82
Password hashing (hashPassword) — Async function. Tries crypto.subtle.digest('SHA-256') (available only on HTTPS). Falls back to a self-contained pure-JS SHA-256 implementation for HTTP environments. Returns a lowercase hex string. Both admin, teacher and student default demo passwords are pre-hashed with this function.
85–187
Database initialisation (initDB) — Runs once per device (guarded by sfft_initialized flag). Seeds: 1 admin + 3 sample teachers + 5 sample students with SHA-256 hashed passwords; 5 subjects; detailed 5-section questionnaires per subject (Math, Physics, English, CS, Chemistry); empty arrays for enrollments, attendance and responses; default settings object with college domain, name and minimum score threshold.
188–199
Settings CRUDgetSettings() returns the settings object; saveSettings(s) persists it. Used by admin panel to store/read college name, email domain and min threshold.
200–240
User CRUDgetUsers(), getUserByEmail() (case-insensitive), getUserById(). saveUser(u) upserts by id. deleteUser(id) removes a user and cascades deletion of their enrollments and responses. getTeachers()/getStudents() are role-filtered views.
241–260
Enrollment functionsgetEnrollments() returns all enrollment records. getTeachersForStudent(studentId) returns teacher objects augmented with _enrolledSubjectId — one entry per teacher-subject pair. getStudentsForTeacher(teacherId) returns matching student objects.
261–310
Feedback response functionshasSubmitted(studentId, teacherId, subjectId) checks if feedback already exists for the specific teacher+subject pair. saveResponse(r) inserts a response only if no duplicate exists. getResponsesForTeacher(teacherId) returns all responses for a teacher. getTeacherStats(teacherId) computes overall average, per-section averages, rating distribution histogram, trend data and comment list from the stored responses.
js/auth.js 320 lines · 3 KB · Authentication & Session Management
1–13
Session key + token generatorSESSION_KEY constant for sessionStorage. generateSessionToken() creates a random token (timestamp base-36 + random suffix) to detect concurrent logins.
15–47
Firestore user fetch fallback (fetchUserFromFirestore) — When a user logs in on a new device and their data isn't in localStorage yet, this async function queries the Firestore users collection by email and merges the result into localStorage. Handles case-sensitivity differences in stored emails.
49–130
Email/password login (login) — Resolves the local user, then calls Firebase auth.signInWithEmailAndPassword. If the Firebase account doesn't exist yet (first login after admin setup), it auto-creates a Firebase Auth account using the supplied password (auto-migration). Falls back to anonymous sign-in if creation fails. Writes the user doc to Firestore as a non-blocking background operation (errors are caught and logged as console warnings), stores Firebase UID in localStorage, and saves a session object in sessionStorage.
132–186
Google Sign-In (googleLogin, googleLoginWithPopup)googleLogin decodes the Google JWT, looks up the user by email, signs in with Firebase signInWithCredential, and creates a session. googleLoginWithPopup wraps Google Identity Services (GIS) one-tap prompt with a rendered fallback button if the prompt is suppressed.
216–246
Session concurrency listener (startSessionListener) — Writes the session token to the Firestore user doc, then subscribes to real-time updates. If another device changes the token, the listener signs the current session out and redirects to the home page with an alert.
248–270
Logout & auth guardslogout() clears sessionStorage and Firebase Auth state. getSession() reads the current session. requireAuth(expectedRole) redirects to home if no session or role mismatch — called at the top of every dashboard.
271–320
Password managementchangePassword() verifies the current password (hashed), updates Firebase Auth password, rehashes and saves the new password in localStorage and Firestore. adminResetPassword() skips the current-password check (admin only). validateCollegeEmail() checks that the email domain matches the configured college domain.
js/firebase-sync.js 237 lines · 10 KB · Firestore Background Sync
1–27
Firestore write helpersfsSetDoc(collection, docId, data) strips password and passwordHash fields before writing (security). For the users collection it prefers the Firebase UID as the document key. fsDeleteDoc(collection, docId) deletes a Firestore document; both functions catch errors and log console warnings without propagating them, so the UI is never blocked by sync failures.
29–60
Merge helpersmergeById(arr, item) upserts an item into an array matching on id or email (fallback). mergeByField(arr, item, field) does the same for arbitrary fields (used for enrollments and attendance). Prevents duplicates when Firestore snapshots arrive out of order.
62–120
Role-based pull syncsyncFromFirestore(role, userId) fetches only the data relevant to the logged-in role. Students fetch their own enrollments and responses. Teachers fetch responses for their teacher ID. Admins fetch all collections. A 5-minute timestamp cache prevents redundant Firestore reads.
121–180
Push sync (localStorage → Firestore)pushToFirestore() reads every localStorage collection and writes each item to Firestore as a separate document. Called non-blocking (not awaited) after any write operation so the UI stays responsive.
181–237
Real-time listener setupsetupRealtimeSync(role, userId) attaches Firestore onSnapshot listeners so that changes made by an admin (new users, enrollments, settings) propagate to other open sessions without a page reload. Updates are merged into localStorage via the helper functions above.
js/charts.js 125 lines · 4 KB · Chart.js Rendering Helpers
1–9
Instance registrychartInstances object tracks live Chart.js instances by canvas ID. destroyChart(id) destroys an existing chart before re-rendering to prevent memory leaks and duplicate canvas contexts.
11–38
renderRadar(canvasId, teacherId) — Calls getTeacherStats() from data.js, extracts section labels and averages, and renders a purple radar chart showing performance across teaching categories (e.g., Teaching Methodology, Communication Skills, etc.).
40–65
renderBar(canvasId, teacherId) — Renders a stacked bar chart showing the distribution of 1–5 star ratings for a teacher. Each bar is colour-coded (red → green → purple) for quick visual interpretation of feedback quality.
67–96
renderTrend(canvasId, teacherId) — Renders a filled line (area) chart of average score over time (each submission as a data point). Uses the trendData array from getTeacherStats() to show performance evolution.
98–125
renderInstitutionBar(canvasId) — Admin-only chart. Calls getInstitutionStats() (returns per-teacher averages) and renders a bar chart comparing all teachers side-by-side. Cycles through 6 purple shades for visual variety.
feedback-form.html 261 lines · 12 KB · Student Feedback Submission
1–30
Head & dependencies — Loads style.css, Firebase SDK, data.js, auth.js and firebase-sync.js. All scripts deferred so the form HTML is parsed first.
31–80
Attendance gate — On page load, calls requireAuth('student'), then reads the teacher and subject IDs from URL params. Fetches the student's attendance record and compares it against ATTENDANCE_THRESHOLD (75%). If below threshold, replaces the form with a locked message showing the student's actual percentage.
81–140
Already-submitted guard — Calls hasSubmitted(studentId, teacherId, subjectId). If true, shows a "Feedback already submitted" banner and hides the form. Prevents duplicate responses for the same teacher-subject pair.
141–200
Dynamic form builder — Reads the questionnaire for the selected subject from data.js. For each section, generates a card with the section title and a 1–5 star rating input (radio buttons styled as stars) for each question. All sections are rendered dynamically — no hardcoded questions in HTML.
201–261
Submission handler — Collects all star-rating values, validates that every question has been answered, builds a response object ({ studentId, teacherId, subjectId, scores, comment, anonymous, timestamp }), calls saveResponse() and fsSetDoc() to persist locally and to Firestore. Redirects back to the student dashboard on success.
student-dashboard.html 489 lines · 25 KB · Student Portal
1–40
Head / sidebar setup — Standard dashboard shell: loads style.css, Firebase, data/auth/sync scripts, and renders a sidebar with the student's name and role badge.
41–120
Profile tab — Displays the student's name, email, roll number, department and section. Shows a list of enrolled teachers with their subject. Roll numbers are sorted ascending before rendering (CSE-101 before CSE-201).
121–250
Feedback status tab — Iterates over each teacher-subject pair returned by getTeachersForStudent(). For each pair, checks hasSubmitted() and renders a green "Submitted ✓" badge or a "Give Feedback" button. The button navigates to feedback-form.html with the teacher and subject IDs as URL query parameters.
251–400
Notifications tab — Reads the push-notification permission state. Shows a "Enable Notifications" toggle that calls the Firebase Cloud Messaging subscription flow. Displays recent notification history from localStorage.
401–489
Init logicrequireAuth('student') guard, Firestore sync, then calls render functions for each tab. Handles tab switching via sidebar nav items. Change-password modal and logout are in the header area.
teacher-dashboard.html 877 lines · 49 KB · Teacher Analytics Portal
1–50
Head + Chart.js — Loads Chart.js 4.4.0 CDN, style.css, data.js, charts.js, auth.js, firebase-sync.js. Script load order matters: data.js must come before charts.js since charts call getTeacherStats().
51–180
Overview tab — Shows 4 stat cards (overall avg, total responses, top category, response count). Renders radar chart (section breakdown), bar chart (rating distribution) and trend line chart using the charts.js helpers. A status banner shows green/amber/red based on the score relative to the minimum threshold from settings.
181–350
Category breakdown tab — For each feedback section, renders a horizontal progress bar showing the section average out of 5, colour-coded (green ≥4, amber ≥3, red <3). Clicking a section expands an accordion showing individual question averages.
351–550
Student responses tab — A filterable table of all submitted feedback. Columns: student (or "Anonymous"), subject, overall score, date, expandable row for per-question scores and comment. Filter dropdown by subject.
551–750
Report generator — The generateReport() function builds a self-contained HTML string with inline SVG bar/radar charts, a summary card grid, a full data table and a comments section. Opens in a new tab via window.open() (note: may be blocked by the browser's popup blocker — users should allow popups for the site). The report uses @media print so it can be saved as PDF from the browser print dialog.
751–877
Init & change passwordrequireAuth('teacher') guard, then syncFromFirestore('teacher'). Renders all tabs. Change-password modal POSTs to changePassword() in auth.js. Logout clears the session and redirects to index.html.
admin-dashboard.html 1,968 lines · 104 KB · Full Admin Panel (7 Tabs)
1–60
Head + dependencies — Loads Chart.js, all JS modules. Defines the 7-tab sidebar navigation: Dashboard, Website Reviews, User Management, Subjects & Questionnaires, Teacher Assignment, Feedback Oversight, Reports & Analytics, Attendance, Settings.
61–250
Dashboard tab — Institution-wide stats (total users, teachers, students, responses). Renders the institution-wide bar chart (renderInstitutionBar()). Shows per-teacher summary cards with average score, response count and a colour-coded performance badge.
251–500
User Management tab — Full CRUD for students and teachers. Add/edit user modal with fields: name, email, password, role, department, section, roll number. Bulk CSV import (normalises column headers, generates unique IDs). "Delete Selected" with checkboxes + "Select All". All operations cascade to Firestore via fsSetDoc/fsDeleteDoc. Table sorted by roll number for students.
501–750
Subjects & Questionnaires tab — Add/delete subjects. For each subject, a questionnaire editor: add sections, add questions per section, reorder or delete questions. Changes saved to sfft_questionnaires localStorage key and synced to Firestore.
751–1000
Teacher Assignment tab — Visual card grid of teachers. Each card expands a student checklist showing all students with checkboxes (sorted by roll number). Selecting students and clicking Save creates enrollment records linking student IDs to the teacher and their subject ID. Supports multi-subject assignment per teacher.
1001–1250
Feedback Oversight tab — Table of all submitted responses with filters by teacher and date range. "Select All" checkbox, "Delete Selected" and "Clear All" buttons. Deletions sync to Firestore. Export button generates a CSV with per-section scores, overall average, comment and a summary row.
1251–1500
Reports & Analytics tab — Admin-level HTML report generator: institution-wide SVG bar chart, per-teacher breakdown table with section averages, top/bottom performers highlighted. Downloadable as a self-contained HTML file. Also renders a doughnut chart for role distribution.
1501–1700
Attendance tab — CSV upload to bulk-import attendance records (columns: email/rollNo, percentage). Validates that each row has a numeric percentage. Stores records in sfft_attendance. "Clear All Attendance" button with Firestore sync. Used by the feedback form's attendance gate.
1701–1968
Settings tab & init — Editable fields: college name, email domain, minimum score threshold. Saved to sfft_settings and Firestore. The init block at the bottom runs requireAuth('admin'), syncFromFirestore('admin'), seeds demo data via initDB(), and renders the default tab. Also registers the service worker for push notifications.
js/firebase-config.js 18 lines · 646 B · Firebase Initialisation
1–18
Firebase app init — Contains the Firebase project config object (apiKey, authDomain, projectId, storageBucket, messagingSenderId, appId). Calls firebase.initializeApp(firebaseConfig) and exports db = firebase.firestore() and auth = firebase.auth() as global variables used by all other scripts. Uses the Firebase Compat SDK (v8 API) to avoid ES module bundling requirements.