Skip to content

Commit b926721

Browse files
committed
Fix: Org chart rendering issue
1 parent d938644 commit b926721

4 files changed

Lines changed: 180 additions & 110 deletions

File tree

dashboard/hr.html

Lines changed: 93 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,8 +1321,8 @@ <h1>Interview Management</h1>
13211321
<div class="custom-tab" data-tab="results" onclick="switchInterviewTab('results', this)">
13221322
<i class="fas fa-chart-simple me-1"></i>Results
13231323
</div>
1324-
<div class="custom-tab" data-tab="360review" onclick="switchInterviewTab('360review', this)">
1325-
<i class="fas fa-arrows-spin me-1" style="color:#7c3aed;"></i>360° Review
1324+
<div class="custom-tab" data-tab="360interview" onclick="switchInterviewTab('360interview', this)">
1325+
<i class="fas fa-street-view me-1" style="color:#0d9488;"></i>360° Interview Result
13261326
</div>
13271327
</div>
13281328

@@ -1486,30 +1486,42 @@ <h5>No Results Yet</h5>
14861486
</div>
14871487
</div>
14881488

1489-
<!-- ===== 360° REVIEW TAB ===== -->
1490-
<div id="interviewTab-360review" class="tab-content">
1489+
<!-- ===== 360° INTERVIEW RESULT TAB ===== -->
1490+
<div id="interviewTab-360interview" class="tab-content">
14911491
<div style="display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:20px;flex-wrap:wrap;gap:12px;">
14921492
<div>
14931493
<h5 style="margin:0 0 4px 0;font-weight:700;display:flex;align-items:center;gap:8px;">
1494-
<i class="fas fa-arrows-spin" style="color:#7c3aed;"></i>360° Interview Review
1494+
<i class="fas fa-street-view" style="color:#0d9488;"></i>360° Interview Results
14951495
</h5>
1496-
<p style="font-size:0.84rem;color:var(--text-secondary);margin:0;">Collect multi-perspective feedback from managers, peers, and cross-functional evaluators</p>
1496+
<p style="font-size:0.84rem;color:var(--text-secondary);margin:0;">View results from AI-proctored 360° interviews with room camera monitoring</p>
14971497
</div>
1498-
<button class="btn-primary-custom" onclick="open360ReviewModal()">
1499-
<i class="fas fa-plus"></i> New 360° Review
1500-
</button>
15011498
</div>
15021499

