Skip to content

Commit

Permalink
Merge pull request #211 from bounswe/issue#204-tracking-mechanism-for…
Browse files Browse the repository at this point in the history
…-training-programs

Issue#204 tracking mechanism for training programs
  • Loading branch information
sametaln authored Nov 24, 2024
2 parents d5711b0 + 99877ee commit f5a37a9
Show file tree
Hide file tree
Showing 12 changed files with 291 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

import com.group7.demo.dtos.TrainingProgramRequest;
import com.group7.demo.dtos.TrainingProgramResponse;
import com.group7.demo.dtos.UserTrainingProgramResponse;
import com.group7.demo.services.TrainingProgramService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Collections;
import java.util.List;
import java.util.Set;

@RestController
@RequestMapping("/api/training-programs")
Expand Down Expand Up @@ -69,8 +72,8 @@ public ResponseEntity<String> leaveProgram(@PathVariable Long programId, HttpSer
}

@GetMapping("/{programId}/participants")
public ResponseEntity<List<String>> getRegisteredUsernames(@PathVariable Long programId) {
List<String> usernames = trainingProgramService.getRegisteredUsernames(programId);
public ResponseEntity<Set<String>> getRegisteredUsernames(@PathVariable Long programId) {
Set<String> usernames = trainingProgramService.getRegisteredUsernames(programId);
return ResponseEntity.ok(usernames);
}

Expand All @@ -81,4 +84,42 @@ public ResponseEntity<List<TrainingProgramResponse>> getTrainingProgramsByTraine
return ResponseEntity.ok(trainingPrograms);
}

@PostMapping("/{trainingProgramId}/exercises/{exerciseId}/complete")
public ResponseEntity<Void> markExerciseAsCompleted(
@PathVariable Long trainingProgramId,
@PathVariable Long exerciseId,
HttpServletRequest request
) {
trainingProgramService.markExerciseAsCompleted(trainingProgramId, exerciseId, request);
return ResponseEntity.ok().build();
}

@PostMapping("/{trainingProgramId}/exercises/{exerciseId}/uncomplete")
public ResponseEntity<Void> unmarkExerciseAsCompleted(
@PathVariable Long trainingProgramId,
@PathVariable Long exerciseId,
HttpServletRequest request) {
trainingProgramService.unmarkExerciseAsCompleted(trainingProgramId, exerciseId, request);
return ResponseEntity.ok().build();
}

@PostMapping("/{trainingProgramId}/complete")
public ResponseEntity<Void> markTrainingProgramAsCompleted(
@PathVariable Long trainingProgramId,
HttpServletRequest request
) {
trainingProgramService.markTrainingProgramAsCompleted(trainingProgramId, request);
return ResponseEntity.ok().build();
}

