feat: create respository and controllers for creating and viewing invitations

This commit is contained in:
sBubshait 2025-07-22 09:12:18 +03:00
parent 63cff0ab24
commit ff87f161df
5 changed files with 191 additions and 0 deletions

View File

@ -0,0 +1,81 @@
package online.wesal.wesal.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import online.wesal.wesal.dto.ApiResponse;
import online.wesal.wesal.dto.CreateInvitationRequest;
import online.wesal.wesal.dto.InvitationResponse;
import online.wesal.wesal.service.InvitationService;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/invitations")
@CrossOrigin(origins = "*")
@Tag(name = "Invitations", description = "Invitation management endpoints")
public class InvitationController {
@Autowired
private InvitationService invitationService;
@PostMapping(value = "/create", consumes = "application/json", produces = "application/json")
@Operation(summary = "Create invitation", description = "Create a new invitation")
public ResponseEntity<ApiResponse<InvitationResponse>> createInvitation(
@Valid @RequestBody CreateInvitationRequest request,
BindingResult bindingResult,
Authentication authentication) {
if (bindingResult.hasErrors()) {
String errorMessage = bindingResult.getFieldErrors().stream()
.map(error -> {
String field = error.getField();
if ("title".equals(field)) return "Title is required";
if ("description".equals(field)) return "Description is required";
if ("maxParticipants".equals(field)) return "Maximum participants must be a positive number";
if ("tagId".equals(field)) return "Tag ID is required";
return error.getDefaultMessage();
})
.collect(Collectors.joining(", "));
return ResponseEntity.badRequest().body(ApiResponse.error(errorMessage));
}
try {
String userEmail = authentication.getName();
InvitationResponse response = invitationService.createInvitation(request, userEmail);
return ResponseEntity.ok(ApiResponse.success(response));
} catch (RuntimeException e) {
String message;
if (e.getMessage().contains("User not found")) {
message = "Authentication error. Please log in again.";
} else if (e.getMessage().contains("Tag not found")) {
message = "The selected tag does not exist.";
} else {
message = "Something went wrong.. We're sorry but try again later";
}
return ResponseEntity.badRequest().body(ApiResponse.error(message));
}
}
@GetMapping("/get")
@Operation(summary = "Get invitation", description = "Get invitation by ID")
public ResponseEntity<ApiResponse<InvitationResponse>> getInvitation(@RequestParam Long id) {
if (id == null || id <= 0) {
return ResponseEntity.badRequest().body(ApiResponse.error("Valid invitation ID is required"));
}
try {
return invitationService.getInvitationById(id)
.map(invitation -> ResponseEntity.ok(ApiResponse.success(invitation)))
.orElse(ResponseEntity.status(404).body(ApiResponse.error("Invitation not found")));
} catch (Exception e) {
return ResponseEntity.status(500).body(ApiResponse.error("Something went wrong.. We're sorry but try again later"));
}
}
}

View File

@ -0,0 +1,9 @@
package online.wesal.wesal.repository;
import online.wesal.wesal.entity.Attendee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface AttendeeRepository extends JpaRepository<Attendee, Long> {
}

View File

@ -0,0 +1,9 @@
package online.wesal.wesal.repository;
import online.wesal.wesal.entity.Invitation;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface InvitationRepository extends JpaRepository<Invitation, Long> {
}

View File

@ -0,0 +1,9 @@
package online.wesal.wesal.repository;
import online.wesal.wesal.entity.Tag;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface TagRepository extends JpaRepository<Tag, Long> {
}

View File

@ -0,0 +1,83 @@
package online.wesal.wesal.service;
import online.wesal.wesal.dto.CreateInvitationRequest;
import online.wesal.wesal.dto.InvitationResponse;
import online.wesal.wesal.entity.Invitation;
import online.wesal.wesal.entity.Tag;
import online.wesal.wesal.entity.User;
import online.wesal.wesal.repository.InvitationRepository;
import online.wesal.wesal.repository.TagRepository;
import online.wesal.wesal.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
@Service
public class InvitationService {
@Autowired
private InvitationRepository invitationRepository;
@Autowired
private TagRepository tagRepository;
@Autowired
private UserRepository userRepository;
@Transactional
public InvitationResponse createInvitation(CreateInvitationRequest request, String userEmail) {
User creator = userRepository.findByEmail(userEmail)
.orElseThrow(() -> new RuntimeException("User not found"));
Tag tag = tagRepository.findById(request.getTagId())
.orElseThrow(() -> new RuntimeException("Tag not found"));
Invitation invitation = new Invitation(
request.getTitle(),
request.getDescription(),
request.getMaxParticipants(),
tag,
creator
);
invitation.setDateTime(request.getDateTime());
invitation.setLocation(request.getLocation());
Invitation saved = invitationRepository.save(invitation);
return mapToResponse(saved);
}
public Optional<InvitationResponse> getInvitationById(Long id) {
return invitationRepository.findById(id)
.map(this::mapToResponse);
}
private InvitationResponse mapToResponse(Invitation invitation) {
InvitationResponse response = new InvitationResponse();
response.setId(invitation.getId());
response.setTitle(invitation.getTitle());
response.setDescription(invitation.getDescription());
response.setDateTime(invitation.getDateTime());
response.setLocation(invitation.getLocation());
response.setMaxParticipants(invitation.getMaxParticipants());
response.setCurrentAttendees(invitation.getCurrentAttendees());
response.setCreatedAt(invitation.getCreatedAt());
InvitationResponse.TagDto tagDto = new InvitationResponse.TagDto();
tagDto.setId(invitation.getTag().getId());
tagDto.setName(invitation.getTag().getName());
tagDto.setColorHex(invitation.getTag().getColorHex());
tagDto.setIconName(invitation.getTag().getIconName());
response.setTag(tagDto);
InvitationResponse.UserDto userDto = new InvitationResponse.UserDto();
userDto.setId(invitation.getCreator().getId());
userDto.setDisplayName(invitation.getCreator().getDisplayName());
userDto.setAvatar(invitation.getCreator().getAvatar());
response.setCreator(userDto);
return response;
}
}