Skip to content

Commit 6a15520

Browse files
author
Archith
committed
Add visible activity dashboard for interviewers
- Add floating activity indicator in bottom-left corner for interviewers - Activity monitor now works in two modes: - Tracking mode for candidates (records activity) - Observer mode for interviewers (displays activity) - Interviewers see real-time activity updates via Firebase - Floating indicator shows: - Activity score with color coding - Tab switch count - Idle periods - Suspicious pattern warnings - Session duration - Dashboard updates every 30 seconds automatically The floating indicator is always visible for interviewers, no need to open notes panel.
1 parent a13947e commit 6a15520

File tree

2 files changed

+121
-21
lines changed

2 files changed

+121
-21
lines changed

scripts/activity-monitor.js

Lines changed: 111 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,57 @@
2020

2121
// Initialize monitoring
2222
window.initActivityMonitor = function(session, user, type) {
23-
// Only monitor candidates
24-
if (type === 'interviewer') {
25-
console.log('Activity monitoring skipped for interviewer');
26-
return;
27-
}
28-
29-
monitoring = true;
3023
sessionCode = session;
3124
userId = user;
3225
userType = type;
33-
metrics.sessionStart = Date.now();
3426

35-
console.log('Activity monitoring started for:', user);
36-
37-
// Start monitoring
38-
setupVisibilityTracking();
39-
setupIdleDetection();
40-
setupActivityTracking();
41-
reportMetricsPeriodically();
27+
// For candidates, track their activity
28+
if (type === 'candidate') {
29+
monitoring = true;
30+
metrics.sessionStart = Date.now();
31+
console.log('Activity monitoring started for candidate:', user);
32+
33+
// Start monitoring
34+
setupVisibilityTracking();
35+
setupIdleDetection();
36+
setupActivityTracking();
37+
reportMetricsPeriodically();
38+
}
39+
// For interviewers, just listen to activity updates from Firebase
40+
else if (type === 'interviewer') {
41+
console.log('Activity monitoring in observer mode for interviewer');
42+
listenToActivityUpdates();
43+
}
4244
};
4345

46+
// Listen to activity updates from Firebase (for interviewers)
47+
function listenToActivityUpdates() {
48+
if (!window.firebase || !sessionCode) return;
49+
50+
// Listen to activity summary updates
51+
firebase.database()
52+
.ref(`sessions/${sessionCode}/activity_summary`)
53+
.on('value', function(snapshot) {
54+
const summary = snapshot.val();
55+
if (summary && window.updateActivityDashboard) {
56+
window.updateActivityDashboard(summary);
57+
}
58+
});
59+
60+
// Listen to alerts
61+
firebase.database()
62+
.ref(`sessions/${sessionCode}/activity_log`)
63+
.orderByChild('timestamp')
64+
.limitToLast(10)
65+
.on('child_added', function(snapshot) {
66+
const event = snapshot.val();
67+
if (event && event.type === 'alert_triggered') {
68+
console.log('Activity alert:', event.message);
69+
// Could show a toast notification here
70+
}
71+
});
72+
}
73+
4474
// 1. VISIBILITY API - This actually works!
4575
function setupVisibilityTracking() {
4676
let hiddenTime = null;
@@ -347,11 +377,11 @@
347377

348378
// 10. Update interviewer UI
349379
window.updateActivityDashboard = function(summary) {
380+
// Update the dashboard in notes panel
350381
const dashboard = document.getElementById('activity-dashboard');
351-
if (!dashboard) return;
352-
353-
dashboard.style.display = 'block';
354-
dashboard.innerHTML = `
382+
if (dashboard) {
383+
dashboard.style.display = 'block';
384+
dashboard.innerHTML = `
355385
<div class="activity-summary">
356386
<h4>Candidate Activity Monitor</h4>
357387
<div class="activity-metrics">
@@ -379,7 +409,69 @@
379409
` : ''}
380410
</div>
381411
`;
412+
}
413+
414+
// Also create/update a floating indicator for interviewers
415+
createFloatingIndicator(summary);
382416
};
383417

