From 677c1ae1b8f4f4d846fac6230729413e55080273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A3=BC=EB=B3=91=ED=98=B8?= Date: Sat, 21 Sep 2024 14:36:37 +0900 Subject: [PATCH] Feat/show group like (#57) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Refactor: 타입 변경 * Feat: 특정 좋아요한 * Chore: 조금 수정 * Feat: 취향차이 --- src/map/dtos/map-response.dto.ts | 2 +- src/map/map.service.ts | 2 +- src/place/dto/place-for-map-response.dto.ts | 6 +++ src/place/place.controller.ts | 30 ++++++++++- src/place/place.service.ts | 56 ++++++++++++++++++++- 5 files changed, 92 insertions(+), 4 deletions(-) diff --git a/src/map/dtos/map-response.dto.ts b/src/map/dtos/map-response.dto.ts index 2f9feb6..a848b3d 100644 --- a/src/map/dtos/map-response.dto.ts +++ b/src/map/dtos/map-response.dto.ts @@ -122,7 +122,7 @@ export class PublicMapResponseDto { @ApiProperty() description: string; - constructor(map: GroupMap & { placeCount: number; userCount: number }) { + constructor(map: PublicMapResponseDto) { this.id = map.id; this.name = map.name; this.placeCount = map.placeCount; diff --git a/src/map/map.service.ts b/src/map/map.service.ts index e02bb37..98b1dbd 100644 --- a/src/map/map.service.ts +++ b/src/map/map.service.ts @@ -117,7 +117,7 @@ export class MapService { }: { order: ArrayElement; name: string; - }) { + }): Promise { const qb = this.placeForMapRepository.createQueryBuilder('placeForMap'); qb.select('map.*') .leftJoin('placeForMap.map', 'map') diff --git a/src/place/dto/place-for-map-response.dto.ts b/src/place/dto/place-for-map-response.dto.ts index 6cbafef..4bc33d0 100644 --- a/src/place/dto/place-for-map-response.dto.ts +++ b/src/place/dto/place-for-map-response.dto.ts @@ -259,6 +259,9 @@ export class PlaceForMapResponseDto { @ApiProperty() updatedAt: Date; + @ApiProperty({ type: [User] }) + likedUser: Partial[]; + constructor(placeForMap: PlaceForMap) { this.place = placeForMap.place; this.tags = placeForMap.tags @@ -269,5 +272,8 @@ export class PlaceForMapResponseDto { this.createdBy = new CreatedUser(placeForMap.createdBy); this.createdAt = placeForMap.createdAt; this.updatedAt = placeForMap.updatedAt; + this.likedUser = placeForMap.likedUser.map((v) => ({ + id: v.id, + })); } } diff --git a/src/place/place.controller.ts b/src/place/place.controller.ts index 0029846..d608fd1 100644 --- a/src/place/place.controller.ts +++ b/src/place/place.controller.ts @@ -9,6 +9,7 @@ import { } from '@nestjs/common'; import { ApiBearerAuth, + ApiOkResponse, ApiOperation, ApiParam, ApiResponse, @@ -26,7 +27,7 @@ import { import { UseAuthGuard } from '../common/decorators/auth-guard.decorator'; import { CurrentUser } from '../common/decorators/user.decorator'; -import { User, UserMapRole } from '../entities'; +import { User, UserMapRole, UserRole } from '../entities'; import { PlaceService } from './place.service'; @ApiTags('place') @@ -53,6 +54,33 @@ export class PlaceController { }); } + @Get('like/:mapId/:userId') + @ApiOperation({ summary: '특정 유저가 좋아요한 맛집을 조회합니다' }) + @ApiOkResponse({ type: PlaceForMapResponseDto, isArray: true }) + @UseMapRoleGuard() + @ApiBearerAuth() + @UseAuthGuard([UserRole.USER]) + async findUserLikePlace( + @Param('mapId') mapId: string, + @Param('userId') userId: number, + ) { + return this.placeService.findUserLikePlace(mapId, userId); + } + + @Get('differ/:mapId/:userId') + @ApiOperation({ summary: '취향 차이' }) + @ApiOkResponse({ type: Number }) + @UseMapRoleGuard() + @ApiBearerAuth() + @UseAuthGuard([UserRole.USER]) + async getDifference( + @Param('mapId') mapId: string, + @Param('userId') userId: number, + @CurrentUser() user: User, + ) { + return this.placeService.getDifference(mapId, userId, user.id); + } + @ApiOperation({ summary: '카카오 place id로 장소 등록' }) @ApiParam({ name: 'mapId', description: '지도(GroupMap) id' }) @ApiParam({ name: 'kakaoPlaceId', description: '카카오 place id' }) diff --git a/src/place/place.service.ts b/src/place/place.service.ts index ec3b08b..4b02a64 100644 --- a/src/place/place.service.ts +++ b/src/place/place.service.ts @@ -65,13 +65,67 @@ export class PlaceService { { map: rel(GroupMap, mapId), }, - { populate: ['place', 'place.kakaoPlace', 'createdBy', 'tags'] }, + { + populate: [ + 'place', + 'place.kakaoPlace', + 'createdBy', + 'tags', + 'likedUser', + ], + }, ); return placesForMapList.map( (placeForMap) => new PlaceForMapResponseDto(placeForMap), ); } + async findUserLikePlace(mapId: string, userId: number) { + const placeForMap = await this.placeForMapRepository.find( + { + likedUser: rel(User, userId), + map: rel(GroupMap, mapId), + }, + { + populate: [ + 'place', + 'place.kakaoPlace', + 'createdBy', + 'tags', + 'likedUser', + ], + }, + ); + + return placeForMap.map((place) => new PlaceForMapResponseDto(place)); + } + + async getDifference(mapId: string, userId: number, myId: number) { + const youLike = await this.placeForMapRepository + .createQueryBuilder('pfm') + .select('pfm.place') + .where({ + likedUser: rel(User, userId), + map: rel(GroupMap, mapId), + }) + .execute(); + + const iLike = await this.placeForMapRepository + .createQueryBuilder('pfm') + .select('pfm.place') + .where({ + likedUser: rel(User, myId), + map: rel(GroupMap, mapId), + }) + .execute(); + + return ( + (iLike.filter((v) => youLike.some((k) => k.place === v.place)).length / + iLike.length) * + 100 + ); + } + async registerPlaceByKakaoId({ kakaoPlaceId, mapId,