244 lines
8.0 KiB
HTML
244 lines
8.0 KiB
HTML
<div class="quiz-review-container">
|
|
<!-- Loading State -->
|
|
@if (isLoading()) {
|
|
<div class="loading-container">
|
|
<mat-spinner diameter="50"></mat-spinner>
|
|
<p>Loading review...</p>
|
|
</div>
|
|
}
|
|
|
|
<!-- Review Content -->
|
|
@if (!isLoading() && results()) {
|
|
<div class="review-content">
|
|
<!-- Header Section -->
|
|
<div class="review-header">
|
|
<button mat-icon-button (click)="backToResults()" class="back-btn">
|
|
<mat-icon>arrow_back</mat-icon>
|
|
</button>
|
|
<div class="header-content">
|
|
<h1 class="review-title">Quiz Review</h1>
|
|
<p class="review-subtitle">Review your answers and learn from mistakes</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Summary Cards -->
|
|
<div class="summary-cards">
|
|
<mat-card class="summary-card">
|
|
<mat-card-content>
|
|
<div class="card-icon total">
|
|
<mat-icon>quiz</mat-icon>
|
|
</div>
|
|
<div class="card-info">
|
|
<div class="card-value">{{ allQuestions().length }}</div>
|
|
<div class="card-label">Total Questions</div>
|
|
</div>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
|
|
<mat-card class="summary-card correct">
|
|
<mat-card-content>
|
|
<div class="card-icon success">
|
|
<mat-icon>check_circle</mat-icon>
|
|
</div>
|
|
<div class="card-info">
|
|
<div class="card-value">{{ correctCount() }}</div>
|
|
<div class="card-label">Correct</div>
|
|
</div>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
|
|
<mat-card class="summary-card incorrect">
|
|
<mat-card-content>
|
|
<div class="card-icon error">
|
|
<mat-icon>cancel</mat-icon>
|
|
</div>
|
|
<div class="card-info">
|
|
<div class="card-value">{{ incorrectCount() }}</div>
|
|
<div class="card-label">Incorrect</div>
|
|
</div>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
|
|
<mat-card class="summary-card score">
|
|
<mat-card-content>
|
|
<div class="card-icon primary">
|
|
<mat-icon>emoji_events</mat-icon>
|
|
</div>
|
|
<div class="card-info">
|
|
<div class="card-value">{{ results()!.percentage }}%</div>
|
|
<div class="card-label">Score</div>
|
|
</div>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
</div>
|
|
|
|
<!-- Filter Tabs -->
|
|
<div class="filter-tabs">
|
|
<button
|
|
mat-stroked-button
|
|
[class.active]="filterType() === 'all'"
|
|
(click)="setFilter('all')"
|
|
>
|
|
<mat-icon>list</mat-icon>
|
|
All Questions ({{ allQuestions().length }})
|
|
</button>
|
|
<button
|
|
mat-stroked-button
|
|
[class.active]="filterType() === 'correct'"
|
|
(click)="setFilter('correct')"
|
|
class="correct-tab"
|
|
>
|
|
<mat-icon>check_circle</mat-icon>
|
|
Correct ({{ correctCount() }})
|
|
</button>
|
|
<button
|
|
mat-stroked-button
|
|
[class.active]="filterType() === 'incorrect'"
|
|
(click)="setFilter('incorrect')"
|
|
class="incorrect-tab"
|
|
>
|
|
<mat-icon>cancel</mat-icon>
|
|
Incorrect ({{ incorrectCount() }})
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Questions List -->
|
|
<div class="questions-list">
|
|
@for (question of paginatedQuestions(); track question.questionId; let i = $index) {
|
|
<mat-card class="question-card" [class.incorrect]="!question.isCorrect">
|
|
<mat-card-header>
|
|
<div class="question-header-content">
|
|
<div class="question-number-badge" [class.correct]="question.isCorrect">
|
|
<span class="number">{{ (pageIndex() * pageSize()) + i + 1 }}</span>
|
|
<mat-icon class="status-icon">
|
|
{{ question.isCorrect ? 'check_circle' : 'cancel' }}
|
|
</mat-icon>
|
|
</div>
|
|
|
|
<div class="question-meta">
|
|
<mat-chip class="type-chip">
|
|
{{ getQuestionTypeText(question.questionType) }}
|
|
</mat-chip>
|
|
<span class="points-badge">{{ question.points }} pts</span>
|
|
</div>
|
|
|
|
@if (isAuthenticated()) {
|
|
<button
|
|
mat-icon-button
|
|
class="bookmark-btn"
|
|
[class.bookmarked]="isBookmarked(question.questionId)"
|
|
(click)="toggleBookmark(question.questionId)"
|
|
[matTooltip]="isBookmarked(question.questionId) ? 'Remove bookmark' : 'Bookmark question'"
|
|
>
|
|
<mat-icon>
|
|
{{ isBookmarked(question.questionId) ? 'bookmark' : 'bookmark_border' }}
|
|
</mat-icon>
|
|
</button>
|
|
}
|
|
</div>
|
|
</mat-card-header>
|
|
|
|
<mat-card-content>
|
|
<div class="question-text">{{ question.questionText }}</div>
|
|
|
|
<mat-divider></mat-divider>
|
|
|
|
<div class="answer-section">
|
|
<div class="answer-row">
|
|
<div class="answer-label">Your Answer:</div>
|
|
<div class="answer-value" [class.incorrect]="!question.isCorrect">
|
|
{{ formatAnswer(question.userAnswer) || 'Not answered' }}
|
|
@if (!question.isCorrect) {
|
|
<mat-icon class="answer-icon error">close</mat-icon>
|
|
} @else {
|
|
<mat-icon class="answer-icon success">check</mat-icon>
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
@if (!question.isCorrect) {
|
|
<div class="answer-row correct-answer">
|
|
<div class="answer-label">Correct Answer:</div>
|
|
<div class="answer-value correct">
|
|
{{ formatAnswer(question.correctAnswer) }}
|
|
<mat-icon class="answer-icon success">check</mat-icon>
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
@if (question.explanation) {
|
|
<div class="explanation-section">
|
|
<div class="explanation-header">
|
|
<mat-icon>lightbulb</mat-icon>
|
|
<span>Explanation</span>
|
|
</div>
|
|
<p class="explanation-text">{{ question.explanation }}</p>
|
|
</div>
|
|
}
|
|
|
|
@if (question.timeSpent) {
|
|
<div class="time-spent">
|
|
<mat-icon>schedule</mat-icon>
|
|
<span>Time spent: {{ question.timeSpent }}s</span>
|
|
</div>
|
|
}
|
|
</mat-card-content>
|
|
</mat-card>
|
|
}
|
|
|
|
@if (paginatedQuestions().length === 0) {
|
|
<div class="empty-state">
|
|
<mat-icon>info</mat-icon>
|
|
<p>No questions match the selected filter</p>
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<!-- Pagination -->
|
|
@if (totalQuestions() > pageSize()) {
|
|
<mat-paginator
|
|
[length]="totalQuestions()"
|
|
[pageSize]="pageSize()"
|
|
[pageIndex]="pageIndex()"
|
|
[pageSizeOptions]="[5, 10, 20, 50]"
|
|
(page)="onPageChange($event)"
|
|
showFirstLastButtons
|
|
>
|
|
</mat-paginator>
|
|
}
|
|
|
|
<!-- Action Buttons -->
|
|
<div class="action-buttons">
|
|
<button
|
|
mat-raised-button
|
|
(click)="backToResults()"
|
|
class="action-btn"
|
|
>
|
|
<mat-icon>arrow_back</mat-icon>
|
|
Back to Results
|
|
</button>
|
|
|
|
<button
|
|
mat-raised-button
|
|
color="primary"
|
|
(click)="retakeQuiz()"
|
|
class="action-btn"
|
|
>
|
|
<mat-icon>refresh</mat-icon>
|
|
Retake Quiz
|
|
</button>
|
|
|
|
<button
|
|
mat-raised-button
|
|
(click)="goToDashboard()"
|
|
class="action-btn"
|
|
>
|
|
<mat-icon>dashboard</mat-icon>
|
|
Dashboard
|
|
</button>
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|