-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
27 changed files
with
626 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 7 additions & 2 deletions
9
src/main/java/com/depromeet/domain/auth/dto/response/SocialLoginResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,19 @@ | ||
package com.depromeet.domain.auth.dto.response; | ||
|
||
import com.depromeet.domain.member.domain.Member; | ||
import io.swagger.v3.oas.annotations.media.Schema; | ||
|
||
public record SocialLoginResponse( | ||
@Schema(description = "멤버 ID", defaultValue = "1") Long memberId, | ||
@Schema(description = "엑세스 토큰", defaultValue = "accessToken") String accessToken, | ||
@Schema(description = "리프레시 토큰", defaultValue = "refreshToken") String refreshToken, | ||
@Schema(description = "게스트 여부", defaultValue = "false") boolean isGuest) { | ||
|
||
public static SocialLoginResponse from(TokenPairResponse tokenPairResponse) { | ||
public static SocialLoginResponse from(Member member, TokenPairResponse tokenPairResponse) { | ||
return new SocialLoginResponse( | ||
tokenPairResponse.accessToken(), tokenPairResponse.refreshToken(), false); | ||
member.getId(), | ||
tokenPairResponse.accessToken(), | ||
tokenPairResponse.refreshToken(), | ||
false); | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
src/main/java/com/depromeet/domain/feed/api/FeedController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package com.depromeet.domain.feed.api; | ||
|
||
import com.depromeet.domain.feed.application.FeedService; | ||
import com.depromeet.domain.feed.dto.response.FeedOneByProfileResponse; | ||
import com.depromeet.domain.feed.dto.response.FeedOneResponse; | ||
import io.swagger.v3.oas.annotations.Operation; | ||
import io.swagger.v3.oas.annotations.tags.Tag; | ||
import java.util.List; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.web.bind.annotation.GetMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RestController; | ||
|
||
@RestController | ||
@Tag(name = "6. [피드]", description = "피드 관련 API입니다.") | ||
@RequestMapping("/feed") | ||
@RequiredArgsConstructor | ||
public class FeedController { | ||
|
||
private final FeedService feedService; | ||
|
||
@Operation(summary = "피드 탭", description = "피드 탭을 조회합니다.") | ||
@GetMapping("/me") | ||
public List<FeedOneResponse> feedFindAll() { | ||
return feedService.findAllFeed(); | ||
} | ||
|
||
@Operation(summary = "프로필 피드", description = "피드 탭을 조회합니다.") | ||
@GetMapping("/{memberId}") | ||
public List<FeedOneByProfileResponse> feedFindAllByTargetId(@PathVariable Long memberId) { | ||
return feedService.findAllFeedByTargetId(memberId); | ||
} | ||
} |
92 changes: 92 additions & 0 deletions
92
src/main/java/com/depromeet/domain/feed/application/FeedService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package com.depromeet.domain.feed.application; | ||
|
||
import com.depromeet.domain.feed.dto.response.FeedOneByProfileResponse; | ||
import com.depromeet.domain.feed.dto.response.FeedOneResponse; | ||
import com.depromeet.domain.follow.dao.MemberRelationRepository; | ||
import com.depromeet.domain.follow.domain.MemberRelation; | ||
import com.depromeet.domain.member.domain.Member; | ||
import com.depromeet.domain.mission.domain.MissionVisibility; | ||
import com.depromeet.domain.missionRecord.dao.MissionRecordRepository; | ||
import com.depromeet.domain.missionRecord.domain.MissionRecord; | ||
import com.depromeet.global.util.MemberUtil; | ||
import com.depromeet.global.util.SecurityUtil; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
import org.springframework.transaction.annotation.Transactional; | ||
|
||
// TODO: Redis 사용해서 캐싱 작업 필요 | ||
@Service | ||
@RequiredArgsConstructor | ||
@Transactional | ||
public class FeedService { | ||
private final MemberUtil memberUtil; | ||
private final MissionRecordRepository missionRecordRepository; | ||
private final MemberRelationRepository memberRelationRepository; | ||
private final SecurityUtil securityUtil; | ||
|
||
@Transactional(readOnly = true) | ||
public List<FeedOneResponse> findAllFeed() { | ||
final Member currentMember = memberUtil.getCurrentMember(); | ||
List<Member> members = | ||
memberRelationRepository.findAllBySourceId(currentMember.getId()).stream() | ||
.map(MemberRelation::getTarget) | ||
.collect(Collectors.toList()); | ||
members.add(currentMember); | ||
|
||
return missionRecordRepository.findFeedAll(members); | ||
} | ||
|
||
@Transactional(readOnly = true) | ||
public List<FeedOneByProfileResponse> findAllFeedByTargetId(Long targetId) { | ||
final Long sourceId = securityUtil.getCurrentMemberId(); | ||
|
||
if (isMyFeedRequired(targetId, sourceId)) { | ||
return findFeedByOtherMember(sourceId, targetId); | ||
} | ||
return findFeedByCurrentMember(sourceId); | ||
} | ||
|
||
private boolean isMyFeedRequired(Long targetId, Long sourceId) { | ||
return !targetId.equals(sourceId); | ||
} | ||
|
||
private List<FeedOneByProfileResponse> findFeedByOtherMember(Long sourceId, Long targetId) { | ||
final Member targetMember = memberUtil.getMemberByMemberId(targetId); | ||
|
||
// 팔로우 관계 true: visibility.FOLLOW and ALL, false: visibility.ALL only | ||
boolean isMemberRelationExistsWithMe = | ||
memberRelationRepository.existsBySourceIdAndTargetId( | ||
sourceId, targetMember.getId()); | ||
List<MissionVisibility> visibilities = | ||
determineVisibilityConditionsByRelationsWithMe(isMemberRelationExistsWithMe); | ||
List<MissionRecord> feedAllByMemberId = | ||
missionRecordRepository.findFeedAllByMemberId(targetId, visibilities); | ||
return extractFeedResponses(feedAllByMemberId); | ||
} | ||
|
||
private List<FeedOneByProfileResponse> findFeedByCurrentMember(Long sourceId) { | ||
List<MissionVisibility> visibilities = | ||
List.of(MissionVisibility.NONE, MissionVisibility.FOLLOWER, MissionVisibility.ALL); | ||
List<MissionRecord> feedAllByMemberId = | ||
missionRecordRepository.findFeedAllByMemberId(sourceId, visibilities); | ||
return extractFeedResponses(feedAllByMemberId); | ||
} | ||
|
||
private List<FeedOneByProfileResponse> extractFeedResponses(List<MissionRecord> records) { | ||
return records.stream().map(FeedOneByProfileResponse::of).toList(); | ||
} | ||
|
||
private List<MissionVisibility> determineVisibilityConditionsByRelationsWithMe( | ||
boolean isMemberRelationExistsWithMe) { | ||
List<MissionVisibility> visibilities = new ArrayList<>(); | ||
visibilities.add(MissionVisibility.ALL); | ||
|
||
if (isMemberRelationExistsWithMe) { | ||
visibilities.add(MissionVisibility.FOLLOWER); | ||
} | ||
return visibilities; | ||
} | ||
} |
49 changes: 49 additions & 0 deletions
49
src/main/java/com/depromeet/domain/feed/dto/response/FeedOneByProfileResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package com.depromeet.domain.feed.dto.response; | ||
|
||
import com.depromeet.domain.missionRecord.domain.MissionRecord; | ||
import com.fasterxml.jackson.annotation.JsonFormat; | ||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import java.time.Duration; | ||
import java.time.LocalDateTime; | ||
|
||
public record FeedOneByProfileResponse( | ||
@Schema(description = "미션 ID", defaultValue = "1") Long missionId, | ||
@Schema(description = "미션 기록 ID", defaultValue = "1") Long recordId, | ||
@Schema(description = "미션 이름", defaultValue = "default name") String name, | ||
@Schema( | ||
description = "미션 기록 인증 사진 Url", | ||
defaultValue = "https://image.10mm.today/default.png") | ||
String recordImageUrl, | ||
@Schema(description = "미션 수행한 시간", defaultValue = "21") long duration, | ||
@Schema(description = "미션 시작한 지 N일차", defaultValue = "3") long sinceDay, | ||
@JsonFormat( | ||
shape = JsonFormat.Shape.STRING, | ||
pattern = "yyyy-MM-dd HH:mm:ss", | ||
timezone = "Asia/Seoul") | ||
@Schema( | ||
description = "미션 기록 시작 시간", | ||
defaultValue = "2023-01-06 00:00:00", | ||
type = "string") | ||
LocalDateTime startedAt, | ||
@JsonFormat( | ||
shape = JsonFormat.Shape.STRING, | ||
pattern = "yyyy-MM-dd HH:mm:ss", | ||
timezone = "Asia/Seoul") | ||
@Schema( | ||
description = "미션 기록 종료 시간", | ||
defaultValue = "2024-01-20 00:34:00", | ||
type = "string") | ||
LocalDateTime finishedAt) { | ||
|
||
public static FeedOneByProfileResponse of(MissionRecord record) { | ||
return new FeedOneByProfileResponse( | ||
record.getMission().getId(), | ||
record.getId(), | ||
record.getMission().getName(), | ||
record.getImageUrl(), | ||
record.getDuration().toMinutes(), | ||
Duration.between(record.getStartedAt(), LocalDateTime.now()).toDays() + 1, | ||
record.getStartedAt(), | ||
record.getFinishedAt()); | ||
} | ||
} |
96 changes: 96 additions & 0 deletions
96
src/main/java/com/depromeet/domain/feed/dto/response/FeedOneResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package com.depromeet.domain.feed.dto.response; | ||
|
||
import com.fasterxml.jackson.annotation.JsonFormat; | ||
import com.querydsl.core.annotations.QueryProjection; | ||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import java.time.Duration; | ||
import java.time.LocalDateTime; | ||
|
||
public record FeedOneResponse( | ||
@Schema(description = "작성자 ID", defaultValue = "1") Long memberId, | ||
@Schema(description = "작성자 닉네임", defaultValue = "default name") String nickname, | ||
@Schema(description = "작성자 프로필 이미지", defaultValue = "https://image.10mm.today/default.png") | ||
String profileImage, | ||
@Schema(description = "미션 ID", defaultValue = "1") Long missionId, | ||
@Schema(description = "미션 이름", defaultValue = "default name") String name, | ||
@Schema(description = "미션 기록 ID", defaultValue = "1") Long recordId, | ||
@Schema(description = "미션 일지 내용", defaultValue = "default remark") String remark, | ||
@Schema( | ||
description = "미션 기록 인증 사진 Url", | ||
defaultValue = "https://image.10mm.today/default.png") | ||
String recordImageUrl, | ||
@Schema(description = "미션 수행한 시간", defaultValue = "21") long duration, | ||
@Schema(description = "미션 시작한 지 N일차", defaultValue = "3") long sinceDay, | ||
@JsonFormat( | ||
shape = JsonFormat.Shape.STRING, | ||
pattern = "yyyy-MM-dd HH:mm:ss", | ||
timezone = "Asia/Seoul") | ||
@Schema( | ||
description = "미션 기록 시작 시간", | ||
defaultValue = "2024-01-06 00:00:00", | ||
type = "string") | ||
LocalDateTime startedAt, | ||
@JsonFormat( | ||
shape = JsonFormat.Shape.STRING, | ||
pattern = "yyyy-MM-dd HH:mm:ss", | ||
timezone = "Asia/Seoul") | ||
@Schema( | ||
description = "미션 기록 종료 시간", | ||
defaultValue = "2024-01-20 00:34:00", | ||
type = "string") | ||
LocalDateTime finishedAt) { | ||
@QueryProjection | ||
public FeedOneResponse( | ||
Long memberId, | ||
String nickname, | ||
String profileImage, | ||
Long missionId, | ||
String name, | ||
Long recordId, | ||
String remark, | ||
String recordImageUrl, | ||
Duration duration, | ||
LocalDateTime startedAt, | ||
LocalDateTime finishedAt) { | ||
this( | ||
memberId, | ||
nickname, | ||
profileImage, | ||
missionId, | ||
name, | ||
recordId, | ||
remark, | ||
recordImageUrl, | ||
duration.toMinutes(), | ||
Duration.between(startedAt, LocalDateTime.now()).toDays() + 1, | ||
startedAt, | ||
finishedAt); | ||
} | ||
|
||
public static FeedOneResponse of( | ||
Long memberId, | ||
String nickname, | ||
String profileImage, | ||
Long missionId, | ||
String name, | ||
Long recordId, | ||
String remark, | ||
String recordImageUrl, | ||
Duration duration, | ||
LocalDateTime startedAt, | ||
LocalDateTime finishedAt) { | ||
return new FeedOneResponse( | ||
memberId, | ||
nickname, | ||
profileImage, | ||
missionId, | ||
name, | ||
recordId, | ||
remark, | ||
recordImageUrl, | ||
duration.toMinutes(), | ||
Duration.between(startedAt, LocalDateTime.now()).toDays() + 1, | ||
startedAt, | ||
finishedAt); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.