lots of work done

This commit is contained in:
2026-03-02 16:23:29 -08:00
parent be4873283d
commit ef09a76bb4
25 changed files with 644 additions and 157 deletions
@@ -1,34 +0,0 @@
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { ApiResult } from '../classes/api-result';
// *****************************************************************
// TODO: This dummy service should be replaced by SaveProgressEvent,
// which will POST real data to the API.
// *****************************************************************
@Injectable({
providedIn: 'root',
})
export class DummySaveProgressEvent {
// ************************** Constructor **************************
// ************************** Declarations *************************
// ************************** Properties ***************************
// ************************ Public Methods *************************
// *****************************************************************
// TODO: DUMMY — Always returns success. Replace with
// SaveProgressEvent calling POST /api/progress-events
// *****************************************************************
async save(studentId: string, goalId: string, content: string): Promise<ApiResult> {
return ApiResult.empty();
}
// ************************ Event Handlers *************************
// ********************** Support Procedures ***********************
}
@@ -1,89 +0,0 @@
import { Injectable } from '@angular/core';
import { ApiResult } from '../classes/api-result';
import { StudentGoalSummary } from '../classes/student-goal';
// *****************************************************************
// TODO: This dummy service should be replaced by StudentGoalService,
// which will fetch real data from the API.
// *****************************************************************
@Injectable({
providedIn: 'root',
})
export class DummyStudentGoalService {
// ************************** Constructor **************************
// ************************** Declarations *************************
// *****************************************************************
// TODO: DUMMY DATA — Maps studentId to identifier and goals.
// Replace with StudentGoalService calling
// GET /api/students/:id/goals
// *****************************************************************
private readonly data: Record<string, StudentGoalSummary> = {
'1': {
studentIdentifier: 'J.B',
goals: [
{ goalId: 'g1', title: 'Improve reading comprehension', description: 'Work on main-idea identification and inference skills across fiction and nonfiction texts.', category: 'Academics', progressEventCount: 5 },
{ goalId: 'g2', title: 'Complete algebra module', description: 'Finish all units in the algebra course including linear equations and graphing.', category: 'Academics', progressEventCount: 2 },
{ goalId: 'g3', title: 'Weekly journal entries', description: 'Write a reflective journal entry each week to build writing fluency.', category: 'Communication', progressEventCount: 8 },
],
},
'2': {
studentIdentifier: 'M.K',
goals: [
{ goalId: 'g4', title: 'Pass certification exam', description: 'Prepare for and pass the industry certification exam by end of quarter.', category: 'Career Readiness', progressEventCount: 3 },
{ goalId: 'g5', title: 'Attendance above 90%', description: 'Maintain consistent attendance throughout the term.', category: 'Behavior', progressEventCount: 0 },
{ goalId: 'g6', title: 'Complete internship hours', description: 'Log the required 40 hours at the assigned internship site.', category: 'Career Readiness', progressEventCount: 12 },
{ goalId: 'g7', title: 'Portfolio project', description: 'Build a personal portfolio showcasing completed coursework and projects.', category: 'Career Readiness', progressEventCount: 1 },
],
},
'3': {
studentIdentifier: 'A.R',
goals: [
{ goalId: 'g8', title: 'GED preparation', description: 'Complete practice tests and study modules for GED math and reading sections.', category: 'Academics', progressEventCount: 6 },
{ goalId: 'g9', title: 'Resume workshop', description: 'Attend the resume writing workshop and produce a final draft.', category: 'Career Readiness', progressEventCount: 0 },
],
},
'4': {
studentIdentifier: 'T.W',
goals: [
{ goalId: 'g10', title: 'Public speaking practice', description: 'Present in front of the class at least once per month.', category: 'Communication', progressEventCount: 4 },
{ goalId: 'g11', title: 'Math placement improvement', description: 'Move up one placement level in math by the end of the semester.', category: 'Academics', progressEventCount: 7 },
{ goalId: 'g12', title: 'Conflict resolution strategies', description: 'Learn and apply at least three de-escalation techniques.', category: 'Behavior', progressEventCount: 2 },
{ goalId: 'g13', title: 'Daily attendance streak', description: 'Achieve a 30-day unbroken attendance streak.', category: 'Behavior', progressEventCount: 0 },
{ goalId: 'g14', title: 'Job shadow experience', description: 'Complete a job shadow day in a field of interest.', category: 'Career Readiness', progressEventCount: 1 },
],
},
'5': {
studentIdentifier: 'L.C',
goals: [
{ goalId: 'g15', title: 'Improve typing speed', description: 'Reach 40 WPM with 95% accuracy on typing assessments.', category: 'Career Readiness', progressEventCount: 3 },
],
},
};
// ************************** Properties ***************************
// ************************ Public Methods *************************
// *****************************************************************
// Returns the student's identifier and their list of goals,
// given a student ID.
// *****************************************************************
async getGoalsForStudent(studentId: string): Promise<ApiResult<StudentGoalSummary | null>> {
var goals = this.data[studentId] ?? null;
if (goals === null)
{
return ApiResult.fail('Student not found');
}
return ApiResult.ok(goals);
}
// ************************ Event Handlers *************************
// ********************** Support Procedures ***********************
}
@@ -1,17 +1,60 @@
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { StudentCardDto } from '../classes/student-card.dto';
import { ApiResult } from '../classes/api-result';
import { StudentGoalSummary } from '../classes/student-goal';
@Injectable({
providedIn: 'root',
})
export class StudentService {
export class DummyStudentService {
// ************************** Constructor **************************
// ************************** Declarations *************************
private readonly data: Record<string, StudentGoalSummary> = {
'1': {
studentIdentifier: 'J.B',
goals: [
{ goalId: 'g1', goalParentId: null, title: 'Improve reading comprehension', description: 'Work on main-idea identification and inference skills across fiction and nonfiction texts.', category: 'Academics', progressEventCount: 5 },
{ goalId: 'g2', goalParentId: null, title: 'Complete algebra module', description: 'Finish all units in the algebra course including linear equations and graphing.', category: 'Academics', progressEventCount: 2 },
{ goalId: 'g3', goalParentId: null, title: 'Weekly journal entries', description: 'Write a reflective journal entry each week to build writing fluency.', category: 'Communication', progressEventCount: 8 },
],
},
'2': {
studentIdentifier: 'M.K',
goals: [
{ goalId: 'g4', goalParentId: null, title: 'Pass certification exam', description: 'Prepare for and pass the industry certification exam by end of quarter.', category: 'Career Readiness', progressEventCount: 3 },
{ goalId: 'g5', goalParentId: null, title: 'Attendance above 90%', description: 'Maintain consistent attendance throughout the term.', category: 'Behavior', progressEventCount: 0 },
{ goalId: 'g6', goalParentId: null, title: 'Complete internship hours', description: 'Log the required 40 hours at the assigned internship site.', category: 'Career Readiness', progressEventCount: 12 },
{ goalId: 'g7', goalParentId: null, title: 'Portfolio project', description: 'Build a personal portfolio showcasing completed coursework and projects.', category: 'Career Readiness', progressEventCount: 1 },
],
},
'3': {
studentIdentifier: 'A.R',
goals: [
{ goalId: 'g8', goalParentId: null, title: 'GED preparation', description: 'Complete practice tests and study modules for GED math and reading sections.', category: 'Academics', progressEventCount: 6 },
{ goalId: 'g9', goalParentId: null, title: 'Resume workshop', description: 'Attend the resume writing workshop and produce a final draft.', category: 'Career Readiness', progressEventCount: 0 },
],
},
'4': {
studentIdentifier: 'T.W',
goals: [
{ goalId: 'g10', goalParentId: null, title: 'Public speaking practice', description: 'Present in front of the class at least once per month.', category: 'Communication', progressEventCount: 4 },
{ goalId: 'g11', goalParentId: null, title: 'Math placement improvement', description: 'Move up one placement level in math by the end of the semester.', category: 'Academics', progressEventCount: 7 },
{ goalId: 'g12', goalParentId: null, title: 'Conflict resolution strategies', description: 'Learn and apply at least three de-escalation techniques.', category: 'Behavior', progressEventCount: 2 },
{ goalId: 'g13', goalParentId: null, title: 'Daily attendance streak', description: 'Achieve a 30-day unbroken attendance streak.', category: 'Behavior', progressEventCount: 0 },
{ goalId: 'g14', goalParentId: null, title: 'Job shadow experience', description: 'Complete a job shadow day in a field of interest.', category: 'Career Readiness', progressEventCount: 1 },
],
},
'5': {
studentIdentifier: 'L.C',
goals: [
{ goalId: 'g15', goalParentId: null, title: 'Improve typing speed', description: 'Reach 40 WPM with 95% accuracy on typing assessments.', category: 'Career Readiness', progressEventCount: 3 },
],
},
};
// ************************** Properties ***************************
// ************************ Public Methods *************************
@@ -20,7 +63,7 @@ export class StudentService {
// Returns student card summaries. Currently returns dummy data
// until the API endpoint is available.
// *****************************************************************
async getStudentCards(): Promise<ApiResult<StudentCardDto[]>> {
async getMyStudents(): Promise<ApiResult<StudentCardDto[]>> {
var payload = [
{
studentId: '1',
@@ -51,24 +94,22 @@ export class StudentService {
return ApiResult.ok(payload);
}
// *****************************************************************
// TODO: DUMMY DATA — Replace with getStudentsPerUser, which will
// call GET /api/users/:id/students to return real data.
// Returns students assigned to the current user with their
// identifier, age, goal count, and progress event count.
// *****************************************************************
async getStudentsForUser(): Promise<ApiResult<StudentCardDto[]>> {
var payload = [
{ studentId: '1', identifier: 'J.B', expectedGradDate: new Date('2027-02-27'), lastEntryDate: new Date('2026-02-21'), goalCount: 3, progressEventCount: 5 },
{ studentId: '2', identifier: 'M.K', expectedGradDate: new Date('2027-02-27'), lastEntryDate: new Date('2026-02-25'), goalCount: 4, progressEventCount: 8 },
{ studentId: '3', identifier: 'A.R', expectedGradDate: new Date('2027-02-27'), lastEntryDate: null, goalCount: 2, progressEventCount: 0 },
{ studentId: '4', identifier: 'T.W', expectedGradDate: new Date('2027-02-27'), lastEntryDate: new Date('2026-02-18'), goalCount: 5, progressEventCount: 12 },
{ studentId: '5', identifier: 'L.C', expectedGradDate: new Date('2027-02-27'), lastEntryDate: new Date('2026-02-27'), goalCount: 1, progressEventCount: 2 },
];
async getGoalsForStudent(studentId: string): Promise<ApiResult<StudentGoalSummary | null>> {
var goals = this.data[studentId] ?? null;
if (goals === null)
{
return ApiResult.fail('Student not found');
}
return ApiResult.ok(goals);
return ApiResult.ok(payload);
}
async addProgressEvent(studentId: string, goalId: string, content: string): Promise<ApiResult> {
return ApiResult.empty();
}
// ************************ Event Handlers *************************
// ********************** Support Procedures ***********************
@@ -0,0 +1,92 @@
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { inject, Injectable } from '@angular/core';
import { firstValueFrom } from 'rxjs';
import { environment } from '../../../environments/environment';
import { ApiResult } from '../classes/api-result';
import { ResponseResult } from '../classes/auth.models';
import { describeHttpError } from '../classes/http-errors';
import { CreateStudentDto } from '../classes/create-student.dto';
import { StudentCardDto } from '../classes/student-card.dto';
import { StudentGoalSummary } from '../classes/student-goal';
@Injectable({
providedIn: 'root',
})
export class StudentService {
// ************************** Constructor **************************
// ************************** Declarations *************************
private readonly http = inject(HttpClient);
private readonly base = environment.apiBaseUrl;
// ************************** Properties ***************************
// ************************ Public Methods *************************
// *****************************************************************
// Returns student card summaries for the authenticated user.
// *****************************************************************
async getMyStudents(): Promise<ApiResult<StudentCardDto[]>> {
try {
const result = await firstValueFrom(
this.http.get<ResponseResult<StudentCardDto[]>>(`${this.base}/api/Student/my`)
);
return result.success && result.data
? ApiResult.ok(result.data)
: ApiResult.fail(result.message);
} catch (error) {
return ApiResult.fail(describeHttpError(error as HttpErrorResponse));
}
}
// *****************************************************************
// Returns goal summary for a given student.
// *****************************************************************
async getGoalsForStudent(studentId: string): Promise<ApiResult<StudentGoalSummary | null>> {
try {
const result = await firstValueFrom(
this.http.get<ResponseResult<StudentGoalSummary>>(`${this.base}/api/Student/${studentId}/goals`)
);
return result.success && result.data
? ApiResult.ok(result.data)
: ApiResult.fail(result.message);
} catch (error) {
return ApiResult.fail(describeHttpError(error as HttpErrorResponse));
}
}
// *****************************************************************
// Creates a new student and returns the created student card.
// *****************************************************************
async createStudent(data: CreateStudentDto): Promise<ApiResult<StudentCardDto>> {
try {
const result = await firstValueFrom(
this.http.post<ResponseResult<StudentCardDto>>(`${this.base}/api/Student`, data)
);
return result.success && result.data
? ApiResult.ok(result.data)
: ApiResult.fail(result.message);
} catch (error) {
return ApiResult.fail(describeHttpError(error as HttpErrorResponse));
}
}
async addProgressEvent(studentId: string, goalId: string, content: string): Promise<ApiResult> {
try {
const result = await firstValueFrom(
this.http.post<ResponseResult<void>>(`${this.base}/api/Student/${studentId}/progress-event`, { goalId, content })
);
return result.success
? ApiResult.empty()
: ApiResult.fail(result.message);
} catch (error) {
return ApiResult.fail(describeHttpError(error as HttpErrorResponse));
}
}
// ************************ Event Handlers *************************
// ********************** Support Procedures ***********************
}