add changes

This commit is contained in:
AD2025
2025-12-19 21:18:47 +02:00
parent b2c564225e
commit 665919c1e2
20 changed files with 841 additions and 879 deletions

View File

@@ -15,7 +15,7 @@ import { UserService } from '../../core/services/user.service';
import { AuthService } from '../../core/services/auth.service';
import { CategoryService } from '../../core/services/category.service';
import { QuizHistoryResponse, PaginationInfo } from '../../core/models/dashboard.model';
import { QuizSession } from '../../core/models/quiz.model';
import { QuizSession, QuizSessionHistory } from '../../core/models/quiz.model';
import { Category } from '../../core/models/category.model';
@Component({
@@ -44,32 +44,32 @@ export class QuizHistoryComponent implements OnInit {
private categoryService = inject(CategoryService);
private router = inject(Router);
private route = inject(ActivatedRoute);
// Signals
isLoading = signal<boolean>(true);
history = signal<QuizSession[]>([]);
history = signal<QuizSessionHistory[]>([]);
pagination = signal<PaginationInfo | null>(null);
categories = signal<Category[]>([]);
error = signal<string | null>(null);
// Filter and sort state
currentPage = signal<number>(1);
pageSize = signal<number>(10);
selectedCategory = signal<string | null>(null);
sortBy = signal<'date' | 'score'>('date');
// Table columns
displayedColumns: string[] = ['date', 'category', 'score', 'time', 'status', 'actions'];
// Computed values
isEmpty = computed(() => this.history().length === 0 && !this.isLoading());
totalItems = computed(() => this.pagination()?.totalItems || 0);
ngOnInit(): void {
this.loadCategories();
this.loadHistoryFromRoute();
}
/**
* Load categories for filter
*/
@@ -83,7 +83,7 @@ export class QuizHistoryComponent implements OnInit {
}
});
}
/**
* Load history based on route query params
*/
@@ -93,31 +93,31 @@ export class QuizHistoryComponent implements OnInit {
const limit = params['limit'] ? parseInt(params['limit'], 10) : 10;
const category = params['category'] || null;
const sortBy = params['sortBy'] || 'date';
this.currentPage.set(page);
this.pageSize.set(limit);
this.selectedCategory.set(category);
this.sortBy.set(sortBy);
this.loadHistory();
});
}
/**
* Load quiz history
*/
loadHistory(): void {
const state: any = (this.authService as any).authState();
const user = state?.user;
if (!user || !user.id) {
this.router.navigate(['/login']);
return;
}
this.isLoading.set(true);
this.error.set(null);
(this.userService as any).getHistory(
user.id,
this.currentPage(),
@@ -126,8 +126,8 @@ export class QuizHistoryComponent implements OnInit {
this.sortBy()
).subscribe({
next: (response: QuizHistoryResponse) => {
this.history.set(response.sessions || []);
this.pagination.set(response.pagination);
this.history.set(response.data.sessions || []);
this.pagination.set(response.data.pagination);
this.isLoading.set(false);
},
error: (err: any) => {
@@ -137,7 +137,7 @@ export class QuizHistoryComponent implements OnInit {
}
});
}
/**
* Handle page change
*/
@@ -146,7 +146,7 @@ export class QuizHistoryComponent implements OnInit {
this.pageSize.set(event.pageSize);
this.updateUrlAndLoad();
}
/**
* Handle category filter change
*/
@@ -155,7 +155,7 @@ export class QuizHistoryComponent implements OnInit {
this.currentPage.set(1); // Reset to first page
this.updateUrlAndLoad();
}
/**
* Handle sort change
*/
@@ -164,7 +164,7 @@ export class QuizHistoryComponent implements OnInit {
this.currentPage.set(1); // Reset to first page
this.updateUrlAndLoad();
}
/**
* Update URL with query params and reload data
*/
@@ -174,18 +174,18 @@ export class QuizHistoryComponent implements OnInit {
limit: this.pageSize(),
sortBy: this.sortBy()
};
if (this.selectedCategory()) {
queryParams.category = this.selectedCategory();
}
this.router.navigate([], {
relativeTo: this.route,
queryParams,
queryParamsHandling: 'merge'
});
}
/**
* View quiz results
*/
@@ -194,7 +194,7 @@ export class QuizHistoryComponent implements OnInit {
this.router.navigate(['/quiz', sessionId, 'results']);
}
}
/**
* Review quiz
*/
@@ -203,13 +203,13 @@ export class QuizHistoryComponent implements OnInit {
this.router.navigate(['/quiz', sessionId, 'review']);
}
}
/**
* Format date
*/
formatDate(dateString: string | undefined): string {
if (!dateString) return 'N/A';
const date = new Date(dateString);
return date.toLocaleDateString('en-US', {
year: 'numeric',
@@ -219,23 +219,23 @@ export class QuizHistoryComponent implements OnInit {
minute: '2-digit'
});
}
/**
* Format duration
*/
formatDuration(seconds: number | undefined): string {
if (!seconds) return '0s';
const minutes = Math.floor(seconds / 60);
const secs = seconds % 60;
if (minutes === 0) {
return `${secs}s`;
}
return `${minutes}m ${secs}s`;
}
/**
* Get score color
*/
@@ -245,7 +245,7 @@ export class QuizHistoryComponent implements OnInit {
if (percentage >= 60) return 'warning';
return 'error';
}
/**
* Get status badge class
*/
@@ -261,7 +261,7 @@ export class QuizHistoryComponent implements OnInit {
return '';
}
}
/**
* Export to CSV
*/
@@ -269,32 +269,32 @@ export class QuizHistoryComponent implements OnInit {
if (this.history().length === 0) {
return;
}
// Create CSV header
const headers = ['Date', 'Category', 'Score', 'Total Questions', 'Percentage', 'Time Spent', 'Status'];
const csvRows = [headers.join(',')];
// Add data rows
this.history().forEach(session => {
const percentage = ((session.score / session.totalQuestions) * 100).toFixed(2);
const percentage = ((session.score.earned / session.questions.total) * 100).toFixed(2);
const row = [
this.formatDate(session.completedAt || session.startedAt),
session.categoryName || 'Unknown',
session.score.toString(),
session.totalQuestions.toString(),
session.category?.name || 'Unknown',
session.score.earned.toString(),
session.questions.total.toString(),
`${percentage}%`,
this.formatDuration(session.timeSpent),
this.formatDuration(session.time.spent),
session.status
];
csvRows.push(row.join(','));
});
// Create blob and download
const csvContent = csvRows.join('\n');
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', `quiz-history-${new Date().toISOString().split('T')[0]}.csv`);
link.style.visibility = 'hidden';
@@ -302,7 +302,7 @@ export class QuizHistoryComponent implements OnInit {
link.click();
document.body.removeChild(link);
}
/**
* Refresh history
*/