diff --git a/Lieb/Data/DbInitializer.cs b/Lieb/Data/DbInitializer.cs index 4166521..e0aac31 100644 --- a/Lieb/Data/DbInitializer.cs +++ b/Lieb/Data/DbInitializer.cs @@ -40,6 +40,7 @@ namespace Lieb.Data GuildWars2Account bloodseeker = new GuildWars2Account() { AccountName = "Bloodseeker.2043" }; var users = new LiebUser[] { + //new LiebUser{DiscordUserId=0, Name="Sarah", Birthday=DateTime.Parse("1992-01-15"), GuildWars2Accounts = new List(){ linaith, sarah} }, new LiebUser{DiscordUserId=194863625477816321, Name="Sarah", Birthday=DateTime.Parse("1992-01-15"), GuildWars2Accounts = new List(){ linaith, sarah} }, #if DEBUG new LiebUser{DiscordUserId=1, Name="Lisa", GuildWars2Accounts = new List(){ hierpiepts}}, @@ -96,9 +97,9 @@ namespace Lieb.Data Guild = "LIEB", Organizer = "Sarah", RaidType = RaidType.RandomWithBoons, - Date = DateTime.Now.Date, - StartTime = DateTime.Now, - EndTime = DateTime.Now.AddHours(2), + StartTimeUTC = DateTime.UtcNow, + EndTimeUTC = DateTime.UtcNow.AddHours(2), + FreeForAllTimeUTC = DateTime.UtcNow.AddHours(-2), VoiceChat = "ts.lieb.games", Roles = new [] { ele, scourge} }; @@ -115,7 +116,7 @@ namespace Lieb.Data context.RaidSignUps.AddRange(signUps); context.SaveChanges(); - GuildWars2Build healTempest = new GuildWars2Build() { BuildName = "HealTempest", Class = GuildWars2Class.Elementalist, EliteSpecialization = EliteSpecialization.Tempest, Heal = 5, Might = 10 }; + GuildWars2Build healTempest = new GuildWars2Build() { BuildName = "HealTempest", Class = GuildWars2Class.Elementalist, EliteSpecialization = EliteSpecialization.Tempest, Heal = 5, Might = 5 }; GuildWars2Build condiScourge = new GuildWars2Build() { BuildName = "CondiScourge", Class = GuildWars2Class.Necromancer, EliteSpecialization = EliteSpecialization.Scourge }; GuildWars2Build quickBrand = new GuildWars2Build() { BuildName = "QuickBrand", Class = GuildWars2Class.Guard, EliteSpecialization = EliteSpecialization.Firebrand, Heal = 5, Quickness = 5 }; GuildWars2Build alacregate = new GuildWars2Build() { BuildName = "Alacregate", Class = GuildWars2Class.Revenant, EliteSpecialization = EliteSpecialization.Renegade, Alacrity = 5 }; diff --git a/Lieb/Data/RaidService.cs b/Lieb/Data/RaidService.cs index a682df3..a16378d 100644 --- a/Lieb/Data/RaidService.cs +++ b/Lieb/Data/RaidService.cs @@ -65,14 +65,16 @@ namespace Lieb.Data .FirstOrDefaultAsync(r => r.RaidId == raid.RaidId); raidToChange.Title = raid.Title; raidToChange.Description = raid.Description; - raidToChange.Date = raid.Date; - raidToChange.StartTime = raid.StartTime; - raidToChange.EndTime = raid.EndTime; + raidToChange.StartTimeUTC = raid.StartTimeUTC; + raidToChange.EndTimeUTC = raid.EndTimeUTC; + raidToChange.TimeZone = raid.TimeZone; raidToChange.Organizer = raid.Organizer; raidToChange.Guild = raid.Guild; raidToChange.VoiceChat = raid.VoiceChat; raidToChange.RaidType = raid.RaidType; raidToChange.Frequency = raid.Frequency; + raidToChange.RequiredRole = raid.RequiredRole; + raidToChange.FreeForAllTimeUTC = raid.FreeForAllTimeUTC; raidToChange.DiscordMessageId = raid.DiscordMessageId; raidToChange.DiscordChannelId = raid.DiscordChannelId; raidToChange.DiscordGuildId = raid.DiscordGuildId; @@ -315,13 +317,6 @@ namespace Lieb.Data return false; } - DateTime freeForAllTime = raid.FreeForAllDate.Date + raid.FreeForAllTime.TimeOfDay; - if (!string.IsNullOrEmpty(raid.RequiredRole) && !user.RoleAssignments.Where(a => a.LiebRole.RoleName == raid.RequiredRole).Any() || freeForAllTime > DateTimeOffset.Now) - { - errorMessage = $"The raid is still locked for {raid.RequiredRole}."; - return false; - } - if (user.GuildWars2Accounts.Count == 0) { errorMessage = "No Guild Wars 2 account found."; @@ -334,6 +329,12 @@ namespace Lieb.Data return false; } + if (!string.IsNullOrEmpty(raid.RequiredRole) && !user.RoleAssignments.Where(a => a.LiebRole.RoleName == raid.RequiredRole).Any() || raid.FreeForAllTimeUTC.UtcDateTime > DateTimeOffset.UtcNow) + { + errorMessage = $"The raid is still locked for {raid.RequiredRole}."; + return false; + } + return true; } } diff --git a/Lieb/Data/TimeZoneService.cs b/Lieb/Data/TimeZoneService.cs new file mode 100644 index 0000000..0def12b --- /dev/null +++ b/Lieb/Data/TimeZoneService.cs @@ -0,0 +1,44 @@ +using Microsoft.JSInterop; + +namespace Lieb.Data +{ + public class TimeZoneService + { + private readonly IJSRuntime _jsRuntime; + + private TimeSpan? _userOffset; + private int _offsetInMinutes; + + public TimeZoneService(IJSRuntime jsRuntime) + { + _jsRuntime = jsRuntime; + } + + public async ValueTask GetLocalDateTime(DateTimeOffset dateTime) + { + if (_userOffset == null) + { + _offsetInMinutes = await _jsRuntime.InvokeAsync("GetTimezoneValue"); + _userOffset = TimeSpan.FromMinutes(-_offsetInMinutes); + } + + return dateTime.ToOffset(_userOffset.Value); + } + + public async ValueTask GetUTCDateTime(DateTimeOffset dateTime) + { + if (_userOffset == null) + { + _offsetInMinutes = await _jsRuntime.InvokeAsync("GetTimezoneValue"); + _userOffset = TimeSpan.FromMinutes(-_offsetInMinutes); + } + + return new DateTimeOffset(dateTime.DateTime.AddMinutes(_offsetInMinutes), new TimeSpan(0)); + } + + public async ValueTask GetUserTimeZone() + { + return await _jsRuntime.InvokeAsync("GetTimezone"); + } + } +} diff --git a/Lieb/Models/GuildWars2/Raid/Raid.cs b/Lieb/Models/GuildWars2/Raid/Raid.cs index 97d8a71..243eb96 100644 --- a/Lieb/Models/GuildWars2/Raid/Raid.cs +++ b/Lieb/Models/GuildWars2/Raid/Raid.cs @@ -23,13 +23,12 @@ namespace Lieb.Models.GuildWars2.Raid public string Description { get; set; } = String.Empty; [Required] - public DateTime Date { get; set; } = DateTime.Now; + public DateTimeOffset StartTimeUTC { get; set; } = DateTime.Now; [Required] - public DateTimeOffset StartTime { get; set; } + public DateTimeOffset EndTimeUTC { get; set; } - [Required] - public DateTimeOffset EndTime { get; set; } + public string TimeZone { get; set; } = String.Empty; [Required] [StringLength(50, ErrorMessage = "Organizer too long (50 character limit).")] @@ -52,9 +51,7 @@ namespace Lieb.Models.GuildWars2.Raid public string RequiredRole { get; set; } = String.Empty; - public DateTime FreeForAllDate { get; set; } = DateTime.Now; - - public DateTimeOffset FreeForAllTime { get; set; } + public DateTimeOffset FreeForAllTimeUTC { get; set; } //role name, number of spots public ICollection Roles { get; set; } = new HashSet(); diff --git a/Lieb/Pages/Raids/RaidDetails.razor b/Lieb/Pages/Raids/RaidDetails.razor index 8b5e57b..11250c1 100644 --- a/Lieb/Pages/Raids/RaidDetails.razor +++ b/Lieb/Pages/Raids/RaidDetails.razor @@ -4,6 +4,7 @@ @using Lieb.Models.GuildWars2.Raid @inject UserService UserService @inject RaidService RaidService +@inject TimeZoneService TimeZoneService @inject RaidRandomizerService RaidRandomizerService @@ -17,11 +18,11 @@
Date
-

@_raid.Date.ToLongDateString()

+

@_startTime.DateTime.ToLongDateString()

Time
-

from: @_raid.StartTime.LocalDateTime.ToShortTimeString() to: @_raid.EndTime.LocalDateTime.ToShortTimeString()

+

from: @_startTime.LocalDateTime.ToShortTimeString() to: @_endTime.LocalDateTime.ToShortTimeString()

@@ -72,7 +73,6 @@ @code { - [Parameter] public Raid _raid { get; set; } @@ -83,9 +83,17 @@ string _errorMessage; + private DateTimeOffset _startTime; + private DateTimeOffset _endTime; + private DateTimeOffset _freeForAllTime; + protected override async Task OnInitializedAsync() { _isRaidSignUpAllowed = _user != null && RaidService.IsRaidSignUpAllowed(_user.LiebUserId, _raid.RaidId, out string _errorMessage); + + _startTime = await TimeZoneService.GetLocalDateTime(_raid.StartTimeUTC); + _endTime = await TimeZoneService.GetLocalDateTime(_raid.EndTimeUTC); + _freeForAllTime = await TimeZoneService.GetLocalDateTime(_raid.FreeForAllTimeUTC); } async Task SignUpClicked(PlannedRaidRole role, LiebUser liebUser, bool isSignedUp, SignUpType signUpType) diff --git a/Lieb/Pages/Raids/RaidEdit.razor b/Lieb/Pages/Raids/RaidEdit.razor index 98d45ac..db9657b 100644 --- a/Lieb/Pages/Raids/RaidEdit.razor +++ b/Lieb/Pages/Raids/RaidEdit.razor @@ -4,6 +4,7 @@ @using Lieb.Models.GuildWars2.Raid @using System.ComponentModel.DataAnnotations @inject RaidService RaidService +@inject TimeZoneService TimeZoneService @inject NavigationManager NavigationManager @inject IJSRuntime JsRuntime @@ -13,7 +14,6 @@ - @{ bool _isEdit = _raid.RaidId != 0; } @@ -44,20 +44,20 @@

@@ -109,7 +109,9 @@

} - + + +
@@ -124,12 +126,26 @@ public Raid _raid; + private string _errosMessage = string.Empty; + + private DateTimeOffset _raidDate = DateTime.Now.Date; + private DateTimeOffset _startTime; + private DateTimeOffset _endTime; + private DateTimeOffset _freeForAllDate = DateTime.Now.Date; + private DateTimeOffset _freeForAllTime; + + protected override async Task OnInitializedAsync() { if(!string.IsNullOrEmpty(raidId) && int.TryParse(raidId, out int parsedId)) { _raid = RaidService.GetRaid(parsedId); + _startTime = await TimeZoneService.GetLocalDateTime(_raid.StartTimeUTC); + _endTime = await TimeZoneService.GetLocalDateTime(_raid.EndTimeUTC); + _raidDate = _startTime.Date; + _freeForAllTime = await TimeZoneService.GetLocalDateTime(_raid.FreeForAllTimeUTC); + _freeForAllDate = _freeForAllTime.Date; } else { @@ -160,8 +176,9 @@ private async Task HandleValidSubmit() { - if(_raid.RaidType != RaidType.Planned && _raid.Roles.Count == 0) + if(_raid.RaidType != RaidType.Planned) { + _raid.Roles.Clear(); _raid.Roles.Add(new PlannedRaidRole() { Spots = 10, @@ -170,6 +187,25 @@ }); } + if(_raid.Roles.Count == 0) + { + _errosMessage = "Roles are needed for a raid."; + return; + } + + _raid.TimeZone = await TimeZoneService.GetUserTimeZone(); + + _raid.StartTimeUTC = await TimeZoneService.GetUTCDateTime(_raidDate.Date + _startTime.TimeOfDay); + if(_startTime.TimeOfDay > _endTime.TimeOfDay) + { + _raid.EndTimeUTC = await TimeZoneService.GetUTCDateTime(_raidDate.Date + _endTime.TimeOfDay); + } + else + { + _raid.EndTimeUTC = await TimeZoneService.GetUTCDateTime(_raidDate.Date.AddDays(1) + _endTime.TimeOfDay); + } + _raid.FreeForAllTimeUTC = await TimeZoneService.GetUTCDateTime(_freeForAllDate.Date + _freeForAllTime.TimeOfDay); + await RaidService.AddOrEditRaid(_raid); NavigationManager.NavigateTo("raidoverview"); } diff --git a/Lieb/Pages/_Host.cshtml b/Lieb/Pages/_Host.cshtml index 7d14b20..cf6953e 100644 --- a/Lieb/Pages/_Host.cshtml +++ b/Lieb/Pages/_Host.cshtml @@ -7,3 +7,14 @@ @(await Html.RenderComponentAsync(RenderMode.Server)) + + \ No newline at end of file diff --git a/Lieb/Pages/_ValidationScriptsPartial.cshtml b/Lieb/Pages/_ValidationScriptsPartial.cshtml deleted file mode 100644 index d8a48e3..0000000 --- a/Lieb/Pages/_ValidationScriptsPartial.cshtml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/Lieb/Program.cs b/Lieb/Program.cs index 0e09fc0..91dbc69 100644 --- a/Lieb/Program.cs +++ b/Lieb/Program.cs @@ -25,6 +25,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddAuthentication(opt =>