From 13f1df603ed15099d39c9d0c4f96b394bc9c5db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Thu, 17 Oct 2024 22:01:46 -0600 Subject: [PATCH 1/3] fix --- backend/src/route/route.controller.ts | 3 ++- backend/src/route/route.service.ts | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/backend/src/route/route.controller.ts b/backend/src/route/route.controller.ts index db4760ed..942e0855 100644 --- a/backend/src/route/route.controller.ts +++ b/backend/src/route/route.controller.ts @@ -48,8 +48,9 @@ export class RouteController { } } - @Get('/:idRoute') + @Get('/:idRoute/:lang') @ApiParam({ name: 'idRoute', type: Number }) + @ApiParam({ name: 'lang', type: String, enum: Object.values(LANGUAGES) }) @ApiBearerAuth('jwt') @UseGuards(AuthUserGuard) async getRoute(@Param('idRoute') idRoute: number, @Param('lang') lang: LANGUAGES, @Req() req: CustomUserRequest) { diff --git a/backend/src/route/route.service.ts b/backend/src/route/route.service.ts index 6ee25f6f..00de4a43 100644 --- a/backend/src/route/route.service.ts +++ b/backend/src/route/route.service.ts @@ -150,6 +150,29 @@ export class RouteService { .where('route.idRoute = :idRoute', { idRoute }) .getOne(); + if (res && res.travelPlace) { + res.travelPlace = res.travelPlace.map((travelPlace: TravelPlace) => { + return { + travelPlaceId: travelPlace.travelPlaceId, + idPlace: travelPlace.place.idPlace, + available: travelPlace.place.available, + latitude: travelPlace.place.latitude, + longitude: travelPlace.place.longitude, + imageName: `${ServerConstants.HOST}/places/${travelPlace.place.imageName}`, + name: travelPlace.place.name, + openAt: travelPlace.place.openAt, + closeAt: travelPlace.place.closeAt, + startDate: travelPlace.startDate, + endDate: travelPlace.endDate, + categories: travelPlace.place.categories, + address: travelPlace.place.address, + done: travelPlace.done, + route: travelPlace.route, + place: { ...travelPlace.place, imageName: `${ServerConstants.HOST}/places/${travelPlace.place.imageName}` }, + }; + }); + } + return res; } } -- GitLab From 75d194c9e619cd7bc91d1e9299ed5e94453d7e0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Mon, 21 Oct 2024 17:10:42 -0600 Subject: [PATCH 2/3] fix done en un place de una ruta --- backend/src/route/route.controller.ts | 16 ++++++++-------- backend/src/visited/visited.module.ts | 2 ++ backend/src/visited/visited.service.ts | 8 ++++++++ backend/tes.sql | 1 + 4 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 backend/tes.sql diff --git a/backend/src/route/route.controller.ts b/backend/src/route/route.controller.ts index 942e0855..d73c6266 100644 --- a/backend/src/route/route.controller.ts +++ b/backend/src/route/route.controller.ts @@ -13,6 +13,14 @@ import { UpdateRouteStatusDto } from './dto/updateRouteStatus.dto'; export class RouteController { constructor(private readonly routeService: RouteService) {} + @Get('/info/:idRoute') + @ApiParam({ name: 'idRoute', type: Number }) + @ApiBearerAuth('jwt') + // @UseGuards(AuthUserGuard) + async getRouteInfo(@Param('idRoute') idRoute: number) { + return await this.routeService.getRouteInfoById(idRoute); + } + @Post('/:idTown') @ApiParam({ name: 'idTown', type: Number }) @ApiBody({ type: CreateRouteReq }) @@ -67,12 +75,4 @@ export class RouteController { async updateRoute(@Body() updateRouteStatusDto: UpdateRouteStatusDto, @Param('idRoute') idRoute: number) { return await this.routeService.updateRoute(idRoute, updateRouteStatusDto.status); } - - @Get('/info/:idRoute') - @ApiParam({ name: 'idRoute', type: Number }) - @ApiBearerAuth('jwt') - @UseGuards(AuthUserGuard) - async getRouteInfo(@Param('idRoute') idRoute: number) { - return await this.routeService.getRouteInfoById(idRoute); - } } diff --git a/backend/src/visited/visited.module.ts b/backend/src/visited/visited.module.ts index f79ac46e..69bd3710 100644 --- a/backend/src/visited/visited.module.ts +++ b/backend/src/visited/visited.module.ts @@ -18,6 +18,7 @@ import { EncryptionService } from 'src/auth/encryption/encryption.service'; import { UserResetCode } from 'src/auth/user/entities/user-reset-code.entity'; import { UserConfirmCode } from 'src/auth/user/entities/user-confirm-code.entity'; import { EmailService } from 'src/email/email.service'; +import { TravelPlace } from 'src/travel-place/entities/travel-place.entity'; @Module({ controllers: [VisitedController], @@ -43,6 +44,7 @@ import { EmailService } from 'src/email/email.service'; Visited, UserResetCode, UserConfirmCode, + TravelPlace, ]), ], }) diff --git a/backend/src/visited/visited.service.ts b/backend/src/visited/visited.service.ts index 7f0c17e0..97ddfce5 100644 --- a/backend/src/visited/visited.service.ts +++ b/backend/src/visited/visited.service.ts @@ -10,6 +10,8 @@ import { PlaceService } from 'src/place/place.service'; import { LANGUAGES } from 'src/shared/enum/languages.enum'; import { VisitedPlacesImageCreator } from './utils/visited_places_image_creator'; import { ServerConstants } from 'src/constants/server.contants'; +import { TravelPlaceService } from 'src/travel-place/travel-place.service'; +import { TravelPlace } from 'src/travel-place/entities/travel-place.entity'; @Injectable() export class VisitedService { @@ -17,6 +19,7 @@ export class VisitedService { @InjectRepository(Visited) private visitedRepository: Repository, private readonly userService: UserService, private readonly placeService: PlaceService, + @InjectRepository(TravelPlace) private travelPlaceRepository: Repository, ) {} async create(createVisitedDto: CreateVisitedDto, email: string) { @@ -24,6 +27,11 @@ export class VisitedService { const user: User = await this.userService.findOne(email); if (!place || !user) throw new BadRequestException('Place or user not found'); + try { + await this.travelPlaceRepository.update({ place }, { done: true }); + } catch (error) { + console.log(error); + } await this.visitedRepository.save({ place, user, rating: createVisitedDto.rating }); } diff --git a/backend/tes.sql b/backend/tes.sql new file mode 100644 index 00000000..ff33b2b6 --- /dev/null +++ b/backend/tes.sql @@ -0,0 +1 @@ +"QueryFailedError: Unknown column 'NaN' in 'where clause'\n at Query.onResult (/home/diego/Desktop/coding/pueblos/backend/src/driver/mysql/MysqlQueryRunner.ts:246:33)\n at Query.execute (/home/diego/Desktop/coding/pueblos/backend/node_modules/mysql2/lib/commands/command.js:36:14)\n at PoolConnection.handlePacket (/home/diego/Desktop/coding/pueblos/backend/node_modules/mysql2/lib/connection.js:481:34)\n at PacketParser.onPacket (/home/diego/Desktop/coding/pueblos/backend/node_modules/mysq…onnection.js:97:12)\n at PacketParser.executeStart (/home/diego/Desktop/coding/pueblos/backend/node_modules/mysql2/lib/packet_parser.js:75:16)\n at Socket. (/home/diego/Desktop/coding/pueblos/backend/node_modules/mysql2/lib/connection.js:104:25)\n at Socket.emit (node:events:520:28)\n at addChunk (node:internal/streams/readable:559:12)\n at readableAddChunkPushByteMode (node:internal/streams/readable:510:3)\n at Socket.Readable.push (node:internal/streams/readable:390:5)" \ No newline at end of file -- GitLab From 3acdc7533c35836ff4dae34476769c6585f55c01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Iv=C3=A1n?= <80365304+Diego-lvan@users.noreply.github.com> Date: Mon, 21 Oct 2024 17:40:20 -0600 Subject: [PATCH 3/3] endpoint para actualziar datos de un usuario y obtener sus datos --- backend/src/user/dto/update-user.dto.ts | 15 ++++++-- backend/src/user/dto/user-response.ts | 16 +++++++++ backend/src/user/entities/user.entity.ts | 3 ++ backend/src/user/user.controller.ts | 45 ++++++++++++++++++++---- backend/src/user/user.service.ts | 33 +++++++++++++++-- backend/src/visited/visited.service.ts | 1 - 6 files changed, 100 insertions(+), 13 deletions(-) create mode 100644 backend/src/user/dto/user-response.ts diff --git a/backend/src/user/dto/update-user.dto.ts b/backend/src/user/dto/update-user.dto.ts index 78ab602d..61fc4598 100644 --- a/backend/src/user/dto/update-user.dto.ts +++ b/backend/src/user/dto/update-user.dto.ts @@ -1,4 +1,13 @@ -import { PartialType } from '@nestjs/swagger'; -import { CreateUserDto } from './create-user.dto'; +import { ApiProperty } from '@nestjs/swagger'; -export class UpdateUserDto extends PartialType(CreateUserDto) {} +export class UpdateUserDto { + @ApiProperty() + name: string; + @ApiProperty() + lastName: string; +} + +export class UpdateImageUserDto { + @ApiProperty({ type: 'string', format: 'binary' }) + image; +} diff --git a/backend/src/user/dto/user-response.ts b/backend/src/user/dto/user-response.ts new file mode 100644 index 00000000..7588283c --- /dev/null +++ b/backend/src/user/dto/user-response.ts @@ -0,0 +1,16 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class UserResponse { + @ApiProperty() + name: string; + @ApiProperty() + lastName: string; + @ApiProperty() + imageUrl: string; + + @ApiProperty() + email: string; + + @ApiProperty() + emailConfirmed: boolean; +} diff --git a/backend/src/user/entities/user.entity.ts b/backend/src/user/entities/user.entity.ts index 9de86956..6723c568 100644 --- a/backend/src/user/entities/user.entity.ts +++ b/backend/src/user/entities/user.entity.ts @@ -24,6 +24,9 @@ export class User { @Column() password: string; + @Column({ nullable: true }) + imageUrl: string; + @Column({ default: false }) isEmailConfirmed: boolean; diff --git a/backend/src/user/user.controller.ts b/backend/src/user/user.controller.ts index ebb7f80f..19cd7bc1 100644 --- a/backend/src/user/user.controller.ts +++ b/backend/src/user/user.controller.ts @@ -1,10 +1,13 @@ -import { Body, Controller, Get, Patch, Query, Req, UseGuards } from '@nestjs/common'; +import { Body, Controller, Get, Patch, Query, Req, UseGuards, UseInterceptors } from '@nestjs/common'; import { UserService } from './user.service'; import { UpdatePreferedCategoriesDto } from './dto/update-preferedCategories.dto'; import { CustomUserRequest } from 'src/auth/user/interface/customUserReq'; -import { ApiBearerAuth, ApiBody, ApiQuery, ApiTags } from '@nestjs/swagger'; +import { ApiBearerAuth, ApiBody, ApiConsumes, ApiQuery, ApiTags } from '@nestjs/swagger'; import { AuthUserGuard } from 'src/auth/user/authUser.guard'; import { LANGUAGES } from 'src/shared/enum/languages.enum'; +import { UpdateImageUserDto, UpdateUserDto } from './dto/update-user.dto'; +import { fileInterceptor } from 'src/shared/interceptors/file-save.interceptor'; +import { CustomAdminRequest } from 'src/auth/admin/interface/customAdminReq'; @Controller('user') @ApiTags('User') @@ -41,14 +44,44 @@ export class UserController { } } - @Get('is-verfied') + @Patch('info') @ApiBearerAuth('jwt') + @ApiBody({ type: UpdateUserDto }) @UseGuards(AuthUserGuard) - async isVerified(@Req() req: CustomUserRequest) { + async updateInfo(@Body() updateUserDto: UpdateUserDto, @Req() req: CustomUserRequest) { try { const { email } = req.user; - const isVerified = await this.userService.isVerified(email); - return { isVerified }; + await this.userService.updateInfo(email, updateUserDto); + return { message: 'User info updated successfully' }; + } catch (error) { + throw error; + } + } + + @Patch('photo') + @ApiBearerAuth('jwt') + @UseGuards(AuthUserGuard) + @ApiConsumes('multipart/form-data') + @ApiBody({ type: UpdateImageUserDto }) + @UseInterceptors(fileInterceptor('image', 'static/user/', ['.jpg', '.jpeg', '.png'])) + async updatePhoto(@Req() reqImg: CustomAdminRequest, @Req() req: CustomUserRequest) { + try { + const { email } = req.user; + const image = reqImg.file.filename; + await this.userService.updatePhoto(email, image); + return { message: 'User photo updated successfully' }; + } catch (error) { + throw error; + } + } + + @Get('info') + @ApiBearerAuth('jwt') + @UseGuards(AuthUserGuard) + async getInfo(@Req() req: CustomUserRequest) { + try { + const { email } = req.user; + return await this.userService.getUserInfo(email); } catch (error) { throw error; } diff --git a/backend/src/user/user.service.ts b/backend/src/user/user.service.ts index d466391f..bbbf98ab 100644 --- a/backend/src/user/user.service.ts +++ b/backend/src/user/user.service.ts @@ -6,6 +6,9 @@ import { CreateUserDto } from './dto/create-user.dto'; import { Category } from 'src/category/entities/category.entity'; import { CategoryService } from 'src/category/category.service'; import { LANGUAGES } from 'src/shared/enum/languages.enum'; +import { UpdateUserDto } from './dto/update-user.dto'; +import { UserResponse } from './dto/user-response'; +import { ServerConstants } from 'src/constants/server.contants'; @Injectable() /** @@ -77,12 +80,36 @@ export class UserService { } } - async isVerified(email: string): Promise { + async updateInfo(email: string, updateUserDto: UpdateUserDto) { + try { + await this.userRepository.update({ email }, updateUserDto); + } catch (error) { + throw new BadRequestException('Error updating user info'); + } + } + + async updatePhoto(email: string, photo: string) { + try { + await this.userRepository.update({ email }, { imageUrl: photo }); + } catch (error) { + throw new BadRequestException('Error updating user photo'); + } + } + + async getUserInfo(email: string) { try { const user = await this.userRepository.findOneBy({ email }); - return user.isEmailConfirmed; + user.imageUrl = `${ServerConstants.HOST}/user/${user.imageUrl}`; + const res: UserResponse = { + imageUrl: user.imageUrl, + lastName: user.lastName, + email: user.email, + name: user.name, + emailConfirmed: user.isEmailConfirmed, + }; + return res; } catch (error) { - throw new BadRequestException('Error getting email verification status'); + throw new BadRequestException('Error getting user info'); } } } diff --git a/backend/src/visited/visited.service.ts b/backend/src/visited/visited.service.ts index 97ddfce5..b9051ee8 100644 --- a/backend/src/visited/visited.service.ts +++ b/backend/src/visited/visited.service.ts @@ -10,7 +10,6 @@ import { PlaceService } from 'src/place/place.service'; import { LANGUAGES } from 'src/shared/enum/languages.enum'; import { VisitedPlacesImageCreator } from './utils/visited_places_image_creator'; import { ServerConstants } from 'src/constants/server.contants'; -import { TravelPlaceService } from 'src/travel-place/travel-place.service'; import { TravelPlace } from 'src/travel-place/entities/travel-place.entity'; @Injectable() -- GitLab