Skip to content

Commit 238c1ea

Browse files
fix api client exceptions, fix validation errors when inviting, add loading for register and login
1 parent 87f7783 commit 238c1ea

File tree

8 files changed

+62
-6
lines changed

8 files changed

+62
-6
lines changed

Frontend/TeamUp.ApiLayer/ApiClient.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,16 @@ private async Task<Result> SendRequestAsync(HttpRequestMessage request, Cancella
105105
{
106106
await InjectAuthToken(request, ct);
107107

108-
var response = await _client.SendAsync(request, ct);
108+
HttpResponseMessage response;
109+
110+
try
111+
{
112+
response = await _client.SendAsync(request, ct);
113+
}
114+
catch (Exception ex)
115+
{
116+
return new ApiUnexpectedError("Api.UnexpectedError", ex.Message);
117+
}
109118

110119
if (!response.IsSuccessStatusCode)
111120
{
@@ -119,7 +128,16 @@ private async Task<Result<TResponse>> SendRequestAsync<TResponse>(HttpRequestMes
119128
{
120129
await InjectAuthToken(request, ct);
121130

122-
var response = await _client.SendAsync(request, ct);
131+
HttpResponseMessage response;
132+
133+
try
134+
{
135+
response = await _client.SendAsync(request, ct);
136+
}
137+
catch (Exception ex)
138+
{
139+
return new ApiUnexpectedError("Api.UnexpectedError", ex.Message);
140+
}
123141

124142
if (!response.IsSuccessStatusCode)
125143
{

Frontend/TeamUp.Client/AnonymousPages/Login.razor

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
<FluentValidationMessage For="() => Input.Password" Class="text-danger" />
3232

3333
<FluentStack Orientation="Orientation.Horizontal" Style="margin-top: 8px">
34-
<FluentButton Type="ButtonType.Submit" Appearance="Appearance.Accent">Log in</FluentButton>
34+
<FluentButton Loading="processing" Type="ButtonType.Submit" Appearance="Appearance.Accent">Log in</FluentButton>
3535
<FluentAnchor Href="register" Appearance="Appearance.Lightweight">Register</FluentAnchor>
3636
</FluentStack>
3737
</FluentStack>
@@ -42,6 +42,8 @@
4242

4343
@code
4444
{
45+
private bool processing = false;
46+
4547
[SupplyParameterFromQuery]
4648
private string? ReturnUrl { get; set; }
4749

@@ -54,7 +56,6 @@
5456

5557
private CustomValidation ValidationComponent { get; set; } = null!;
5658

57-
5859
protected override async Task OnInitializedAsync()
5960
{
6061
var state = await AuthenticationStateProvider.GetAuthenticationStateAsync();
@@ -66,6 +67,7 @@
6667

6768
public async Task LoginAsync()
6869
{
70+
processing = true;
6971
var result = await ApiClient.LoginAsync(Input, CTS.Token);
7072
if (result.IsFailure)
7173
{
@@ -76,6 +78,7 @@
7678

7779
ToastService.ShowError(result.Error.Message);
7880
Input.Password = "";
81+
processing = false;
7982
return;
8083
}
8184

Frontend/TeamUp.Client/AnonymousPages/Register.razor

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
<FluentValidationMessage For="() => Input.ConfirmPassword" Class="text-danger" />
4747

4848
<FluentStack Orientation="Orientation.Horizontal" Style="margin-top: 8px">
49-
<FluentButton Type="ButtonType.Submit" Appearance="Appearance.Accent">Register</FluentButton>
49+
<FluentButton Loading="processing" Type="ButtonType.Submit" Appearance="Appearance.Accent">Register</FluentButton>
5050
<FluentAnchor Href="login" Appearance="Appearance.Lightweight">Log in</FluentAnchor>
5151
</FluentStack>
5252
</FluentStack>
@@ -59,6 +59,7 @@
5959
@code
6060
{
6161
private string? email = null;
62+
private bool processing = false;
6263

6364
[SupplyParameterFromForm]
6465
private RegisterModel Input { get; set; } = new();
@@ -76,6 +77,7 @@
7677

7778
public async Task RegisterAsync()
7879
{
80+
processing = true;
7981
var request = new RegisterUserRequest()
8082
{
8183
Email = Input.Email,
@@ -94,11 +96,13 @@
9496
ToastService.ShowError(result.Error.Message);
9597
Input.Password = "";
9698
Input.ConfirmPassword = "";
99+
processing = false;
97100
return;
98101
}
99102

100103
ToastService.ShowSuccess("Successful registration, please activate your account via email.");
101104
email = Input.Email;
105+
processing = false;
102106
}
103107

104108
private sealed class RegisterModel

Frontend/TeamUp.Client/Pages/Components/TeamInvitationsComponent.razor

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@
9494

9595
if (result.Cancelled)
9696
{
97+
emailInput.Email = "";
98+
emailInput.Errors = null;
9799
return;
98100
}
99101

@@ -106,9 +108,18 @@
106108
if (invitationResult.IsFailure)
107109
{
108110
ToastService.ShowError(invitationResult.Error.Message);
111+
112+
if (invitationResult.Error is ApiValidationError error)
113+
{
114+
emailInput.Errors = error.Errors;
115+
}
116+
109117
return;
110118
}
111119

120+
emailInput.Email = "";
121+
emailInput.Errors = null;
122+
112123
ToastService.ShowInfo("The invitation request was accepted for processing, invitation should be created in upcoming minutes.");
113124
await LoadInvitationsAsync();
114125
}

Frontend/TeamUp.Client/Pages/Panels/EmailInput.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ public sealed class EmailInput
77
[Required]
88
[EmailAddress]
99
public required string Email { get; set; }
10+
11+
public IDictionary<string, string[]>? Errors { get; set; }
1012
}

Frontend/TeamUp.Client/Pages/Panels/InviteUserPanel.razor

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,25 @@
33
@using System.ComponentModel.DataAnnotations
44

55
<FluentDialogBody>
6-
<FluentTextField @bind-Value="@Content.Email">Email:</FluentTextField>
6+
<EditForm Model="@Content" Style="margin: 1px">
7+
<CustomValidation @ref="ValidationComponent" />
8+
<FluentTextField @bind-Value="@Content.Email" Required="true" Placeholder="name@example.com" Label="Email" />
9+
<FluentValidationMessage For="() => Content.Email" Class="text-danger" />
10+
</EditForm>
711
</FluentDialogBody>
812

913
@code
1014
{
1115
[Parameter]
1216
public EmailInput Content { get; set; } = default!;
17+
18+
private CustomValidation ValidationComponent { get; set; } = null!;
19+
20+
protected override void OnAfterRender(bool firstRender)
21+
{
22+
if (Content?.Errors is not null)
23+
{
24+
ValidationComponent.DisplayErrors(Content.Errors);
25+
}
26+
}
1327
}

Frontend/TeamUp.Client/Pages/Team.razor

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
<strong style="margin-left: 4px;">@teamContext.Role.ToString()</strong>
3535
</div>
3636

37+
<FluentDivider Style="margin-top: 8px; margin-bottom: 8px" />
38+
3739
@if (teamContext.Role.IsOwner())
3840
{
3941
<div style="margin-top: 8px">

Frontend/TeamUp.Contracts/ApiError.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace TeamUp.Contracts;
66

7+
public sealed record ApiUnexpectedError(string Key, string Message) : Error(Key, Message);
8+
79
public sealed record ApiError(string Key, string Message, HttpStatusCode HttpStatusCode) : Error(Key, Message);
810

911
public sealed record ApiValidationError(string Key, string Message, IDictionary<string, string[]> Errors) : Error(Key, Message);

0 commit comments

Comments
 (0)