Skip to content

Commit c264fcd

Browse files
merge: hotfix v1.0.16
2 parents 106fd68 + 8d47e23 commit c264fcd

6 files changed

Lines changed: 79 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,3 +1158,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
11581158
- Added component coverage for the dashboard Question Progress section, guest prompt, progress toolbar, confirmation modal, and Q&A integration
11591159
- Added hook coverage for authenticated loading, optimistic viewed/bookmark updates, rollback behavior, reset semantics, and focus synchronization
11601160
- Added API coverage for topic progress, individual-question mutations, authentication guards, and saved-question filtering
1161+
1162+
## [1.0.16] - 2026-08-30
1163+
1164+
### Fixed
1165+
1166+
- Applied the missing `0035_daffy_captain_cross.sql` production migration so authenticated Q&A viewed and bookmarked progress can load and persist
1167+
- Isolated dashboard Q&A progress loading so a temporary failure in the optional learning-progress section no longer prevents the entire dashboard from rendering
1168+
- Bumped the frontend package version to `1.0.16`

frontend/app/[locale]/dashboard/page.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { getUserGlobalRank, getUserProfile } from '@/db/queries/users';
2121
import { redirect } from '@/i18n/routing';
2222
import { computeAchievements } from '@/lib/achievements';
2323
import { getCurrentUser } from '@/lib/auth';
24+
import { loadQuestionProgressSafely } from '@/lib/dashboard-question-progress';
2425
import { getUserStatsForAchievements } from '@/lib/user-stats';
2526

2627
export async function generateMetadata({
@@ -63,7 +64,11 @@ export default async function DashboardPage({
6364
getUserLastAttemptPerQuiz(session.id, locale),
6465
getUserGlobalRank(session.id),
6566
getUserStatsForAchievements(session.id),
66-
getUserQuestionProgressForDashboard(session.id, locale),
67+
loadQuestionProgressSafely(
68+
getUserQuestionProgressForDashboard,
69+
session.id,
70+
locale
71+
),
6772
]);
6873

6974
const totalAttempts = attempts.length;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type { DashboardQuestionProgress } from '@/db/queries/question-progress';
2+
3+
type QuestionProgressLoader = (
4+
userId: string,
5+
locale: string
6+
) => Promise<DashboardQuestionProgress[]>;
7+
8+
export async function loadQuestionProgressSafely(
9+
loadProgress: QuestionProgressLoader,
10+
userId: string,
11+
locale: string
12+
): Promise<DashboardQuestionProgress[]> {
13+
try {
14+
return await loadProgress(userId, locale);
15+
} catch (error) {
16+
console.error('[dashboard] Failed to load question progress', error);
17+
return [];
18+
}
19+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { describe, expect, it, vi } from 'vitest';
2+
3+
import { loadQuestionProgressSafely } from '@/lib/dashboard-question-progress';
4+
5+
describe('loadQuestionProgressSafely', () => {
6+
it('returns loaded question progress', async () => {
7+
const progress = [
8+
{
9+
categoryId: 'category-1',
10+
categorySlug: 'git',
11+
categoryTitle: 'Git',
12+
totalQuestions: 100,
13+
viewedCount: 3,
14+
bookmarkedCount: 1,
15+
lastOpenedAt: null,
16+
lastActivityAt: null,
17+
lastOpenedQuestionId: null,
18+
},
19+
];
20+
const loadProgress = vi.fn().mockResolvedValue(progress);
21+
22+
await expect(
23+
loadQuestionProgressSafely(loadProgress, 'user-1', 'en')
24+
).resolves.toEqual(progress);
25+
expect(loadProgress).toHaveBeenCalledWith('user-1', 'en');
26+
});
27+
28+
it('returns an empty section when progress loading fails', async () => {
29+
const error = new Error('database unavailable');
30+
const loadProgress = vi.fn().mockRejectedValue(error);
31+
const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {});
32+
33+
await expect(
34+
loadQuestionProgressSafely(loadProgress, 'user-1', 'en')
35+
).resolves.toEqual([]);
36+
expect(consoleError).toHaveBeenCalledWith(
37+
'[dashboard] Failed to load question progress',
38+
error
39+
);
40+
41+
consoleError.mockRestore();
42+
});
43+
});

frontend/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "frontend",
3-
"version": "1.0.15",
3+
"version": "1.0.16",
44
"private": true,
55
"scripts": {
66
"dev": "next dev",

0 commit comments

Comments
 (0)