1503-
<!-- Active 360 Reviews -->
1504-
<div id="review360List"></div>
1505-
1506-
<div id="review360EmptyState" class="empty-state" style="display:none;">
1507-
<i class="fas fa-arrows-spin" style="color:#7c3aed;"></i>
1508-
<h5>No 360° Reviews Yet</h5>
1509-
<p>Create a 360° interview review to collect holistic feedback from multiple evaluators.</p>
1510-
<button class="btn-primary-custom mt-3" onclick="open360ReviewModal()">
1511-
<i class="fas fa-plus"></i> Create First Review
1512-
</button>
1500+
<div class="card">
1501+
<div class="card-header">
1502+
<h5><i class="fas fa-street-view me-2" style="color:#0d9488;"></i>360° Proctored Interview Results</h5>
1503+
</div>
1504+
<div class="card-body">
1505+
<div class="table-responsive">
1506+
<table class="data-table">
1507+
<thead>
1508+
<tr>
1509+
<th>Candidate</th><th>Position</th><th>Date</th>
1510+
<th>Overall Score</th><th>Trust Score</th><th>Room Camera</th><th>Violations</th><th>Status</th><th>Actions</th>
1511+
</tr>
1512+
</thead>
1513+
<tbody id="interview360ResultsBody"></tbody>
1514+
</table>
1515+
</div>
1516+
<div id="interview360EmptyState" class="empty-state" style="display:none;">
1517+
<i class="fas fa-street-view" style="color:#0d9488;"></i>
1518+
<h5>No 360° Interview Results</h5>
1519+
<p>Schedule a proctored 360° interview to see results here.</p>
1520+
<button class="btn-primary-custom mt-3" onclick="openModal('scheduleInterviewModal')">
1521+
<i class="fas fa-plus"></i> Schedule 360° Interview
1522+
</button>
1523+
</div>
1524+
</div>
15131525
</div>
15141526
</div>
15151527
</div>
@@ -2238,6 +2250,12 @@ <h5 class="modal-title"><i class="fas fa-calendar-plus me-2" style="color:var(--
22382250
<div class="mode-label">Proctored</div>
22392251
<div class="mode-desc">AI-monitored session</div>
22402252
</div>
2253+
<div class="mode-card" onclick="selectInterviewMode('proctored_360', this)" style="position:relative;">
2254+
<i class="fas fa-street-view" style="color:#0d9488;"></i>
2255+
<div class="mode-label">Proctored 360&#176;</div>
2256+
<div class="mode-desc">AI + 360&#176; room camera</div>
2257+
<span style="position:absolute;top:6px;right:6px;font-size:0.6rem;font-weight:700;color:#7c3aed;background:#ede9fe;padding:1px 6px;border-radius:8px;letter-spacing:0.3px;">OPTIONAL</span>
2258+
</div>
22412259
</div>
22422260
<input type="hidden" id="intMode" required>
22432261
</div>
@@ -2490,64 +2508,7 @@ <h5 class="modal-title" id="jobDetailTitle"><i class="fas fa-briefcase me-2" sty
24902508
</div>
24912509
</div>
24922510

2493-
<!-- ===== 360° REVIEW MODAL ===== -->
2494-
<div class="modal fade" id="review360Modal" tabindex="-1">
2495-
<div class="modal-dialog modal-lg">
2496-
<div class="modal-content">
2497-
<div class="modal-header" style="background:linear-gradient(135deg,#f5f3ff,#ede9fe);border-bottom:1.5px solid #c4b5fd;">
2498-
<h5 class="modal-title"><i class="fas fa-arrows-spin me-2" style="color:#7c3aed;"></i>New 360° Interview Review</h5>
2499-
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
2500-
</div>
2501-
<div class="modal-body">
2502-
<div class="row">
2503-
<div class="col-md-6">
2504-
<div class="form-group">
2505-
<label>Candidate Name <span style="color:var(--danger)">*</span></label>
2506-
<input type="text" class="form-control-custom" id="r360CandidateName" placeholder="Enter candidate name" required>
2507-
</div>
2508-
</div>
2509-
<div class="col-md-6">
2510-
<div class="form-group">
2511-
<label>Position <span style="color:var(--danger)">*</span></label>
2512-
<select class="form-control-custom" id="r360Position" required>
2513-
<option value="">Select Position</option>
2514-
</select>
2515-
</div>
2516-
</div>
2517-
</div>
2518-
<div class="form-group">
2519-
<label>Review Deadline</label>
2520-
<input type="date" class="form-control-custom" id="r360Deadline">
2521-
</div>
2522-
2523-
<div style="border-top:1px solid var(--border-color);margin:16px 0 12px;padding-top:14px;">
2524-
<h6 style="font-size:0.88rem;font-weight:700;margin-bottom:10px;display:flex;align-items:center;gap:8px;">
2525-
<i class="fas fa-users" style="color:#7c3aed;"></i>Evaluators
2526-
<span style="font-size:0.72rem;font-weight:400;color:var(--text-secondary);">Add at least 2 evaluators from different perspectives</span>
2527-
</h6>
2528-
<div id="r360EvaluatorsList"></div>
2529-
<button type="button" class="btn-outline-custom" style="width:100%;margin-top:8px;border-style:dashed;" onclick="add360Evaluator()">
2530-
<i class="fas fa-plus"></i> Add Evaluator
2531-
</button>
2532-
</div>
2533-
2534-
<div style="border-top:1px solid var(--border-color);margin:16px 0 12px;padding-top:14px;">
2535-
<h6 style="font-size:0.88rem;font-weight:700;margin-bottom:10px;display:flex;align-items:center;gap:8px;">
2536-
<i class="fas fa-clipboard-list" style="color:var(--primary);"></i>Competencies to Evaluate
2537-
</h6>
2538-
<div id="r360CompetenciesList" style="display:flex;flex-wrap:wrap;gap:8px;">
2539-
</div>
2540-
</div>
2541-
</div>
2542-
<div class="modal-footer">
2543-
<button type="button" class="btn-outline-custom" data-bs-dismiss="modal">Cancel</button>
2544-
<button type="button" class="btn-primary-custom" onclick="create360Review()" style="background:#7c3aed;border-color:#7c3aed;">
2545-
<i class="fas fa-arrows-spin"></i> Create 360° Review
2546-
</button>
2547-
</div>
2548-
</div>
2549-
</div>
2550-
</div>
2511+
<!-- 360° Review Modal removed — replaced by 360° Interview Result tab -->
25512512

