| |
| <header class="site-header"> |
| <div class="header-inner"> |
| <div class="logo-cluster"> |
| <span (click)="navigateHome()" style="cursor:pointer"> |
| <img src="/assets/pykara-logo.png" alt="PyDetect Logo" class="logo-img-header" /> |
| </span> |
| <div class="py-detect-title-header"> |
| <span class="py-letter p">P</span> |
| <span class="py-letter y">Y</span> |
| <span class="py-shape"></span> |
| <span class="py-letter d">D</span> |
| <span class="py-letter e">E</span> |
| <span class="py-letter t">T</span> |
| <span class="py-letter e2">E</span> |
| <span class="py-letter c">C</span> |
| <span class="py-letter t2">T</span> |
| </div> |
| </div> |
| <div class="header-actions-right-group"> |
| <button class="back-btn" (click)="navigateBackToCaseDetails()"> |
| <i class="fas fa-arrow-left"></i> |
| <span>Back to Case Details</span> |
| </button> |
| <div class="header-actions-icons"> |
| <button class="evidence-btn" (click)="showEvidencePanel = !showEvidencePanel" title="Upload Evidence"> |
| <i class="fas fa-file-upload"></i> |
| </button> |
| <button class="summary-btn" (click)="showSummaryPanel = !showSummaryPanel" title="Investigation Summary"> |
| <i class="fas fa-clipboard-list"></i> |
| </button> |
| </div> |
| </div> |
| </div> |
| </header> |
|
|
| |
| <div class="main-content-card"> |
| <div class="card-inner"> |
| <div class="content-grid"> |
| |
| <div class="left-panel"> |
| |
| <div *ngIf="currentQuestionIndex < 0" class="guidance-banner"> |
| <div class="guidance-content"> |
| <div class="guidance-icon"> |
| <i class="fas fa-lightbulb"></i> |
| </div> |
| <div class="guidance-text"> |
| <h3>Ready to Begin Investigation</h3> |
| <p>Click "Start Investigation" to activate camera and begin questioning</p> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <button class="start-investigation-btn" (click)="onStartInvestigation()"> |
| <i class="fas fa-search"></i> |
| Start Investigation |
| </button> |
|
|
| |
| <div class="question-section"> |
| <div class="question-header"> |
| <div class="question-badge">Question {{ currentQuestionIndex + 1 }}</div> |
| <div class="status-indicator" *ngIf="infoText"> |
| <i class="fas fa-info-circle"></i> |
| {{ infoText }} |
| </div> |
| </div> |
| <div class="question-content"> |
| <h3>Current Question</h3> |
| <div class="question-text"> |
| <ng-container *ngIf="questions.length > 0 && currentQuestionIndex >= 0"> |
| {{ questions[currentQuestionIndex] }} |
| </ng-container> |
| <ng-container *ngIf="!questions.length || currentQuestionIndex < 0"> |
| <span *ngIf="currentQuestionText">{{ currentQuestionText }}</span> |
| <span *ngIf="!currentQuestionText" class="no-question"> |
| Awaiting first question. Click "Start Investigation" to begin. |
| </span> |
| </ng-container> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="answer-section"> |
| <h3>Your Answer</h3> |
| <textarea id="answerInput" |
| [(ngModel)]="textAnswer" |
| (focus)="captureTextStart()" |
| class="answer-input" |
| placeholder="Type or speak your answer here..." |
| rows="5" |
| maxlength="3000"> |
| </textarea> |
|
|
| <div class="answer-actions"> |
| <button (click)="submitCombinedAnswer()" class="btn-primary"> |
| <i class="fas fa-paper-plane"></i> |
| Submit Answer |
| </button> |
| <button (click)="toggleVoiceRecording()" class="btn-secondary"> |
| <i class="fas fa-microphone"></i> |
| <span *ngIf="!isVoiceRecording">Start Recording</span> |
| <span *ngIf="isVoiceRecording">Stop Recording</span> |
| </button> |
| </div> |
|
|
| <div *ngIf="isVoiceRecording" class="recording-status"> |
| <div class="recording-dot"></div> |
| <span>Recording... Speak now</span> |
| </div> |
| </div> |
|
|
| |
| <div class="results-section"> |
| |
| <div *ngIf="truthScore !== null" class="result-card"> |
| <div class="result-header"> |
| <div class="result-icon truth"> |
| <i class="fas fa-check-circle"></i> |
| </div> |
| <div class="result-title">Truth Score</div> |
| <div class="result-value">{{ truthScore }}</div> |
| </div> |
| </div> |
|
|
| |
| <div *ngIf="faceDetectionScore !== null" class="result-card"> |
| <div class="result-header"> |
| <div class="result-icon face"> |
| <i class="fas fa-user-check"></i> |
| </div> |
| <div class="result-title">Face Detection</div> |
| <div class="result-value">{{ faceDetectionScore }}</div> |
| </div> |
| </div> |
|
|
| |
| <div *ngIf="involvementScore !== null" class="result-card"> |
| <div class="result-header"> |
| <div class="result-icon involvement"> |
| <i class="fas fa-user-tag"></i> |
| </div> |
| <div class="result-title">Involvement Score</div> |
| <div class="result-value">{{ involvementScore | number:'1.1-1' }}</div> |
| </div> |
| <div class="progress-bar"> |
| <div class="progress-fill" [style.width]="involvementScore + '%'"></div> |
| </div> |
|
|
| <div *ngIf="involvementCues.length" class="cues-container"> |
| <span *ngFor="let cue of involvementCues" class="cue-tag"> |
| {{ cue.replace('_cue','').replace('_',' ') }} |
| </span> |
| </div> |
|
|
| <div *ngIf="bodyLanguageMeaning || bodyLanguageExplanation" style="margin-top: 12px; font-size: 12px; color: #64748b;"> |
| <div *ngIf="bodyLanguageMeaning" style="margin-bottom: 4px;"> |
| <strong>Body Language:</strong> {{ bodyLanguageMeaning }} |
| </div> |
| <div *ngIf="bodyLanguageExplanation"> |
| <strong>Analysis:</strong> {{ bodyLanguageExplanation }} |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div *ngIf="ferEmotion" class="result-card"> |
| <div class="result-header"> |
| <div class="result-icon emotion"> |
| <i class="fas fa-smile"></i> |
| </div> |
| <div class="result-title">Emotion (FER)</div> |
| <div class="result-value">{{ ferEmotion }}</div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="right-panel"> |
| |
| <div class="camera-section"> |
| <ng-container *ngIf="!videoStream"> |
| <div class="camera-placeholder"> |
| <div class="camera-icon"> |
| <i class="fas fa-video"></i> |
| </div> |
| <h3>Camera Inactive</h3> |
| <p>Click "Start Investigation" to begin video recording and analysis</p> |
| </div> |
| </ng-container> |
|
|
| <ng-container *ngIf="videoStream"> |
| <div class="video-active"> |
| <video #videoElement [srcObject]="videoStream" autoplay muted playsinline class="camera-video"></video> |
| <div *ngIf="isRecording && currentQuestionIndex >= 0 && currentQuestionIndex < totalQuestions" class="recording-overlay"> |
| <i class="fas fa-circle" style="font-size: 8px;"></i> |
| LIVE RECORDING |
| </div> |
| </div> |
| </ng-container> |
| </div> |
|
|
| |
| <div class="transcription-section"> |
| <div class="transcription-header"> |
| <h3> |
| <i class="fas fa-comments"></i> |
| Transcription |
| <span class="live-badge">LIVE</span> |
| </h3> |
| </div> |
| <div class="transcription-content"> |
| <div *ngFor="let line of transcriptLines" class="transcription-line"> |
| {{ line }} |
| </div> |
| <div *ngIf="!transcriptLines.length" class="transcription-line" style="text-align: center; color: #94a3b8;"> |
| <i class="fas fa-microphone-alt"></i> |
| <div style="margin-top: 8px;">Waiting for speech input...</div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="final-action"> |
| <button class="evaluate-btn" (click)="navigateToValidationPage()"> |
| <i class="fas fa-check-circle"></i> |
| Submit & Evaluate |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="evidence-sidebar" [class.open]="showEvidencePanel"> |
| <div class="sidebar-header"> |
| <div class="sidebar-title"> |
| <i class="fas fa-file-upload"></i> |
| Evidence Panel |
| </div> |
| <button class="close-btn" (click)="showEvidencePanel = false" title="Close"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| <div class="sidebar-content"> |
| <form class="evidence-upload-form" (submit)="$event.preventDefault(); uploadDocument()"> |
| <div style="margin-bottom: 24px;"> |
| <label style="display: block; margin-bottom: 8px; font-weight: 600; color: #1e293b;">Upload Document</label> |
| <input type="file" (change)="onEvidenceFileSelect($event, 'document')" |
| style="width: 100%; padding: 12px; border: 2px dashed #cbd5e1; border-radius: 10px; background: #f8fafc; cursor: pointer;"> |
| </div> |
| <div style="margin-bottom: 24px;"> |
| <label style="display: block; margin-bottom: 8px; font-weight: 600; color: #1e293b;">Upload Photo</label> |
| <input type="file" accept="image/*" (change)="onEvidenceFileSelect($event, 'photo')" |
| style="width: 100%; padding: 12px; border: 2px dashed #cbd5e1; border-radius: 10px; background: #f8fafc; cursor: pointer;"> |
| </div> |
| <div style="margin-bottom: 24px;"> |
| <label style="display: block; margin-bottom: 8px; font-weight: 600; color: #1e293b;">Upload Recording</label> |
| <input type="file" accept="audio/*,video/*" (change)="onEvidenceFileSelect($event, 'recording')" |
| style="width: 100%; padding: 12px; border: 2px dashed #cbd5e1; border-radius: 10px; background: #f8fafc; cursor: pointer;"> |
| </div> |
|
|
| <div style="margin-bottom: 24px;"> |
| <label style="display: block; margin-bottom: 8px; font-weight: 600; color: #1e293b;">Remarks</label> |
| <textarea [(ngModel)]="evidenceSummary" [ngModelOptions]="{standalone: true}" |
| rows="4" placeholder="Enter any additional remarks..." |
| style="width: 100%; padding: 12px; border: 2px solid #cbd5e1; border-radius: 10px; background: white; font-family: inherit;"></textarea> |
| </div> |
|
|
| <button type="submit" class="btn-primary" style="width: 100%;"> |
| <i class="fas fa-paper-plane"></i> |
| Submit Evidence |
| </button> |
| </form> |
| </div> |
| </div> |
|
|
| |
| <div class="summary-sidebar" [class.open]="showSummaryPanel"> |
| <div class="sidebar-header"> |
| <div class="sidebar-title"> |
| <i class="fas fa-clipboard-list"></i> |
| Investigation Summary |
| </div> |
| <button class="close-btn" (click)="showSummaryPanel = false" title="Close"> |
| <i class="fas fa-times"></i> |
| </button> |
| </div> |
| <div class="sidebar-content"> |
| <div style="margin-bottom: 24px;"> |
| <h4 style="color: #2563eb; margin-bottom: 12px; font-size: 14px; font-weight: 600;">Case Details</h4> |
| <div style="background: #f0f9ff; border-radius: 10px; padding: 16px;"> |
| <div style="display: flex; justify-content: space-between; margin-bottom: 8px;"> |
| <span style="color: #475569; font-size: 13px;">Case ID:</span> |
| <span style="font-weight: 600; color: #1e293b;">{{ caseId }}</span> |
| </div> |
| <div style="display: flex; justify-content: space-between; margin-bottom: 8px;"> |
| <span style="color: #475569; font-size: 13px;">Crime Type:</span> |
| <span style="font-weight: 600; color: #1e293b;">{{ crimeType }}</span> |
| </div> |
| <div style="display: flex; justify-content: space-between; margin-bottom: 8px;"> |
| <span style="color: #475569; font-size: 13px;">Date & Time:</span> |
| <span style="font-weight: 600; color: #1e293b;">{{ dateTime }}</span> |
| </div> |
| <div style="display: flex; justify-content: space-between; margin-bottom: 8px;"> |
| <span style="color: #475569; font-size: 13px;">Location:</span> |
| <span style="font-weight: 600; color: #1e293b;">{{ location }}</span> |
| </div> |
| </div> |
| </div> |
|
|
| <div style="margin-bottom: 24px;"> |
| <h4 style="color: #2563eb; margin-bottom: 12px; font-size: 14px; font-weight: 600;">Person Details</h4> |
| <div style="background: #f0f9ff; border-radius: 10px; padding: 16px;"> |
| <div style="display: flex; justify-content: space-between; margin-bottom: 8px;"> |
| <span style="color: #475569; font-size: 13px;">Suspect Name:</span> |
| <span style="font-weight: 600; color: #1e293b;">{{ suspectName }}</span> |
| </div> |
| <div style="display: flex; justify-content: space-between;"> |
| <span style="color: #475569; font-size: 13px;">Investigation Officer:</span> |
| <span style="font-weight: 600; color: #1e293b;">{{ investigationOfficer }}</span> |
| </div> |
| </div> |
| </div> |
|
|
| <div> |
| <h4 style="color: #2563eb; margin-bottom: 12px; font-size: 14px; font-weight: 600;">Progress Details</h4> |
| <div style="background: #f0f9ff; border-radius: 10px; padding: 16px;"> |
| <div style="display: flex; justify-content: space-between; margin-bottom: 8px;"> |
| <span style="color: #475569; font-size: 13px;">Status:</span> |
| <span style="font-weight: 600; color: #1e293b;">{{ statusText }}</span> |
| </div> |
| <div style="display: flex; justify-content: space-between; margin-bottom: 8px;"> |
| <span style="color: #475569; font-size: 13px;">Progress:</span> |
| <span style="font-weight: 600; color: #1e293b;">{{progress}}% ({{ progressStage }})</span> |
| </div> |
| <div style="display: flex; justify-content: space-between;"> |
| <span style="color: #475569; font-size: 13px;">Session Time:</span> |
| <span style="font-weight: 600; color: #1e293b;">{{ sessionTime }}</span> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| |
| <div class="blur-bg" [class.active]="showEvidencePanel || showSummaryPanel"></div> |
|
|
| |
| <footer> |
| <p>© 2025 Pykara Technologies Pvt. Ltd. All rights reserved.</p> |
| </footer> |
|
|