Skip to content

Commit

Permalink
follow, create and join programs
Browse files Browse the repository at this point in the history
  • Loading branch information
sametaln committed Oct 21, 2024
1 parent c5d27b4 commit 59a8519
Show file tree
Hide file tree
Showing 18 changed files with 623 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
.cors(cors -> cors.configurationSource(corsConfigurationSource())) // Enable CORS configuration
.authorizeHttpRequests(auth -> auth
.requestMatchers("/auth/register", "/auth/login").permitAll() // Allow registration and login without authentication
.requestMatchers("GET", "/api/user/{username}", "/api/user/{username}/followers", "/api/user/{username}/following", "/api/posts/random").permitAll()
.requestMatchers("GET", "/api/user/{username}", "/api/user/{username}/followers", "/api/user/{username}/following", "/api/posts/random", "api/training-programs").permitAll()
.anyRequest().authenticated() // All other requests require authentication
)
.sessionManagement(session -> session
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ public ResponseEntity<Void> deleteTrainingProgram(@PathVariable Long id, HttpSer


@PostMapping("/{programId}/join")
public ResponseEntity<String> joinTrainingProgram(@RequestParam Long userId, @PathVariable Long programId , HttpServletRequest request) {
trainingProgramService.joinTrainingProgram(userId, programId ,request);
public ResponseEntity<String> joinTrainingProgram(@PathVariable Long programId , HttpServletRequest request) {
trainingProgramService.joinTrainingProgram(programId ,request);
return ResponseEntity.ok("User has successfully joined the training program.");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ public class UserProfileResponse {
private Set<String> following;
private List<PostResponse> posts;
private List<TrainingProgramResponse> trainingPrograms;
private List<TrainingProgramResponse> joinedPrograms;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
import com.group7.demo.models.UserTrainingProgram;
import org.springframework.data.jpa.repository.JpaRepository;

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

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

List<UserTrainingProgram> findByUser(User user);

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ public class TrainingProgramService {
private final UserTrainingProgramRepository userTrainingProgramRepository;

private final UserRepository userRepository;

private final UserService userService;

@Transactional
public TrainingProgramResponse createTrainingProgram(TrainingProgramRequest trainingProgramRequest, HttpServletRequest request) throws IllegalAccessException {
User user = authenticationService.getAuthenticatedUserInternal(request);
Expand Down Expand Up @@ -148,7 +149,7 @@ public void deleteTrainingProgram(Long id, HttpServletRequest request) throws Ex
}

@Transactional
public void joinTrainingProgram(Long userId, Long trainingProgramId , HttpServletRequest request) {
public void joinTrainingProgram(Long trainingProgramId , HttpServletRequest request) {
User user = authenticationService.getAuthenticatedUserInternal(request);

TrainingProgram trainingProgram = trainingProgramRepository.findById(trainingProgramId)
Expand Down Expand Up @@ -198,5 +199,20 @@ public List<String> getRegisteredUsernames(Long trainingProgramId) {
.collect(Collectors.toList());
}

// Return the list of joined training programs for the authenticated user
public List<TrainingProgramResponse> getJoinedTrainingPrograms(String username) throws Exception {
// Fetch the authenticated user
User user = userService.getUserByUsername(username);

// Fetch the list of training programs the user has joined
List<UserTrainingProgram> userTrainingPrograms = userTrainingProgramRepository.findByUser(user);

// Map the list of UserTrainingProgram entities to TrainingProgramResponse DTOs
return userTrainingPrograms.stream()
.map(UserTrainingProgram::getTrainingProgram)
.map(this::mapToTrainingProgramResponse)
.collect(Collectors.toList());
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,30 @@
import com.group7.demo.repository.UserRepository;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

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

@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final AuthenticationService authenticationService;
private final PostService postService;
private final TrainingProgramService trainingProgramService;

public UserService(UserRepository userRepository,
@Lazy AuthenticationService authenticationService,
@Lazy PostService postService,
@Lazy TrainingProgramService trainingProgramService) {
this.userRepository = userRepository;
this.authenticationService = authenticationService;
this.postService = postService;
this.trainingProgramService = trainingProgramService;
}

public UserProfileResponse getUserProfile(String username) throws Exception {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new Exception("User not found"));
Expand All @@ -37,6 +47,7 @@ public UserProfileResponse getUserProfile(String username) throws Exception {

List<PostResponse> posts = postService.getPostsByUser(user.getUsername());
List<TrainingProgramResponse> trainingPrograms = trainingProgramService.getTrainingProgramByTrainer(user.getUsername());
List<TrainingProgramResponse> joinedPrograms = trainingProgramService.getJoinedTrainingPrograms(user.getUsername());

return UserProfileResponse.builder()
.username(user.getUsername())
Expand All @@ -46,6 +57,7 @@ public UserProfileResponse getUserProfile(String username) throws Exception {
.following(following)
.posts(posts)
.trainingPrograms(trainingPrograms)
.joinedPrograms(joinedPrograms)
.build();
}

Expand Down Expand Up @@ -95,4 +107,9 @@ public Set<String> getFollowing(String username) throws Exception {
.collect(Collectors.toSet());
}

public User getUserByUsername(String username) throws Exception {
return userRepository.findByUsername(username)
.orElseThrow(() -> new Exception("User not found"));
}

}
33 changes: 12 additions & 21 deletions frontend/src/components/CreateProgramModal.component.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,7 @@ import { useDispatch } from 'react-redux'
import { useContext } from 'react'
import { PostContext } from '../context/PostContext'
import { useMutation, useQueryClient } from '@tanstack/react-query'

const programTypes = [
{ value: 'GROUP', label: 'Group' },
{ value: 'INDIVIDUAL', label: 'Individual' },
]

const muscleGroups = [
{ value: 'CHEST', label: 'Chest' },
{ value: 'BACK', label: 'Back' },
{ value: 'SHOULDERS', label: 'Shoulders' },
{ value: 'LEGS', label: 'Legs' },
{ value: 'ARMS', label: 'Arms' },
{ value: 'CORE', label: 'Core' },
]

const locationType = [
{ value: 'HOME', label: 'Home' },
{ value: 'GYM', label: 'Gym' },
{ value: 'OUTDOOR', label: 'Outdoors' },
]
import { muscleGroups, locationType, programTypes } from '../constants/program'

function CreateProgramModal({
isOpen,
Expand Down Expand Up @@ -211,7 +192,17 @@ function CreateProgramModal({
onSuccess: (data) => {
queryClient.invalidateQueries(
{
queryKey: ['posts', 'training-programs', 'profile']
queryKey: ['posts']
}
)
queryClient.invalidateQueries(
{
queryKey: ['training-programs']
}
)
queryClient.invalidateQueries(
{
queryKey: ['user']
}
)
onClose()
Expand Down
62 changes: 21 additions & 41 deletions frontend/src/components/PostFeed.component.jsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import React from 'react'
import React, { useContext } from 'react';
import {
Box,
Button,
Flex,
Heading,
Input,
Stack,
Text,
useColorModeValue,
Spinner
} from '@chakra-ui/react'
import { useContext } from 'react'
import { PostContext } from '../context/PostContext'
import PostFeedCard from './PostFeedCard.component'
} from '@chakra-ui/react';
import { PostContext } from '../context/PostContext';
import PostFeedCard from './PostFeedCard.component';
import ProgramFeedCard from './ProgramFeedCard.component';

function PostFeed() {
const { posts, isLoadingPosts, isFetchingPosts, programs, isFetchingPrograms, isLoadingPrograms } = useContext(PostContext)
const { posts, isLoadingPosts, isFetchingPosts, programs, isFetchingPrograms, isLoadingPrograms } = useContext(PostContext);

const isLoading = isLoadingPosts || isFetchingPrograms;

return (
<Box
Expand All @@ -33,51 +34,30 @@ function PostFeed() {
>
<Heading size="lg">Your Feed</Heading>
</Flex>
{isLoadingPosts && isFetchingPrograms && (
{isLoading ? (
<Flex justify="center">
<Spinner />
<Text>
Loading Content...
</Text>
<Text>Loading Content...</Text>
</Flex>
)}
{posts.length > 0 ? (
) : posts.length > 0 ? (
posts.map((post) => (
<PostFeedCard post={post} key={post.id} />
))
) : (
<Text>
Nothing to show here...
</Text>
<Text>Nothing to show here...</Text>
)}
{
programs.length > 0 && (
<Stack>
<Heading size="md">Recommended Programs</Heading>
{programs.map((program) => (
<Box
key={program.id}
p={4}
borderWidth={1}
borderRadius={8}
borderColor={useColorModeValue('gray.200', 'gray.700')}
>
<Heading size="sm">{program.name}</Heading>
<Text>{program.description}</Text>
<Button
colorScheme="purple"
mt={4}
>
View Program
</Button>
</Box>
))}
</Stack>
)
// Recommended Programs
}
<Heading size="lg">Recommended Programs</Heading>
{programs.length > 0 && (
programs.map((program) => (
<ProgramFeedCard program={program} key={program.id} />
))
)}
</Stack>
</Box>
)
);
}

export default PostFeed
export default PostFeed;
Loading

0 comments on commit 59a8519

Please sign in to comment.