|
43 | 43 |
|
44 | 44 | // Enable/disable join button |
45 | 45 | function updateJoinButton() { |
| 46 | + const privacyConsent = document.getElementById('candidatePrivacyConsent'); |
46 | 47 | candidateJoinBtn.disabled = |
47 | 48 | !candidateName.value.trim() || |
48 | | - candidateSessionCode.value.length !== 6; |
| 49 | + candidateSessionCode.value.length !== 6 || |
| 50 | + !privacyConsent.checked; |
49 | 51 | } |
50 | 52 |
|
51 | 53 | candidateName.addEventListener('input', updateJoinButton); |
52 | 54 | candidateSessionCode.addEventListener('input', function() { |
53 | 55 | this.value = this.value.replace(/[^0-9]/g, '').slice(0, 6); |
54 | 56 | updateJoinButton(); |
55 | 57 | }); |
| 58 | + |
| 59 | + // Privacy consent checkbox |
| 60 | + const privacyConsent = document.getElementById('candidatePrivacyConsent'); |
| 61 | + if (privacyConsent) { |
| 62 | + privacyConsent.addEventListener('change', updateJoinButton); |
| 63 | + } |
56 | 64 |
|
57 | 65 | // Join session |
58 | 66 | candidateJoinBtn.addEventListener('click', async function() { |
|
81 | 89 | // Remove the security check message - just proceed |
82 | 90 | } |
83 | 91 |
|
84 | | - // Initialize activity monitoring for candidates |
| 92 | + // Initialize activity monitoring for candidates (with consent) |
85 | 93 | if (window.initActivityMonitor) { |
86 | 94 | console.log('Starting activity monitoring for candidate:', name); |
87 | 95 | window.initActivityMonitor(sessionCode, name, 'candidate'); |
| 96 | + |
| 97 | + // Log consent status |
| 98 | + if (window.firebase) { |
| 99 | + firebase.database() |
| 100 | + .ref(`sessions/${sessionCode}/privacy_consent/${name}`) |
| 101 | + .set({ |
| 102 | + consented: true, |
| 103 | + timestamp: Date.now(), |
| 104 | + consentedTo: 'Activity monitoring during interview session' |
| 105 | + }); |
| 106 | + } |
88 | 107 | } |
89 | 108 |
|
90 | 109 | Auth.joinAsCandidate(name); |
|
1135 | 1154 | }); |
1136 | 1155 | } |
1137 | 1156 |
|
| 1157 | + // Display activity tab data |
| 1158 | + function displayActivityTab(sessionCode) { |
| 1159 | + const container = document.getElementById('activity-tracking-data'); |
| 1160 | + if (!container) return; |
| 1161 | + |
| 1162 | + // Start loading |
| 1163 | + container.innerHTML = '<p class="loading-message">Loading activity data...</p>'; |
| 1164 | + |
| 1165 | + // Get activity data from Firebase |
| 1166 | + if (window.firebase) { |
| 1167 | + // Try to get final summary first, then regular summary |
| 1168 | + firebase.database() |
| 1169 | + .ref(`sessions/${sessionCode}/activity_final_summary`) |
| 1170 | + .once('value') |
| 1171 | + .then(snapshot => { |
| 1172 | + let activityData = snapshot.val(); |
| 1173 | + |
| 1174 | + // If no final summary, try regular summary |
| 1175 | + if (!activityData) { |
| 1176 | + return firebase.database() |
| 1177 | + .ref(`sessions/${sessionCode}/activity_summary`) |
| 1178 | + .once('value'); |
| 1179 | + } |
| 1180 | + return snapshot; |
| 1181 | + }) |
| 1182 | + .then(snapshot => { |
| 1183 | + const activityData = snapshot.val(); |
| 1184 | + |
| 1185 | + if (!activityData) { |
| 1186 | + container.innerHTML = ` |
| 1187 | + <div style="padding: 20px; text-align: center; color: #666;"> |
| 1188 | + <p>No activity data available for this session.</p> |
| 1189 | + <p style="font-size: 12px; margin-top: 10px;">Activity tracking may not have been enabled for this session.</p> |
| 1190 | + </div> |
| 1191 | + `; |
| 1192 | + return; |
| 1193 | + } |
| 1194 | + |
| 1195 | + // Display activity data |
| 1196 | + const scoreColor = activityData.activityScore > 80 ? '#4caf50' : |
| 1197 | + activityData.activityScore > 60 ? '#ff9800' : '#ff4444'; |
| 1198 | + |
| 1199 | + container.innerHTML = ` |
| 1200 | + <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 20px; border-radius: 8px; color: white; margin-bottom: 20px;"> |
| 1201 | + <div style="display: flex; justify-content: space-between; align-items: center;"> |
| 1202 | + <div> |
| 1203 | + <h3 style="margin: 0; font-size: 24px;">Activity Score</h3> |
| 1204 | + <div style="font-size: 48px; font-weight: bold; color: ${scoreColor}; text-shadow: 0 2px 4px rgba(0,0,0,0.2);"> |
| 1205 | + ${activityData.activityScore || 0}% |
| 1206 | + </div> |
| 1207 | + </div> |
| 1208 | + <div style="text-align: right;"> |
| 1209 | + <div style="font-size: 14px; opacity: 0.9;">Session Duration</div> |
| 1210 | + <div style="font-size: 20px; font-weight: bold;">${activityData.sessionDurationMinutes || 0} min</div> |
| 1211 | + </div> |
| 1212 | + </div> |
| 1213 | + </div> |
| 1214 | + |
| 1215 | + <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 20px;"> |
| 1216 | + <div style="background: #f8f9fa; padding: 15px; border-radius: 8px; border-left: 4px solid #42a5f5;"> |
| 1217 | + <div style="color: #666; font-size: 12px; text-transform: uppercase; margin-bottom: 5px;">Tab Switches</div> |
| 1218 | + <div style="font-size: 24px; font-weight: bold; color: ${activityData.tabSwitches > 10 ? '#ff9800' : '#333'};"> |
| 1219 | + ${activityData.tabSwitches || 0} |
| 1220 | + </div> |
| 1221 | + </div> |
| 1222 | + |
| 1223 | + <div style="background: #f8f9fa; padding: 15px; border-radius: 8px; border-left: 4px solid #66bb6a;"> |
| 1224 | + <div style="color: #666; font-size: 12px; text-transform: uppercase; margin-bottom: 5px;">Idle Periods</div> |
| 1225 | + <div style="font-size: 24px; font-weight: bold; color: #333;"> |
| 1226 | + ${activityData.idlePeriods || 0} |
| 1227 | + </div> |
| 1228 | + </div> |
| 1229 | + |
| 1230 | + <div style="background: #f8f9fa; padding: 15px; border-radius: 8px; border-left: 4px solid #ffa726;"> |
| 1231 | + <div style="color: #666; font-size: 12px; text-transform: uppercase; margin-bottom: 5px;">Total Idle Time</div> |
| 1232 | + <div style="font-size: 24px; font-weight: bold; color: #333;"> |
| 1233 | + ${activityData.totalIdleSeconds || 0}s |
| 1234 | + </div> |
| 1235 | + </div> |
| 1236 | + </div> |
| 1237 | + |
| 1238 | + ${activityData.suspiciousPatterns && activityData.suspiciousPatterns.length > 0 ? ` |
| 1239 | + <div style="background: rgba(255,152,0,0.1); border: 1px solid rgba(255,152,0,0.3); border-radius: 8px; padding: 15px; margin-top: 20px;"> |
| 1240 | + <h4 style="color: #ff9800; margin-top: 0;">⚠️ Suspicious Patterns Detected</h4> |
| 1241 | + <ul style="margin: 10px 0;"> |
| 1242 | + ${activityData.suspiciousPatterns.map(p => ` |
| 1243 | + <li style="color: #666; margin: 5px 0;"> |
| 1244 | + ${p.type.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase())} |
| 1245 | + ${p.duration ? `(${Math.round(p.duration/1000)}s)` : ''} |
| 1246 | + ${p.size ? `(${p.size} chars)` : ''} |
| 1247 | + </li> |
| 1248 | + `).join('')} |
| 1249 | + </ul> |
| 1250 | + </div> |
| 1251 | + ` : ''} |
| 1252 | + |
| 1253 | + ${activityData.finalReport ? ` |
| 1254 | + <div style="margin-top: 20px; padding: 10px; background: #e8f5e9; border-radius: 4px; text-align: center; color: #2e7d32;"> |
| 1255 | + ✅ Final activity report saved at session end |
| 1256 | + </div> |
| 1257 | + ` : ''} |
| 1258 | + `; |
| 1259 | + }) |
| 1260 | + .catch(error => { |
| 1261 | + console.error('Error loading activity data:', error); |
| 1262 | + container.innerHTML = ` |
| 1263 | + <div style="padding: 20px; text-align: center; color: #f44336;"> |
| 1264 | + <p>Error loading activity data.</p> |
| 1265 | + <p style="font-size: 12px; margin-top: 10px;">${error.message}</p> |
| 1266 | + </div> |
| 1267 | + `; |
| 1268 | + }); |
| 1269 | + } else { |
| 1270 | + container.innerHTML = '<p>Firebase not initialized</p>'; |
| 1271 | + } |
| 1272 | + } |
| 1273 | + |
1138 | 1274 | // View session details with notes |
1139 | 1275 | function viewSessionDetails(sessionCode, sessionData) { |
1140 | 1276 | console.log('viewSessionDetails called with:', sessionCode, sessionData); |
|
1337 | 1473 | const sessionCode = document.getElementById('detail-session-code').textContent; |
1338 | 1474 | window.SessionTracking.displaySecurityTab(sessionCode); |
1339 | 1475 | } |
| 1476 | + |
| 1477 | + // If activity tab, load activity data |
| 1478 | + if (tabName === 'activity') { |
| 1479 | + const sessionCode = document.getElementById('detail-session-code').textContent; |
| 1480 | + displayActivityTab(sessionCode); |
| 1481 | + } |
1340 | 1482 | } |
1341 | 1483 | }); |
1342 | 1484 | }); |
|
0 commit comments