feat: add certificates, groups, support system, and moderation

Backend changes:
- Add Certificate generation service with beautiful HTML templates
- Add CourseGroup, GroupMember, GroupMessage models for group collaboration
- Add Homework and HomeworkSubmission models with AI + teacher grading
- Add SupportTicket and TicketMessage models for help desk
- Add Moderation API for admin/moderator course approval workflow
- All new modules: CertificatesModule, GroupsModule, SupportModule, ModerationModule

Frontend changes:
- Add certificate download button when course completed
- Update course page to load enrollment progress from backend
- Integrate lesson completion with backend API

Database schema now supports:
- Course groups with chat functionality
- Homework assignments with dual AI/human grading
- Support ticket system with admin responses
- Full moderation workflow (PENDING_REVIEW -> PUBLISHED/REJECTED)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
root
2026-02-06 10:50:04 +00:00
parent 2ed65f5678
commit 5ddb3db1ac
16 changed files with 605 additions and 1 deletions

View File

@ -0,0 +1,32 @@
import { Controller, Post, Get, Param, Body } from '@nestjs/common';
import { ApiTags, ApiBearerAuth } from '@nestjs/swagger';
import { GroupsService } from './groups.service';
import { CurrentUser } from '../auth/decorators/current-user.decorator';
import { User } from '@coursecraft/database';
@ApiTags('groups')
@Controller('groups')
@ApiBearerAuth()
export class GroupsController {
constructor(private groupsService: GroupsService) {}
@Post()
async createGroup(@Body() body: { courseId: string; name: string; description?: string }, @CurrentUser() user: User): Promise<any> {
return this.groupsService.createGroup(body.courseId, user.id, body.name, body.description);
}
@Post(':groupId/members')
async addMember(@Param('groupId') groupId: string, @Body('userId') userId: string): Promise<any> {
return this.groupsService.addMember(groupId, userId);
}
@Get(':groupId/messages')
async getMessages(@Param('groupId') groupId: string, @CurrentUser() user: User): Promise<any> {
return this.groupsService.getGroupMessages(groupId, user.id);
}
@Post(':groupId/messages')
async sendMessage(@Param('groupId') groupId: string, @Body('content') content: string, @CurrentUser() user: User): Promise<any> {
return this.groupsService.sendMessage(groupId, user.id, content);
}
}