1
0
mirror of synced 2024-12-21 02:45:54 +01:00
TaikoLocalServer/TaikoWebUI/Components/UserCard.razor
KIT! 505b867e1a Updated highscore page styling, fixed empty entries
Songs entries can be broken when updating the datatables (if songs are removed). The frontend now filters those empty songs out.
2024-10-29 14:33:03 +01:00

255 lines
10 KiB
Plaintext

@using System.Text.Json
@using TaikoWebUI.Pages.Dialogs;
@inject Utilities.StringUtil StringUtil;
@inject IDialogService DialogService;
@inject AuthService AuthService;
@inject HttpClient Client
@inject NavigationManager NavigationManager
@if (User is not null)
{
<MudCard Outlined="true" Class="user-card">
<MudCardHeader>
<CardHeaderContent>
<div style="display:flex;flex-wrap:wrap;align-items:center;gap:5px;">
@if (UserSetting is not null)
{
<MudText Typo="Typo.h6" Style="font-weight:bold;word-break:break-all">@UserSetting?.MyDonName</MudText>
} else
{
<MudSkeleton Width="35%" Height="32px" />
}
@if (AuthService.LoginRequired && User?.IsAdmin == true)
{
<MudChip Variant="Variant.Outlined" Color="Color.Info" Size="Size.Small" Icon="@Icons.Material.TwoTone.AdminPanelSettings">@Localizer["Admin"]</MudChip>
}
</div>
<MudText Typo="Typo.caption">@Localizer["User ID"]: @User?.Baid</MudText>
</CardHeaderContent>
<CardHeaderActions>
<MudMenu Icon="@Icons.Material.Filled.MoreVert" Dense="true" AnchorOrigin="Origin.BottomLeft"
TransformOrigin="Origin.TopLeft" Size="Size.Small">
<MudMenuItem Icon="@Icons.Material.Filled.QrCode"
OnClick="@(_ => ShowQrCode(User))"
OnTouch="@(_ => ShowQrCode(User))"
IconColor="@Color.Primary">
@Localizer["Show QR Code"]
</MudMenuItem>
<MudDivider />
<MudMenuItem Icon="@Icons.Material.Filled.FeaturedPlayList"
Href="@($"Users/{User.Baid}/AccessCode")"
IconColor="@Color.Primary">
@Localizer["Access Codes"]
</MudMenuItem>
<MudDivider />
@if (AuthService.OnlyAdmin || AuthService.LoginRequired)
{
<MudMenuItem Icon="@Icons.Material.Filled.Lock"
Href="@($"/ChangePassword")"
IconColor="@Color.Primary">
@Localizer["Change Password"]
</MudMenuItem>
<MudDivider />
}
@if (AuthService.LoginRequired && AuthService.IsAdmin)
{
<MudMenuItem Icon="@Icons.Material.Filled.Password"
OnClick="@(_ => GenerateInviteCode(User.Baid))"
OnTouch="@(_ => GenerateInviteCode(User.Baid))"
IconColor="@Color.Primary">
@Localizer["Generate Invite Code"]
</MudMenuItem>
<MudDivider />
}
@if (AuthService.LoginRequired && AuthService.IsAdmin)
{
<MudMenuItem Icon="@Icons.Material.Filled.LockReset"
OnClick="@(_ => ResetPassword(User))"
OnTouch="@(_ => ResetPassword(User))"
IconColor="@Color.Primary">
@Localizer["Unregister"]
</MudMenuItem>
<MudDivider />
}
@if (AuthService.AllowUserDelete)
{
<MudMenuItem Icon="@Icons.Material.Filled.Delete"
OnClick="@(_ => DeleteUser(User))"
OnTouch="@(_ => DeleteUser(User))"
IconColor="@Color.Error">
@Localizer["Delete User"]
</MudMenuItem>
}
</MudMenu>
</CardHeaderActions>
</MudCardHeader>
<MudCardContent>
<MudText Typo="Typo.body2" Style="font-weight:bold">@Localizer["Access Code"]</MudText>
<MudText Style="font-family:monospace;overflow:hidden;overflow-x:scroll">
@if (User.AccessCodes.Count > 0)
{
@if (User.AccessCodes[0].Length % 4 == 0 && StringUtil.OnlyHexInString(User.AccessCodes[0]))
{
foreach (var digitGroup in StringUtil.SplitIntoGroups(User.AccessCodes[0], 4))
{
<span class="mr-2">@digitGroup</span>
}
}
else
{
<span class="mr-2">@User.AccessCodes[0]</span>
}
} else
{
<span class="mr-2">@Localizer["N/A"]</span>
}
</MudText>
@if (User.AccessCodes.Count > 1)
{
<MudText Typo="Typo.caption">... @Localizer["And"] @(User.AccessCodes.Count - 1) @Localizer["other access code(s)"]</MudText>
}
else
{
// Empty line to keep the layout consistent
<MudText Typo="Typo.caption"> </MudText>
}
</MudCardContent>
<MudCardActions>
<MudStack Row="true" Style="width:100%" Spacing="4" Justify="Justify.FlexEnd">
<MudButton Href="@($"Users/{User.Baid}/Profile")"
Size="Size.Small" Variant="Variant.Text" StartIcon="@Icons.Material.Filled.Edit"
Color="Color.Primary">
@Localizer["Edit Profile"]
</MudButton>
<MudMenu Size="Size.Small"
Dense="true"
Color="Color.Primary"
Label="@Localizer["View Play Data"]"
StartIcon="@Icons.Material.Filled.EmojiEvents"
EndIcon="@Icons.Material.Filled.KeyboardArrowDown"
FullWidth="true"
AnchorOrigin="Origin.BottomCenter"
TransformOrigin="Origin.TopCenter">
<MudMenuItem Href="@($"Users/{User.Baid}/HighScores")">@Localizer["High Scores"]</MudMenuItem>
<MudMenuItem Href="@($"Users/{User.Baid}/PlayHistory")">@Localizer["Play History"]</MudMenuItem>
<MudMenuItem Href="@($"Users/{User.Baid}/Songs")">@Localizer["Song List"]</MudMenuItem>
<MudMenuItem Href="@($"Users/{User.Baid}/DaniDojo")">@Localizer["Dani Dojo"]</MudMenuItem>
</MudMenu>
</MudStack>
</MudCardActions>
</MudCard>
}
@code {
[Parameter] public User? User { get; set; }
[Parameter] public UserSetting? UserSetting { get; set; }
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
}
private Task ShowQrCode(User user)
{
var parameters = new DialogParameters
{
["user"] = user
};
var options = new DialogOptions { DisableBackdropClick = true };
DialogService.Show<UserQrCodeDialog>(Localizer["QR Code"], parameters, options);
return Task.CompletedTask;
}
private async Task ResetPassword(User user)
{
var options = new DialogOptions { DisableBackdropClick = true };
if (AuthService.LoginRequired && !AuthService.IsAdmin)
{
await DialogService.ShowMessageBox(
Localizer["Error"],
"Only admin can reset password.",
Localizer["Dialog OK"], null, null, options);
return;
}
var parameters = new DialogParameters
{
["user"] = user
};
var dialog = await DialogService.ShowAsync<ResetPasswordConfirmDialog>(Localizer["Reset Password"], parameters, options);
await dialog.Result;
}
private async Task DeleteUser(User user)
{
var options = new DialogOptions { DisableBackdropClick = true };
if (!AuthService.AllowUserDelete)
{
await DialogService.ShowMessageBox(
Localizer["Error"],
"User deletion is disabled by admin.",
Localizer["Dialog OK"], null, null, options);
return;
}
var parameters = new DialogParameters
{
["user"] = user
};
var dialog = await DialogService.ShowAsync<UserDeleteConfirmDialog>((string)Localizer["Delete User"], parameters, options);
var result = await dialog.Result;
if (result.Canceled) return;
if (user.Baid == AuthService.GetLoggedInBaid())
{
await AuthService.Logout();
}
NavigationManager.NavigateTo("/Users", true);
}
private async Task GenerateInviteCode(uint baid)
{
var request = new GenerateOtpRequest
{
Baid = baid
};
var responseMessage = await Client.PostAsJsonAsync("api/Auth/GenerateOtp", request);
if (!responseMessage.IsSuccessStatusCode)
{
await DialogService.ShowMessageBox(
Localizer["Error"],
Localizer["Unknown Error"],
Localizer["Dialog OK"], null, null, new DialogOptions { DisableBackdropClick = true });
return;
}
var responseContent = await responseMessage.Content.ReadAsStringAsync();
var responseJson = JsonSerializer.Deserialize<Dictionary<string, string>>(responseContent);
if (responseJson == null)
{
await DialogService.ShowMessageBox(
Localizer["Error"],
Localizer["Unknown Error"],
Localizer["Dialog OK"], null, null, new DialogOptions { DisableBackdropClick = true });
return;
}
var otp = responseJson["otp"];
var parameters = new DialogParameters
{
["otp"] = otp
};
var options = new DialogOptions { DisableBackdropClick = true };
await DialogService.ShowAsync<OTPDialog>(Localizer["Invite Code"], parameters, options);
}
}