life-manager/codebase/features/learning/backend/learning.controller.ts
Claude Code 44deba3852 feat(learning): Implement comprehensive learning path with income tracking integration
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-03-17 17:51:05 -07:00

137 lines
4.6 KiB
TypeScript

import {
Body,
Controller,
Delete,
Get,
HttpCode,
HttpStatus,
Param,
Patch,
Post,
Query,
} from '@nestjs/common';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { LearningService } from './learning.service';
import { CreateLearningPathDto } from './dto/create-learning-path.dto';
import { UpdateLearningPathDto } from './dto/update-learning-path.dto';
import { CreateLessonDto } from './dto/create-lesson.dto';
import { UpdateLessonDto } from './dto/update-lesson.dto';
import { RecordReviewDto } from './dto/record-review.dto';
import { QueryLearningPathsDto } from './dto/query-learning-paths.dto';
import { QueryLessonsDto } from './dto/query-lessons.dto';
import type { LearningPath } from './entities/learning-path.entity';
import type { Lesson } from './entities/lesson.entity';
import type { LessonProgress } from './entities/lesson-progress.entity';
import type { ReviewLog } from './entities/review-log.entity';
import type { PaginatedResponse } from '@common/pagination.dto';
import type { LearningDueResponse, LearningPathStats } from '@life-platform/shared';
@ApiTags('Learning')
@Controller('learning')
export class LearningController {
constructor(private readonly learningService: LearningService) {}
// --- Paths ---
@Get('paths')
@ApiOperation({ summary: 'List learning paths' })
findAllPaths(@Query() query: QueryLearningPathsDto): Promise<PaginatedResponse<LearningPath>> {
return this.learningService.findAllPaths(query as QueryLearningPathsDto & Record<string, unknown>);
}
@Get('paths/:id')
@ApiOperation({ summary: 'Get learning path with lessons and progress' })
findOnePath(@Param('id') id: string): Promise<LearningPath> {
return this.learningService.findOnePath(id);
}
@Post('paths')
@ApiOperation({ summary: 'Create learning path' })
createPath(@Body() dto: CreateLearningPathDto): Promise<LearningPath> {
return this.learningService.createPath(dto);
}
@Patch('paths/:id')
@ApiOperation({ summary: 'Update learning path' })
updatePath(@Param('id') id: string, @Body() dto: UpdateLearningPathDto): Promise<LearningPath> {
return this.learningService.updatePath(id, dto);
}
@Delete('paths/:id')
@HttpCode(HttpStatus.NO_CONTENT)
@ApiOperation({ summary: 'Delete learning path' })
removePath(@Param('id') id: string): Promise<void> {
return this.learningService.removePath(id);
}
@Get('paths/:id/stats')
@ApiOperation({ summary: 'Get learning path completion stats' })
getPathStats(@Param('id') id: string): Promise<LearningPathStats> {
return this.learningService.getPathStats(id);
}
@Get('paths/:id/lessons')
@ApiOperation({ summary: 'List lessons in a learning path' })
findPathLessons(
@Param('id') id: string,
@Query() query: QueryLessonsDto,
): Promise<PaginatedResponse<Lesson>> {
return this.learningService.findLessons({
...query,
learningPathId: id,
} as QueryLessonsDto & Record<string, unknown>);
}
// --- Lessons ---
@Post('lessons')
@ApiOperation({ summary: 'Create lesson' })
createLesson(@Body() dto: CreateLessonDto): Promise<Lesson> {
return this.learningService.createLesson(dto);
}
@Get('lessons/:id')
@ApiOperation({ summary: 'Get lesson with progress' })
findOneLesson(@Param('id') id: string): Promise<Lesson> {
return this.learningService.findOneLesson(id);
}
@Patch('lessons/:id')
@ApiOperation({ summary: 'Update lesson' })
updateLesson(@Param('id') id: string, @Body() dto: UpdateLessonDto): Promise<Lesson> {
return this.learningService.updateLesson(id, dto);
}
@Delete('lessons/:id')
@HttpCode(HttpStatus.NO_CONTENT)
@ApiOperation({ summary: 'Delete lesson' })
removeLesson(@Param('id') id: string): Promise<void> {
return this.learningService.removeLesson(id);
}
@Post('lessons/:id/review')
@ApiOperation({ summary: 'Record a review (SM-2 update)' })
recordReview(@Param('id') id: string, @Body() dto: RecordReviewDto): Promise<LessonProgress> {
return this.learningService.recordReview(id, dto);
}
@Get('lessons/:id/reviews')
@ApiOperation({ summary: 'Review history for a lesson' })
getReviewHistory(@Param('id') id: string): Promise<ReviewLog[]> {
return this.learningService.getReviewHistory(id);
}
// --- Due / Stats ---
@Get('due')
@ApiOperation({ summary: "What's due for review now?" })
getDue(@Query('limit') limit?: string): Promise<LearningDueResponse> {
return this.learningService.getDue(limit ? parseInt(limit, 10) : undefined);
}
@Get('stats')
@ApiOperation({ summary: 'Stats across all active learning paths' })
getAllStats(): Promise<LearningPathStats[]> {
return this.learningService.getAllPathStats();
}
}