feat(activities): editable stages with tab and kanban views

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-07 11:18:53 +03:30
co-authored by Cursor
parent b4ffef9b6f
commit aa2f39256a
15 changed files with 1860 additions and 88 deletions
@@ -18,15 +18,22 @@ import { FileInterceptor } from '@nestjs/platform-express';
import { memoryStorage } from 'multer';
import type { Response } from 'express';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { RolesGuard } from '../auth/roles.guard';
import { Roles } from '../auth/roles.decorator';
import { CurrentUser } from '../auth/current-user.decorator';
import type { Actor } from '../common/record-scope';
import { ActivitiesService } from './activities.service';
import { ActivitiesExcelService } from './activities-excel.service';
import { ActivityStagesService } from './activity-stages.service';
import {
CreateActivityDto,
CreateActivityStageDto,
ImportActivityRowsDto,
ListActivitiesQueryDto,
MoveActivityStageDto,
ReorderActivityStagesDto,
UpdateActivityDto,
UpdateActivityStageDto,
} from './dto';
import { brand } from '@mento/shared';
@@ -41,6 +48,7 @@ export class ActivitiesController {
constructor(
private readonly activitiesService: ActivitiesService,
private readonly excelService: ActivitiesExcelService,
private readonly stagesService: ActivityStagesService,
) {}
@Get('summary')
@@ -48,6 +56,63 @@ export class ActivitiesController {
return this.activitiesService.summary(user.organizationId, user);
}
@Get('stages')
listStages(@CurrentUser() user: Actor) {
return this.stagesService.list(user.organizationId);
}
@Post('stages')
@UseGuards(RolesGuard)
@Roles('owner', 'admin')
createStage(@CurrentUser() user: Actor, @Body() dto: CreateActivityStageDto) {
return this.stagesService.create(user.organizationId, dto);
}
@Patch('stages/reorder')
@UseGuards(RolesGuard)
@Roles('owner', 'admin')
reorderStages(@CurrentUser() user: Actor, @Body() dto: ReorderActivityStagesDto) {
return this.stagesService.reorder(user.organizationId, dto.stageIds);
}
@Patch('stages/:id')
@UseGuards(RolesGuard)
@Roles('owner', 'admin')
updateStage(
@CurrentUser() user: Actor,
@Param('id') id: string,
@Body() dto: UpdateActivityStageDto,
) {
return this.stagesService.update(user.organizationId, id, dto);
}
@Delete('stages/:id')
@UseGuards(RolesGuard)
@Roles('owner', 'admin')
async removeStage(@CurrentUser() user: Actor, @Param('id') id: string) {
await this.stagesService.remove(user.organizationId, id);
return { ok: true };
}
@Get('stage-counts')
stageCounts(
@CurrentUser() user: Actor,
@Query() query: ListActivitiesQueryDto,
) {
return this.activitiesService.stageCounts(
user.organizationId,
user,
query.filter ?? 'all',
query.q,
query.desk,
{
type: query.type,
status: query.status,
assigneeId: query.assigneeId,
},
);
}
@Get()
list(
@CurrentUser() user: Actor,
@@ -75,6 +140,7 @@ export class ActivitiesController {
status: query.status,
assigneeId: query.assigneeId,
},
query.stageId ? { stageId: query.stageId } : undefined,
);
}
@@ -174,6 +240,15 @@ export class ActivitiesController {
return this.activitiesService.update(user.organizationId, id, user, dto);
}
@Patch(':id/stage')
moveStage(
@CurrentUser() user: Actor,
@Param('id') id: string,
@Body() dto: MoveActivityStageDto,
) {
return this.activitiesService.moveToStage(user.organizationId, id, user, dto.stageId);
}
@Patch(':id/complete')
complete(@CurrentUser() user: Actor, @Param('id') id: string) {
return this.activitiesService.complete(user.organizationId, id, user);