mirror of
https://codeberg.org/beerbrawl/beerbrawl.git
synced 2024-09-22 21:20:52 +02:00
feat/#16/team-self-registration
This commit is contained in:
parent
13dcb3e951
commit
7e2a3cb942
|
@ -8,6 +8,8 @@ import org.slf4j.LoggerFactory;
|
|||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
@ -20,14 +22,17 @@ import at.ac.tuwien.sepr.groupphase.backend.endpoint.dto.TournamentListDto;
|
|||
import at.ac.tuwien.sepr.groupphase.backend.endpoint.dto.TournamentDto;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.endpoint.dto.TournamentQualificationMatchDto;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.endpoint.mapper.TournamentMapper;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.entity.Tournament.SignupTeamResult;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.service.TournamentService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = TournamentEndpoint.BASE_ENDPOINT)
|
||||
|
@ -59,14 +64,14 @@ public class TournamentEndpoint {
|
|||
@PostMapping
|
||||
@Operation(summary = "Create a new tournament", security = @SecurityRequirement(name = "apiKey"))
|
||||
public TournamentDto createTournament(
|
||||
@Valid @RequestBody CreateTournamentDto messageDto,
|
||||
Authentication authentication) {
|
||||
@Valid @RequestBody CreateTournamentDto messageDto,
|
||||
Authentication authentication) {
|
||||
LOG.info("POST /api/v1/tournaments body: {}", messageDto);
|
||||
|
||||
return tournamentMapper.entityToDto(
|
||||
tournamentService.create(
|
||||
tournamentMapper.createDtoToEntity(messageDto),
|
||||
authentication.getName()));
|
||||
tournamentService.create(
|
||||
tournamentMapper.createDtoToEntity(messageDto),
|
||||
authentication.getName()));
|
||||
}
|
||||
|
||||
@Secured("ROLE_USER")
|
||||
|
@ -74,15 +79,52 @@ public class TournamentEndpoint {
|
|||
@PostMapping(value = "{id}/generate-qualification-matches")
|
||||
@Operation(summary = "Create a new tournament", security = @SecurityRequirement(name = "apiKey"))
|
||||
public List<TournamentQualificationMatchDto> generateQualificationMatches(
|
||||
@PathVariable(name = "id") Long tournamentId,
|
||||
Authentication authentication) {
|
||||
@PathVariable(name = "id") Long tournamentId,
|
||||
Authentication authentication) {
|
||||
LOG.info("POST /api/v1/tournaments/{}/generate-qualification-matches", tournamentId);
|
||||
|
||||
return tournamentService.generateQualificationMatchesForTournament(
|
||||
tournamentId,
|
||||
authentication.getName())
|
||||
.stream()
|
||||
.map(tournamentMapper::qualificationMatchEntityToDto)
|
||||
.toList();
|
||||
.stream()
|
||||
.map(tournamentMapper::qualificationMatchEntityToDto)
|
||||
.toList();
|
||||
}
|
||||
|
||||
// as of now, information is accessible to everyone
|
||||
@PermitAll
|
||||
@GetMapping("{tournamentId}/public")
|
||||
@Operation(summary = "Get public info about tournament")
|
||||
public ResponseEntity<TournamentDto> get(@PathVariable("tournamentId") long tournamentId) {
|
||||
LOG.info("GET {}{}", BASE_ENDPOINT, tournamentId);
|
||||
final var tournament = tournamentService.findOne(tournamentId);
|
||||
final var dto = TournamentDto.fromEntity(tournament);
|
||||
return ResponseEntity.ok(dto);
|
||||
}
|
||||
|
||||
// region Team
|
||||
record CreateTeamDto(@NotBlank @Size(min = 3, max = 20) String name) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Response for team signup. Compared to enum, has openapi-generator support.
|
||||
*/
|
||||
public record SignupTeamResponseDto(SignupTeamResult signupTeamResult) {
|
||||
}
|
||||
|
||||
@PermitAll
|
||||
@ResponseStatus(HttpStatus.OK) // No location header, thus 200
|
||||
@PostMapping("{tournamentId}/teams")
|
||||
@Operation(summary = "Create a new team")
|
||||
public ResponseEntity<SignupTeamResponseDto> signupTeamForTournament(
|
||||
@PathVariable("tournamentId") long tournamentId,
|
||||
@Valid @RequestBody CreateTeamDto messageDto) {
|
||||
LOG.info("POST {} body: {}", BASE_ENDPOINT, messageDto);
|
||||
final var signupResult = tournamentService.signupTeamForTournament(tournamentId, messageDto.name);
|
||||
if (signupResult != SignupTeamResult.SUCCESS) {
|
||||
return ResponseEntity.badRequest().body(new SignupTeamResponseDto(signupResult));
|
||||
}
|
||||
return ResponseEntity.ok(new SignupTeamResponseDto(SignupTeamResult.SUCCESS));
|
||||
}
|
||||
// endregion team
|
||||
}
|
|
@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JsonFormat;
|
|||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import at.ac.tuwien.sepr.groupphase.backend.entity.Tournament;
|
||||
|
||||
public record TournamentDto(
|
||||
Long id,
|
||||
String name,
|
||||
|
@ -11,4 +13,13 @@ public record TournamentDto(
|
|||
LocalDateTime registrationEnd,
|
||||
Long maxParticipants,
|
||||
String description) {
|
||||
|
||||
public static TournamentDto fromEntity(Tournament e) {
|
||||
return new TournamentDto(
|
||||
e.getId(),
|
||||
e.getName(),
|
||||
e.getRegistrationEnd(),
|
||||
e.getMaxParticipants(),
|
||||
e.getDescription());
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ import jakarta.persistence.GenerationType;
|
|||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -15,10 +16,12 @@ public class Team {
|
|||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
private String name;
|
||||
private Boolean checkedIn;
|
||||
|
||||
@ManyToOne
|
||||
@Size(min = 3, max = 20)
|
||||
private String name;
|
||||
private boolean checkedIn;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
private Tournament tournament;
|
||||
|
||||
@OneToMany(mappedBy = "team", cascade = CascadeType.REMOVE)
|
||||
|
|
|
@ -1,23 +1,25 @@
|
|||
package at.ac.tuwien.sepr.groupphase.backend.entity;
|
||||
|
||||
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.Hibernate;
|
||||
|
||||
@Entity
|
||||
public class Tournament {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
public Tournament(String name, LocalDateTime registrationEnd, Long maxParticipants, String description, ApplicationUser organizer, List<Team> teams, List<BeerPongTable> tables) {
|
||||
public Tournament(String name, LocalDateTime registrationEnd, Long maxParticipants, String description,
|
||||
ApplicationUser organizer, List<Team> teams, List<BeerPongTable> tables) {
|
||||
this.name = name;
|
||||
this.registrationEnd = registrationEnd;
|
||||
this.maxParticipants = maxParticipants;
|
||||
|
@ -31,6 +33,7 @@ public class Tournament {
|
|||
private LocalDateTime registrationEnd;
|
||||
private Long maxParticipants;
|
||||
private String description;
|
||||
|
||||
@ManyToOne
|
||||
private ApplicationUser organizer;
|
||||
|
||||
|
@ -64,6 +67,7 @@ public class Tournament {
|
|||
return maxParticipants;
|
||||
}
|
||||
|
||||
// requires careful validation, disabled for now
|
||||
public void setMaxParticipants(Long maxParticipants) {
|
||||
this.maxParticipants = maxParticipants;
|
||||
}
|
||||
|
@ -80,6 +84,7 @@ public class Tournament {
|
|||
return organizer;
|
||||
}
|
||||
|
||||
// hibernate-required
|
||||
public void setOrganizer(ApplicationUser organizer) {
|
||||
this.organizer = organizer;
|
||||
}
|
||||
|
@ -91,4 +96,52 @@ public class Tournament {
|
|||
public void setRegistrationEnd(LocalDateTime registrationEnd) {
|
||||
this.registrationEnd = registrationEnd;
|
||||
}
|
||||
|
||||
public List<Team> getTeams() {
|
||||
return Collections.unmodifiableList(teams);
|
||||
}
|
||||
|
||||
public enum SignupTeamResult {
|
||||
SUCCESS,
|
||||
REGISTRATION_CLOSED,
|
||||
MAX_PARTICIPANTS_REACHED,
|
||||
TEAM_ALREADY_EXISTS
|
||||
}
|
||||
|
||||
/**
|
||||
* Precondition: transaction that manages this tournament is still active for
|
||||
* the lazy initialization to work.
|
||||
*
|
||||
* @return Result enum
|
||||
*/
|
||||
public SignupTeamResult signupTeam(Team team) {
|
||||
Hibernate.initialize(teams);
|
||||
if (registrationEnd.isBefore(LocalDateTime.now())) {
|
||||
return SignupTeamResult.REGISTRATION_CLOSED;
|
||||
}
|
||||
if (teams.size() >= maxParticipants) {
|
||||
return SignupTeamResult.MAX_PARTICIPANTS_REACHED;
|
||||
}
|
||||
if (teams.stream().anyMatch(
|
||||
t -> t.getName().equals(team.getName()))) {
|
||||
return SignupTeamResult.TEAM_ALREADY_EXISTS;
|
||||
}
|
||||
// relation is not set otherwise
|
||||
team.setTournament(this);
|
||||
teams.add(team);
|
||||
return SignupTeamResult.SUCCESS;
|
||||
}
|
||||
|
||||
// hibernate-required
|
||||
private void setTeams(List<Team> teams) {
|
||||
this.teams = teams;
|
||||
}
|
||||
|
||||
public List<BeerPongTable> getTables() {
|
||||
return tables;
|
||||
}
|
||||
|
||||
public void setTables(List<BeerPongTable> tables) {
|
||||
this.tables = tables;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import at.ac.tuwien.sepr.groupphase.backend.entity.QualificationMatch;
|
|||
import at.ac.tuwien.sepr.groupphase.backend.entity.Tournament;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.exception.NotFoundException;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.exception.PreconditionFailedException;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.entity.Tournament.SignupTeamResult;
|
||||
|
||||
public interface TournamentService {
|
||||
/**
|
||||
|
@ -40,4 +41,20 @@ public interface TournamentService {
|
|||
*/
|
||||
List<QualificationMatch> generateQualificationMatchesForTournament(Long tournamentId, String currentUserName)
|
||||
throws PreconditionFailedException, AccessDeniedException, NotFoundException;
|
||||
|
||||
/**
|
||||
* Create a new tournament.
|
||||
* name may not be duplicate within the same tournament
|
||||
*
|
||||
* @return created tournament entity
|
||||
*/
|
||||
SignupTeamResult signupTeamForTournament(long tournamentId, String name);
|
||||
|
||||
/**
|
||||
* Find a single tournament entity by id.
|
||||
*
|
||||
* @param tournamentId the id of the tournament entity
|
||||
* @return the tournament entity
|
||||
*/
|
||||
Tournament findOne(long tournamentId);
|
||||
}
|
||||
|
|
|
@ -17,9 +17,12 @@ import at.ac.tuwien.sepr.groupphase.backend.exception.NotFoundException;
|
|||
import at.ac.tuwien.sepr.groupphase.backend.exception.PreconditionFailedException;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.repository.QualificationMatchRepository;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.repository.TeamRepository;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.entity.Team;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.entity.Tournament.SignupTeamResult;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.repository.TournamentRepository;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.repository.UserRepository;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.service.TournamentService;
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
@Service
|
||||
public class TournamentServiceImpl implements TournamentService {
|
||||
|
@ -56,6 +59,7 @@ public class TournamentServiceImpl implements TournamentService {
|
|||
return tournamentRepository.findAllByOrganizerIdOrderByNameAsc(organizerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tournament create(Tournament tournament, String currentUserName) {
|
||||
LOGGER.debug("Create new tournament {}", tournament);
|
||||
|
||||
|
@ -120,4 +124,34 @@ public class TournamentServiceImpl implements TournamentService {
|
|||
|
||||
return matches;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public SignupTeamResult signupTeamForTournament(long tournamentId, String name) {
|
||||
LOGGER.debug("Create new team {} for tournament {}", name, tournamentId);
|
||||
|
||||
final var tournament = tournamentRepository.findById(tournamentId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Tournament not found"));
|
||||
|
||||
final var newTeam = new Team();
|
||||
newTeam.setName(name);
|
||||
var result = tournament.signupTeam(newTeam);
|
||||
if (result != SignupTeamResult.SUCCESS) {
|
||||
return result;
|
||||
}
|
||||
|
||||
tournamentRepository.saveAndFlush(tournament);
|
||||
return SignupTeamResult.SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tournament findOne(long tournamentId) {
|
||||
LOGGER.debug("Get basic information about tournament {}", tournamentId);
|
||||
|
||||
var tournament = tournamentRepository.findById(tournamentId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Tournament not found"));
|
||||
return tournament;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ spring:
|
|||
# is disabled since it breaks the principle of least astonishment and leads to bad performance. To learn more,
|
||||
# follow this link: https://bit.ly/2LaX9ku
|
||||
open-in-view: false
|
||||
h2:
|
||||
console:
|
||||
enabled: true
|
||||
|
||||
security:
|
||||
auth:
|
||||
|
@ -65,7 +68,6 @@ management:
|
|||
springdoc:
|
||||
default-consumes-media-type: application/json
|
||||
default-produces-media-type: application/json
|
||||
|
||||
---
|
||||
spring:
|
||||
config:
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
package at.ac.tuwien.sepr.groupphase.backend.integrationtest;
|
||||
|
||||
import at.ac.tuwien.sepr.groupphase.backend.basetest.TestData;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.config.properties.SecurityProperties;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.endpoint.dto.CreateTournamentDto;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.endpoint.dto.TournamentDto;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.repository.MessageRepository;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.security.JwtTokenizer;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import static org.junit.jupiter.api.Assertions.assertAll;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
@ -20,12 +22,14 @@ import org.springframework.test.context.ActiveProfiles;
|
|||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.basetest.TestData;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.config.properties.SecurityProperties;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.endpoint.dto.CreateTournamentDto;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.endpoint.dto.TournamentDto;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.repository.MessageRepository;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.security.JwtTokenizer;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
|
|
|
@ -38,7 +38,7 @@ public class TournamentServiceTest implements TestData {
|
|||
var tournament = new Tournament();
|
||||
tournament.setName("TEST_TOURNAMENT");
|
||||
tournament.setRegistrationEnd(LocalDateTime.now().plusDays(1));
|
||||
tournament.setMaxParticipants(64l);
|
||||
tournament.setMaxParticipants(64L);
|
||||
tournament = tournamentService.create(tournament, user.getUsername());
|
||||
|
||||
assertNotNull(tournament);
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package at.ac.tuwien.sepr.groupphase.backend.unittests;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.basetest.TestData;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.entity.Team;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.entity.Tournament;
|
||||
import at.ac.tuwien.sepr.groupphase.backend.entity.Tournament.SignupTeamResult;
|
||||
|
||||
@ActiveProfiles("test")
|
||||
public class TournamentTest implements TestData {
|
||||
|
||||
@Test
|
||||
public void signUpTeam_givenDuplicateName_Fails() {
|
||||
final var tournament = new Tournament(
|
||||
"TestTournament",
|
||||
LocalDateTime.MIN,
|
||||
64L,
|
||||
"TestDescription",
|
||||
null,
|
||||
new LinkedList<>(),
|
||||
null
|
||||
);
|
||||
tournament.setRegistrationEnd(LocalDateTime.MAX);
|
||||
var team1 = new Team();
|
||||
team1.setName("DuplicateName");
|
||||
assertEquals(SignupTeamResult.SUCCESS, tournament.signupTeam(team1));
|
||||
var team2 = new Team();
|
||||
team2.setName("DuplicateName");
|
||||
assertEquals(SignupTeamResult.TEAM_ALREADY_EXISTS, tournament.signupTeam(team2));
|
||||
}
|
||||
}
|
2
frontend/.gitattributes
vendored
2
frontend/.gitattributes
vendored
|
@ -1 +1 @@
|
|||
openapi-generated/**/* -merge -diff
|
||||
openapi-generated/**/* -merge -diff
|
||||
|
|
17
frontend/.vscode/launch.json
vendored
Normal file
17
frontend/.vscode/launch.json
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch",
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "npm: start",
|
||||
"url": "http://localhost:4200",
|
||||
//Prevent Chrome from debugging library code
|
||||
"skipFiles": ["node_modules/**/*.js", "lib/**/*.js"]
|
||||
}
|
||||
]
|
||||
}
|
24
frontend/.vscode/tasks.json
vendored
Normal file
24
frontend/.vscode/tasks.json
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "start",
|
||||
"isBackground": true,
|
||||
"problemMatcher": {
|
||||
"owner": "typescript",
|
||||
"pattern": "$tsc",
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": {
|
||||
"regexp": "(.*?)"
|
||||
},
|
||||
"endsPattern": {
|
||||
"regexp": "bundle generation complete"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -11,10 +11,12 @@ configuration.ts
|
|||
encoder.ts
|
||||
git_push.sh
|
||||
index.ts
|
||||
model/createTeamDto.ts
|
||||
model/createTournamentDto.ts
|
||||
model/detailedMessageDto.ts
|
||||
model/messageInquiryDto.ts
|
||||
model/models.ts
|
||||
model/signupTeamResponseDto.ts
|
||||
model/simpleMessageDto.ts
|
||||
model/tournamentDto.ts
|
||||
model/tournamentListDto.ts
|
||||
|
|
|
@ -18,9 +18,13 @@ import { HttpClient, HttpHeaders, HttpParams,
|
|||
import { CustomHttpParameterCodec } from '../encoder';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
// @ts-ignore
|
||||
import { CreateTeamDto } from '../model/createTeamDto';
|
||||
// @ts-ignore
|
||||
import { CreateTournamentDto } from '../model/createTournamentDto';
|
||||
// @ts-ignore
|
||||
import { SignupTeamResponseDto } from '../model/signupTeamResponseDto';
|
||||
// @ts-ignore
|
||||
import { TournamentDto } from '../model/tournamentDto';
|
||||
// @ts-ignore
|
||||
import { TournamentListDto } from '../model/tournamentListDto';
|
||||
|
@ -235,6 +239,148 @@ export class TournamentEndpointService {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get public info about tournament
|
||||
* @param tournamentId
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public get(tournamentId: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<TournamentDto>;
|
||||
public get(tournamentId: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<TournamentDto>>;
|
||||
public get(tournamentId: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<TournamentDto>>;
|
||||
public get(tournamentId: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {
|
||||
if (tournamentId === null || tournamentId === undefined) {
|
||||
throw new Error('Required parameter tournamentId was null or undefined when calling get.');
|
||||
}
|
||||
|
||||
let localVarHeaders = this.defaultHeaders;
|
||||
|
||||
let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
||||
if (localVarHttpHeaderAcceptSelected === undefined) {
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
}
|
||||
if (localVarHttpHeaderAcceptSelected !== undefined) {
|
||||
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
let localVarHttpContext: HttpContext | undefined = options && options.context;
|
||||
if (localVarHttpContext === undefined) {
|
||||
localVarHttpContext = new HttpContext();
|
||||
}
|
||||
|
||||
let localVarTransferCache: boolean | undefined = options && options.transferCache;
|
||||
if (localVarTransferCache === undefined) {
|
||||
localVarTransferCache = true;
|
||||
}
|
||||
|
||||
|
||||
let responseType_: 'text' | 'json' | 'blob' = 'json';
|
||||
if (localVarHttpHeaderAcceptSelected) {
|
||||
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||
responseType_ = 'text';
|
||||
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
|
||||
responseType_ = 'json';
|
||||
} else {
|
||||
responseType_ = 'blob';
|
||||
}
|
||||
}
|
||||
|
||||
let localVarPath = `/api/v1/tournaments/${this.configuration.encodeParam({name: "tournamentId", value: tournamentId, in: "path", style: "simple", explode: false, dataType: "number", dataFormat: "int64"})}/public`;
|
||||
return this.httpClient.request<TournamentDto>('get', `${this.configuration.basePath}${localVarPath}`,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
transferCache: localVarTransferCache,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new team
|
||||
* @param tournamentId
|
||||
* @param createTeamDto
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public signupTeamForTournament(tournamentId: number, createTeamDto: CreateTeamDto, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<SignupTeamResponseDto>;
|
||||
public signupTeamForTournament(tournamentId: number, createTeamDto: CreateTeamDto, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpResponse<SignupTeamResponseDto>>;
|
||||
public signupTeamForTournament(tournamentId: number, createTeamDto: CreateTeamDto, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<HttpEvent<SignupTeamResponseDto>>;
|
||||
public signupTeamForTournament(tournamentId: number, createTeamDto: CreateTeamDto, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext, transferCache?: boolean}): Observable<any> {
|
||||
if (tournamentId === null || tournamentId === undefined) {
|
||||
throw new Error('Required parameter tournamentId was null or undefined when calling signupTeamForTournament.');
|
||||
}
|
||||
if (createTeamDto === null || createTeamDto === undefined) {
|
||||
throw new Error('Required parameter createTeamDto was null or undefined when calling signupTeamForTournament.');
|
||||
}
|
||||
|
||||
let localVarHeaders = this.defaultHeaders;
|
||||
|
||||
let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
||||
if (localVarHttpHeaderAcceptSelected === undefined) {
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
}
|
||||
if (localVarHttpHeaderAcceptSelected !== undefined) {
|
||||
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
let localVarHttpContext: HttpContext | undefined = options && options.context;
|
||||
if (localVarHttpContext === undefined) {
|
||||
localVarHttpContext = new HttpContext();
|
||||
}
|
||||
|
||||
let localVarTransferCache: boolean | undefined = options && options.transferCache;
|
||||
if (localVarTransferCache === undefined) {
|
||||
localVarTransferCache = true;
|
||||
}
|
||||
|
||||
|
||||
// to determine the Content-Type header
|
||||
const consumes: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes);
|
||||
if (httpContentTypeSelected !== undefined) {
|
||||
localVarHeaders = localVarHeaders.set('Content-Type', httpContentTypeSelected);
|
||||
}
|
||||
|
||||
let responseType_: 'text' | 'json' | 'blob' = 'json';
|
||||
if (localVarHttpHeaderAcceptSelected) {
|
||||
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||
responseType_ = 'text';
|
||||
} else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
|
||||
responseType_ = 'json';
|
||||
} else {
|
||||
responseType_ = 'blob';
|
||||
}
|
||||
}
|
||||
|
||||
let localVarPath = `/api/v1/tournaments/${this.configuration.encodeParam({name: "tournamentId", value: tournamentId, in: "path", style: "simple", explode: false, dataType: "number", dataFormat: "int64"})}/teams`;
|
||||
return this.httpClient.request<SignupTeamResponseDto>('post', `${this.configuration.basePath}${localVarPath}`,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
body: createTeamDto,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
transferCache: localVarTransferCache,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all tournaments from a specific Organizer
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
|
|
|
@ -94,6 +94,7 @@ export class UserEndpointService {
|
|||
}
|
||||
|
||||
/**
|
||||
* Delete user and all data belonging to them(Tournaments, Teams, etc) from the database.
|
||||
* @param username
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
|
@ -157,6 +158,7 @@ export class UserEndpointService {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get detailed information about user and their tournaments.
|
||||
* @param username
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
|
|
17
frontend/openapi-generated/model/createTeamDto.ts
Normal file
17
frontend/openapi-generated/model/createTeamDto.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* OpenAPI definition
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: v0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
export interface CreateTeamDto {
|
||||
name: string;
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
export * from './createTeamDto';
|
||||
export * from './createTournamentDto';
|
||||
export * from './detailedMessageDto';
|
||||
export * from './messageInquiryDto';
|
||||
export * from './signupTeamResponseDto';
|
||||
export * from './simpleMessageDto';
|
||||
export * from './tournamentDto';
|
||||
export * from './tournamentListDto';
|
||||
|
|
18
frontend/openapi-generated/model/signupTeamResponse.ts
Normal file
18
frontend/openapi-generated/model/signupTeamResponse.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* OpenAPI definition
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: v0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
export interface SignupTeamResponse {
|
||||
registrationClosed?: boolean;
|
||||
teamAlreadyExists?: boolean;
|
||||
}
|
||||
|
27
frontend/openapi-generated/model/signupTeamResponseDto.ts
Normal file
27
frontend/openapi-generated/model/signupTeamResponseDto.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* OpenAPI definition
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: v0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
export interface SignupTeamResponseDto {
|
||||
signupTeamResult?: SignupTeamResponseDto.SignupTeamResultEnum;
|
||||
}
|
||||
export namespace SignupTeamResponseDto {
|
||||
export type SignupTeamResultEnum = 'SUCCESS' | 'REGISTRATION_CLOSED' | 'MAX_PARTICIPANTS_REACHED' | 'TEAM_ALREADY_EXISTS';
|
||||
export const SignupTeamResultEnum = {
|
||||
Success: 'SUCCESS' as SignupTeamResultEnum,
|
||||
RegistrationClosed: 'REGISTRATION_CLOSED' as SignupTeamResultEnum,
|
||||
MaxParticipantsReached: 'MAX_PARTICIPANTS_REACHED' as SignupTeamResultEnum,
|
||||
TeamAlreadyExists: 'TEAM_ALREADY_EXISTS' as SignupTeamResultEnum
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -8,27 +8,42 @@ import { UserRegisterComponent } from './components/user-register/user-register.
|
|||
import { TournamentsComponent } from './components/tournaments/tournaments.component';
|
||||
import { TournamentCreateComponent } from './components/tournament-create/tournament-create.component';
|
||||
import { UserDetailComponent } from './components/user-detail/user-detail.component';
|
||||
import { TeamSignupComponent } from './components/tournament/team-signup/team-signup.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: HomeComponent },
|
||||
{ path: 'login', component: LoginDialogComponent },
|
||||
{ path: 'register', component: UserRegisterComponent },
|
||||
{ path: 'message', canActivate: mapToCanActivate([AuthGuard]), component: MessageComponent },
|
||||
{
|
||||
path: 'tournaments',
|
||||
canActivate: mapToCanActivate([AuthGuard]),
|
||||
component: TournamentsComponent,
|
||||
},
|
||||
{
|
||||
path: 'tournaments/create',
|
||||
canActivate: mapToCanActivate([AuthGuard]),
|
||||
component: TournamentCreateComponent,
|
||||
},
|
||||
{
|
||||
path: 'details/:username',
|
||||
canActivate: mapToCanActivate([AuthGuard]),
|
||||
component: UserDetailComponent,
|
||||
},
|
||||
{
|
||||
path: 'tournaments',
|
||||
children: [
|
||||
{
|
||||
path: 'list',
|
||||
canActivate: mapToCanActivate([AuthGuard]),
|
||||
component: TournamentsComponent,
|
||||
},
|
||||
{
|
||||
path: 'create',
|
||||
canActivate: mapToCanActivate([AuthGuard]),
|
||||
component: TournamentCreateComponent,
|
||||
},
|
||||
{
|
||||
path: ':tournamentId',
|
||||
children: [
|
||||
{
|
||||
path: 'signup',
|
||||
component: TeamSignupComponent,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { LOCALE_ID, NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { HeaderComponent } from './components/header/header.component';
|
||||
|
@ -14,13 +12,12 @@ import { MessageComponent } from './components/message/message.component';
|
|||
import { httpInterceptorProviders } from './interceptors';
|
||||
import { MatToolbar } from '@angular/material/toolbar';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { MatButton, MatIconButton } from '@angular/material/button';
|
||||
import { MatButton, MatButtonModule, MatIconButton } from '@angular/material/button';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { MatDialogModule, MatDialogRef } from '@angular/material/dialog';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInput } from '@angular/material/input';
|
||||
import { TournamentsComponent } from './components/tournaments/tournaments.component';
|
||||
import { TournamentCardComponent } from './components/tournament-card/tournament-card.component';
|
||||
import { UserDetailComponent } from './components/user-detail/user-detail.component';
|
||||
|
@ -30,6 +27,9 @@ import localeDe from '@angular/common/locales/de';
|
|||
import { registerLocaleData } from '@angular/common';
|
||||
registerLocaleData(localeDe);
|
||||
import { ConfirmDialogComponent } from './components/confirm-dialog/confirm-dialog.component';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TeamSignupComponent } from './components/tournament/team-signup/team-signup.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
@ -45,10 +45,10 @@ import { ConfirmDialogComponent } from './components/confirm-dialog/confirm-dial
|
|||
UserDetailComponent,
|
||||
UserEditDetailsForm,
|
||||
UpdateUserComponent,
|
||||
TeamSignupComponent,
|
||||
ConfirmDialogComponent,
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
AppRoutingModule,
|
||||
ReactiveFormsModule,
|
||||
HttpClientModule,
|
||||
|
@ -62,7 +62,9 @@ import { ConfirmDialogComponent } from './components/confirm-dialog/confirm-dial
|
|||
BrowserAnimationsModule,
|
||||
MatDialogModule,
|
||||
MatFormFieldModule,
|
||||
MatInput,
|
||||
MatInputModule,
|
||||
MatButtonModule,
|
||||
CommonModule,
|
||||
],
|
||||
providers: [
|
||||
httpInterceptorProviders,
|
||||
|
|
|
@ -105,7 +105,7 @@ export class TournamentCreateComponent {
|
|||
this.snackBar.open('Successfully created new tournament', 'Close', {
|
||||
duration: 3000,
|
||||
});
|
||||
this.router.navigate(['/tournaments']);
|
||||
this.router.navigate(['/tournaments/list']);
|
||||
},
|
||||
error: async (er: HttpErrorResponse) => {
|
||||
this.snackBar.open(
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
@if (isTournamentLoadedAndRegistrationOpen) {
|
||||
@if (success) {
|
||||
<h2>Signed up successfully</h2>
|
||||
} @else {
|
||||
<div class="form-container">
|
||||
<form [formGroup]="newTeamNameForm" (ngSubmit)="createTeam()" class="form">
|
||||
<h2>Sign Up for {{ tournament?.name }}</h2>
|
||||
<mat-form-field appearance="outline">
|
||||
<input matInput formControlName="name" placeholder="Team Name" autofocus />
|
||||
@if (nameFormControl.errors?.required) {
|
||||
<mat-error> A team name is required! </mat-error>
|
||||
}
|
||||
@if (nameFormControl.errors?.minlength) {
|
||||
<mat-error>Team name must be at least 3 characters long!</mat-error>
|
||||
}
|
||||
@if (nameFormControl.errors?.maxlength) {
|
||||
<mat-error>Team name must be at most 20 characters long!</mat-error>
|
||||
}
|
||||
@if (nameFormControl.errors?.teamAlreadyExists) {
|
||||
<mat-error>Team name already exists!</mat-error>
|
||||
}
|
||||
@if (nameFormControl.errors?.maxParticipantsReached) {
|
||||
<mat-error>No more spots left!</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<button mat-raised-button type="submit">Sign up!</button>
|
||||
</form>
|
||||
</div>
|
||||
}
|
||||
} @else {
|
||||
<h2>Tournament not loaded or registration closed</h2>
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
.form-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TeamSignupComponent } from './team-signup.component';
|
||||
|
||||
describe('TeamSignupComponent', () => {
|
||||
let component: TeamSignupComponent;
|
||||
let fixture: ComponentFixture<TeamSignupComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [TeamSignupComponent],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(TeamSignupComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,73 @@
|
|||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { TournamentEndpointService } from '../../../../../openapi-generated/api/tournamentEndpoint.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { SignupTeamResponseDto, TournamentDto } from 'openapi-generated';
|
||||
import { catchError, tap, firstValueFrom, of } from 'rxjs';
|
||||
import { extend } from 'lodash';
|
||||
|
||||
@Component({
|
||||
selector: 'app-team-signup',
|
||||
templateUrl: './team-signup.component.html',
|
||||
styleUrl: './team-signup.component.scss',
|
||||
})
|
||||
export class TeamSignupComponent {
|
||||
tournament: TournamentDto | undefined;
|
||||
success = false;
|
||||
nameFormControl = new FormControl('', [
|
||||
Validators.minLength(3),
|
||||
Validators.maxLength(20),
|
||||
Validators.required,
|
||||
]);
|
||||
newTeamNameForm = new FormGroup({
|
||||
name: this.nameFormControl,
|
||||
});
|
||||
|
||||
get isTournamentLoadedAndRegistrationOpen(): boolean {
|
||||
if (!this.tournament?.registrationEnd) {
|
||||
return false;
|
||||
}
|
||||
return new Date() < new Date(this.tournament.registrationEnd);
|
||||
}
|
||||
|
||||
constructor(
|
||||
private tournamentService: TournamentEndpointService,
|
||||
private route: ActivatedRoute,
|
||||
) {
|
||||
const tournamentId = Number(this.route.snapshot.paramMap.get('tournamentId'));
|
||||
this.tournamentService.get(tournamentId).subscribe(tournament => {
|
||||
this.tournament = tournament;
|
||||
});
|
||||
}
|
||||
|
||||
async createTeam() {
|
||||
const request = this.tournamentService.signupTeamForTournament(
|
||||
this.tournament?.id!,
|
||||
{ name: this.newTeamNameForm.controls.name.value! },
|
||||
'response',
|
||||
);
|
||||
request
|
||||
.pipe(
|
||||
catchError(e => {
|
||||
if (e.status !== 400) {
|
||||
return [];
|
||||
}
|
||||
const response = e.error as SignupTeamResponseDto;
|
||||
switch (response.signupTeamResult) {
|
||||
case SignupTeamResponseDto.SignupTeamResultEnum.TeamAlreadyExists:
|
||||
this.nameFormControl.setErrors({ teamAlreadyExists: true });
|
||||
return of();
|
||||
case SignupTeamResponseDto.SignupTeamResultEnum.MaxParticipantsReached:
|
||||
this.nameFormControl.setErrors({ maxParticipantsReached: true });
|
||||
return of();
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
|
||||
this.nameFormControl.setErrors({ nameAlreadyTaken: true });
|
||||
return of();
|
||||
}),
|
||||
)
|
||||
.subscribe(response => (this.success = true));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue