Skip to content

Commit

Permalink
feat: add feature to like and/or save a post and get my saved courses
Browse files Browse the repository at this point in the history
  • Loading branch information
peageon committed Jun 19, 2024
1 parent bf66ee1 commit cb4e48e
Show file tree
Hide file tree
Showing 7 changed files with 232 additions and 10 deletions.
7 changes: 4 additions & 3 deletions src/main/java/com/runningmate/backend/member/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
import com.runningmate.backend.entity.BaseTimeEntity;
import jakarta.persistence.*;
import lombok.*;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -50,6 +47,10 @@ public class Member extends BaseTimeEntity {
@Builder.Default
private List<Follow> followings = new ArrayList<>();

@OneToMany(mappedBy = "member")
@Builder.Default
private List<MemberRoute> memberRoutes = new ArrayList<>();

public void updateRefreshToken(String token) {
this.refreshtoken = token;
}
Expand Down
47 changes: 47 additions & 0 deletions src/main/java/com/runningmate/backend/member/MemberRoute.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.runningmate.backend.member;

import com.runningmate.backend.route.Route;
import jakarta.persistence.*;
import lombok.*;

import java.util.UUID;

@Entity
@Table(name = "member_route")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public class MemberRoute {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;

@ManyToOne
@JoinColumn(name = "member_id")
private Member member;

@ManyToOne
@JoinColumn(name = "route_id")
private Route route;

private boolean liked;

private boolean saved;

public void saveRoute() {
this.saved = true;
}

public void unsaveRoute() {
this.saved = false;
}

public void likeRoute() {
this.liked = true;
}

public void unlikeRoute() {
this.liked = false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.runningmate.backend.member.repository;

import com.runningmate.backend.member.Member;
import com.runningmate.backend.member.MemberRoute;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

@Repository
public interface MemberRouteRepository extends JpaRepository<MemberRoute, UUID> {
List<MemberRoute> findByMemberAndSavedTrue(Member member);
List<MemberRoute> findByMemberAndLikedTrue(Member member);
Optional<MemberRoute> findByMemberIdAndRouteId(Long memberId, Long routeId);
}
8 changes: 7 additions & 1 deletion src/main/java/com/runningmate/backend/route/Route.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

import com.runningmate.backend.entity.BaseTimeEntity;
import com.runningmate.backend.member.Member;
import com.runningmate.backend.member.MemberRoute;
import jakarta.persistence.*;
import lombok.*;
import org.locationtech.jts.geom.LineString;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table(name = "route")
Expand All @@ -25,6 +27,10 @@ public class Route extends BaseTimeEntity {
@JoinColumn(name = "member_id")
private Member member;

@OneToMany(mappedBy = "route")
@Builder.Default
private List<MemberRoute> memberRoutes = new ArrayList<>();

@Column(nullable = false)
private String title;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package com.runningmate.backend.route.controller;

import com.runningmate.backend.member.Member;
import com.runningmate.backend.member.MemberRoute;
import com.runningmate.backend.member.service.MemberService;
import com.runningmate.backend.route.Route;
import com.runningmate.backend.route.dto.MemberRouteResponseDto;
import com.runningmate.backend.route.dto.RouteListResponseDto;
import com.runningmate.backend.route.dto.RouteRequestDto;
import com.runningmate.backend.route.dto.RouteResponseDto;
Expand All @@ -21,28 +26,69 @@
@RequiredArgsConstructor
public class RouteController {
private final RouteService routeService;
private final MemberService memberService;

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public RouteResponseDto createRoute(@Valid @RequestBody RouteRequestDto routeRequest, @AuthenticationPrincipal UserDetails userDetails) throws BadRequestException {
String username = userDetails.getUsername();
return routeService.saveRoute(routeRequest, username);
return routeService.createRoute(routeRequest, username);
}

@GetMapping("/{routeId}")
@ResponseStatus(HttpStatus.OK)
public RouteResponseDto getRouteById(@PathVariable(name = "routeId") Long routeId, @AuthenticationPrincipal UserDetails userDetails) {
public RouteResponseDto getRouteById(@PathVariable(name = "routeId") Long routeId) {
RouteResponseDto routeResponseDto = routeService.getRouteById(routeId);
return routeResponseDto;
}

@GetMapping("/radius")
@ResponseStatus(HttpStatus.OK)
public RouteListResponseDto getCourseWithinRadius(@RequestParam(name = "latitude") double latitude,
@RequestParam(name = "longitude") double longitude,
@RequestParam(name = "radius") @Max(5000) @Min(0) int radius) {
public RouteListResponseDto getRouteWithinRadius(@RequestParam(name = "latitude") double latitude,
@RequestParam(name = "longitude") double longitude,
@RequestParam(name = "radius") @Max(5000) @Min(0) int radius) {
List<RouteResponseDto> routeResponseDtoList = routeService.getRoutesWithinRadius(latitude, longitude, radius);

return new RouteListResponseDto(routeResponseDtoList);
}

@PostMapping("/{routeId}/save")
@ResponseStatus(HttpStatus.CREATED)
public MemberRouteResponseDto saveRoute(@PathVariable(name = "routeId") Long routeId, @AuthenticationPrincipal UserDetails userDetails) {
Member member = memberService.getMemberByUsername(userDetails.getUsername());
MemberRoute memberRoute = routeService.saveRoute(routeId, member);
return new MemberRouteResponseDto(memberRoute);
}

@DeleteMapping("/{routeId}/unsave")
@ResponseStatus(HttpStatus.OK) //Return 200 instead of 204 for uniformity
public void unsaveRoute(@PathVariable(name = "routeId") Long routeId, @AuthenticationPrincipal UserDetails userDetails) {
Member member = memberService.getMemberByUsername(userDetails.getUsername());
routeService.unsaveRoute(routeId, member);
}

@PostMapping("/{routeId}/like")
@ResponseStatus(HttpStatus.CREATED)
public MemberRouteResponseDto likeRoute(@PathVariable(name = "routeId") Long routeId, @AuthenticationPrincipal UserDetails userDetails) {
Member member = memberService.getMemberByUsername(userDetails.getUsername());
MemberRoute memberRoute = routeService.likeRoute(routeId, member);
return new MemberRouteResponseDto(memberRoute);
}

@DeleteMapping("/{routeId}/unlike")
@ResponseStatus(HttpStatus.OK) //Return 200 instead of 204 for uniformity
public void unlikeRoute(@PathVariable(name = "routeId") Long routeId, @AuthenticationPrincipal UserDetails userDetails) {
Member member = memberService.getMemberByUsername(userDetails.getUsername());
routeService.unlikeRoute(routeId, member);
}

@GetMapping("/saved")
@ResponseStatus(HttpStatus.OK)
public RouteListResponseDto getSavedRoutes(@AuthenticationPrincipal UserDetails userDetails) {
String username = userDetails.getUsername();
Member member = memberService.getMemberByUsername(username);
List<Route> routes = routeService.getSavedRoutes(member);
List<RouteResponseDto> routeResponseDtos = routeService.changeRoutesToRouteResponseDtos(routes);
return new RouteListResponseDto(routeResponseDtos);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.runningmate.backend.route.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.runningmate.backend.member.MemberRoute;
import lombok.Getter;

@Getter
public class MemberRouteResponseDto {
private Long memberId;
@JsonProperty("courseId")
private Long routeId;
private boolean liked;
private boolean saved;

public MemberRouteResponseDto(MemberRoute memberRoute) {
this.memberId = memberRoute.getMember().getId();
this.routeId = memberRoute.getRoute().getId();
this.liked = memberRoute.isLiked();
this.saved = memberRoute.isSaved();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

import com.runningmate.backend.exception.BadRequestException;
import com.runningmate.backend.exception.ResourceNotFoundException;
import com.runningmate.backend.member.Member;
import com.runningmate.backend.member.MemberRoute;
import com.runningmate.backend.member.dto.MemberDto;
import com.runningmate.backend.member.repository.MemberRouteRepository;
import com.runningmate.backend.member.service.MemberService;
import com.runningmate.backend.route.Route;
import com.runningmate.backend.route.dto.CoordinateDto;
import com.runningmate.backend.route.dto.RouteListResponseDto;
import com.runningmate.backend.route.dto.RouteRequestDto;
import com.runningmate.backend.route.dto.RouteResponseDto;
import com.runningmate.backend.route.repository.RouteRepository;
Expand All @@ -25,10 +29,11 @@
@RequiredArgsConstructor
public class RouteService {
private final RouteRepository routeRepository;
private final MemberRouteRepository memberRouteRepository;
private final MemberService memberService;

@Transactional
public RouteResponseDto saveRoute(RouteRequestDto request, String username) {
public RouteResponseDto createRoute(RouteRequestDto request, String username) {
List<CoordinateDto> coordinateDtos = request.getRoute();
validateCoordinates(coordinateDtos);
LineString lineString = coordinateDtoListToLineString(coordinateDtos);
Expand All @@ -47,6 +52,85 @@ public RouteResponseDto getRouteById(Long routeId) {
public List<RouteResponseDto> getRoutesWithinRadius(double latitude, double longitude, int radius) {
validateCoordinate(new CoordinateDto(latitude, longitude));
List<Route> routes = routeRepository.findRoutesWithinRadius(latitude, longitude, radius);
List<RouteResponseDto> routeDtos = changeRoutesToRouteResponseDtos(routes);
return routeDtos;
}

public List<Route> getSavedRoutes(Member member) {
List<MemberRoute> memberRoutes = memberRouteRepository.findByMemberAndSavedTrue(member);
List<Route> routes = new ArrayList<>();
for (MemberRoute memberRoute: memberRoutes) {
routes.add(memberRoute.getRoute());
}
return routes;
}

@Transactional
public MemberRoute saveRoute(Long routeId, Member member) {
Route route = routeRepository.findById(routeId)
.orElseThrow(
() -> new ResourceNotFoundException("Route with id " + routeId + " does not exist.")
);
Optional<MemberRoute> memberRouteOptional = memberRouteRepository.findByMemberIdAndRouteId(member.getId(), routeId);
MemberRoute memberRoute = memberRouteOptional.orElseGet(() -> MemberRoute.builder()
.route(route)
.member(member)
.build());

memberRoute.saveRoute();
return memberRouteRepository.save(memberRoute);
}

@Transactional
public void unsaveRoute(Long routeId, Member member) {
Route route = routeRepository.findById(routeId)
.orElseThrow(
() -> new ResourceNotFoundException("Route with id " + routeId + " does not exist.")
);
Optional<MemberRoute> memberRouteOptional = memberRouteRepository.findByMemberIdAndRouteId(member.getId(), routeId);
if (memberRouteOptional.isPresent()) {
MemberRoute memberRoute = memberRouteOptional.get();
memberRoute.unsaveRoute();
if (!memberRoute.isLiked() && !memberRoute.isSaved()) {
memberRouteRepository.delete(memberRoute);
} else {
memberRouteRepository.save(memberRoute);
}
}
}

@Transactional
public MemberRoute likeRoute(Long routeId, Member member) {
Route route = routeRepository.findById(routeId)
.orElseThrow(() -> new ResourceNotFoundException("Route with id " + routeId + " does not exist."));
Optional<MemberRoute> memberRouteOptional = memberRouteRepository.findByMemberIdAndRouteId(member.getId(), routeId);
MemberRoute memberRoute = memberRouteOptional.orElseGet(() -> MemberRoute.builder()
.route(route)
.member(member)
.build());
memberRoute.likeRoute();
return memberRouteRepository.save(memberRoute);
}

@Transactional
public void unlikeRoute(Long routeId, Member member) {
Route route = routeRepository.findById(routeId)
.orElseThrow(
() -> new ResourceNotFoundException("Route with id " + routeId + " does not exist.")
);
Optional<MemberRoute> memberRouteOptional = memberRouteRepository.findByMemberIdAndRouteId(member.getId(), routeId);
if (memberRouteOptional.isPresent()) {
MemberRoute memberRoute = memberRouteOptional.get();
memberRoute.unlikeRoute();
if (!memberRoute.isLiked() && !memberRoute.isSaved()) {
memberRouteRepository.delete(memberRoute);
} else {
memberRouteRepository.save(memberRoute);
}
}
}

public List<RouteResponseDto> changeRoutesToRouteResponseDtos(List<Route> routes) {
List<RouteResponseDto> routeDtos = new ArrayList<>();
for (Route route: routes) {
List<CoordinateDto> translatedCoordinates = lineStringToCoordinateDtoList(route.getPath());
Expand Down

0 comments on commit cb4e48e

Please sign in to comment.