@GetMapping("/joined/{username}")
public ResponseEntity<List<UserTrainingProgramResponse>> getJoinedTrainingPrograms(@PathVariable String username) {
try {
List<UserTrainingProgramResponse> responses = trainingProgramService.getJoinedTrainingPrograms(username);
return ResponseEntity.ok(responses);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Collections.emptyList());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
@Builder
@AllArgsConstructor
public class ExerciseDetail {
private Long id;
private Exercise exercise;
private int repetitions;
private int sets;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

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

@Data
@Builder
Expand All @@ -16,6 +17,6 @@ public class TrainingProgramResponse {
private List<ExerciseDetail> exercises;
private String description;
private String trainerUsername;
private List<String> participants;
private Set<String> participants;
private LocalDateTime createdAt;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.group7.demo.dtos;

import com.group7.demo.models.Exercise;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

@Data
@Builder
@AllArgsConstructor
public class UserExerciseDetail {
private Long id;
private Exercise exercise;
private int repetitions;
private int sets;
private boolean completed;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ public class UserProfileResponse {
private Set<String> following;
private List<PostResponse> posts;
private List<TrainingProgramResponse> trainingPrograms;
private List<TrainingProgramResponse> joinedPrograms;
private List<UserTrainingProgramResponse> joinedPrograms;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.group7.demo.dtos;

import com.group7.demo.models.enums.UserTrainingProgramStatus;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;

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

@Data
@Builder
@AllArgsConstructor
public class UserTrainingProgramResponse {
private Long id;
private String title;
private List<UserExerciseDetail> exercises;
private String description;
private String trainerUsername;
private Set<String> participants;
private UserTrainingProgramStatus status;
private LocalDateTime createdAt;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
import com.group7.demo.models.*;
import org.springframework.stereotype.Component;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Component
Expand All @@ -29,20 +32,56 @@ public TrainingProgramResponse mapToTrainingProgramResponse(TrainingProgram prog
.createdAt(program.getCreatedAt())
.exercises(program.getExercises().stream()
.map(this::mapToExerciseDetailResponse)
.sorted(Comparator.comparing(ExerciseDetail::getId))
.collect(Collectors.toList()))
.participants(program.getParticipants() == null ?
List.of() :
Set.of() :
program.getParticipants().stream()
.map(userTrainingProgram -> userTrainingProgram.getUser().getUsername())
.collect(Collectors.toList()))
.collect(Collectors.toSet()))
.build();
}

public ExerciseDetail mapToExerciseDetailResponse(TrainingProgramExercise trainingProgramExercise) {
return ExerciseDetail.builder()
.id(trainingProgramExercise.getId())
.exercise(trainingProgramExercise.getExercise())
.repetitions(trainingProgramExercise.getRepetitions())
.sets(trainingProgramExercise.getSets())
.build();
}

public UserTrainingProgramResponse mapToUserTrainingProgramResponse(UserTrainingProgram userTrainingProgram) {
TrainingProgram program = userTrainingProgram.getTrainingProgram();
Map<Long, Boolean> completedExercises = userTrainingProgram.getExerciseProgress(); // Now returns Map<Long, Boolean>

// Use the new mapper function for exercises
List<UserExerciseDetail> exerciseDetails = program.getExercises().stream()
.map(exercise -> mapToUserExerciseDetailResponse(exercise, completedExercises))
.sorted(Comparator.comparing(UserExerciseDetail::getId))
.collect(Collectors.toList());

return UserTrainingProgramResponse.builder()
.id(program.getId())
.title(program.getTitle())
.description(program.getDescription())
.trainerUsername(program.getTrainer().getUsername())
.participants(program.getParticipants().stream()
.map(participant -> participant.getUser().getUsername())
.collect(Collectors.toSet()))
.exercises(exerciseDetails)
.status(userTrainingProgram.getStatus())
.createdAt(program.getCreatedAt())
.build();
}

public UserExerciseDetail mapToUserExerciseDetailResponse(TrainingProgramExercise trainingProgramExercise, Map<Long, Boolean> completedExercises) {
return UserExerciseDetail.builder()
.id(trainingProgramExercise.getId())
.exercise(trainingProgramExercise.getExercise())
.repetitions(trainingProgramExercise.getRepetitions())
.sets(trainingProgramExercise.getSets())
.completed(completedExercises.getOrDefault(trainingProgramExercise.getId(), false)) // Use `getOrDefault` to handle missing keys
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package com.group7.demo.models;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.group7.demo.models.enums.UserTrainingProgramStatus;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Entity
@Builder
Expand All @@ -27,5 +32,29 @@ public class UserTrainingProgram {
@JoinColumn(name = "training_program_id", nullable = false)
private TrainingProgram trainingProgram;

@Enumerated(EnumType.STRING)
@Column(nullable = false)
private UserTrainingProgramStatus status;

@Lob
@Column(columnDefinition = "TEXT")
private String exerciseProgress; // JSON progress tracking

private LocalDateTime joinedAt;

// Deserialize the JSON string into a Map
public Map<Long, Boolean> getExerciseProgress() {
if (exerciseProgress == null) {
return new HashMap<>(); // return empty map if no progress is available
}

try {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(exerciseProgress, new TypeReference<Map<Long, Boolean>>() {});
} catch (Exception e) {
e.printStackTrace();
return new HashMap<>(); // return empty map on error
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.group7.demo.models.enums;

public enum UserTrainingProgramStatus {
ONGOING,
LEFT,
COMPLETED
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.group7.demo.repository;

import com.group7.demo.models.TrainingProgram;
import com.group7.demo.models.User;
import com.group7.demo.models.UserTrainingProgram;
import org.springframework.data.jpa.repository.JpaRepository;
Expand All @@ -9,7 +8,7 @@
import java.util.Optional;

public interface UserTrainingProgramRepository extends JpaRepository<UserTrainingProgram, Long> {
boolean existsByUserAndTrainingProgram(User user, TrainingProgram trainingProgram);
List<UserTrainingProgram> findAllByUserAndTrainingProgramId(User user, Long trainingProgramId);
Optional<UserTrainingProgram> findByUserIdAndTrainingProgramId(Long userId, Long programId);

List<UserTrainingProgram> findByUser(User user);
Expand Down
Loading

0 comments on commit f5a37a9

Please sign in to comment.