feat(src/modules/cities/cities.controller.ts): добавляет ответы API для получения всех городов и районов

 feat(src/modules/chat/chat.controller.ts): добавляет ответы API для создания чата и получения сообщений

 feat(src/modules/greetings/greetings.controller.ts): добавляет ответы API для получения и создания приветствий

 feat(src/modules/likes/likes.controller.ts): добавляет ответы API для создания лайков и получения совпадений

 feat(src/modules/reports/reports.controller.ts): добавляет ответы API для создания и получения отчетов

 feat(src/modules/feed/feed.controller.ts): добавляет ответ API для получения отфильтрованного фида

 feat(src/auth/auth.controller.ts): добавляет ответы API для регистрации, входа и выхода пользователей

 feat(src/modules/media/media.controller.ts): добавляет ответы API для загрузки и получения медиа

 feat(src/modules/users/users.controller.ts): добавляет ответы API для получения текущего пользователя и управления пользователями

 feat(src/modules/tags/tags.controller.ts): добавляет ответы API для получения и создания тегов

 feat(src/modules/profiles/profiles.controller.ts): добавляет ответы API для управления профилями пользователей

 feat(src/modules/dates/dates.controller.ts): добавляет ответы API для создания и получения встреч
This commit is contained in:
Oscar
2026-06-08 14:22:50 +03:00
parent bc3e48bcad
commit 102b6b4026
24 changed files with 598 additions and 12 deletions

View File