25522513
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
25532514
<script src="https://cdn.jsdelivr.net/npm/qrcode-generator@1.4.4/qrcode.min.js"></script>
@@ -2763,6 +2724,7 @@ <h6 style="font-size:0.88rem;font-weight:700;margin-bottom:10px;display:flex;ali
27632724
renderCompletedInterviewTable();
27642725
renderCancelledInterviewTable();
27652726
renderProctoredTable();
2727+
render360InterviewResults();
27662728
renderResultsTable();
27672729
renderCandidates();
27682730
updateInterviewCounts();
@@ -2782,6 +2744,7 @@ <h6 style="font-size:0.88rem;font-weight:700;margin-bottom:10px;display:flex;ali
27822744
renderCompletedInterviewTable();
27832745
renderCancelledInterviewTable();
27842746
renderProctoredTable();
2747+
render360InterviewResults();
27852748
renderResultsTable();
27862749
renderCandidates();
27872750
updateInterviewCounts();
@@ -3565,11 +3528,18 @@ <h6 style="font-size:0.88rem;font-weight:700;margin-bottom:10px;display:flex;ali
35653528
const meetingHint = document.getElementById('meetingLinkHint');
35663529
const meetingInput = document.getElementById('intMeetingLink');
35673530

3568-
if (mode === 'proctored') {
3531+
if (mode === 'proctored' || mode === 'proctored_360') {
35693532
proctoredSettings.classList.add('visible');
35703533
meetingHint.style.display = 'block';
35713534
meetingHint.textContent = '🔒 A secure tokenised interview link will be auto-generated for the candidate.';
35723535
meetingInput.placeholder = 'Auto-generated (or enter custom proctored platform URL)';
3536+
// Auto-enable 360 room camera for proctored_360 mode
3537+
const cam360 = document.getElementById('proctor360Camera');
3538+
const cam360Info = document.getElementById('proctor360Info');
3539+
if (mode === 'proctored_360' && cam360) {
3540+
cam360.checked = true;
3541+
if (cam360Info) cam360Info.style.display = 'block';
3542+
}
35733543
} else {
35743544
proctoredSettings.classList.remove('visible');
35753545
const hints = {
@@ -3943,7 +3913,7 @@ <h3>${stats.tokenLinksGenerated}</h3>
39433913
const emptyState = document.getElementById('proctoredEmptyState');
39443914
if (!tbody) return;
39453915

3946-
const proctored = appData.interviews.filter(i => i.mode === 'proctored');
3916+
const proctored = appData.interviews.filter(i => i.mode === 'proctored' || i.mode === 'proctored_360');
39473917

39483918
if (proctored.length === 0) {
39493919
try { tbody.closest('table').style.display = 'none'; } catch(e) {}
@@ -4018,6 +3988,42 @@ <h3>${stats.tokenLinksGenerated}</h3>
40183988
`).join('');
40193989
}
40203990

3991+
3992+
function render360InterviewResults() {
3993+
const tbody = document.getElementById('interview360ResultsBody');
3994+
const emptyState = document.getElementById('interview360EmptyState');
3995+
if (!tbody) return;
3996+
const results360 = appData.interviews.filter(i => (i.mode === 'proctored_360' || (i.mode === 'proctored' && i.proctorSettings && i.proctorSettings.roomCamera360)) && i.status === 'completed');
3997+
if (results360.length === 0) {
3998+
try { tbody.closest('table').style.display = 'none'; } catch(e) {}
3999+
if (emptyState) emptyState.style.display = 'block';
4000+
return;
4001+
}
4002+
try { tbody.closest('table').style.display = 'table'; } catch(e) {}
4003+
if (emptyState) emptyState.style.display = 'none';
4004+
tbody.innerHTML = results360.map(int => {
4005+
const score = int.score || int.overall_score || '---';
4006+
const trust = int.trust_score || '---';
4007+
const violations = int.violation_count || 0;
4008+
const scoreColor = typeof score === 'number' ? (score >= 70 ? 'var(--success)' : score >= 40 ? 'var(--warning)' : 'var(--danger)') : 'var(--text-secondary)';
4009+
const trustColor = typeof trust === 'number' ? (trust >= 70 ? 'var(--success)' : trust >= 40 ? 'var(--warning)' : 'var(--danger)') : 'var(--text-secondary)';
4010+
return `
4011+
+ '<tr>'
4012+
+ '<td><strong>' + escapeHtml(int.candidateName) + '</strong></td>'
4013+
+ '<td>' + escapeHtml(int.position) + '</td>'
4014+
+ '<td>' + formatDate(int.date) + '</td>'
4015+
+ '<td><span style="font-weight:700;color:' + scoreColor + ';">' + score + (typeof score === 'number' ? '%' : '') + '</span></td>'
4016+
+ '<td><span style="font-weight:700;color:' + trustColor + ';">' + trust + (typeof trust === 'number' ? '%' : '') + '</span></td>'
4017+
+ '<td><span style="display:inline-flex;align-items:center;gap:4px;padding:3px 10px;border-radius:6px;font-size:0.78rem;font-weight:600;background:#ccfbf1;color:#0d9488;"><i class="fas fa-street-view"></i> Active</span></td>'
4018+
+ '<td><span style="font-weight:600;color:' + (violations > 3 ? 'var(--danger)' : 'var(--success)') + ';">' + violations + '</span></td>'
4019+
+ '<td><span class="status-badge ' + int.status + '">' + capitalize(int.status) + '</span></td>'
4020+
+ '<td>'
4021+
+ '<button class="btn-sm-action view" onclick="viewInterview(\'' + int.id + '\')" title="Details"><i class="fas fa-eye"></i></button>'
4022+
+ (int.token ? '<button class="btn-sm-action view" onclick="window.open(\'/interview/results.html?token=' + int.token + '\', \'_blank\')" title="Full Report"><i class="fas fa-file-contract"></i></button>' : '')
4023+
+ '</td>'
4024+
+ '</tr>';
4025+
}).join('');
4026+
}
40214027
function updateInterviewCounts() {
40224028
const scheduled = appData.interviews.filter(i => i.status === 'scheduled').length;
40234029
const completed = appData.interviews.filter(i => i.status === 'completed').length;
@@ -4314,7 +4320,7 @@ <h3>${stats.tokenLinksGenerated}</h3>
43144320
const token = generateInterviewToken();
43154321
const interviewLink = getInterviewLink(token);
43164322
4317-
const proctorSettings = mode === 'proctored' ? {
4323+
const proctorSettings = (mode === 'proctored' || mode === 'proctored_360') ? {
43184324
camera: document.getElementById('proctorCamera')?.checked || false,
43194325
eyeTracking: document.getElementById('proctorEyeTracking')?.checked || false,
43204326
screenRecord: document.getElementById('proctorScreenRecord')?.checked || false,
@@ -4340,10 +4346,10 @@ <h3>${stats.tokenLinksGenerated}</h3>
43404346
candidate_phone: candidatePhone,
43414347
interview_role: position,
43424348
interview_level: round,
4343-
interview_type: mode === 'proctored' ? 'ai_voice' : 'human_live',
4344-
token_type: mode === 'proctored' ? 'shortlist' : 'custom',
4349+
interview_type: (mode === 'proctored' || mode === 'proctored_360') ? 'ai_voice' : 'human_live',
4350+
token_type: (mode === 'proctored' || mode === 'proctored_360') ? 'shortlist' : 'custom',
43454351
token,
4346-
status: mode === 'proctored' ? 'pending' : 'scheduled',
4352+
status: (mode === 'proctored' || mode === 'proctored_360') ? 'pending' : 'scheduled',
43474353
job_id: selectedJobId,
43484354
tenant_id: user.company_id || user.tenant_id || null,
43494355
company_id: user.company_id || user.tenant_id || null,
@@ -4389,9 +4395,9 @@ <h3>${stats.tokenLinksGenerated}</h3>
43894395
DataStore.update(data => {
43904396
data.interviews.unshift(localPayload);
43914397
data.activities.unshift({
4392-
type: mode === 'proctored' ? 'proctored' : 'interview',
4398+
type: (mode === 'proctored' || mode === 'proctored_360') ? 'proctored' : 'interview',
43934399
title: `Interview Scheduled: ${candidateName}`,
4394-
description: `${position} · ${round} · ${formatDate(date)} ${formatTime(startTime)} · ${mode === 'proctored' ? '🔒 Proctored' : mode}`,
4400+
description: `${position} · ${round} · ${formatDate(date)} ${formatTime(startTime)} · ${(mode === 'proctored' || mode === 'proctored_360') ? '🔒 Proctored' : mode}`,
43954401
timestamp: Date.now()
43964402
});
43974403
});
@@ -4402,6 +4408,7 @@ <h3>${stats.tokenLinksGenerated}</h3>
44024408
renderCompletedInterviewTable();
44034409
renderCancelledInterviewTable();
44044410
renderProctoredTable();
4411+
render360InterviewResults();
44054412
renderDashboardStats();
44064413
renderDashboardInterviews();
44074414
renderDashboardActivities();
@@ -4894,6 +4901,7 @@ <h6 style="color:var(--text-primary);margin-bottom:4px;">No Applications Yet</h6
48944901
renderCompletedInterviewTable();
48954902
renderCancelledInterviewTable();
48964903
renderProctoredTable();
4904+
render360InterviewResults();
48974905
renderDashboardStats();
48984906
renderDashboardActivities();
48994907
updateInterviewCounts();

hr-ops.html

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>HR Ops — Simpatico HR</title>
7-
<link rel="stylesheet" href="/hr-modules.css">
7+
<link rel="stylesheet" href="../hr-modules.css">
88
<script>
99
// Hide shell when loaded inside dashboard iframe
1010
if (window.self !== window.top) {
@@ -339,10 +339,11 @@ <h2>Initiate Offboarding</h2>
339339

340340

341341

342+
342343
<script src="https://cdn.jsdelivr.net/npm/@supabase/supabase-js@2"></script>
343-
<script src="/js/hr-config.js"></script>
344-
<script src="/js/shared-utils.js"></script>
345-
<script src="/js/supabase-client.js"></script>
346-
<script src="/js/hr-ops.js"></script>
344+
<script src="../js/hr-config.js"></script>
345+
<script src="../js/shared-utils.js"></script>
346+
<script src="../js/supabase-client.js"></script>
347+
<script src="../js/hr-ops.js"></script>
347348
</body>
348349
</html>

0 commit comments

Comments
 (0)