feat: implement password reset functionality and global search feature

- Added forgot password and reset password APIs in the LMS service.
- Created database migrations for password reset tokens and xAPI statements.
- Implemented global search functionality with indexing for courses, lessons, discussions, and announcements.
- Developed frontend pages for forgot password and reset password.
- Introduced SCORM player component to handle xAPI statements tracking.
This commit is contained in:
2026-04-22 16:44:03 -04:00
parent 77eceee2f3
commit 0d6f1c9f9c
19 changed files with 1353 additions and 19 deletions
+38
View File
@@ -224,9 +224,22 @@ export interface Block {
initial_code?: string;
solution?: string;
test_cases?: { description: string; expected: string }[];
// SCORM/xAPI fields
launch_url?: string;
metadata?: any;
}
export interface TrackXapiPayload {
course_id: string;
lesson_id: string;
verb: string;
object_id: string;
score?: number;
progress?: number;
completed?: boolean;
raw_statement?: unknown;
}
export interface CourseInstructor {
id: string;
course_id: string;
@@ -607,6 +620,31 @@ export const lmsApi = {
});
},
async forgotPassword(email: string): Promise<{ message: string }> {
return apiFetch('/auth/forgot-password', {
method: 'POST',
body: JSON.stringify({ email })
});
},
async resetPassword(token: string, new_password: string): Promise<{ message: string }> {
return apiFetch('/auth/reset-password', {
method: 'POST',
body: JSON.stringify({ token, new_password })
});
},
async globalSearch(q: string, limit = 20): Promise<{ query: string; total: number; results: Array<{ id: string; kind: string; title: string; snippet?: string; url: string; course_id?: string; course_title?: string }> }> {
return apiFetch(`/search?q=${encodeURIComponent(q)}&limit=${limit}`);
},
async trackXapiStatement(payload: TrackXapiPayload): Promise<{ id: string; message: string }> {
return apiFetch('/xapi/statements', {
method: 'POST',
body: JSON.stringify(payload)
});
},
async getMe(): Promise<User> {
return apiFetch('/auth/me', {}, false);
},