@@ -1,12 +1,14 @@
import { Body, Controller, Post, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { AuthService } from './auth.service';
import { LoginDto } from './dto/login.dto';
import { RefreshTokenDto } from './dto/refresh-token.dto';
import { RegisterDto } from './dto/register.dto';
import { TokensResponseDto } from './dto/tokens-response.dto';
import { Public } from '../common/decorators/public.decorator';
import { CurrentUser } from '../common/decorators/current-user.decorator';
import { JwtAuthGuard } from '../common/guards/jwt-auth.guard';
import { MessageResponseDto } from '../common/dto/message-response.dto';
@ApiTags('auth')
@Controller('auth')
@@ -16,6 +18,7 @@ export class AuthController {
@Public()
@Post('register')
@ApiOperation({ summary: 'Register new user' })
@ApiResponse({ status: 201, type: TokensResponseDto })
register(@Body() dto: RegisterDto) {
return this.authService.register(dto);
}
@@ -23,6 +26,7 @@ export class AuthController {
@Public()
@Post('login')
@ApiOperation({ summary: 'Login with phone and password' })
@ApiResponse({ status: 201, type: TokensResponseDto })
login(@Body() dto: LoginDto) {
return this.authService.login(dto);
}
@@ -31,6 +35,7 @@ export class AuthController {
@Post('logout')
@ApiBearerAuth()
@ApiOperation({ summary: 'Logout current user' })
@ApiResponse({ status: 201, type: MessageResponseDto })
logout(@CurrentUser('id') userId: string) {
return this.authService.logout(userId);
}
@@ -38,6 +43,7 @@ export class AuthController {
@Public()
@Post('refresh')
@ApiOperation({ summary: 'Refresh access token' })
@ApiResponse({ status: 201, type: TokensResponseDto })
refresh(@Body() dto: RefreshTokenDto) {
return this.authService.refreshTokens(dto.refreshToken);
}
@@ -46,6 +52,7 @@ export class AuthController {
@Post('fcm-token')
@ApiBearerAuth()
@ApiOperation({ summary: 'Update FCM push token' })
@ApiResponse({ status: 201, type: MessageResponseDto })
updateFcmToken(
@CurrentUser('id') userId: string,
@Body('fcmToken') fcmToken: string,

View File

@@ -0,0 +1,9 @@
import { ApiProperty } from '@nestjs/swagger';
export class TokensResponseDto {
@ApiProperty({ example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' })
accessToken: string;
@ApiProperty({ example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' })
refreshToken: string;
}

View File

@@ -0,0 +1,6 @@
import { ApiProperty } from '@nestjs/swagger';
export class MessageResponseDto {
@ApiProperty({ example: 'Operation successful' })
message: string;
}

View File

@@ -1,10 +1,12 @@
import { Body, Controller, Delete, Get, Param, Post, Query, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiBearerAuth, ApiOperation, ApiQuery, ApiResponse, ApiTags } from '@nestjs/swagger';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { ChatService } from './chat.service';
import { CreateChatDto } from './dto/create-chat.dto';
import { SendMessageDto } from './dto/send-message.dto';
import { ChatDto, MessageDto } from './dto/chat-response.dto';
import { MessageResponseDto } from '../../common/dto/message-response.dto';
@ApiTags('chat')
@ApiBearerAuth()
@@ -15,12 +17,14 @@ export class ChatController {
@Post()
@ApiOperation({ summary: 'Open a chat for a match' })
@ApiResponse({ status: 201, type: ChatDto })
createChat(@CurrentUser('id') userId: string, @Body() dto: CreateChatDto) {
return this.chatService.createChat(userId, dto);
}
@Get()
@ApiOperation({ summary: 'Get active chats for a profile' })
@ApiResponse({ status: 200, type: [ChatDto] })
getChats(
@CurrentUser('id') userId: string,
@Query('profileId') profileId: string,
@@ -30,6 +34,9 @@ export class ChatController {
@Get(':chatId/messages')
@ApiOperation({ summary: 'Get chat messages' })
@ApiQuery({ name: 'page', required: false, schema: { default: 1, type: 'number' } })
@ApiQuery({ name: 'limit', required: false, schema: { default: 50, type: 'number' } })
@ApiResponse({ status: 200, type: [MessageDto] })
getMessages(
@CurrentUser('id') userId: string,
@Query('profileId') profileId: string,
@@ -42,6 +49,7 @@ export class ChatController {
@Post(':chatId/messages')
@ApiOperation({ summary: 'Send a message' })
@ApiResponse({ status: 201, type: MessageDto })
sendMessage(
@CurrentUser('id') userId: string,
@Query('profileId') profileId: string,
@@ -53,6 +61,7 @@ export class ChatController {
@Delete(':chatId')
@ApiOperation({ summary: 'Close a chat' })
@ApiResponse({ status: 200, type: MessageResponseDto })
closeChat(
@CurrentUser('id') userId: string,
@Query('profileId') profileId: string,

View File

@@ -0,0 +1,18 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
export class ChatDto {
@ApiProperty() id: string;
@ApiProperty() profile1Id: string;
@ApiProperty() profile2Id: string;
@ApiProperty({ enum: ['active', 'closed'] }) status: string;
}
export class MessageDto {
@ApiProperty() id: string;
@ApiProperty() chatId: string;
@ApiProperty() profileId: string;
@ApiPropertyOptional({ nullable: true }) text: string | null;
@ApiPropertyOptional({ nullable: true }) mediaUrl: string | null;
@ApiPropertyOptional({ enum: ['photo', 'voice', 'video'], nullable: true }) mediaType: string | null;
@ApiProperty() createdAt: string;
}

View File

@@ -1,10 +1,11 @@
import { Body, Controller, Get, Param, Post, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { Public } from '../../common/decorators/public.decorator';
import { Roles } from '../../common/decorators/roles.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { RolesGuard } from '../../common/guards/roles.guard';
import { CitiesService } from './cities.service';
import { CityResponseDto, DistrictResponseDto } from './dto/city-response.dto';
@ApiTags('cities')
@Controller('cities')
@@ -14,6 +15,7 @@ export class CitiesController {
@Public()
@Get()
@ApiOperation({ summary: 'Get all cities' })
@ApiResponse({ status: 200, type: [CityResponseDto] })
findAll() {
return this.citiesService.findAll();
}
@@ -21,6 +23,7 @@ export class CitiesController {
@Public()
@Get(':cityId/districts')
@ApiOperation({ summary: 'Get districts for a city' })
@ApiResponse({ status: 200, type: [DistrictResponseDto] })
findDistricts(@Param('cityId') cityId: string) {
return this.citiesService.findDistricts(cityId);
}
@@ -30,6 +33,7 @@ export class CitiesController {
@Roles('admin')
@Post()
@ApiOperation({ summary: 'Create city (admin only)' })
@ApiResponse({ status: 201, type: CityResponseDto })
createCity(@Body() body: { name: string; lat: number; lng: number }) {
return this.citiesService.createCity(body.name, body.lat, body.lng);
}
@@ -39,6 +43,7 @@ export class CitiesController {
@Roles('admin')
@Post(':cityId/districts')
@ApiOperation({ summary: 'Create district (admin only)' })
@ApiResponse({ status: 201, type: DistrictResponseDto })
createDistrict(@Param('cityId') cityId: string, @Body() body: { name: string }) {
return this.citiesService.createDistrict(cityId, body.name);
}

View File

@@ -0,0 +1,14 @@
import { ApiProperty } from '@nestjs/swagger';
export class CityResponseDto {
@ApiProperty() id: string;
@ApiProperty() name: string;
@ApiProperty() lat: string;
@ApiProperty() lng: string;
}
export class DistrictResponseDto {
@ApiProperty() id: string;
@ApiProperty() cityId: string;
@ApiProperty() name: string;
}

View File

@@ -1,10 +1,11 @@
import { Body, Controller, Get, Param, Patch, Post, Query, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { DatesService } from './dates.service';
import { CreateDateDto } from './dto/create-date.dto';
import { UpdateDateStatusDto } from './dto/update-date-status.dto';
import { DateDto, DateStatusDto, DateWithStatusDto } from './dto/dates-response.dto';
@ApiTags('dates')
@ApiBearerAuth()
@@ -15,12 +16,14 @@ export class DatesController {
@Post()
@ApiOperation({ summary: 'Propose a meetup' })
@ApiResponse({ status: 201, type: DateDto })
create(@CurrentUser('id') userId: string, @Body() dto: CreateDateDto) {
return this.datesService.create(userId, dto);
}
@Get()
@ApiOperation({ summary: 'Get dates for a profile' })
@ApiResponse({ status: 200, type: [DateWithStatusDto] })
getDates(
@CurrentUser('id') userId: string,
@Query('profileId') profileId: string,
@@ -30,6 +33,7 @@ export class DatesController {
@Patch(':id/status')
@ApiOperation({ summary: 'Update date status' })
@ApiResponse({ status: 200, type: DateDto })
updateStatus(
@CurrentUser('id') userId: string,
@Query('profileId') profileId: string,
@@ -41,6 +45,7 @@ export class DatesController {
@Get('statuses')
@ApiOperation({ summary: 'Get available date statuses' })
@ApiResponse({ status: 200, type: [DateStatusDto] })
getStatuses() {
return this.datesService.getStatuses();
}

View File

@@ -0,0 +1,21 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
export class DateStatusDto {
@ApiProperty() id: string;
@ApiProperty() text: string;
}
export class DateDto {
@ApiProperty() id: string;
@ApiProperty() profile1Id: string;
@ApiProperty() profile2Id: string;
@ApiProperty() lat: string;
@ApiProperty() lng: string;
@ApiProperty() time: string;
@ApiPropertyOptional({ nullable: true }) statusId: string | null;
}
export class DateWithStatusDto {
@ApiProperty({ type: DateDto }) date: DateDto;
@ApiPropertyOptional({ type: DateStatusDto, nullable: true }) date_status: DateStatusDto | null;
}

View File

@@ -1,9 +1,10 @@
import { Controller, Get, Query, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { FeedFilterDto } from './dto/feed-filter.dto';
import { FeedService } from './feed.service';
import { ProfileResponseDto } from '../profiles/dto/profile-response.dto';
@ApiTags('feed')
@ApiBearerAuth()
@@ -14,6 +15,7 @@ export class FeedController {
@Get()
@ApiOperation({ summary: 'Get filtered feed (requires profileId)' })
@ApiResponse({ status: 200, type: [ProfileResponseDto] })
getFeed(@CurrentUser('id') userId: string, @Query() filter: FeedFilterDto) {
return this.feedService.getFeed(userId, filter);
}

View File

@@ -0,0 +1,6 @@
import { ApiProperty } from '@nestjs/swagger';
export class GreetingDto {
@ApiProperty() id: string;
@ApiProperty() text: string;
}

View File

@@ -1,10 +1,12 @@
import { Body, Controller, Delete, Get, Param, Post, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { Public } from '../../common/decorators/public.decorator';
import { Roles } from '../../common/decorators/roles.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { RolesGuard } from '../../common/guards/roles.guard';
import { GreetingsService } from './greetings.service';
import { GreetingDto } from './dto/greeting-response.dto';
import { MessageResponseDto } from '../../common/dto/message-response.dto';
@ApiTags('greetings')
@Controller('greetings')
@@ -14,6 +16,7 @@ export class GreetingsController {
@Public()
@Get()
@ApiOperation({ summary: 'Get all greeting phrases' })
@ApiResponse({ status: 200, type: [GreetingDto] })
findAll() {
return this.greetingsService.findAll();
}
@@ -23,6 +26,7 @@ export class GreetingsController {
@Roles('admin')
@Post()
@ApiOperation({ summary: 'Add greeting phrase (admin only)' })
@ApiResponse({ status: 201, type: GreetingDto })
create(@Body('text') text: string) {
return this.greetingsService.create(text);
}
@@ -32,6 +36,7 @@ export class GreetingsController {
@Roles('admin')
@Delete(':id')
@ApiOperation({ summary: 'Delete greeting phrase (admin only)' })
@ApiResponse({ status: 200, type: MessageResponseDto })
delete(@Param('id') id: string) {
return this.greetingsService.delete(id);
}

View File

@@ -0,0 +1,21 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
export class LikeDto {
@ApiProperty() id: string;
@ApiProperty() sourceProfileId: string;
@ApiProperty() targetProfileId: string;
@ApiProperty({ enum: ['like', 'dislike'] }) type: string;
@ApiProperty() createdAt: string;
}
export class MatchDto {
@ApiProperty() id: string;
@ApiProperty() profile1Id: string;
@ApiProperty() profile2Id: string;
@ApiProperty() createdAt: string;
}
export class CreateLikeResponseDto {
@ApiProperty({ type: LikeDto }) like: LikeDto;
@ApiPropertyOptional({ type: MatchDto, nullable: true }) match: MatchDto | null;
}

View File

@@ -1,8 +1,9 @@
import { Body, Controller, Get, Post, Query, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { CreateLikeDto } from './dto/create-like.dto';
import { CreateLikeResponseDto, MatchDto } from './dto/likes-response.dto';
import { LikesService } from './likes.service';
@ApiTags('likes')
@@ -14,12 +15,14 @@ export class LikesController {
@Post()
@ApiOperation({ summary: 'Like or dislike a profile' })
@ApiResponse({ status: 201, type: CreateLikeResponseDto })
createLike(@CurrentUser('id') userId: string, @Body() dto: CreateLikeDto) {
return this.likesService.createLike(userId, dto);
}
@Get('matches')
@ApiOperation({ summary: 'Get matches for a profile' })
@ApiResponse({ status: 200, type: [MatchDto] })
getMyMatches(
@CurrentUser('id') userId: string,
@Query('profileId') profileId: string,

View File

@@ -1,9 +1,11 @@
import { Controller, Delete, Get, Param, Post, Query, Req, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiConsumes, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiBearerAuth, ApiConsumes, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { FastifyRequest } from 'fastify';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { MediaService } from './media.service';
import { MediaItemDto } from '../profiles/dto/profile-response.dto';
import { MessageResponseDto } from '../../common/dto/message-response.dto';
@ApiTags('media')
@ApiBearerAuth()
@@ -15,6 +17,7 @@ export class MediaController {
@Post('upload')
@ApiOperation({ summary: 'Upload photo / video / audio to profile' })
@ApiConsumes('multipart/form-data')
@ApiResponse({ status: 201, type: MediaItemDto })
async upload(
@CurrentUser('id') userId: string,
@Param('profileId') profileId: string,
@@ -34,12 +37,14 @@ export class MediaController {
@Get()
@ApiOperation({ summary: 'Get all media for a profile' })
@ApiResponse({ status: 200, type: [MediaItemDto] })
getMedia(@Param('profileId') profileId: string) {
return this.mediaService.getByProfileId(profileId);
}
@Delete(':mediaId')
@ApiOperation({ summary: 'Delete media item' })
@ApiResponse({ status: 200, type: MessageResponseDto })
deleteMedia(
@CurrentUser('id') userId: string,
@Param('mediaId') mediaId: string,

View File

@@ -0,0 +1,46 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
export class CityDto {
@ApiProperty() id: string;
@ApiProperty() name: string;
@ApiProperty() lat: string;
@ApiProperty() lng: string;
}
export class DistrictDto {
@ApiProperty() id: string;
@ApiProperty() cityId: string;
@ApiProperty() name: string;
}
export class TagDto {
@ApiProperty() id: string;
@ApiProperty() value: string;
}
export class MediaItemDto {
@ApiProperty() id: string;
@ApiProperty() profileId: string;
@ApiProperty() path: string;
@ApiProperty({ enum: ['photo', 'video', 'audio'] }) type: string;
@ApiProperty() sortOrder: number;
}
export class ProfileResponseDto {
@ApiProperty() id: string;
@ApiProperty() userId: string;
@ApiProperty() name: string;
@ApiProperty({ example: '1995-06-15' }) birthDate: string;
@ApiProperty({ enum: ['male', 'female'] }) gender: string;
@ApiPropertyOptional({ nullable: true }) cityId: string | null;
@ApiPropertyOptional({ nullable: true }) districtId: string | null;
@ApiPropertyOptional({ nullable: true }) description: string | null;
@ApiPropertyOptional({ nullable: true }) nation: string | null;
@ApiPropertyOptional({ nullable: true }) height: number | null;
@ApiPropertyOptional({ nullable: true }) weight: number | null;
@ApiPropertyOptional({ nullable: true }) activeChatId: string | null;
@ApiPropertyOptional({ type: CityDto, nullable: true }) city: CityDto | null;
@ApiPropertyOptional({ type: DistrictDto, nullable: true }) district: DistrictDto | null;
@ApiProperty({ type: [TagDto] }) tags: TagDto[];
@ApiProperty({ type: [MediaItemDto] }) media: MediaItemDto[];
}

View File

@@ -1,10 +1,12 @@
import { Body, Controller, Delete, Get, Param, Post, Put, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { CreateProfileDto } from './dto/create-profile.dto';
import { UpdateProfileDto } from './dto/update-profile.dto';
import { ProfileResponseDto } from './dto/profile-response.dto';
import { ProfilesService } from './profiles.service';
import { MessageResponseDto } from '../../common/dto/message-response.dto';
@ApiTags('profiles')
@ApiBearerAuth()
@@ -15,18 +17,21 @@ export class ProfilesController {
@Post()
@ApiOperation({ summary: 'Create a new profile (one user can have many)' })
@ApiResponse({ status: 201, type: ProfileResponseDto })
create(@CurrentUser('id') userId: string, @Body() dto: CreateProfileDto) {
return this.profilesService.create(userId, dto);
}
@Get('my')
@ApiOperation({ summary: 'Get all my profiles' })
@ApiResponse({ status: 200, type: [ProfileResponseDto] })
getMyProfiles(@CurrentUser('id') userId: string) {
return this.profilesService.findAllByUserId(userId);
}
@Put(':profileId')
@ApiOperation({ summary: 'Update profile by ID (must be owner)' })
@ApiResponse({ status: 200, type: ProfileResponseDto })
update(
@CurrentUser('id') userId: string,
@Param('profileId') profileId: string,
@@ -37,12 +42,14 @@ export class ProfilesController {
@Get(':profileId')
@ApiOperation({ summary: 'Get profile by ID' })
@ApiResponse({ status: 200, type: ProfileResponseDto })
findOne(@Param('profileId') profileId: string) {
return this.profilesService.findByProfileId(profileId);
}
@Delete(':profileId')
@ApiOperation({ summary: 'Delete profile (must be owner)' })
@ApiResponse({ status: 200, type: MessageResponseDto })
delete(@CurrentUser('id') userId: string, @Param('profileId') profileId: string) {
return this.profilesService.delete(userId, profileId);
}

View File

@@ -0,0 +1,9 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
export class ReportDto {
@ApiProperty() id: string;
@ApiProperty() sourceProfileId: string;
@ApiProperty() entityId: string;
@ApiProperty({ enum: ['profile', 'message'] }) entityType: string;
@ApiPropertyOptional({ nullable: true }) description: string | null;
}

View File

@@ -1,10 +1,11 @@
import { Body, Controller, Get, Post, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { Roles } from '../../common/decorators/roles.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { RolesGuard } from '../../common/guards/roles.guard';
import { CreateReportDto } from './dto/create-report.dto';
import { ReportDto } from './dto/report-response.dto';
import { ReportsService } from './reports.service';
@ApiTags('reports')
@@ -16,6 +17,7 @@ export class ReportsController {
@Post()
@ApiOperation({ summary: 'Submit a report' })
@ApiResponse({ status: 201, type: ReportDto })
create(@CurrentUser('id') userId: string, @Body() dto: CreateReportDto) {
return this.reportsService.create(userId, dto);
}
@@ -24,6 +26,7 @@ export class ReportsController {
@Roles('admin', 'moderator')
@UseGuards(RolesGuard)
@ApiOperation({ summary: 'Get all reports (admin/moderator)' })
@ApiResponse({ status: 200, type: [ReportDto] })
getAll() {
return this.reportsService.getAll();
}

View File

@@ -0,0 +1,6 @@
import { ApiProperty } from '@nestjs/swagger';
export class TagResponseDto {
@ApiProperty() id: string;
@ApiProperty() value: string;
}

View File

@@ -1,10 +1,12 @@
import { Body, Controller, Delete, Get, Param, Post, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { Public } from '../../common/decorators/public.decorator';
import { Roles } from '../../common/decorators/roles.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { RolesGuard } from '../../common/guards/roles.guard';
import { TagsService } from './tags.service';
import { TagResponseDto } from './dto/tag-response.dto';
import { MessageResponseDto } from '../../common/dto/message-response.dto';
@ApiTags('tags')
@Controller('tags')
@@ -14,6 +16,7 @@ export class TagsController {
@Public()
@Get()
@ApiOperation({ summary: 'Get all tags' })
@ApiResponse({ status: 200, type: [TagResponseDto] })
findAll() {
return this.tagsService.findAll();
}
@@ -23,6 +26,7 @@ export class TagsController {
@Roles('admin')
@Post()
@ApiOperation({ summary: 'Create tag (admin only)' })
@ApiResponse({ status: 201, type: TagResponseDto })
create(@Body('value') value: string) {
return this.tagsService.create(value);
}
@@ -32,6 +36,7 @@ export class TagsController {
@Roles('admin')
@Delete(':id')
@ApiOperation({ summary: 'Delete tag (admin only)' })
@ApiResponse({ status: 200, type: MessageResponseDto })
delete(@Param('id') id: string) {
return this.tagsService.delete(id);
}

View File

@@ -0,0 +1,27 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
export class RoleDto {
@ApiProperty() id: string;
@ApiProperty() name: string;
}
export class ProfileSummaryDto {
@ApiProperty() id: string;
@ApiProperty() name: string;
@ApiProperty({ enum: ['male', 'female'] }) gender: string;
}
export class UserResponseDto {
@ApiProperty() id: string;
@ApiProperty() phone: string;
@ApiProperty({ enum: ['active', 'banned', 'pending'] }) status: string;
@ApiPropertyOptional({ nullable: true }) roleId: string | null;
@ApiPropertyOptional({ nullable: true }) tariffId: string | null;
@ApiPropertyOptional({ nullable: true }) paymentId: string | null;
@ApiPropertyOptional({ nullable: true }) fcmToken: string | null;
}
export class MeResponseDto extends UserResponseDto {
@ApiPropertyOptional({ type: RoleDto, nullable: true }) role: RoleDto | null;
@ApiProperty({ type: [ProfileSummaryDto] }) profiles: ProfileSummaryDto[];
}

View File

@@ -1,10 +1,12 @@
import { Controller, Get, Param, Patch, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { Roles } from '../../common/decorators/roles.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { RolesGuard } from '../../common/guards/roles.guard';
import { UsersService } from './users.service';
import { MeResponseDto, UserResponseDto } from './dto/user-response.dto';
import { MessageResponseDto } from '../../common/dto/message-response.dto';
@ApiTags('users')
@ApiBearerAuth()
@@ -15,12 +17,14 @@ export class UsersController {
@Get('me')
@ApiOperation({ summary: 'Get current user with profile list' })
@ApiResponse({ status: 200, type: MeResponseDto })
getMe(@CurrentUser('id') userId: string) {
return this.usersService.getMe(userId);
}
@Get(':id')
@ApiOperation({ summary: 'Get user by ID' })
@ApiResponse({ status: 200, type: UserResponseDto })
findOne(@Param('id') id: string) {
return this.usersService.findById(id);
}
@@ -29,6 +33,7 @@ export class UsersController {
@Roles('admin', 'moderator')
@UseGuards(RolesGuard)
@ApiOperation({ summary: 'Ban user' })
@ApiResponse({ status: 200, type: MessageResponseDto })
ban(@Param('id') id: string) {
return this.usersService.banUser(id);
}
@@ -37,6 +42,7 @@ export class UsersController {
@Roles('admin', 'moderator')
@UseGuards(RolesGuard)
@ApiOperation({ summary: 'Activate user' })
@ApiResponse({ status: 200, type: MessageResponseDto })
activate(@Param('id') id: string) {
return this.usersService.activateUser(id);
}