418+
// Create a floating activity indicator that's always visible
419+
function createFloatingIndicator(summary) {
420+
// Only show for interviewers
421+
const user = window.Auth && window.Auth.getCurrentUser();
422+
if (!user || !user.isAdmin) return;
423+
424+
let indicator = document.getElementById('floating-activity-indicator');
425+
if (!indicator) {
426+
// Create the floating indicator
427+
indicator = document.createElement('div');
428+
indicator.id = 'floating-activity-indicator';
429+
indicator.style.cssText = `
430+
position: fixed;
431+
bottom: 20px;
432+
left: 20px;
433+
background: rgba(30, 30, 30, 0.95);
434+
border: 1px solid rgba(66, 165, 245, 0.3);
435+
border-radius: 8px;
436+
padding: 12px;
437+
min-width: 200px;
438+
z-index: 1000;
439+
font-family: monospace;
440+
font-size: 12px;
441+
color: #fff;
442+
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
443+
`;
444+
document.body.appendChild(indicator);
445+
}
446+
447+
// Color based on activity score
448+
const scoreColor = summary.activityScore > 80 ? '#4caf50' :
449+
summary.activityScore > 60 ? '#ff9800' : '#ff4444';
450+
451+
indicator.innerHTML = `
452+
<div style="font-weight: bold; margin-bottom: 8px; color: #42a5f5;">
453+
📊 Candidate Activity
454+
</div>
455+
<div style="display: grid; grid-template-columns: auto auto; gap: 4px 12px; font-size: 11px;">
456+
<span style="color: #999;">Score:</span>
457+
<span style="color: ${scoreColor}; font-weight: bold;">${summary.activityScore}%</span>
458+
459+
<span style="color: #999;">Tab Switches:</span>
460+
<span style="color: ${summary.tabSwitches > 10 ? '#ff9800' : '#fff'};">${summary.tabSwitches}</span>
461+
462+
<span style="color: #999;">Idle:</span>
463+
<span>${summary.idlePeriods} periods</span>
464+
465+
${summary.suspiciousPatterns > 0 ? `
466+
<span style="color: #ff9800;">⚠️ Suspicious:</span>
467+
<span style="color: #ff9800;">${summary.suspiciousPatterns}</span>
468+
` : ''}
469+
</div>
470+
<div style="margin-top: 8px; padding-top: 8px; border-top: 1px solid rgba(255,255,255,0.1); font-size: 10px; color: #666;">
471+
Session: ${summary.sessionDurationMinutes} min
472+
</div>
473+
`;
474+
}
475+
384476
console.log('Activity Monitor module loaded - using reliable browser APIs');
385477
})();

scripts/app.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,11 @@
266266
`${interviewerName} (${currentUser.email})` :
267267
currentUser.email || 'Interviewer';
268268

269-
// No tracking for interviewers creating sessions
269+
// Initialize activity monitor in observer mode for interviewer
270+
if (window.initActivityMonitor) {
271+
console.log('Starting activity monitor in observer mode for interviewer');
272+
window.initActivityMonitor(sessionCode, adminName, 'interviewer');
273+
}
270274

271275
// Start session - DON'T set sessionStarting here, let startSession handle it
272276
startSession(adminName, sessionCode, true);
@@ -284,7 +288,11 @@
284288
`${interviewerName} (${currentUser.email})` :
285289
currentUser.email || 'Interviewer';
286290

287-
// No tracking for interviewers joining sessions
291+
// Initialize activity monitor in observer mode for interviewer
292+
if (window.initActivityMonitor) {
293+
console.log('Starting activity monitor in observer mode for interviewer');
294+
window.initActivityMonitor(sessionCode, adminName, 'interviewer');
295+
}
288296

289297
window.location.hash = sessionCode;
290298
startSession(adminName, sessionCode, false);

0 commit comments

Comments
 (0)