sls/resources/views/interview/report.blade.php
2026-07-23 17:23:32 +05:30

443 lines
19 KiB
PHP

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Executive Evaluation Report - {{ $interview->candidate_name }} | SingleLogin</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600;700&family=Outfit:wght@500;600;700;800&family=Fira+Code:wght@400;500&display=swap" rel="stylesheet">
<style>
:root {
--primary: #0f172a;
--accent: #6366f1;
--text-dark: #0f172a;
--text-muted: #64748b;
--card-bg: #f8fafc;
--border: #e2e8f0;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Instrument Sans', sans-serif;
background-color: #f1f5f9;
color: var(--text-dark);
line-height: 1.5;
padding: 40px 20px;
}
.report-container {
max-width: 900px;
margin: 0 auto;
background: white;
border-radius: 16px;
box-shadow: 0 20px 40px rgba(0,0,0,0.08);
border: 1px solid var(--border);
padding: 40px;
position: relative;
}
.header-bar {
display: flex;
justify-content: space-between;
align-items: flex-start;
border-bottom: 2px solid var(--accent);
padding-bottom: 20px;
margin-bottom: 24px;
}
.brand-title {
font-family: 'Outfit', sans-serif;
font-size: 1.6rem;
font-weight: 800;
color: var(--primary);
display: flex;
align-items: center;
gap: 10px;
}
.report-badge {
background: rgba(99,102,241,0.1);
color: var(--accent);
font-size: 0.75rem;
font-weight: 700;
padding: 4px 12px;
border-radius: 999px;
text-transform: uppercase;
}
.meta-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
background: var(--card-bg);
border-radius: 12px;
padding: 16px;
border: 1px solid var(--border);
margin-bottom: 28px;
}
.meta-item label {
display: block;
font-size: 0.7rem;
text-transform: uppercase;
font-weight: 700;
color: var(--text-muted);
margin-bottom: 4px;
}
.meta-item span {
font-weight: 700;
font-size: 0.9rem;
color: var(--primary);
}
.score-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
margin-bottom: 28px;
}
.score-card {
background: var(--card-bg);
border: 1px solid var(--border);
border-radius: 14px;
padding: 20px;
position: relative;
}
.score-val {
font-family: 'Outfit', sans-serif;
font-size: 2.4rem;
font-weight: 800;
margin-top: 6px;
}
.section-heading {
font-family: 'Outfit', sans-serif;
font-size: 1.1rem;
font-weight: 700;
color: var(--primary);
margin-bottom: 12px;
display: flex;
align-items: center;
gap: 8px;
}
.audit-table {
width: 100%;
border-collapse: collapse;
margin-bottom: 28px;
font-size: 0.8rem;
}
.audit-table th {
background: #f1f5f9;
color: var(--text-muted);
font-weight: 700;
text-align: left;
padding: 10px;
border-bottom: 1px solid var(--border);
}
.audit-table td {
padding: 10px;
border-bottom: 1px solid #edf2f7;
}
.code-box {
background: #0f172a;
color: #38bdf8;
border-radius: 12px;
padding: 18px;
font-family: 'Fira Code', monospace;
font-size: 0.8rem;
white-space: pre-wrap;
margin-bottom: 20px;
max-height: 300px;
overflow-y: auto;
}
.output-box {
background: #050811;
color: #34d399;
border-radius: 10px;
padding: 14px;
font-family: 'Fira Code', monospace;
font-size: 0.75rem;
white-space: pre-wrap;
margin-bottom: 28px;
}
.print-btn {
position: fixed;
bottom: 30px;
right: 30px;
background: var(--accent);
color: white;
border: none;
padding: 14px 28px;
border-radius: 999px;
font-weight: 700;
font-size: 0.9rem;
box-shadow: 0 10px 25px rgba(99,102,241,0.4);
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
z-index: 100;
}
@media print {
body {
background: white;
padding: 0;
}
.report-container {
box-shadow: none;
border: none;
max-width: 100%;
padding: 0;
}
.print-btn, .top-download-pdf-btn {
display: none !important;
}
}
</style>
</head>
<body>
<button onclick="window.print()" class="print-btn">
📥 Download / Print Executive PDF Report
</button>
<div class="report-container">
<!-- Top Bar with Download PDF Button -->
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; padding-bottom: 12px; border-bottom: 1px solid var(--border);">
<div style="font-size: 0.85rem; font-weight: 700; color: var(--primary); display: flex; align-items: center; gap: 6px;">
<span>📄 Executive Assessment Performance Report</span>
</div>
<button onclick="window.print()" class="top-download-pdf-btn" style="background: #6366f1; color: white; border: none; font-weight: 700; font-size: 0.85rem; padding: 10px 20px; border-radius: 10px; cursor: pointer; display: flex; align-items: center; gap: 8px; box-shadow: 0 4px 14px rgba(99,102,241,0.3);">
📥 Download PDF Report
</button>
</div>
<!-- Header -->
<div class="header-bar">
<div>
<div class="brand-title">
SingleLogin Enterprise Assessment
</div>
<div style="font-size: 0.8rem; color: var(--text-muted); margin-top: 4px;">
Candidate Technical Competency & Behavioral Audit Report
</div>
</div>
<div style="text-align: right;">
<span class="report-badge">Executive Summary</span>
<div style="font-size: 0.7rem; color: var(--text-muted); margin-top: 6px;">
Report ID: RPT-{{ $interview->submission_unique_id }}
</div>
<div style="font-size: 0.7rem; color: var(--text-muted);">
Date: {{ now()->format('M d, Y - H:i:s T') }}
</div>
</div>
</div>
<!-- Meta Grid -->
<div class="meta-grid">
<div class="meta-item">
<label>Candidate Name</label>
<span>{{ $interview->candidate_name }}</span>
</div>
<div class="meta-item">
<label>Email Address</label>
<span style="font-size: 0.8rem;">{{ $interview->candidate_email }}</span>
</div>
<div class="meta-item">
<label>Language & Tech</label>
<span>{{ strtoupper($interview->language) }}</span>
</div>
<div class="meta-item">
<label>Assessment Status</label>
<span style="color: {{ $interview->status === 'completed' ? '#10b981' : ($interview->status === 'blocked' ? '#ef4444' : '#6366f1') }};">
{{ strtoupper($interview->status) }}
</span>
</div>
</div>
<!-- Scores Summary Grid -->
<div class="score-grid">
<!-- Behavioral Integrity Score -->
<div class="score-card" style="border-left: 5px solid {{ $integrityColor }};">
<div style="font-size: 0.75rem; font-weight: 700; color: var(--text-muted); text-transform: uppercase;">
🛡️ Behavioral Integrity Rating
</div>
<div class="score-val" style="color: {{ $integrityColor }};">
{{ $integrityScore }}%
</div>
<div style="font-size: 0.8rem; font-weight: 700; color: {{ $integrityColor }}; margin-top: 4px;">
{{ $integrityLabel }}
</div>
<div style="font-size: 0.7rem; color: var(--text-muted); margin-top: 6px;">
Recorded Violations: <strong>{{ count($logs) }} incident(s)</strong>
</div>
</div>
<!-- Technical Score -->
<div class="score-card" style="border-left: 5px solid #6366f1;">
<div style="font-size: 0.75rem; font-weight: 700; color: var(--text-muted); text-transform: uppercase;">
💻 Technical Code Competency
</div>
<div class="score-val" style="color: #6366f1;">
{{ $codeScore }} / 100
</div>
<div style="font-size: 0.8rem; font-weight: 700; color: #6366f1; margin-top: 4px;">
{{ $codeScore >= 80 ? 'Strong Technical Match' : ($codeScore >= 50 ? 'Moderate Competency' : 'Needs Further Review') }}
</div>
<div style="font-size: 0.7rem; color: var(--text-muted); margin-top: 6px;">
Solution Code: <strong>{{ !empty($interview->submitted_code) ? 'Submitted' : 'Pending' }}</strong>
</div>
</div>
</div>
<!-- Proctoring Violation Metrics & Breakdown -->
<div class="section-heading">
🔍 Behavioral Audit & Proctoring Incident Breakdown
</div>
<div style="display: grid; grid-template-columns: repeat(6, 1fr); gap: 10px; margin-bottom: 20px;">
<div style="background: var(--card-bg); padding: 10px; border-radius: 10px; border: 1px solid var(--border); text-align: center;">
<div style="font-size: 1.1rem; font-weight: 800; color: #ef4444;">{{ $tabSwitches }}</div>
<div style="font-size: 0.6rem; color: var(--text-muted); font-weight: 700;">Tab Switches</div>
</div>
<div style="background: var(--card-bg); padding: 10px; border-radius: 10px; border: 1px solid var(--border); text-align: center;">
<div style="font-size: 1.1rem; font-weight: 800; color: #f59e0b;">{{ $focusLosses }}</div>
<div style="font-size: 0.6rem; color: var(--text-muted); font-weight: 700;">Focus Lost</div>
</div>
<div style="background: var(--card-bg); padding: 10px; border-radius: 10px; border: 1px solid var(--border); text-align: center;">
<div style="font-size: 1.1rem; font-weight: 800; color: #38bdf8;">{{ $gazeAnomalies }}</div>
<div style="font-size: 0.6rem; color: var(--text-muted); font-weight: 700;">Gaze Anomalies</div>
</div>
<div style="background: var(--card-bg); padding: 10px; border-radius: 10px; border: 1px solid var(--border); text-align: center;">
<div style="font-size: 1.1rem; font-weight: 800; color: #818cf8;">{{ $pasteEvents }}</div>
<div style="font-size: 0.6rem; color: var(--text-muted); font-weight: 700;">Code Pastes</div>
</div>
<div style="background: var(--card-bg); padding: 10px; border-radius: 10px; border: 1px solid var(--border); text-align: center;">
<div style="font-size: 1.1rem; font-weight: 800; color: #ef4444;">{{ $lowerGazeViolations }}</div>
<div style="font-size: 0.6rem; color: var(--text-muted); font-weight: 700;">📱 Lower Gaze</div>
</div>
<div style="background: var(--card-bg); padding: 10px; border-radius: 10px; border: 1px solid var(--border); text-align: center;">
<div style="font-size: 1.1rem; font-weight: 800; color: #f43f5e;">{{ $questionRepeatViolations }}</div>
<div style="font-size: 0.6rem; color: var(--text-muted); font-weight: 700;">🗣️ Question Repeat</div>
</div>
</div>
@if(is_array($logs) && count($logs) > 0)
<table class="audit-table">
<thead>
<tr>
<th>Timestamp</th>
<th>Violation Category</th>
<th>Audit Details</th>
</tr>
</thead>
<tbody>
@foreach($logs as $log)
<tr>
<td style="color: var(--text-muted);">{{ \Carbon\Carbon::parse($log['timestamp'])->format('H:i:s T') }}</td>
<td><strong>{{ strtoupper($log['type']) }}</strong></td>
<td>{{ $log['details'] ?? 'Incident flagged by proctoring engine.' }}</td>
</tr>
@endforeach
</tbody>
</table>
@else
<div style="background: rgba(16,185,129,0.1); color: #10b981; padding: 12px; border-radius: 10px; font-size: 0.8rem; font-weight: 600; margin-bottom: 28px;">
Zero proctoring violations or malpractice detected during the session.
</div>
@endif
<!-- Code Solution Block -->
<div class="section-heading">
💻 Submitted Code Solution ({{ strtoupper($interview->submitted_language ?? $interview->language) }})
</div>
<div class="code-box">
{{ $interview->submitted_code ?? '// No code solution submitted by candidate.' }}
</div>
<!-- Code Output Block -->
<div class="section-heading">
🖥️ Engine Execution Stdout Output
</div>
<div class="output-box">
{{ $interview->code_output ?? 'No execution output recorded.' }}
</div>
<!-- Candidate Notes, Interviewer Evaluation Notes, Drawing & Video Recordings Section -->
@if(!empty($interview->candidate_notes) || !empty($interview->interviewer_notes) || !empty($interview->candidate_drawing) || (is_array($interview->formatted_recordings) && count($interview->formatted_recordings) > 0))
<div class="section-heading">
📝 Workspace Artifacts, Evaluation Notes & Call Session Recordings
</div>
<div style="background: var(--card-bg); border: 1px solid var(--border); border-radius: 12px; padding: 16px; margin-bottom: 28px;">
@if(!empty($interview->candidate_notes))
<div style="font-size: 0.75rem; font-weight: 700; color: var(--text-muted); margin-bottom: 6px;">CANDIDATE NOTEPAD NOTES (UNIQUE ID SYNCED):</div>
<pre style="font-family: monospace; font-size: 0.8rem; background: white; padding: 10px; border-radius: 8px; border: 1px solid var(--border); margin-bottom: 12px;">{{ $interview->candidate_notes }}</pre>
@endif
@if(!empty($interview->interviewer_notes))
<div style="font-size: 0.75rem; font-weight: 700; color: #10b981; margin-bottom: 6px;">INTERVIEWER EVALUATION NOTES (STORED BY UNIQUE ID):</div>
<pre style="font-family: sans-serif; font-size: 0.8rem; background: #f0fdf4; color: #166534; padding: 10px; border-radius: 8px; border: 1px solid #bbf7d0; margin-bottom: 12px;">{{ $interview->interviewer_notes }}</pre>
@endif
@if(!empty($interview->candidate_drawing))
<div style="font-size: 0.75rem; font-weight: 700; color: var(--text-muted); margin-bottom: 6px;">CANDIDATE DRAWING DIAGRAM:</div>
<img src="{{ $interview->candidate_drawing }}" alt="Candidate Drawing" style="max-width: 100%; max-height: 250px; border-radius: 8px; border: 1px solid var(--border); margin-bottom: 12px;" />
@endif
@if(is_array($interview->formatted_recordings) && count($interview->formatted_recordings) > 0)
<div style="font-size: 0.75rem; font-weight: 700; color: #6366f1; margin-bottom: 8px;">📹 STORED CALL SESSION RECORDINGS ({{ count($interview->formatted_recordings) }} RECORDINGS):</div>
@foreach($interview->formatted_recordings as $idx => $rec)
<div style="margin-bottom: 12px; background: white; border: 1px solid var(--border); border-radius: 8px; padding: 10px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px;">
<span style="font-size: 0.75rem; font-weight: 700; color: var(--primary);">Recording #{{ $idx + 1 }} ({{ $rec['created_at'] }})</span>
<a href="{{ $rec['download_url'] }}" download style="font-size: 0.7rem; color: #6366f1; font-weight: 700; text-decoration: none;">📥 Download MP4 Video</a>
</div>
<video src="{{ $rec['stream_url'] }}" controls style="width: 100%; max-height: 220px; border-radius: 6px; background: #000; outline: none;"></video>
</div>
@endforeach
@endif
</div>
@endif
<!-- Panel Sign-Off Block -->
<div style="border-top: 2px solid var(--border); padding-top: 20px; display: flex; justify-content: space-between; align-items: center;">
<div>
<div style="font-size: 0.7rem; font-weight: 700; color: var(--text-muted); text-transform: uppercase;">
HR & Lead Panel Approval
</div>
<div style="font-weight: 700; font-size: 0.9rem; color: var(--primary); margin-top: 4px;">
SingleLogin Enterprise HR Board
</div>
</div>
<div style="text-align: right;">
<div style="font-size: 0.7rem; font-weight: 700; color: var(--text-muted); text-transform: uppercase;">
Final Recommendation
</div>
<div style="font-weight: 800; font-size: 1rem; color: {{ $integrityScore >= 80 && $codeScore >= 50 ? '#10b981' : '#ef4444' }};">
{{ $integrityScore >= 80 && $codeScore >= 50 ? 'RECOMMENDED FOR HIRE' : 'REQUIRES FURTHER REVIEW / FLAGGED' }}
</div>
</div>
</div>
</div>
</body>
</html>