-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreport.html
More file actions
401 lines (389 loc) · 48.5 KB
/
report.html
File metadata and controls
401 lines (389 loc) · 48.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="description" content="MGIT Feedback System project report — overview of features, architecture, and implementation details." />
<meta name="keywords" content="feedback, students, teachers, MGIT" />
<meta property="og:title" content="Project Report — MGIT Feedback System" />
<meta property="og:description" content="MGIT Feedback System project report — overview of features, architecture, and implementation details." />
<meta property="og:url" content="https://mgitfeedback.me/report.html" />
<meta property="og:type" content="website" />
<link rel="canonical" href="https://mgitfeedback.me/report.html" />
<title>Project Report — Feedback System</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&display=swap');
*{margin:0;padding:0;box-sizing:border-box;}
body{font-family:'Inter',system-ui,sans-serif;background:#0f172a;color:#e2e8f0;line-height:1.6;}
.container{max-width:880px;margin:0 auto;padding:30px 28px;}
.header{text-align:center;padding:36px 24px;background:linear-gradient(135deg,rgba(124,58,237,0.15),rgba(59,130,246,0.1));border:1.5px solid rgba(124,58,237,0.3);border-radius:20px;margin-bottom:32px;}
.header h1{font-size:26px;font-weight:900;background:linear-gradient(135deg,#a78bfa,#60a5fa);-webkit-background-clip:text;-webkit-text-fill-color:transparent;letter-spacing:-0.5px;}
.header .sub{font-size:14px;color:#94a3b8;margin-top:6px;}
.header .badges{display:flex;gap:10px;justify-content:center;margin-top:14px;flex-wrap:wrap;}
.header .badge{padding:5px 14px;border-radius:20px;font-size:11px;font-weight:700;}
.bg-purple{background:rgba(124,58,237,0.2);color:#c4b5fd;}
.bg-blue{background:rgba(59,130,246,0.2);color:#93c5fd;}
.bg-green{background:rgba(34,197,94,0.2);color:#86efac;}
.bg-amber{background:rgba(245,158,11,0.2);color:#fcd34d;}
.section{margin-bottom:28px;}
.section-title{font-size:18px;font-weight:800;color:#f1f5f9;margin-bottom:14px;display:flex;align-items:center;gap:10px;padding-bottom:10px;border-bottom:2px solid rgba(124,58,237,0.3);}
.stats-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:24px;}
.stat-card{background:rgba(30,41,59,0.8);border:1px solid rgba(100,116,139,0.2);border-radius:14px;padding:16px;text-align:center;}
.stat-card .num{font-size:28px;font-weight:900;color:#a78bfa;}
.stat-card .lbl{font-size:10px;color:#94a3b8;font-weight:700;text-transform:uppercase;letter-spacing:0.5px;margin-top:2px;}
.info-table{width:100%;border-collapse:collapse;font-size:13px;}
.info-table td{padding:10px 14px;border-bottom:1px solid rgba(100,116,139,0.15);}
.info-table td:first-child{font-weight:700;color:#94a3b8;width:180px;}
.info-table td:last-child{color:#e2e8f0;}
.file-table{width:100%;border-collapse:collapse;font-size:12px;}
.file-table th{background:rgba(124,58,237,0.2);color:#c4b5fd;padding:10px 12px;text-align:left;font-weight:700;font-size:11px;text-transform:uppercase;letter-spacing:0.3px;}
.file-table td{padding:9px 12px;border-bottom:1px solid rgba(100,116,139,0.1);}
.file-table tr:hover{background:rgba(124,58,237,0.05);}
.file-name{font-weight:600;color:#e2e8f0;}
.arch-grid{display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px;margin-bottom:20px;}
.arch-card{background:rgba(30,41,59,0.8);border:1px solid rgba(100,116,139,0.2);border-radius:14px;padding:18px;}
.arch-card h4{font-size:13px;font-weight:800;color:#c4b5fd;margin-bottom:8px;text-transform:uppercase;letter-spacing:0.5px;}
.arch-card ul{list-style:none;font-size:12px;}
.arch-card li{padding:3px 0;color:#cbd5e1;}
.arch-card li::before{content:'▶ ';color:#7c3aed;font-weight:700;}
.feat-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;}
.feat-card{background:rgba(30,41,59,0.8);border:1px solid rgba(100,116,139,0.2);border-radius:14px;padding:18px;}
.feat-card h4{font-size:14px;font-weight:700;color:#f1f5f9;margin-bottom:6px;}
.feat-card p{font-size:12px;color:#94a3b8;}
.feat-tag{display:inline-block;padding:2px 8px;border-radius:10px;font-size:10px;font-weight:600;margin-right:4px;margin-top:6px;}
.flow{display:flex;align-items:center;justify-content:center;gap:10px;flex-wrap:wrap;margin:18px 0;}
.flow-box{background:rgba(124,58,237,0.15);border:1.5px solid rgba(124,58,237,0.3);border-radius:12px;padding:10px 18px;font-size:12px;font-weight:700;color:#c4b5fd;text-align:center;}
.flow-arrow{color:#7c3aed;font-size:18px;font-weight:900;}
.commit-list{font-size:12px;}
.commit{display:flex;gap:12px;padding:8px 0;border-bottom:1px solid rgba(100,116,139,0.1);}
.commit-dot{width:10px;height:10px;border-radius:50%;background:#7c3aed;margin-top:5px;flex-shrink:0;}
.commit-msg{color:#cbd5e1;font-weight:500;}
.commit-type{font-size:10px;padding:1px 6px;border-radius:8px;font-weight:700;margin-left:6px;}
.ct-feat{background:rgba(34,197,94,0.2);color:#86efac;}
.ct-fix{background:rgba(239,68,68,0.2);color:#fca5a5;}
.back-btn{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;background:rgba(124,58,237,0.2);border:1.5px solid rgba(124,58,237,0.4);color:#c4b5fd;border-radius:10px;text-decoration:none;font-weight:700;font-size:13px;margin-bottom:20px;transition:all 0.2s;}
.back-btn:hover{background:rgba(124,58,237,0.35);}
.pdf-btn{display:inline-flex;align-items:center;gap:6px;padding:8px 18px;background:rgba(34,197,94,0.2);border:1.5px solid rgba(34,197,94,0.4);color:#86efac;border-radius:10px;cursor:pointer;font-weight:700;font-size:13px;margin-bottom:20px;margin-left:10px;transition:all 0.2s;font-family:inherit;}
.pdf-btn:hover{background:rgba(34,197,94,0.35);}
.footer{text-align:center;padding:24px 0;margin-top:16px;border-top:2px solid rgba(124,58,237,0.2);font-size:11px;color:#64748b;}
/* Line-by-line analysis styles */
.analysis-file{background:rgba(15,23,42,0.9);border:1.5px solid rgba(124,58,237,0.25);border-radius:16px;margin-bottom:20px;overflow:hidden;}
.analysis-file-header{background:rgba(124,58,237,0.18);padding:14px 18px;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px;}
.analysis-file-name{font-size:14px;font-weight:800;color:#c4b5fd;font-family:monospace;}
.analysis-file-meta{font-size:11px;color:#94a3b8;}
.analysis-body{padding:0;}
.line-group{border-bottom:1px solid rgba(100,116,139,0.1);}
.line-group:last-child{border-bottom:none;}
.line-range{display:flex;align-items:flex-start;gap:0;}
.line-nums{background:rgba(124,58,237,0.08);color:#7c3aed;font-family:monospace;font-size:11px;font-weight:700;padding:10px 14px;min-width:90px;text-align:right;white-space:nowrap;flex-shrink:0;border-right:1.5px solid rgba(124,58,237,0.15);}
.line-desc{padding:10px 16px;font-size:12px;color:#cbd5e1;line-height:1.65;}
.line-desc strong{color:#e2e8f0;font-weight:700;}
.line-desc code{background:rgba(124,58,237,0.15);color:#c4b5fd;padding:1px 6px;border-radius:4px;font-family:monospace;font-size:11px;}
@media(max-width:700px){.stats-grid,.arch-grid{grid-template-columns:1fr 1fr;}.feat-grid{grid-template-columns:1fr;}.line-nums{min-width:60px;}}
@media print{
@page{margin:15mm 12mm;}
body{background:#fff!important;color:#1e293b!important;}
.stat-card,.arch-card,.feat-card,.analysis-file{border-color:#e2e8f0!important;background:#f8fafc!important;}
.stat-card .num{color:#7c3aed!important;}
.section-title{color:#1e293b!important;border-bottom-color:#7c3aed!important;}
.back-btn,.pdf-btn{display:none!important;}
.header{background:linear-gradient(135deg,rgba(124,58,237,0.08),rgba(59,130,246,0.06))!important;border-color:rgba(124,58,237,0.4)!important;}
.header h1{-webkit-text-fill-color:#4c1d95!important;background:none!important;color:#4c1d95!important;}
.header .sub,.info-table td,.file-table td,.arch-card li,.commit-msg,.line-desc{color:#374151!important;}
.analysis-file-header{background:rgba(124,58,237,0.12)!important;}
.line-nums{background:rgba(124,58,237,0.06)!important;color:#6d28d9!important;}
.flow-box{background:rgba(124,58,237,0.08)!important;color:#4c1d95!important;border-color:rgba(124,58,237,0.4)!important;}
.section{page-break-inside:avoid;}
.analysis-file{page-break-inside:avoid;}
}
</style>
</head>
<body>
<div class="container">
<a href="index.html" class="back-btn">← Back to Home</a>
<button class="pdf-btn" onclick="window.print()">📄 Download as PDF</button>
<div class="header">
<h1>📊 Feedback System — Project Report</h1>
<div class="sub">Student, Teacher & Admin Portal · Built by P Vishnuvardhan Reddy</div>
<div class="badges">
<span class="badge bg-purple">HTML / CSS / JS</span>
<span class="badge bg-blue">Firebase Firestore</span>
<span class="badge bg-green">Chart.js</span>
<span class="badge bg-amber">5,434 Lines of Code</span>
</div>
</div>
<div class="section">
<div class="section-title">📋 Project Overview</div>
<table class="info-table">
<tr><td>📦 Repository</td><td><a href="https://github.com/Vishnumgit/feedback" style="color:#a78bfa;">Vishnumgit/feedback</a></td></tr>
<tr><td>📝 Description</td><td>A multi-role feedback collection and analytics system for educational institutions with Student, Teacher, and Admin portals</td></tr>
<tr><td>👤 Author</td><td>P Vishnuvardhan Reddy (Vishnumgit)</td></tr>
<tr><td>🏫 Institution</td><td>MGIT — Mahatma Gandhi Institute of Technology</td></tr>
<tr><td>📅 Created</td><td>12 March 2026</td></tr>
<tr><td>🌐 Visibility</td><td>Public</td></tr>
<tr><td>🗃 Total Size</td><td>137 KB (15 files + 2 folders)</td></tr>
<tr><td>💻 Language</td><td>HTML, CSS, JavaScript (Vanilla — No frameworks)</td></tr>
<tr><td>🗄 Database</td><td>Firebase Firestore (Cloud) + localStorage (Offline)</td></tr>
<tr><td>📊 Charts</td><td>Chart.js 4.4.0 (Radar, Bar, Doughnut, Trend)</td></tr>
</table>
</div>
<div class="section">
<div class="section-title">📈 Project Statistics</div>
<div class="stats-grid">
<div class="stat-card"><div class="num">5,434</div><div class="lbl">Lines of Code</div></div>
<div class="stat-card"><div class="num">15</div><div class="lbl">Source Files</div></div>
<div class="stat-card"><div class="num">20</div><div class="lbl">Git Commits</div></div>
<div class="stat-card"><div class="num">3</div><div class="lbl">User Roles</div></div>
</div>
<div class="stats-grid">
<div class="stat-card"><div class="num" style="font-size:22px;color:#60a5fa;">7</div><div class="lbl">Admin Tabs</div></div>
<div class="stat-card"><div class="num" style="font-size:22px;color:#60a5fa;">6</div><div class="lbl">Teacher Views</div></div>
<div class="stat-card"><div class="num" style="font-size:22px;color:#60a5fa;">7</div><div class="lbl">Firestore Collections</div></div>
<div class="stat-card"><div class="num" style="font-size:22px;color:#60a5fa;">2</div><div class="lbl">Report Generators</div></div>
</div>
</div>
<div class="section">
<div class="section-title">🏗 System Architecture</div>
<div class="flow">
<div class="flow-box">👤 Student Portal</div><div class="flow-arrow">→</div>
<div class="flow-box">📝 Feedback Form</div><div class="flow-arrow">→</div>
<div class="flow-box">🗄 localStorage</div><div class="flow-arrow">⇔</div>
<div class="flow-box">🔥 Firebase Firestore</div>
</div>
<div class="flow">
<div class="flow-box">👨‍🏫 Teacher Dashboard</div><div class="flow-arrow">←</div>
<div class="flow-box">📊 Analytics Engine</div><div class="flow-arrow">←</div>
<div class="flow-box">🗄 data.js</div><div class="flow-arrow">→</div>
<div class="flow-box">📄 HTML Report</div>
</div>
<div class="flow">
<div class="flow-box">🔑 Admin Panel</div><div class="flow-arrow">→</div>
<div class="flow-box">👥 User Mgmt</div><div class="flow-arrow">+</div>
<div class="flow-box">📋 Assignments</div><div class="flow-arrow">+</div>
<div class="flow-box">📊 Reports</div>
</div>
<div class="arch-grid" style="margin-top:18px;">
<div class="arch-card"><h4>🖥 Frontend</h4><ul><li>Vanilla HTML/CSS/JS</li><li>Dark theme UI (CSS vars)</li><li>Chart.js 4.4.0</li><li>Responsive sidebar layout</li><li>SVG inline charts for reports</li><li>Inter font (Google Fonts)</li></ul></div>
<div class="arch-card"><h4>🗄 Data Layer</h4><ul><li>localStorage primary store</li><li>Firebase Firestore cloud sync</li><li>Background non-blocking sync</li><li>Auto-seed on first visit</li><li>Offline-first architecture</li><li>7 data collections</li></ul></div>
<div class="arch-card"><h4>🔒 Auth System</h4><ul><li>Role-based (Admin/Teacher/Student)</li><li>Session via localStorage</li><li>Login page per role</li><li>Protected dashboard routes</li><li>Email domain validation</li><li>Password-based login</li></ul></div>
</div>
</div>
<div class="section">
<div class="section-title">🔥 Firebase Firestore Schema</div>
<table class="file-table"><thead><tr><th>Collection</th><th>localStorage Key</th><th>Purpose</th></tr></thead><tbody>
<tr><td class="file-name">users</td><td>sfft_users</td><td>All student, teacher, admin accounts</td></tr>
<tr><td class="file-name">subjects</td><td>sfft_subjects</td><td>Academic subjects (Math, Physics, etc.)</td></tr>
<tr><td class="file-name">questionnaires</td><td>sfft_questionnaires</td><td>Subject-specific feedback question sets</td></tr>
<tr><td class="file-name">enrollments</td><td>sfft_enrollments</td><td>Student-teacher assignment mappings</td></tr>
<tr><td class="file-name">responses</td><td>sfft_responses</td><td>Submitted feedback with scores & comments</td></tr>
<tr><td class="file-name">attendance</td><td>sfft_attendance</td><td>Student attendance records per section</td></tr>
<tr><td class="file-name">settings</td><td>sfft_settings</td><td>College name, domain, min threshold</td></tr>
</tbody></table>
</div>
<div class="section">
<div class="section-title">📁 File Structure</div>
<table class="file-table"><thead><tr><th>File</th><th>Lines</th><th>Size</th><th>Purpose</th></tr></thead><tbody>
<tr><td class="file-name">admin-dashboard.html</td><td>1,968</td><td>104 KB</td><td>Full admin panel (7 tabs, reports, user mgmt)</td></tr>
<tr><td class="file-name">teacher-dashboard.html</td><td>877</td><td>49 KB</td><td>Teacher portal (analytics, charts, report gen)</td></tr>
<tr><td class="file-name">student-dashboard.html</td><td>489</td><td>25 KB</td><td>Student portal (profile, feedback status)</td></tr>
<tr><td class="file-name">feedback-form.html</td><td>261</td><td>12 KB</td><td>Feedback submission form</td></tr>
<tr><td class="file-name">style.css</td><td>523</td><td>24 KB</td><td>Global dark theme styles</td></tr>
<tr><td class="file-name">data.js</td><td>309</td><td>17 KB</td><td>localStorage data layer (CRUD, analytics)</td></tr>
<tr><td class="file-name">firebase-sync.js</td><td>237</td><td>10 KB</td><td>Firestore background sync</td></tr>
<tr><td class="file-name">charts.js</td><td>125</td><td>4 KB</td><td>Chart.js rendering helpers</td></tr>
<tr><td class="file-name">auth.js</td><td>76</td><td>3 KB</td><td>Authentication & session management</td></tr>
<tr><td class="file-name">firebase-config.js</td><td>18</td><td>646 B</td><td>Firebase initialization</td></tr>
<tr><td class="file-name">fix_emojis.js</td><td>99</td><td>3 KB</td><td>Emoji compatibility fixes</td></tr>
<tr><td class="file-name">index.html</td><td>63</td><td>3 KB</td><td>Landing page / role selection</td></tr>
<tr><td class="file-name">admin-login.html</td><td>127</td><td>6 KB</td><td>Admin login page</td></tr>
<tr><td class="file-name">teacher-login.html</td><td>125</td><td>6 KB</td><td>Teacher login page</td></tr>
<tr><td class="file-name">student-login.html</td><td>137</td><td>6 KB</td><td>Student login page</td></tr>
</tbody></table>
</div>
<div class="section">
<div class="section-title">🚀 Features by Portal</div>
<h3 style="color:#c4b5fd;font-size:14px;margin:16px 0 10px;">🔑 Admin Panel (7 Tabs)</h3>
<div class="feat-grid">
<div class="feat-card"><h4>👥 User Management</h4><p>Create, edit, delete students/teachers. Bulk CSV import. Select All + Delete Selected with Firestore sync.</p><span class="feat-tag bg-green">CRUD</span><span class="feat-tag bg-blue">Bulk Import</span></div>
<div class="feat-card"><h4>📚 Subjects & Questionnaires</h4><p>Add/remove subjects. Build multi-section feedback questionnaires per subject.</p><span class="feat-tag bg-green">Dynamic Forms</span><span class="feat-tag bg-blue">Multi-Section</span></div>
<div class="feat-card"><h4>👥 Teacher Assignment</h4><p>Assign students to teachers with visual checklist cards. Roll No display. Section grouping.</p><span class="feat-tag bg-green">Visual Cards</span><span class="feat-tag bg-amber">Roll No</span></div>
<div class="feat-card"><h4>💬 Feedback Oversight</h4><p>View all submissions with filters. Select All checkbox. Delete Selected + Clear All with Firestore sync.</p><span class="feat-tag bg-green">Filters</span><span class="feat-tag bg-purple">Firestore Delete</span></div>
<div class="feat-card"><h4>📊 Reports & Analytics</h4><p>Institution-wide charts. Per-teacher breakdown. Downloadable HTML report with SVG charts.</p><span class="feat-tag bg-green">Charts</span><span class="feat-tag bg-blue">Download Report</span></div>
<div class="feat-card"><h4>📋 Attendance + ⚙ Settings</h4><p>Upload CSV attendance. 75% threshold gate. College name, domain, min threshold config.</p><span class="feat-tag bg-green">CSV Upload</span><span class="feat-tag bg-blue">Config</span></div>
</div>
<h3 style="color:#c4b5fd;font-size:14px;margin:20px 0 10px;">👨‍🏫 Teacher Dashboard</h3>
<div class="feat-grid">
<div class="feat-card"><h4>📊 Performance Overview</h4><p>Score cards, radar chart, bar chart, trend line. Status banner. Category breakdown.</p></div>
<div class="feat-card"><h4>📄 Report Generator</h4><p>Beautiful HTML report with SVG charts, summary cards, data table, comments. Print/PDF.</p></div>
</div>
<h3 style="color:#c4b5fd;font-size:14px;margin:20px 0 10px;">🎓 Student Portal</h3>
<div class="feat-grid">
<div class="feat-card"><h4>📝 Feedback Submission</h4><p>Multi-section questionnaire with 1-5 star ratings. Anonymous option. Attendance-gated.</p></div>
<div class="feat-card"><h4>👤 Student Dashboard</h4><p>Profile with Roll No. Assigned teachers list. Submission status per teacher.</p></div>
</div>
</div>
<div class="section">
<div class="section-title">🔧 Development History</div>
<div class="commit-list">
<div class="commit"><div class="commit-dot"></div><div><span class="commit-msg">Show Roll No in student dashboard profile</span><span class="commit-type ct-feat">FEAT</span></div></div>
<div class="commit"><div class="commit-dot"></div><div><span class="commit-msg">Add Roll No to user modal + Delete Selected users</span><span class="commit-type ct-feat">FEAT</span></div></div>
<div class="commit"><div class="commit-dot"></div><div><span class="commit-msg">Normalize CSV column names for bulk import</span><span class="commit-type ct-fix">FIX</span></div></div>
<div class="commit"><div class="commit-dot"></div><div><span class="commit-msg">Unique user IDs to prevent overwrites</span><span class="commit-type ct-fix">FIX</span></div></div>
<div class="commit"><div class="commit-dot"></div><div><span class="commit-msg">Batch insert for bulk import — single write</span><span class="commit-type ct-fix">FIX</span></div></div>
<div class="commit"><div class="commit-dot"></div><div><span class="commit-msg">Batch delete users + clean all related Firestore data</span><span class="commit-type ct-fix">FIX</span></div></div>
<div class="commit"><div class="commit-dot"></div><div><span class="commit-msg">Enhanced CSV export with section scores & summary row</span><span class="commit-type ct-feat">FEAT</span></div></div>
<div class="commit"><div class="commit-dot"></div><div><span class="commit-msg">Clear All Enrollments + Clear All Attendance buttons</span><span class="commit-type ct-feat">FEAT</span></div></div>
<div class="commit"><div class="commit-dot"></div><div><span class="commit-msg">Feedback clear buttons + checkboxes + Firestore sync</span><span class="commit-type ct-feat">FEAT</span></div></div>
<div class="commit"><div class="commit-dot"></div><div><span class="commit-msg">Rich HTML reports with SVG charts (Teacher + Admin)</span><span class="commit-type ct-feat">FEAT</span></div></div>
<div class="commit"><div class="commit-dot"></div><div><span class="commit-msg">Roll No in Teacher Assignment student cards</span><span class="commit-type ct-feat">FEAT</span></div></div>
</div>
</div>
<div class="section">
<div class="section-title">🛠 Technology Stack</div>
<div class="arch-grid">
<div class="arch-card"><h4>Frontend</h4><ul><li>HTML5 (Semantic)</li><li>CSS3 (Custom Properties)</li><li>Vanilla JavaScript (ES6+)</li><li>Chart.js 4.4.0</li><li>SVG (Inline Charts)</li><li>Google Fonts (Inter)</li></ul></div>
<div class="arch-card"><h4>Backend / Database</h4><ul><li>Firebase Firestore (NoSQL)</li><li>Firebase Compat SDK</li><li>localStorage (Offline)</li><li>Background Sync Pattern</li><li>Batch Write Operations</li><li>Auto-seed on First Run</li></ul></div>
<div class="arch-card"><h4>DevOps / Tools</h4><ul><li>GitHub (Version Control)</li><li>CodeWords (AI Automation)</li><li>Pipedream (GitHub API)</li><li>20 Commits in 1 Day</li><li>Zero-framework approach</li><li>No build step needed</li></ul></div>
</div>
</div>
<div class="section">
<div class="section-title">🔍 Detailed File Analysis — Line by Line</div>
<!-- data.js -->
<div class="analysis-file">
<div class="analysis-file-header">
<span class="analysis-file-name">js/data.js</span>
<span class="analysis-file-meta">309 lines · 17 KB · localStorage Data Layer</span>
</div>
<div class="analysis-body">
<div class="line-group"><div class="line-range"><div class="line-nums">1–13</div><div class="line-desc"><strong>DB key constants</strong> — Defines the <code>DB</code> object mapping 7 collection names (<code>USERS</code>, <code>SUBJECTS</code>, <code>QUESTIONNAIRES</code>, <code>ENROLLMENTS</code>, <code>RESPONSES</code>, <code>ATTENDANCE</code>, <code>SETTINGS</code>) to their <code>sfft_*</code> localStorage keys. Centralises all key strings to prevent typos across the codebase.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">15–21</div><div class="line-desc"><strong>CRUD helpers</strong> — Four tiny arrow functions: <code>get()</code>/<code>set()</code> parse/stringify JSON arrays, <code>getObj()</code>/<code>setObj()</code> do the same for plain objects. Used by every higher-level function to read/write localStorage.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">24–82</div><div class="line-desc"><strong>Password hashing (<code>hashPassword</code>)</strong> — Async function. Tries <code>crypto.subtle.digest('SHA-256')</code> (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.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">85–187</div><div class="line-desc"><strong>Database initialisation (<code>initDB</code>)</strong> — Runs once per device (guarded by <code>sfft_initialized</code> 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.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">188–199</div><div class="line-desc"><strong>Settings CRUD</strong> — <code>getSettings()</code> returns the settings object; <code>saveSettings(s)</code> persists it. Used by admin panel to store/read college name, email domain and min threshold.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">200–240</div><div class="line-desc"><strong>User CRUD</strong> — <code>getUsers()</code>, <code>getUserByEmail()</code> (case-insensitive), <code>getUserById()</code>. <code>saveUser(u)</code> upserts by id. <code>deleteUser(id)</code> removes a user and cascades deletion of their enrollments and responses. <code>getTeachers()</code>/<code>getStudents()</code> are role-filtered views.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">241–260</div><div class="line-desc"><strong>Enrollment functions</strong> — <code>getEnrollments()</code> returns all enrollment records. <code>getTeachersForStudent(studentId)</code> returns teacher objects augmented with <code>_enrolledSubjectId</code> — one entry per teacher-subject pair. <code>getStudentsForTeacher(teacherId)</code> returns matching student objects.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">261–310</div><div class="line-desc"><strong>Feedback response functions</strong> — <code>hasSubmitted(studentId, teacherId, subjectId)</code> checks if feedback already exists for the specific teacher+subject pair. <code>saveResponse(r)</code> inserts a response only if no duplicate exists. <code>getResponsesForTeacher(teacherId)</code> returns all responses for a teacher. <code>getTeacherStats(teacherId)</code> computes overall average, per-section averages, rating distribution histogram, trend data and comment list from the stored responses.</div></div></div>
</div>
</div>
<!-- auth.js -->
<div class="analysis-file">
<div class="analysis-file-header">
<span class="analysis-file-name">js/auth.js</span>
<span class="analysis-file-meta">320 lines · 3 KB · Authentication & Session Management</span>
</div>
<div class="analysis-body">
<div class="line-group"><div class="line-range"><div class="line-nums">1–13</div><div class="line-desc"><strong>Session key + token generator</strong> — <code>SESSION_KEY</code> constant for sessionStorage. <code>generateSessionToken()</code> creates a random token (timestamp base-36 + random suffix) to detect concurrent logins.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">15–47</div><div class="line-desc"><strong>Firestore user fetch fallback (<code>fetchUserFromFirestore</code>)</strong> — When a user logs in on a new device and their data isn't in localStorage yet, this async function queries the Firestore <code>users</code> collection by email and merges the result into localStorage. Handles case-sensitivity differences in stored emails.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">49–130</div><div class="line-desc"><strong>Email/password login (<code>login</code>)</strong> — Resolves the local user, then calls Firebase <code>auth.signInWithEmailAndPassword</code>. If the Firebase account doesn't exist yet (first login after admin setup), it auto-creates a Firebase Auth account using the supplied password (<em>auto-migration</em>). 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.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">132–186</div><div class="line-desc"><strong>Google Sign-In (<code>googleLogin</code>, <code>googleLoginWithPopup</code>)</strong> — <code>googleLogin</code> decodes the Google JWT, looks up the user by email, signs in with Firebase <code>signInWithCredential</code>, and creates a session. <code>googleLoginWithPopup</code> wraps Google Identity Services (GIS) one-tap prompt with a rendered fallback button if the prompt is suppressed.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">216–246</div><div class="line-desc"><strong>Session concurrency listener (<code>startSessionListener</code>)</strong> — 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.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">248–270</div><div class="line-desc"><strong>Logout & auth guards</strong> — <code>logout()</code> clears sessionStorage and Firebase Auth state. <code>getSession()</code> reads the current session. <code>requireAuth(expectedRole)</code> redirects to home if no session or role mismatch — called at the top of every dashboard.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">271–320</div><div class="line-desc"><strong>Password management</strong> — <code>changePassword()</code> verifies the current password (hashed), updates Firebase Auth password, rehashes and saves the new password in localStorage and Firestore. <code>adminResetPassword()</code> skips the current-password check (admin only). <code>validateCollegeEmail()</code> checks that the email domain matches the configured college domain.</div></div></div>
</div>
</div>
<!-- firebase-sync.js -->
<div class="analysis-file">
<div class="analysis-file-header">
<span class="analysis-file-name">js/firebase-sync.js</span>
<span class="analysis-file-meta">237 lines · 10 KB · Firestore Background Sync</span>
</div>
<div class="analysis-body">
<div class="line-group"><div class="line-range"><div class="line-nums">1–27</div><div class="line-desc"><strong>Firestore write helpers</strong> — <code>fsSetDoc(collection, docId, data)</code> strips <code>password</code> and <code>passwordHash</code> fields before writing (security). For the <code>users</code> collection it prefers the Firebase UID as the document key. <code>fsDeleteDoc(collection, docId)</code> deletes a Firestore document; both functions catch errors and log console warnings without propagating them, so the UI is never blocked by sync failures.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">29–60</div><div class="line-desc"><strong>Merge helpers</strong> — <code>mergeById(arr, item)</code> upserts an item into an array matching on <code>id</code> or <code>email</code> (fallback). <code>mergeByField(arr, item, field)</code> does the same for arbitrary fields (used for enrollments and attendance). Prevents duplicates when Firestore snapshots arrive out of order.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">62–120</div><div class="line-desc"><strong>Role-based pull sync</strong> — <code>syncFromFirestore(role, userId)</code> 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.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">121–180</div><div class="line-desc"><strong>Push sync (localStorage → Firestore)</strong> — <code>pushToFirestore()</code> 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.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">181–237</div><div class="line-desc"><strong>Real-time listener setup</strong> — <code>setupRealtimeSync(role, userId)</code> attaches Firestore <code>onSnapshot</code> 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.</div></div></div>
</div>
</div>
<!-- charts.js -->
<div class="analysis-file">
<div class="analysis-file-header">
<span class="analysis-file-name">js/charts.js</span>
<span class="analysis-file-meta">125 lines · 4 KB · Chart.js Rendering Helpers</span>
</div>
<div class="analysis-body">
<div class="line-group"><div class="line-range"><div class="line-nums">1–9</div><div class="line-desc"><strong>Instance registry</strong> — <code>chartInstances</code> object tracks live Chart.js instances by canvas ID. <code>destroyChart(id)</code> destroys an existing chart before re-rendering to prevent memory leaks and duplicate canvas contexts.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">11–38</div><div class="line-desc"><strong><code>renderRadar(canvasId, teacherId)</code></strong> — Calls <code>getTeacherStats()</code> from <code>data.js</code>, extracts section labels and averages, and renders a purple radar chart showing performance across teaching categories (e.g., Teaching Methodology, Communication Skills, etc.).</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">40–65</div><div class="line-desc"><strong><code>renderBar(canvasId, teacherId)</code></strong> — 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.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">67–96</div><div class="line-desc"><strong><code>renderTrend(canvasId, teacherId)</code></strong> — Renders a filled line (area) chart of average score over time (each submission as a data point). Uses the <code>trendData</code> array from <code>getTeacherStats()</code> to show performance evolution.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">98–125</div><div class="line-desc"><strong><code>renderInstitutionBar(canvasId)</code></strong> — Admin-only chart. Calls <code>getInstitutionStats()</code> (returns per-teacher averages) and renders a bar chart comparing all teachers side-by-side. Cycles through 6 purple shades for visual variety.</div></div></div>
</div>
</div>
<!-- feedback-form.html -->
<div class="analysis-file">
<div class="analysis-file-header">
<span class="analysis-file-name">feedback-form.html</span>
<span class="analysis-file-meta">261 lines · 12 KB · Student Feedback Submission</span>
</div>
<div class="analysis-body">
<div class="line-group"><div class="line-range"><div class="line-nums">1–30</div><div class="line-desc"><strong>Head & dependencies</strong> — Loads <code>style.css</code>, Firebase SDK, <code>data.js</code>, <code>auth.js</code> and <code>firebase-sync.js</code>. All scripts deferred so the form HTML is parsed first.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">31–80</div><div class="line-desc"><strong>Attendance gate</strong> — On page load, calls <code>requireAuth('student')</code>, then reads the teacher and subject IDs from URL params. Fetches the student's attendance record and compares it against <code>ATTENDANCE_THRESHOLD</code> (75%). If below threshold, replaces the form with a locked message showing the student's actual percentage.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">81–140</div><div class="line-desc"><strong>Already-submitted guard</strong> — Calls <code>hasSubmitted(studentId, teacherId, subjectId)</code>. If true, shows a "Feedback already submitted" banner and hides the form. Prevents duplicate responses for the same teacher-subject pair.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">141–200</div><div class="line-desc"><strong>Dynamic form builder</strong> — Reads the questionnaire for the selected subject from <code>data.js</code>. For each section, generates a card with the section title and a 1–5 star rating input (<code>radio</code> buttons styled as stars) for each question. All sections are rendered dynamically — no hardcoded questions in HTML.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">201–261</div><div class="line-desc"><strong>Submission handler</strong> — Collects all star-rating values, validates that every question has been answered, builds a response object (<code>{ studentId, teacherId, subjectId, scores, comment, anonymous, timestamp }</code>), calls <code>saveResponse()</code> and <code>fsSetDoc()</code> to persist locally and to Firestore. Redirects back to the student dashboard on success.</div></div></div>
</div>
</div>
<!-- student-dashboard.html -->
<div class="analysis-file">
<div class="analysis-file-header">
<span class="analysis-file-name">student-dashboard.html</span>
<span class="analysis-file-meta">489 lines · 25 KB · Student Portal</span>
</div>
<div class="analysis-body">
<div class="line-group"><div class="line-range"><div class="line-nums">1–40</div><div class="line-desc"><strong>Head / sidebar setup</strong> — Standard dashboard shell: loads <code>style.css</code>, Firebase, data/auth/sync scripts, and renders a sidebar with the student's name and role badge.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">41–120</div><div class="line-desc"><strong>Profile tab</strong> — 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).</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">121–250</div><div class="line-desc"><strong>Feedback status tab</strong> — Iterates over each teacher-subject pair returned by <code>getTeachersForStudent()</code>. For each pair, checks <code>hasSubmitted()</code> and renders a green "Submitted ✓" badge or a "Give Feedback" button. The button navigates to <code>feedback-form.html</code> with the teacher and subject IDs as URL query parameters.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">251–400</div><div class="line-desc"><strong>Notifications tab</strong> — 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.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">401–489</div><div class="line-desc"><strong>Init logic</strong> — <code>requireAuth('student')</code> 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.</div></div></div>
</div>
</div>
<!-- teacher-dashboard.html -->
<div class="analysis-file">
<div class="analysis-file-header">
<span class="analysis-file-name">teacher-dashboard.html</span>
<span class="analysis-file-meta">877 lines · 49 KB · Teacher Analytics Portal</span>
</div>
<div class="analysis-body">
<div class="line-group"><div class="line-range"><div class="line-nums">1–50</div><div class="line-desc"><strong>Head + Chart.js</strong> — Loads Chart.js 4.4.0 CDN, <code>style.css</code>, <code>data.js</code>, <code>charts.js</code>, <code>auth.js</code>, <code>firebase-sync.js</code>. Script load order matters: <code>data.js</code> must come before <code>charts.js</code> since charts call <code>getTeacherStats()</code>.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">51–180</div><div class="line-desc"><strong>Overview tab</strong> — 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 <code>charts.js</code> helpers. A status banner shows green/amber/red based on the score relative to the minimum threshold from settings.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">181–350</div><div class="line-desc"><strong>Category breakdown tab</strong> — 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.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">351–550</div><div class="line-desc"><strong>Student responses tab</strong> — 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.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">551–750</div><div class="line-desc"><strong>Report generator</strong> — The <code>generateReport()</code> 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 <code>window.open()</code> (note: may be blocked by the browser's popup blocker — users should allow popups for the site). The report uses <code>@media print</code> so it can be saved as PDF from the browser print dialog.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">751–877</div><div class="line-desc"><strong>Init & change password</strong> — <code>requireAuth('teacher')</code> guard, then <code>syncFromFirestore('teacher')</code>. Renders all tabs. Change-password modal POSTs to <code>changePassword()</code> in <code>auth.js</code>. Logout clears the session and redirects to <code>index.html</code>.</div></div></div>
</div>
</div>
<!-- admin-dashboard.html -->
<div class="analysis-file">
<div class="analysis-file-header">
<span class="analysis-file-name">admin-dashboard.html</span>
<span class="analysis-file-meta">1,968 lines · 104 KB · Full Admin Panel (7 Tabs)</span>
</div>
<div class="analysis-body">
<div class="line-group"><div class="line-range"><div class="line-nums">1–60</div><div class="line-desc"><strong>Head + dependencies</strong> — 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.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">61–250</div><div class="line-desc"><strong>Dashboard tab</strong> — Institution-wide stats (total users, teachers, students, responses). Renders the institution-wide bar chart (<code>renderInstitutionBar()</code>). Shows per-teacher summary cards with average score, response count and a colour-coded performance badge.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">251–500</div><div class="line-desc"><strong>User Management tab</strong> — 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 <code>fsSetDoc</code>/<code>fsDeleteDoc</code>. Table sorted by roll number for students.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">501–750</div><div class="line-desc"><strong>Subjects & Questionnaires tab</strong> — Add/delete subjects. For each subject, a questionnaire editor: add sections, add questions per section, reorder or delete questions. Changes saved to <code>sfft_questionnaires</code> localStorage key and synced to Firestore.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">751–1000</div><div class="line-desc"><strong>Teacher Assignment tab</strong> — 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.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">1001–1250</div><div class="line-desc"><strong>Feedback Oversight tab</strong> — 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.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">1251–1500</div><div class="line-desc"><strong>Reports & Analytics tab</strong> — 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.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">1501–1700</div><div class="line-desc"><strong>Attendance tab</strong> — CSV upload to bulk-import attendance records (columns: email/rollNo, percentage). Validates that each row has a numeric percentage. Stores records in <code>sfft_attendance</code>. "Clear All Attendance" button with Firestore sync. Used by the feedback form's attendance gate.</div></div></div>
<div class="line-group"><div class="line-range"><div class="line-nums">1701–1968</div><div class="line-desc"><strong>Settings tab & init</strong> — Editable fields: college name, email domain, minimum score threshold. Saved to <code>sfft_settings</code> and Firestore. The init block at the bottom runs <code>requireAuth('admin')</code>, <code>syncFromFirestore('admin')</code>, seeds demo data via <code>initDB()</code>, and renders the default tab. Also registers the service worker for push notifications.</div></div></div>
</div>
</div>
<!-- firebase-config.js -->
<div class="analysis-file">
<div class="analysis-file-header">
<span class="analysis-file-name">js/firebase-config.js</span>
<span class="analysis-file-meta">18 lines · 646 B · Firebase Initialisation</span>
</div>
<div class="analysis-body">
<div class="line-group"><div class="line-range"><div class="line-nums">1–18</div><div class="line-desc"><strong>Firebase app init</strong> — Contains the Firebase project config object (apiKey, authDomain, projectId, storageBucket, messagingSenderId, appId). Calls <code>firebase.initializeApp(firebaseConfig)</code> and exports <code>db = firebase.firestore()</code> and <code>auth = firebase.auth()</code> as global variables used by all other scripts. Uses the Firebase Compat SDK (v8 API) to avoid ES module bundling requirements.</div></div></div>
</div>
</div>
</div>
<div class="footer">
<div style="font-weight:600;color:#94a3b8;">📊 Feedback System Project Report</div>
</div>
</div>
</body>
</html>