mirror of
https://github.com/TomasiDeveloping/PlayerManagement.git
synced 2026-04-16 17:22:21 +00:00
v. 0.11.0
This commit is contained in:
parent
fa3a0ec218
commit
bfbb030cb2
37
Api/Controllers/v1/SquadTypesController.cs
Normal file
37
Api/Controllers/v1/SquadTypesController.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using Application.DataTransferObjects.SquadType;
|
||||||
|
using Application.Interfaces;
|
||||||
|
using Asp.Versioning;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Api.Controllers.v1
|
||||||
|
{
|
||||||
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
[ApiVersion("1.0")]
|
||||||
|
[Authorize]
|
||||||
|
public class SquadTypesController(ISquadTypeRepository squadTypeRepository, ILogger<SquadTypesController> logger)
|
||||||
|
: ControllerBase
|
||||||
|
{
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult<List<SquadTypeDto>>> GetSquadTypes(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var squadTypesResult = await squadTypeRepository.GetSquadTypesAsync(cancellationToken);
|
||||||
|
if (squadTypesResult.IsFailure) return BadRequest(squadTypesResult.Error);
|
||||||
|
return squadTypesResult.Value.Count > 0
|
||||||
|
? Ok(squadTypesResult.Value)
|
||||||
|
: NoContent();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError(e, "{ErrorMessage}", e.Message);
|
||||||
|
return Problem(
|
||||||
|
detail: $"Failed to process {nameof(GetSquadTypes)}",
|
||||||
|
statusCode: StatusCodes.Status500InternalServerError,
|
||||||
|
title: "Internal server error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
106
Api/Controllers/v1/SquadsController.cs
Normal file
106
Api/Controllers/v1/SquadsController.cs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
using Application.DataTransferObjects.Squad;
|
||||||
|
using Application.Interfaces;
|
||||||
|
using Asp.Versioning;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Api.Controllers.v1
|
||||||
|
{
|
||||||
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
[ApiVersion("1.0")]
|
||||||
|
[Authorize]
|
||||||
|
public class SquadsController(ISquadRepository squadRepository, ILogger<SquadsController> logger) : ControllerBase
|
||||||
|
{
|
||||||
|
[HttpGet("player/{playerId:guid}")]
|
||||||
|
public async Task<ActionResult<List<SquadDto>>> GetPlayerSquads(Guid playerId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var playerSquadsResult = await squadRepository.GetPlayerSquadsAsync(playerId, cancellationToken);
|
||||||
|
|
||||||
|
if (playerSquadsResult.IsFailure) return BadRequest(playerSquadsResult.Error);
|
||||||
|
|
||||||
|
return playerSquadsResult.Value.Count > 0
|
||||||
|
? Ok(playerSquadsResult.Value)
|
||||||
|
: NoContent();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError(e, "{ErrorMessage}", e.Message);
|
||||||
|
return Problem(
|
||||||
|
detail: $"Failed to process {nameof(GetPlayerSquads)}",
|
||||||
|
statusCode: StatusCodes.Status500InternalServerError,
|
||||||
|
title: "Internal server error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult<SquadDto>> CreateSquad(CreateSquadDto createSquadDto,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!ModelState.IsValid) return UnprocessableEntity(ModelState);
|
||||||
|
|
||||||
|
var createSquadResult = await squadRepository.CreateSquadAsync(createSquadDto, cancellationToken);
|
||||||
|
|
||||||
|
return createSquadResult.IsSuccess
|
||||||
|
? Ok(createSquadResult.Value)
|
||||||
|
: BadRequest(createSquadResult.Error);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError(e, "{ErrorMessage}", e.Message);
|
||||||
|
return Problem(
|
||||||
|
detail: $"Failed to process {nameof(GetPlayerSquads)}",
|
||||||
|
statusCode: StatusCodes.Status500InternalServerError,
|
||||||
|
title: "Internal server error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("{squadId:guid}")]
|
||||||
|
public async Task<ActionResult<SquadDto>> UpdateSquad(Guid squadId, UpdateSquadDto updateSquadDto, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!ModelState.IsValid) return UnprocessableEntity(ModelState);
|
||||||
|
|
||||||
|
var updateSquadResult = await squadRepository.UpdateSquadAsync(updateSquadDto, cancellationToken);
|
||||||
|
return updateSquadResult.IsSuccess
|
||||||
|
? Ok(updateSquadResult.Value)
|
||||||
|
: BadRequest(updateSquadResult.Error);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError(e, "{ErrorMessage}", e.Message);
|
||||||
|
return Problem(
|
||||||
|
detail: $"Failed to process {nameof(UpdateSquad)}",
|
||||||
|
statusCode: StatusCodes.Status500InternalServerError,
|
||||||
|
title: "Internal server error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("{squadId:guid}")]
|
||||||
|
public async Task<ActionResult<bool>> DeleteSquad(Guid squadId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var deleteSquadResult = await squadRepository.DeleteSquadAsync(squadId, cancellationToken);
|
||||||
|
|
||||||
|
return deleteSquadResult.IsSuccess
|
||||||
|
? Ok(deleteSquadResult.Value)
|
||||||
|
: BadRequest(deleteSquadResult.Error);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError(e, "{ErrorMessage}", e.Message);
|
||||||
|
return Problem(
|
||||||
|
detail: $"Failed to process {nameof(DeleteSquad)}",
|
||||||
|
statusCode: StatusCodes.Status500InternalServerError,
|
||||||
|
title: "Internal server error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,23 +0,0 @@
|
|||||||
using Api.Helpers;
|
|
||||||
using Asp.Versioning;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace Api.Controllers.v1
|
|
||||||
{
|
|
||||||
[Route("api/v{version:apiVersion}/[controller]")]
|
|
||||||
[ApiController]
|
|
||||||
[ApiVersion("1.0")]
|
|
||||||
public class ValuesController : ControllerBase
|
|
||||||
{
|
|
||||||
[AllowApiKey]
|
|
||||||
[HttpGet]
|
|
||||||
public async Task<IActionResult> Test([FromQuery] Guid allianceId, [FromQuery] string? key)
|
|
||||||
{
|
|
||||||
return Ok(new
|
|
||||||
{
|
|
||||||
AllianceId = allianceId,
|
|
||||||
Key = key
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -37,6 +37,8 @@ public static class ApplicationDependencyInjection
|
|||||||
services.AddScoped<ICustomEventCategoryRepository, CustomEventCategoryRepository>();
|
services.AddScoped<ICustomEventCategoryRepository, CustomEventCategoryRepository>();
|
||||||
services.AddScoped<ICustomEventLeaderBoardRepository, CustomEventLeaderboardRepository>();
|
services.AddScoped<ICustomEventLeaderBoardRepository, CustomEventLeaderboardRepository>();
|
||||||
services.AddScoped<IStatRepository, StatRepository>();
|
services.AddScoped<IStatRepository, StatRepository>();
|
||||||
|
services.AddScoped<ISquadTypeRepository, SquadTypeRepository>();
|
||||||
|
services.AddScoped<ISquadRepository, SquadRepository>();
|
||||||
|
|
||||||
|
|
||||||
services.AddTransient<IJwtService, JwtService>();
|
services.AddTransient<IJwtService, JwtService>();
|
||||||
|
|||||||
12
Application/DataTransferObjects/Squad/CreateSquadDto.cs
Normal file
12
Application/DataTransferObjects/Squad/CreateSquadDto.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace Application.DataTransferObjects.Squad;
|
||||||
|
|
||||||
|
public class CreateSquadDto
|
||||||
|
{
|
||||||
|
public Guid SquadTypeId { get; set; }
|
||||||
|
|
||||||
|
public Guid PlayerId { get; set; }
|
||||||
|
|
||||||
|
public decimal Power { get; set; }
|
||||||
|
|
||||||
|
public int Position { get; set; }
|
||||||
|
}
|
||||||
19
Application/DataTransferObjects/Squad/SquadDto.cs
Normal file
19
Application/DataTransferObjects/Squad/SquadDto.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
namespace Application.DataTransferObjects.Squad;
|
||||||
|
|
||||||
|
public class SquadDto
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
public Guid SquadTypeId { get; set; }
|
||||||
|
|
||||||
|
public Guid PlayerId { get; set; }
|
||||||
|
|
||||||
|
public required string TypeName { get; set; }
|
||||||
|
|
||||||
|
public decimal Power { get; set; }
|
||||||
|
|
||||||
|
public int Position { get; set; }
|
||||||
|
|
||||||
|
public DateTime LastUpdateAt { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
14
Application/DataTransferObjects/Squad/UpdateSquadDto.cs
Normal file
14
Application/DataTransferObjects/Squad/UpdateSquadDto.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
namespace Application.DataTransferObjects.Squad;
|
||||||
|
|
||||||
|
public class UpdateSquadDto
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
public Guid SquadTypeId { get; set; }
|
||||||
|
|
||||||
|
public Guid PlayerId { get; set; }
|
||||||
|
|
||||||
|
public decimal Power { get; set; }
|
||||||
|
|
||||||
|
public int Position { get; set; }
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
namespace Application.DataTransferObjects.SquadType;
|
||||||
|
|
||||||
|
public class SquadTypeDto
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
public required string TypeName { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
9
Application/Errors/SquadErrors.cs
Normal file
9
Application/Errors/SquadErrors.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace Application.Errors;
|
||||||
|
|
||||||
|
public class SquadErrors
|
||||||
|
{
|
||||||
|
public static readonly Error NotFound = new("Error.Squad.NotFound",
|
||||||
|
"The quad with the specified identifier was not found");
|
||||||
|
|
||||||
|
public static readonly Error IdConflict = new("Error.Note.IdConflict", "There is a conflict with the id's");
|
||||||
|
}
|
||||||
15
Application/Interfaces/ISquadRepository.cs
Normal file
15
Application/Interfaces/ISquadRepository.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Application.Classes;
|
||||||
|
using Application.DataTransferObjects.Squad;
|
||||||
|
|
||||||
|
namespace Application.Interfaces;
|
||||||
|
|
||||||
|
public interface ISquadRepository
|
||||||
|
{
|
||||||
|
Task<Result<List<SquadDto>>> GetPlayerSquadsAsync(Guid playerId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
Task<Result<SquadDto>> CreateSquadAsync(CreateSquadDto createSquadDto, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
Task<Result<SquadDto>> UpdateSquadAsync(UpdateSquadDto updateSquadDto, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
Task<Result<bool>> DeleteSquadAsync(Guid squadId, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
9
Application/Interfaces/ISquadTypeRepository.cs
Normal file
9
Application/Interfaces/ISquadTypeRepository.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using Application.Classes;
|
||||||
|
using Application.DataTransferObjects.SquadType;
|
||||||
|
|
||||||
|
namespace Application.Interfaces;
|
||||||
|
|
||||||
|
public interface ISquadTypeRepository
|
||||||
|
{
|
||||||
|
Task<Result<List<SquadTypeDto>>> GetSquadTypesAsync(CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
21
Application/Profiles/SquadProfile.cs
Normal file
21
Application/Profiles/SquadProfile.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using Application.DataTransferObjects.Squad;
|
||||||
|
using AutoMapper;
|
||||||
|
using Database.Entities;
|
||||||
|
|
||||||
|
namespace Application.Profiles;
|
||||||
|
|
||||||
|
public class SquadProfile : Profile
|
||||||
|
{
|
||||||
|
public SquadProfile()
|
||||||
|
{
|
||||||
|
CreateMap<Squad, SquadDto>()
|
||||||
|
.ForMember(des => des.TypeName, opt => opt.MapFrom(src => src.SquadType.TypeName));
|
||||||
|
|
||||||
|
CreateMap<CreateSquadDto, Squad>()
|
||||||
|
.ForMember(dest => dest.LastUpdateAt, opt => opt.MapFrom(src => DateTime.UtcNow))
|
||||||
|
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => Guid.CreateVersion7()));
|
||||||
|
|
||||||
|
CreateMap<UpdateSquadDto, Squad>()
|
||||||
|
.ForMember(des => des.LastUpdateAt, opt => opt.MapFrom(src => DateTime.UtcNow));
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Application/Profiles/SquadTypeProfile.cs
Normal file
13
Application/Profiles/SquadTypeProfile.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using Application.DataTransferObjects.SquadType;
|
||||||
|
using AutoMapper;
|
||||||
|
using Database.Entities;
|
||||||
|
|
||||||
|
namespace Application.Profiles;
|
||||||
|
|
||||||
|
public class SquadTypeProfile : Profile
|
||||||
|
{
|
||||||
|
public SquadTypeProfile()
|
||||||
|
{
|
||||||
|
CreateMap<SquadType, SquadTypeDto>();
|
||||||
|
}
|
||||||
|
}
|
||||||
91
Application/Repositories/SquadRepository.cs
Normal file
91
Application/Repositories/SquadRepository.cs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
using Application.Classes;
|
||||||
|
using Application.DataTransferObjects.Squad;
|
||||||
|
using Application.Errors;
|
||||||
|
using Application.Interfaces;
|
||||||
|
using AutoMapper;
|
||||||
|
using AutoMapper.QueryableExtensions;
|
||||||
|
using Database;
|
||||||
|
using Database.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace Application.Repositories;
|
||||||
|
|
||||||
|
public class SquadRepository(ApplicationContext dbContext, IMapper mapper, ILogger<SquadRepository> logger) : ISquadRepository
|
||||||
|
{
|
||||||
|
public async Task<Result<List<SquadDto>>> GetPlayerSquadsAsync(Guid playerId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var playerSquads = await dbContext.Squads
|
||||||
|
.Where(squad => squad.PlayerId == playerId)
|
||||||
|
.ProjectTo<SquadDto>(mapper.ConfigurationProvider)
|
||||||
|
.OrderBy(squad => squad.Position)
|
||||||
|
.AsNoTracking()
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
return Result.Success(playerSquads);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result<SquadDto>> CreateSquadAsync(CreateSquadDto createSquadDto, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var newSuad = mapper.Map<Squad>(createSquadDto);
|
||||||
|
|
||||||
|
await dbContext.Squads.AddAsync(newSuad, cancellationToken);
|
||||||
|
|
||||||
|
await dbContext.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
return Result.Success(mapper.Map<SquadDto>(newSuad));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError(e, "{DatabaseException}", e.Message);
|
||||||
|
return Result.Failure<SquadDto>(GeneralErrors.DatabaseError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result<SquadDto>> UpdateSquadAsync(UpdateSquadDto updateSquadDto, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var squadToUpdate = await dbContext.Squads
|
||||||
|
.FirstOrDefaultAsync(squad => squad.Id == updateSquadDto.Id, cancellationToken);
|
||||||
|
|
||||||
|
if (squadToUpdate is null) return Result.Failure<SquadDto>(SquadErrors.NotFound);
|
||||||
|
|
||||||
|
mapper.Map(updateSquadDto, squadToUpdate);
|
||||||
|
|
||||||
|
await dbContext.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
return Result.Success(mapper.Map<SquadDto>(squadToUpdate));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError(e, "{DatabaseException}", e.Message);
|
||||||
|
return Result.Failure<SquadDto>(GeneralErrors.DatabaseError);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result<bool>> DeleteSquadAsync(Guid squadId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var squadToDelete = await dbContext.Squads
|
||||||
|
.FirstOrDefaultAsync(squad => squad.Id == squadId, cancellationToken);
|
||||||
|
|
||||||
|
if (squadToDelete is null) return Result.Failure<bool>(SquadErrors.NotFound);
|
||||||
|
|
||||||
|
dbContext.Squads.Remove(squadToDelete);
|
||||||
|
|
||||||
|
await dbContext.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
return Result.Success(mapper.Map<bool>(true));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError(e, "{DatabaseException}", e.Message);
|
||||||
|
return Result.Failure<bool>(GeneralErrors.DatabaseError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
Application/Repositories/SquadTypeRepository.cs
Normal file
22
Application/Repositories/SquadTypeRepository.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using Application.Classes;
|
||||||
|
using Application.DataTransferObjects.SquadType;
|
||||||
|
using Application.Interfaces;
|
||||||
|
using AutoMapper;
|
||||||
|
using AutoMapper.QueryableExtensions;
|
||||||
|
using Database;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Application.Repositories;
|
||||||
|
|
||||||
|
public class SquadTypeRepository(ApplicationContext dbContext, IMapper mapper) : ISquadTypeRepository
|
||||||
|
{
|
||||||
|
public async Task<Result<List<SquadTypeDto>>> GetSquadTypesAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var squadTypes = await dbContext.SquadTypes
|
||||||
|
.ProjectTo<SquadTypeDto>(mapper.ConfigurationProvider)
|
||||||
|
.AsNoTracking()
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
return Result.Success(squadTypes);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -46,6 +46,10 @@ public class ApplicationContext(DbContextOptions<ApplicationContext> options) :
|
|||||||
|
|
||||||
public DbSet<CustomEventCategory> CustomEventCategories { get; set; }
|
public DbSet<CustomEventCategory> CustomEventCategories { get; set; }
|
||||||
|
|
||||||
|
public DbSet<Squad> Squads { get; set; }
|
||||||
|
|
||||||
|
public DbSet<SquadType> SquadTypes { get; set; }
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
{
|
{
|
||||||
base.OnConfiguring(optionsBuilder);
|
base.OnConfiguring(optionsBuilder);
|
||||||
|
|||||||
28
Database/Configurations/SquadConfiguration.cs
Normal file
28
Database/Configurations/SquadConfiguration.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using Database.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace Database.Configurations;
|
||||||
|
|
||||||
|
public class SquadConfiguration : IEntityTypeConfiguration<Squad>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<Squad> builder)
|
||||||
|
{
|
||||||
|
builder.HasKey(squad => squad.Id);
|
||||||
|
builder.Property(squad => squad.Id).ValueGeneratedNever();
|
||||||
|
|
||||||
|
builder.Property(squad => squad.Power).IsRequired().HasPrecision(18,2);
|
||||||
|
builder.Property(squad => squad.Position).IsRequired();
|
||||||
|
builder.Property(squad => squad.LastUpdateAt).IsRequired();
|
||||||
|
|
||||||
|
builder.HasOne(squad => squad.SquadType)
|
||||||
|
.WithMany(squadType => squadType.Squads)
|
||||||
|
.HasForeignKey(squad => squad.SquadTypeId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
builder.HasOne(squatType => squatType.Player)
|
||||||
|
.WithMany(player => player.Squads)
|
||||||
|
.HasForeignKey(squad => squad.PlayerId)
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
}
|
||||||
|
}
|
||||||
46
Database/Configurations/SquadTypeConfiguration.cs
Normal file
46
Database/Configurations/SquadTypeConfiguration.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using Database.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace Database.Configurations;
|
||||||
|
|
||||||
|
public class SquadTypeConfiguration : IEntityTypeConfiguration<SquadType>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<SquadType> builder)
|
||||||
|
{
|
||||||
|
builder.HasKey(squadType => squadType.Id);
|
||||||
|
builder.Property(squadType => squadType.Id).ValueGeneratedNever();
|
||||||
|
|
||||||
|
builder.Property(squadType => squadType.TypeName)
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(150);
|
||||||
|
|
||||||
|
var squadTypes = new List<SquadType>()
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Id = Guid.CreateVersion7(),
|
||||||
|
TypeName = "Tanks"
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Id = Guid.CreateVersion7(),
|
||||||
|
TypeName = "Missile"
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Id = Guid.CreateVersion7(),
|
||||||
|
TypeName = "Aircraft"
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Id = Guid.CreateVersion7(),
|
||||||
|
TypeName = "Mixed"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
builder.HasData(squadTypes);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -41,4 +41,6 @@ public class Player : BaseEntity
|
|||||||
public ICollection<CustomEventParticipant> CustomEventParticipants { get; set; } = [];
|
public ICollection<CustomEventParticipant> CustomEventParticipants { get; set; } = [];
|
||||||
|
|
||||||
public ICollection<ZombieSiegeParticipant> ZombieSiegeParticipants { get; set; } = [];
|
public ICollection<ZombieSiegeParticipant> ZombieSiegeParticipants { get; set; } = [];
|
||||||
|
|
||||||
|
public ICollection<Squad> Squads { get; set; } = [];
|
||||||
}
|
}
|
||||||
18
Database/Entities/Squad.cs
Normal file
18
Database/Entities/Squad.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
namespace Database.Entities;
|
||||||
|
|
||||||
|
public class Squad : BaseEntity
|
||||||
|
{
|
||||||
|
public Guid SquadTypeId { get; set; }
|
||||||
|
|
||||||
|
public SquadType SquadType { get; set; } = null!;
|
||||||
|
|
||||||
|
public decimal Power { get; set; }
|
||||||
|
|
||||||
|
public int Position { get; set; }
|
||||||
|
|
||||||
|
public Guid PlayerId { get; set; }
|
||||||
|
|
||||||
|
public Player Player { get; set; } = null!;
|
||||||
|
|
||||||
|
public DateTime LastUpdateAt { get; set; }
|
||||||
|
}
|
||||||
8
Database/Entities/SquadType.cs
Normal file
8
Database/Entities/SquadType.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Database.Entities;
|
||||||
|
|
||||||
|
public class SquadType : BaseEntity
|
||||||
|
{
|
||||||
|
public required string TypeName { get; set; }
|
||||||
|
|
||||||
|
public ICollection<Squad> Squads { get; set; } = [];
|
||||||
|
}
|
||||||
1379
Database/Migrations/20250617074428_Add_Squds.Designer.cs
generated
Normal file
1379
Database/Migrations/20250617074428_Add_Squds.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
96
Database/Migrations/20250617074428_Add_Squds.cs
Normal file
96
Database/Migrations/20250617074428_Add_Squds.cs
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
||||||
|
|
||||||
|
namespace Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Add_Squds : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "SquadType",
|
||||||
|
schema: "dbo",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
TypeName = table.Column<string>(type: "nvarchar(150)", maxLength: 150, nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_SquadType", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Squad",
|
||||||
|
schema: "dbo",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
SquadTypeId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||||
|
Power = table.Column<long>(type: "bigint", nullable: false),
|
||||||
|
PlayerId = table.Column<Guid>(type: "uniqueidentifier", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Squad", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Squad_Players_PlayerId",
|
||||||
|
column: x => x.PlayerId,
|
||||||
|
principalSchema: "dbo",
|
||||||
|
principalTable: "Players",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Squad_SquadType_SquadTypeId",
|
||||||
|
column: x => x.SquadTypeId,
|
||||||
|
principalSchema: "dbo",
|
||||||
|
principalTable: "SquadType",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
schema: "dbo",
|
||||||
|
table: "SquadType",
|
||||||
|
columns: new[] { "Id", "TypeName" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ new Guid("01977cd8-bb62-7089-85cb-5a48223a6e92"), "Aircraft" },
|
||||||
|
{ new Guid("01977cd8-bb62-7150-a0f9-5415e46a87e4"), "Mixed" },
|
||||||
|
{ new Guid("01977cd8-bb62-79aa-9a71-95d57250d723"), "Missile" },
|
||||||
|
{ new Guid("01977cd8-bb62-7d5b-823e-b77c6121c4f1"), "Tanks" }
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Squad_PlayerId",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squad",
|
||||||
|
column: "PlayerId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Squad_SquadTypeId",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squad",
|
||||||
|
column: "SquadTypeId");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Squad",
|
||||||
|
schema: "dbo");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "SquadType",
|
||||||
|
schema: "dbo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1382
Database/Migrations/20250617082727_Update_Squad.Designer.cs
generated
Normal file
1382
Database/Migrations/20250617082727_Update_Squad.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
224
Database/Migrations/20250617082727_Update_Squad.cs
Normal file
224
Database/Migrations/20250617082727_Update_Squad.cs
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
||||||
|
|
||||||
|
namespace Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Update_Squad : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_Squad_Players_PlayerId",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squad");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_Squad_SquadType_SquadTypeId",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squad");
|
||||||
|
|
||||||
|
migrationBuilder.DropPrimaryKey(
|
||||||
|
name: "PK_SquadType",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "SquadType");
|
||||||
|
|
||||||
|
migrationBuilder.DropPrimaryKey(
|
||||||
|
name: "PK_Squad",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squad");
|
||||||
|
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "SquadType",
|
||||||
|
schema: "dbo",
|
||||||
|
newName: "SquadTypes",
|
||||||
|
newSchema: "dbo");
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "Squad",
|
||||||
|
schema: "dbo",
|
||||||
|
newName: "Squads",
|
||||||
|
newSchema: "dbo");
|
||||||
|
|
||||||
|
migrationBuilder.RenameIndex(
|
||||||
|
name: "IX_Squad_SquadTypeId",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squads",
|
||||||
|
newName: "IX_Squads_SquadTypeId");
|
||||||
|
|
||||||
|
migrationBuilder.RenameIndex(
|
||||||
|
name: "IX_Squad_PlayerId",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squads",
|
||||||
|
newName: "IX_Squads_PlayerId");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "Position",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squads",
|
||||||
|
type: "int",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddPrimaryKey(
|
||||||
|
name: "PK_SquadTypes",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "SquadTypes",
|
||||||
|
column: "Id");
|
||||||
|
|
||||||
|
migrationBuilder.AddPrimaryKey(
|
||||||
|
name: "PK_Squads",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squads",
|
||||||
|
column: "Id");
|
||||||
|
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_Squads_Players_PlayerId",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squads",
|
||||||
|
column: "PlayerId",
|
||||||
|
principalSchema: "dbo",
|
||||||
|
principalTable: "Players",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_Squads_SquadTypes_SquadTypeId",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squads",
|
||||||
|
column: "SquadTypeId",
|
||||||
|
principalSchema: "dbo",
|
||||||
|
principalTable: "SquadTypes",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_Squads_Players_PlayerId",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squads");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_Squads_SquadTypes_SquadTypeId",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squads");
|
||||||
|
|
||||||
|
migrationBuilder.DropPrimaryKey(
|
||||||
|
name: "PK_SquadTypes",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "SquadTypes");
|
||||||
|
|
||||||
|
migrationBuilder.DropPrimaryKey(
|
||||||
|
name: "PK_Squads",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squads");
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
schema: "dbo",
|
||||||
|
table: "SquadTypes",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("01977d00-1596-7078-b24d-f5abd8baaec1"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
schema: "dbo",
|
||||||
|
table: "SquadTypes",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("01977d00-1596-71a1-bbff-db88a4a59f32"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
schema: "dbo",
|
||||||
|
table: "SquadTypes",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("01977d00-1596-7644-98aa-ff20f05f13bb"));
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
schema: "dbo",
|
||||||
|
table: "SquadTypes",
|
||||||
|
keyColumn: "Id",
|
||||||
|
keyValue: new Guid("01977d00-1596-7c18-a665-e079870ae3cb"));
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Position",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squads");
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "SquadTypes",
|
||||||
|
schema: "dbo",
|
||||||
|
newName: "SquadType",
|
||||||
|
newSchema: "dbo");
|
||||||
|
|
||||||
|
migrationBuilder.RenameTable(
|
||||||
|
name: "Squads",
|
||||||
|
schema: "dbo",
|
||||||
|
newName: "Squad",
|
||||||
|
newSchema: "dbo");
|
||||||
|
|
||||||
|
migrationBuilder.RenameIndex(
|
||||||
|
name: "IX_Squads_SquadTypeId",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squad",
|
||||||
|
newName: "IX_Squad_SquadTypeId");
|
||||||
|
|
||||||
|
migrationBuilder.RenameIndex(
|
||||||
|
name: "IX_Squads_PlayerId",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squad",
|
||||||
|
newName: "IX_Squad_PlayerId");
|
||||||
|
|
||||||
|
migrationBuilder.AddPrimaryKey(
|
||||||
|
name: "PK_SquadType",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "SquadType",
|
||||||
|
column: "Id");
|
||||||
|
|
||||||
|
migrationBuilder.AddPrimaryKey(
|
||||||
|
name: "PK_Squad",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squad",
|
||||||
|
column: "Id");
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
schema: "dbo",
|
||||||
|
table: "SquadType",
|
||||||
|
columns: new[] { "Id", "TypeName" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ new Guid("01977cd8-bb62-7089-85cb-5a48223a6e92"), "Aircraft" },
|
||||||
|
{ new Guid("01977cd8-bb62-7150-a0f9-5415e46a87e4"), "Mixed" },
|
||||||
|
{ new Guid("01977cd8-bb62-79aa-9a71-95d57250d723"), "Missile" },
|
||||||
|
{ new Guid("01977cd8-bb62-7d5b-823e-b77c6121c4f1"), "Tanks" }
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_Squad_Players_PlayerId",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squad",
|
||||||
|
column: "PlayerId",
|
||||||
|
principalSchema: "dbo",
|
||||||
|
principalTable: "Players",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_Squad_SquadType_SquadTypeId",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squad",
|
||||||
|
column: "SquadTypeId",
|
||||||
|
principalSchema: "dbo",
|
||||||
|
principalTable: "SquadType",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1385
Database/Migrations/20250619052205_Add_Lastupdate_to_squad.Designer.cs
generated
Normal file
1385
Database/Migrations/20250619052205_Add_Lastupdate_to_squad.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
||||||
|
|
||||||
|
namespace Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Add_Lastupdate_to_squad : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "LastUpdateAt",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squads",
|
||||||
|
type: "datetime2",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "LastUpdateAt",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squads");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1386
Database/Migrations/20250619075856_Change_squad_power_to_decimal.Designer.cs
generated
Normal file
1386
Database/Migrations/20250619075856_Change_squad_power_to_decimal.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,43 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
||||||
|
|
||||||
|
namespace Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Change_squad_power_to_decimal : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<decimal>(
|
||||||
|
name: "Power",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squads",
|
||||||
|
type: "decimal(18,2)",
|
||||||
|
precision: 18,
|
||||||
|
scale: 2,
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(long),
|
||||||
|
oldType: "bigint");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<long>(
|
||||||
|
name: "Power",
|
||||||
|
schema: "dbo",
|
||||||
|
table: "Squads",
|
||||||
|
type: "bigint",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(decimal),
|
||||||
|
oldType: "decimal(18,2)",
|
||||||
|
oldPrecision: 18,
|
||||||
|
oldScale: 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -510,6 +510,73 @@ namespace Database.Migrations
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Database.Entities.Squad", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<DateTime>("LastUpdateAt")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<Guid>("PlayerId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<int>("Position")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("Power")
|
||||||
|
.HasPrecision(18, 2)
|
||||||
|
.HasColumnType("decimal(18,2)");
|
||||||
|
|
||||||
|
b.Property<Guid>("SquadTypeId")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PlayerId");
|
||||||
|
|
||||||
|
b.HasIndex("SquadTypeId");
|
||||||
|
|
||||||
|
b.ToTable("Squads", "dbo");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Database.Entities.SquadType", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.HasColumnType("uniqueidentifier");
|
||||||
|
|
||||||
|
b.Property<string>("TypeName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(150)
|
||||||
|
.HasColumnType("nvarchar(150)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SquadTypes", "dbo");
|
||||||
|
|
||||||
|
b.HasData(
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = new Guid("01978732-b32b-7af9-bf5f-a69585d89eb7"),
|
||||||
|
TypeName = "Tanks"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = new Guid("01978732-b32b-7fe8-9ee5-68b0d0df44f4"),
|
||||||
|
TypeName = "Missile"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = new Guid("01978732-b32b-780e-bef0-6bcf784ee1b4"),
|
||||||
|
TypeName = "Aircraft"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = new Guid("01978732-b32b-79c9-adaa-19ed53157f67"),
|
||||||
|
TypeName = "Mixed"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Database.Entities.User", b =>
|
modelBuilder.Entity("Database.Entities.User", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
@ -661,19 +728,19 @@ namespace Database.Migrations
|
|||||||
b.HasData(
|
b.HasData(
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("01972f47-5fb5-7584-a312-e749206f0036"),
|
Id = new Guid("01978732-b32e-7aa5-8e77-507b8b20977d"),
|
||||||
Code = 1,
|
Code = 1,
|
||||||
Name = "Silver League"
|
Name = "Silver League"
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("01972f47-5fb6-7dec-93aa-b62f0e167fde"),
|
Id = new Guid("01978732-b32e-76d6-9beb-3fd062efe9ef"),
|
||||||
Code = 2,
|
Code = 2,
|
||||||
Name = "Gold League"
|
Name = "Gold League"
|
||||||
},
|
},
|
||||||
new
|
new
|
||||||
{
|
{
|
||||||
Id = new Guid("01972f47-5fb6-7f9a-8a2d-9f47fa1803e1"),
|
Id = new Guid("01978732-b32e-7583-9522-90dde6d778b6"),
|
||||||
Code = 3,
|
Code = 3,
|
||||||
Name = "Diamond League"
|
Name = "Diamond League"
|
||||||
});
|
});
|
||||||
@ -1078,6 +1145,25 @@ namespace Database.Migrations
|
|||||||
b.Navigation("Rank");
|
b.Navigation("Rank");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Database.Entities.Squad", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Database.Entities.Player", "Player")
|
||||||
|
.WithMany("Squads")
|
||||||
|
.HasForeignKey("PlayerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Database.Entities.SquadType", "SquadType")
|
||||||
|
.WithMany("Squads")
|
||||||
|
.HasForeignKey("SquadTypeId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Player");
|
||||||
|
|
||||||
|
b.Navigation("SquadType");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Database.Entities.User", b =>
|
modelBuilder.Entity("Database.Entities.User", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Database.Entities.Alliance", "Alliance")
|
b.HasOne("Database.Entities.Alliance", "Alliance")
|
||||||
@ -1260,6 +1346,8 @@ namespace Database.Migrations
|
|||||||
|
|
||||||
b.Navigation("Notes");
|
b.Navigation("Notes");
|
||||||
|
|
||||||
|
b.Navigation("Squads");
|
||||||
|
|
||||||
b.Navigation("VsDuelParticipants");
|
b.Navigation("VsDuelParticipants");
|
||||||
|
|
||||||
b.Navigation("ZombieSiegeParticipants");
|
b.Navigation("ZombieSiegeParticipants");
|
||||||
@ -1270,6 +1358,11 @@ namespace Database.Migrations
|
|||||||
b.Navigation("Players");
|
b.Navigation("Players");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Database.Entities.SquadType", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Squads");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Database.Entities.VsDuel", b =>
|
modelBuilder.Entity("Database.Entities.VsDuel", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("VsDuelParticipants");
|
b.Navigation("VsDuelParticipants");
|
||||||
|
|||||||
13
README.md
13
README.md
@ -21,6 +21,19 @@ This project is currently in the **Beta Phase**.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### **[0.11.0]** - *2025-06-19*
|
||||||
|
#### ✨ Added
|
||||||
|
- **Squad Management per Player:** You can now add up to **four squads per player**, each with:
|
||||||
|
- **Power** (in millions)
|
||||||
|
- **Position**
|
||||||
|
- **Type**: Tank, Aircraft, Missile, or Mixed
|
||||||
|
- **Visual Enhancements:** Squad types are displayed with custom icons and total power is summarized at the top of the squad card.
|
||||||
|
|
||||||
|
🛠️ **Fixed**
|
||||||
|
- (N/A)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### **[0.10.0]** - *2025-06-02*
|
### **[0.10.0]** - *2025-06-02*
|
||||||
#### ✨ Added
|
#### ✨ Added
|
||||||
- **Team Selection for Desert Storm:** You can now assign **Team A** or **Team B** when creating a Desert Storm entry.
|
- **Team Selection for Desert Storm:** You can now assign **Team A** or **Team B** when creating a Desert Storm entry.
|
||||||
|
|||||||
@ -66,6 +66,8 @@ import { CustomEventLeaderboardComponent } from './pages/custom-event/custom-eve
|
|||||||
import { CustomEventEventsComponent } from './pages/custom-event/custom-event-events/custom-event-events.component';
|
import { CustomEventEventsComponent } from './pages/custom-event/custom-event-events/custom-event-events.component';
|
||||||
import {NgxMaskDirective, NgxMaskPipe, provideNgxMask} from "ngx-mask";
|
import {NgxMaskDirective, NgxMaskPipe, provideNgxMask} from "ngx-mask";
|
||||||
import {CountUpModule} from "ngx-countup";
|
import {CountUpModule} from "ngx-countup";
|
||||||
|
import { PlayerSquadsComponent } from './pages/player-squads/player-squads.component';
|
||||||
|
import { SquadEditModalComponent } from './modals/squad-edit-modal/squad-edit-modal.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -119,7 +121,9 @@ import {CountUpModule} from "ngx-countup";
|
|||||||
ImprintComponent,
|
ImprintComponent,
|
||||||
CustomEventCategoryComponent,
|
CustomEventCategoryComponent,
|
||||||
CustomEventLeaderboardComponent,
|
CustomEventLeaderboardComponent,
|
||||||
CustomEventEventsComponent
|
CustomEventEventsComponent,
|
||||||
|
PlayerSquadsComponent,
|
||||||
|
SquadEditModalComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
|||||||
@ -0,0 +1,68 @@
|
|||||||
|
@if (squadForm) {
|
||||||
|
<div class="modal-header" xmlns="http://www.w3.org/1999/html">
|
||||||
|
<h4 class="modal-title">{{ isUpdate ? 'Update Squad ' : 'Insert new Squad' }}</h4>
|
||||||
|
<button type="button" class="btn-close" aria-label="Close" (click)="activeModal.dismiss()"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
<form [formGroup]="squadForm">
|
||||||
|
|
||||||
|
<div class="form-floating mb-3 is-invalid">
|
||||||
|
<select [ngClass]="{
|
||||||
|
'is-invalid': f['position'].invalid && (f['position'].dirty || !f['position'].untouched),
|
||||||
|
'is-valid': f['position'].valid}" class="form-select" id="position" formControlName="position">
|
||||||
|
@for (position of positions; track position) {
|
||||||
|
<option [ngValue]="position">{{ position }}</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
<label for="position">Position</label>
|
||||||
|
@if (f['position'].invalid && (f['position'].dirty || !f['position'].untouched)) {
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
@if (f['position'].hasError('required')) {
|
||||||
|
<p>Position is required</p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="form-floating mb-3 is-invalid">
|
||||||
|
<input [ngClass]="{
|
||||||
|
'is-invalid': f['power'].invalid && (f['power'].dirty || !f['power'].untouched),
|
||||||
|
'is-valid': f['power'].valid}"
|
||||||
|
type="number" class="form-control" id="power" placeholder="power" formControlName="power">
|
||||||
|
<label for="power">Power in millions</label>
|
||||||
|
@if (f['power'].invalid && (f['power'].dirty || !f['power'].untouched)) {
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
@if (f['power'].hasError('required')) {
|
||||||
|
<p>Power is required</p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="form-floating mb-3 is-invalid">
|
||||||
|
<select [ngClass]="{
|
||||||
|
'is-invalid': f['squadTypeId'].invalid && (f['squadTypeId'].dirty || !f['squadTypeId'].untouched),
|
||||||
|
'is-valid': f['squadTypeId'].valid}" class="form-select" id="squadTypeId" formControlName="squadTypeId">
|
||||||
|
@for (type of squadTypes; track type.id) {
|
||||||
|
<option [ngValue]="type.id">{{ type.typeName }}</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
<label for="squadTypeId">Squad Type</label>
|
||||||
|
@if (f['squadTypeId'].invalid && (f['squadTypeId'].dirty || !f['squadTypeId'].untouched)) {
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
@if (f['squadTypeId'].hasError('required')) {
|
||||||
|
<p>Squad Type is required</p>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-warning" (click)="activeModal.dismiss()">Close</button>
|
||||||
|
<button [disabled]="squadForm.invalid" (click)="onSubmit()" type="submit"
|
||||||
|
class=" btn btn-success">{{ isUpdate ? 'Update' : 'Insert' }} Squad
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
@ -0,0 +1,94 @@
|
|||||||
|
import {Component, inject, Input, OnInit} from '@angular/core';
|
||||||
|
import {SquadTypeService} from "../../services/squad-type.service";
|
||||||
|
import {SquadService} from "../../services/squad.service";
|
||||||
|
import {SquadTypeModel} from "../../models/squadType.model";
|
||||||
|
import {CreateSquadModel, SquadModel, UpdateSquadModel} from "../../models/squad.model";
|
||||||
|
import {NgbActiveModal} from "@ng-bootstrap/ng-bootstrap";
|
||||||
|
import {FormControl, FormGroup, Validators} from "@angular/forms";
|
||||||
|
import {ToastrService} from "ngx-toastr";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-squad-edit-modal',
|
||||||
|
templateUrl: './squad-edit-modal.component.html',
|
||||||
|
styleUrl: './squad-edit-modal.component.css'
|
||||||
|
})
|
||||||
|
export class SquadEditModalComponent implements OnInit {
|
||||||
|
|
||||||
|
public activeModal: NgbActiveModal = inject(NgbActiveModal);
|
||||||
|
@Input({required: true}) playerId!: string;
|
||||||
|
@Input({required: true}) isUpdate!: boolean;
|
||||||
|
@Input({required: true}) currentSquad!: SquadModel;
|
||||||
|
public squadTypes: SquadTypeModel[] = [];
|
||||||
|
public positions: number[] = [1, 2, 3, 4];
|
||||||
|
public squadForm!: FormGroup;
|
||||||
|
private readonly _squadTypeService: SquadTypeService = inject(SquadTypeService);
|
||||||
|
private readonly _squadService: SquadService = inject(SquadService);
|
||||||
|
private readonly _toaster: ToastrService = inject(ToastrService);
|
||||||
|
|
||||||
|
get f() {
|
||||||
|
return this.squadForm.controls;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.getSquadTypes();
|
||||||
|
this.squadForm = new FormGroup({
|
||||||
|
id: new FormControl<string>(this.currentSquad.id),
|
||||||
|
playerId: new FormControl<string>(this.currentSquad.playerId),
|
||||||
|
power: new FormControl<number | null>(this.isUpdate ? this.currentSquad.power : null, [Validators.required]),
|
||||||
|
position: new FormControl<number | null>(this.isUpdate ? this.currentSquad.position : null, [Validators.required]),
|
||||||
|
squadTypeId: new FormControl<string>(this.currentSquad.squadTypeId, [Validators.required]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getSquadTypes() {
|
||||||
|
this._squadTypeService.getSquadTypes().subscribe({
|
||||||
|
next: (response: SquadTypeModel[]) => {
|
||||||
|
this.squadTypes = response;
|
||||||
|
},
|
||||||
|
error: (error: Error) => {
|
||||||
|
console.error(error);
|
||||||
|
this._toaster.error('Could not get squad types', 'Get squad types');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
if (this.squadForm.invalid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.isUpdate) {
|
||||||
|
const squad: UpdateSquadModel = this.squadForm.value as UpdateSquadModel;
|
||||||
|
this.updateSquad(squad);
|
||||||
|
} else {
|
||||||
|
const squad: CreateSquadModel = this.squadForm.value as CreateSquadModel;
|
||||||
|
this.addSquad(squad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateSquad(squad: UpdateSquadModel) {
|
||||||
|
this._squadService.updateSquad(squad.id, squad).subscribe({
|
||||||
|
next: (_: SquadModel) => {
|
||||||
|
this._toaster.success('Squad updated successfully', 'Squad update');
|
||||||
|
this.activeModal.close();
|
||||||
|
},
|
||||||
|
error: (error: Error) => {
|
||||||
|
console.error(error);
|
||||||
|
this._toaster.error('Could not update squad types', 'Squad update');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private addSquad(squad: CreateSquadModel) {
|
||||||
|
this._squadService.createSquad(squad).subscribe({
|
||||||
|
next: (_: SquadModel) => {
|
||||||
|
this._toaster.success('Squad created successfully', 'Squad create');
|
||||||
|
this.activeModal.close();
|
||||||
|
},
|
||||||
|
error: (error: Error) => {
|
||||||
|
console.error(error);
|
||||||
|
this._toaster.error('Could not create squad', 'Squad create');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
16
Ui/src/app/models/squad.model.ts
Normal file
16
Ui/src/app/models/squad.model.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export interface SquadModel extends CreateSquadModel{
|
||||||
|
id: string;
|
||||||
|
typeName: string;
|
||||||
|
lastUpdateAt: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreateSquadModel {
|
||||||
|
squadTypeId: string;
|
||||||
|
playerId: string;
|
||||||
|
power: number;
|
||||||
|
position: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateSquadModel extends CreateSquadModel {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
4
Ui/src/app/models/squadType.model.ts
Normal file
4
Ui/src/app/models/squadType.model.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface SquadTypeModel {
|
||||||
|
id: string;
|
||||||
|
typeName: string;
|
||||||
|
}
|
||||||
@ -5,9 +5,11 @@
|
|||||||
</div>
|
</div>
|
||||||
@if (currentPlayer) {
|
@if (currentPlayer) {
|
||||||
<!-- Player card-->
|
<!-- Player card-->
|
||||||
<div class="card border-info mt-3">
|
<div class="row mt-3">
|
||||||
|
<div class="col-md-6 mb-3 d-flex">
|
||||||
|
<div class="card border-info flex-fill">
|
||||||
<h5 class="card-header border-info text-center">Player Information</h5>
|
<h5 class="card-header border-info text-center">Player Information</h5>
|
||||||
<div class="card-body">
|
<div class="card-body d-flex flex-column">
|
||||||
<h5 class="card-title">Name: <span class="text-primary">{{ currentPlayer.playerName }}</span></h5>
|
<h5 class="card-title">Name: <span class="text-primary">{{ currentPlayer.playerName }}</span></h5>
|
||||||
<p class="card-text">Rank: <span class="text-primary">{{ currentPlayer.rankName }}</span></p>
|
<p class="card-text">Rank: <span class="text-primary">{{ currentPlayer.rankName }}</span></p>
|
||||||
<p class="card-text">Headquarter: <span class="text-primary">{{ currentPlayer.level }}</span></p>
|
<p class="card-text">Headquarter: <span class="text-primary">{{ currentPlayer.level }}</span></p>
|
||||||
@ -19,7 +21,7 @@
|
|||||||
class="text-primary">{{ currentPlayer.modifiedOn | date: 'dd.MM.yyyy HH:mm' }}</span></p>
|
class="text-primary">{{ currentPlayer.modifiedOn | date: 'dd.MM.yyyy HH:mm' }}</span></p>
|
||||||
<p class="card-text">Modified by: <span class="text-primary">{{currentPlayer.modifiedBy}}</span></p>
|
<p class="card-text">Modified by: <span class="text-primary">{{currentPlayer.modifiedBy}}</span></p>
|
||||||
}
|
}
|
||||||
<div class="d-flex justify-content-between">
|
<div class="mt-auto d-flex justify-content-between">
|
||||||
<button (click)="openPlayerNotes(currentPlayer)" type="button" class="btn btn-primary position-relative">
|
<button (click)="openPlayerNotes(currentPlayer)" type="button" class="btn btn-primary position-relative">
|
||||||
Notes
|
Notes
|
||||||
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
|
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
|
||||||
@ -36,9 +38,17 @@
|
|||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3 d-flex">
|
||||||
|
<app-player-squads [playerId]="playerId"></app-player-squads>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Accordion-->
|
<!-- Accordion-->
|
||||||
<div ngbAccordion #accordion="ngbAccordion" class="mt-3 pb-5">
|
<div ngbAccordion #accordion="ngbAccordion" class="mt-3 pb-5">
|
||||||
<!-- Marshal guard-->
|
<!-- Marshal guard-->
|
||||||
|
|||||||
@ -64,5 +64,4 @@ export class PlayerInformationComponent implements OnInit {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
.cursor-pointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
76
Ui/src/app/pages/player-squads/player-squads.component.html
Normal file
76
Ui/src/app/pages/player-squads/player-squads.component.html
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<div class="card border-info flex-fill w-100">
|
||||||
|
<h5 class="card-header border-info text-center">
|
||||||
|
Squad Power
|
||||||
|
@if (squads.length > 0) {
|
||||||
|
<span class="text-success fw-bold">
|
||||||
|
{{ totalPower | number:'1.2-2' }} million
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
<!-- Add Squad -->
|
||||||
|
@if (squads.length < 4) {
|
||||||
|
<div class="d-flex justify-content-end mb-3">
|
||||||
|
<button (click)="addSquad()" class="btn btn-sm btn-success" title="Add Squad">
|
||||||
|
<i class="bi bi-plus-lg"></i> Add
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Squad List -->
|
||||||
|
@for (squad of squads; track squad.id) {
|
||||||
|
<div class="mb-3 border-bottom pb-3">
|
||||||
|
|
||||||
|
<!-- Title Row -->
|
||||||
|
<h6 class="mb-2">{{ squad.position }}. Squad ({{ squad.typeName }})</h6>
|
||||||
|
|
||||||
|
<!-- Power | Actions | Image -->
|
||||||
|
<div class="d-flex align-items-center justify-content-between">
|
||||||
|
|
||||||
|
<!-- Power -->
|
||||||
|
<div>
|
||||||
|
<strong>Power:</strong> {{ squad.power | number:'1.2-2' }}M
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Edit / Delete Icons -->
|
||||||
|
<div>
|
||||||
|
<i
|
||||||
|
(click)="editSquad(squad)"
|
||||||
|
class="bi bi-pencil text-primary me-3 cursor-pointer"
|
||||||
|
title="Edit Squad">
|
||||||
|
</i>
|
||||||
|
<i
|
||||||
|
(click)="deleteSquad(squad)"
|
||||||
|
class="bi bi-trash text-danger cursor-pointer"
|
||||||
|
title="Delete Squad">
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Image -->
|
||||||
|
<img
|
||||||
|
[src]="'assets/images/icons/' + squad.typeName + '.png'"
|
||||||
|
alt="{{ squad.typeName }}"
|
||||||
|
style="width: 50px; height: 50px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Last Update -->
|
||||||
|
<div class="text-muted">
|
||||||
|
<small>Last updated: {{ squad.lastUpdateAt | date:'dd.MM.yyyy' }}</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<!-- No Squads -->
|
||||||
|
@if (!squads?.length) {
|
||||||
|
<div class="text-muted text-center">
|
||||||
|
No squads available.
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
103
Ui/src/app/pages/player-squads/player-squads.component.ts
Normal file
103
Ui/src/app/pages/player-squads/player-squads.component.ts
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import {Component, inject, Input, OnInit} from '@angular/core';
|
||||||
|
import {NgbModal} from "@ng-bootstrap/ng-bootstrap";
|
||||||
|
import {SquadEditModalComponent} from "../../modals/squad-edit-modal/squad-edit-modal.component";
|
||||||
|
import {SquadModel} from "../../models/squad.model";
|
||||||
|
import {SquadService} from "../../services/squad.service";
|
||||||
|
import Swal from "sweetalert2";
|
||||||
|
import {ToastrService} from "ngx-toastr";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-player-squads',
|
||||||
|
templateUrl: './player-squads.component.html',
|
||||||
|
styleUrl: './player-squads.component.css'
|
||||||
|
})
|
||||||
|
export class PlayerSquadsComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input({required: true}) playerId!: string;
|
||||||
|
public squads: SquadModel[] = [];
|
||||||
|
private readonly _modalService: NgbModal = inject(NgbModal);
|
||||||
|
private readonly _squadService: SquadService = inject(SquadService);
|
||||||
|
private readonly _toaster: ToastrService = inject(ToastrService);
|
||||||
|
|
||||||
|
get totalPower(): number {
|
||||||
|
return this.squads?.reduce((sum, squad) => sum + squad.power, 0) || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.getPlayerSquads();
|
||||||
|
}
|
||||||
|
|
||||||
|
getPlayerSquads(): void {
|
||||||
|
this._squadService.getPlayerSquads(this.playerId).subscribe({
|
||||||
|
next: (result) => {
|
||||||
|
if (result) {
|
||||||
|
this.squads = result;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: err => {
|
||||||
|
console.log(err);
|
||||||
|
this._toaster.error('Error getting player squads', 'Getting player squads');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
editSquad(squad: SquadModel) {
|
||||||
|
this.onOpenModal(this.playerId, squad, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteSquad(squad: SquadModel) {
|
||||||
|
Swal.fire({
|
||||||
|
title: "Delete Squad ?",
|
||||||
|
text: `Do you really want to delete the ${squad.typeName} squad`,
|
||||||
|
icon: "warning",
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
confirmButtonText: "Yes, delete it!"
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
this._squadService.deleteSquad(squad.id).subscribe({
|
||||||
|
next: ((response) => {
|
||||||
|
if (response) {
|
||||||
|
Swal.fire({
|
||||||
|
title: "Deleted!",
|
||||||
|
text: "Squad has been deleted",
|
||||||
|
icon: "success"
|
||||||
|
}).then(_ => this.getPlayerSquads());
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
error: (error: Error) => {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addSquad() {
|
||||||
|
const squad: SquadModel = {
|
||||||
|
id: '',
|
||||||
|
playerId: this.playerId,
|
||||||
|
squadTypeId: '',
|
||||||
|
power: 0,
|
||||||
|
position: 0,
|
||||||
|
lastUpdateAt: new Date(),
|
||||||
|
typeName: ''
|
||||||
|
};
|
||||||
|
this.onOpenModal(this.playerId, squad, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
onOpenModal(playerId: string, squad: SquadModel, isUpdate: boolean) {
|
||||||
|
const modalRef = this._modalService.open(SquadEditModalComponent,
|
||||||
|
{animation: true, backdrop: 'static', centered: true, size: 'lg'});
|
||||||
|
modalRef.componentInstance.playerId = playerId;
|
||||||
|
modalRef.componentInstance.currentSquad = squad;
|
||||||
|
modalRef.componentInstance.isUpdate = isUpdate;
|
||||||
|
modalRef.closed.subscribe({
|
||||||
|
next: (() => {
|
||||||
|
this.getPlayerSquads();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
18
Ui/src/app/services/squad-type.service.ts
Normal file
18
Ui/src/app/services/squad-type.service.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import {inject, Injectable} from '@angular/core';
|
||||||
|
import {environment} from "../../environments/environment";
|
||||||
|
import {HttpClient} from "@angular/common/http";
|
||||||
|
import {Observable} from "rxjs";
|
||||||
|
import {SquadTypeModel} from "../models/squadType.model";
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class SquadTypeService {
|
||||||
|
|
||||||
|
private readonly _serviceUrl = environment.apiBaseUrl + 'SquadTypes/';
|
||||||
|
private readonly _httpClient: HttpClient = inject(HttpClient);
|
||||||
|
|
||||||
|
getSquadTypes(): Observable<SquadTypeModel[]> {
|
||||||
|
return this._httpClient.get<SquadTypeModel[]>(this._serviceUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
30
Ui/src/app/services/squad.service.ts
Normal file
30
Ui/src/app/services/squad.service.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import {inject, Injectable} from '@angular/core';
|
||||||
|
import {environment} from "../../environments/environment";
|
||||||
|
import {HttpClient} from "@angular/common/http";
|
||||||
|
import {Observable} from "rxjs";
|
||||||
|
import {CreateSquadModel, SquadModel, UpdateSquadModel} from "../models/squad.model";
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class SquadService {
|
||||||
|
|
||||||
|
private readonly _serviceUrl = environment.apiBaseUrl + 'Squads/';
|
||||||
|
private readonly _httpClient: HttpClient = inject(HttpClient);
|
||||||
|
|
||||||
|
getPlayerSquads(playerId: string): Observable<SquadModel[]> {
|
||||||
|
return this._httpClient.get<SquadModel[]>(this._serviceUrl + 'player/' + playerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
createSquad(createSquad: CreateSquadModel): Observable<SquadModel> {
|
||||||
|
return this._httpClient.post<SquadModel>(this._serviceUrl, createSquad);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSquad(squadId: string, updateSquad: UpdateSquadModel): Observable<SquadModel> {
|
||||||
|
return this._httpClient.put<SquadModel>(this._serviceUrl + squadId, updateSquad);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteSquad(squadId: string): Observable<boolean> {
|
||||||
|
return this._httpClient.delete<boolean>(this._serviceUrl + squadId);
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
Ui/src/assets/images/icons/Aircraft.png
Normal file
BIN
Ui/src/assets/images/icons/Aircraft.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
BIN
Ui/src/assets/images/icons/Missile.png
Normal file
BIN
Ui/src/assets/images/icons/Missile.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
BIN
Ui/src/assets/images/icons/Mixed.png
Normal file
BIN
Ui/src/assets/images/icons/Mixed.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 MiB |
BIN
Ui/src/assets/images/icons/Tanks.png
Normal file
BIN
Ui/src/assets/images/icons/Tanks.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
Loading…
x
Reference in New Issue
Block a user