Skip to content

Commit b03a921

Browse files
committed
Upgrade UI for Profile Info and Nav Menu
1 parent 058a977 commit b03a921

File tree

10 files changed

+912
-12
lines changed

10 files changed

+912
-12
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
@namespace FSH.Framework.Blazor.UI.Components.Dialogs
2+
3+
<MudDialog Class="fsh-confirm-dialog">
4+
<TitleContent>
5+
<div class="fsh-dialog-header">
6+
@if (!string.IsNullOrEmpty(Icon))
7+
{
8+
<MudIcon Icon="@Icon" Color="@IconColor" Size="Size.Large" Class="fsh-dialog-icon" />
9+
}
10+
<MudText Typo="Typo.h6" Class="fsh-dialog-title">@Title</MudText>
11+
</div>
12+
</TitleContent>
13+
<DialogContent>
14+
<div class="fsh-dialog-content">
15+
@if (ContentFragment is not null)
16+
{
17+
@ContentFragment
18+
}
19+
else
20+
{
21+
<MudText Typo="Typo.body1" Class="fsh-dialog-message">@Message</MudText>
22+
}
23+
</div>
24+
</DialogContent>
25+
<DialogActions>
26+
<div class="fsh-dialog-actions">
27+
<MudButton Variant="Variant.Text"
28+
Color="Color.Default"
29+
OnClick="Cancel"
30+
Class="fsh-dialog-btn-cancel">
31+
@CancelText
32+
</MudButton>
33+
<MudButton Variant="Variant.Filled"
34+
Color="@ConfirmColor"
35+
OnClick="Confirm"
36+
Class="fsh-dialog-btn-confirm">
37+
@ConfirmText
38+
</MudButton>
39+
</div>
40+
</DialogActions>
41+
</MudDialog>
42+
43+
@code {
44+
[CascadingParameter]
45+
private IMudDialogInstance MudDialog { get; set; } = default!;
46+
47+
[Parameter]
48+
public string Title { get; set; } = "Confirm";
49+
50+
[Parameter]
51+
public string Message { get; set; } = "Are you sure you want to proceed?";
52+
53+
[Parameter]
54+
public RenderFragment? ContentFragment { get; set; }
55+
56+
[Parameter]
57+
public string Icon { get; set; } = Icons.Material.Outlined.Help;
58+
59+
[Parameter]
60+
public Color IconColor { get; set; } = Color.Primary;
61+
62+
[Parameter]
63+
public string ConfirmText { get; set; } = "Confirm";
64+
65+
[Parameter]
66+
public string CancelText { get; set; } = "Cancel";
67+
68+
[Parameter]
69+
public Color ConfirmColor { get; set; } = Color.Primary;
70+
71+
private void Confirm() => MudDialog.Close(DialogResult.Ok(true));
72+
73+
private void Cancel() => MudDialog.Cancel();
74+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
::deep .fsh-confirm-dialog {
2+
border-radius: 16px;
3+
overflow: hidden;
4+
}
5+
6+
::deep .fsh-confirm-dialog .mud-dialog-title {
7+
padding: 24px 24px 0 24px;
8+
}
9+
10+
::deep .fsh-confirm-dialog .mud-dialog-content {
11+
padding: 16px 24px;
12+
}
13+
14+
::deep .fsh-confirm-dialog .mud-dialog-actions {
15+
padding: 16px 24px 24px 24px;
16+
}
17+
18+
.fsh-dialog-header {
19+
display: flex;
20+
align-items: center;
21+
gap: 12px;
22+
}
23+
24+
.fsh-dialog-icon {
25+
flex-shrink: 0;
26+
}
27+
28+
.fsh-dialog-title {
29+
font-weight: 600;
30+
color: var(--mud-palette-text-primary);
31+
}
32+
33+
.fsh-dialog-content {
34+
padding-top: 8px;
35+
}
36+
37+
.fsh-dialog-message {
38+
color: var(--mud-palette-text-secondary);
39+
line-height: 1.6;
40+
}
41+
42+
.fsh-dialog-actions {
43+
display: flex;
44+
justify-content: flex-end;
45+
gap: 12px;
46+
width: 100%;
47+
}
48+
49+
.fsh-dialog-btn-cancel {
50+
font-weight: 500;
51+
}
52+
53+
.fsh-dialog-btn-confirm {
54+
font-weight: 600;
55+
border-radius: 8px;
56+
padding: 8px 20px;
57+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using Microsoft.AspNetCore.Components;
2+
using MudBlazor;
3+
4+
namespace FSH.Framework.Blazor.UI.Components.Dialogs;
5+
6+
public static class FshDialogService
7+
{
8+
public static async Task<bool> ShowConfirmAsync(
9+
this IDialogService dialogService,
10+
string title,
11+
string message,
12+
string confirmText = "Confirm",
13+
string cancelText = "Cancel",
14+
Color confirmColor = Color.Primary,
15+
string icon = Icons.Material.Outlined.Help,
16+
Color iconColor = Color.Primary)
17+
{
18+
var parameters = new DialogParameters<FshConfirmDialog>
19+
{
20+
{ x => x.Title, title },
21+
{ x => x.Message, message },
22+
{ x => x.ConfirmText, confirmText },
23+
{ x => x.CancelText, cancelText },
24+
{ x => x.ConfirmColor, confirmColor },
25+
{ x => x.Icon, icon },
26+
{ x => x.IconColor, iconColor }
27+
};
28+
29+
var options = new DialogOptions
30+
{
31+
CloseButton = false,
32+
MaxWidth = MaxWidth.ExtraSmall,
33+
FullWidth = true,
34+
BackdropClick = false,
35+
CloseOnEscapeKey = true
36+
};
37+
38+
var dialog = await dialogService.ShowAsync<FshConfirmDialog>(title, parameters, options);
39+
var result = await dialog.Result;
40+
41+
return result is not null && !result.Canceled;
42+
}
43+
44+
public static Task<bool> ShowDeleteConfirmAsync(
45+
this IDialogService dialogService,
46+
string itemName = "this item")
47+
{
48+
return dialogService.ShowConfirmAsync(
49+
title: "Delete Confirmation",
50+
message: $"Are you sure you want to delete {itemName}? This action cannot be undone.",
51+
confirmText: "Delete",
52+
cancelText: "Cancel",
53+
confirmColor: Color.Error,
54+
icon: Icons.Material.Outlined.DeleteForever,
55+
iconColor: Color.Error);
56+
}
57+
58+
public static Task<bool> ShowSignOutConfirmAsync(this IDialogService dialogService)
59+
{
60+
return dialogService.ShowConfirmAsync(
61+
title: "Sign Out",
62+
message: "Are you sure you want to sign out of your account?",
63+
confirmText: "Sign Out",
64+
cancelText: "Cancel",
65+
confirmColor: Color.Error,
66+
icon: Icons.Material.Outlined.Logout,
67+
iconColor: Color.Warning);
68+
}
69+
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
@namespace FSH.Framework.Blazor.UI.Components.User
2+
@inherits FSH.Framework.Blazor.UI.Components.Base.FshComponentBase
3+
4+
<div class="fsh-account-menu">
5+
<MudMenu AnchorOrigin="Origin.BottomRight"
6+
TransformOrigin="Origin.TopRight"
7+
PopoverClass="fsh-account-popover"
8+
Dense="false">
9+
<ActivatorContent>
10+
<MudButton Class="fsh-account-trigger" Variant="Variant.Text" Color="Color.Inherit">
11+
<MudAvatar Size="Size.Small" Class="fsh-trigger-avatar">
12+
@if (!string.IsNullOrEmpty(AvatarUrl))
13+
{
14+
<MudImage Src="@AvatarUrl" Alt="@UserName" />
15+
}
16+
else
17+
{
18+
@GetInitials(UserName)
19+
}
20+
</MudAvatar>
21+
<MudIcon Icon="@Icons.Material.Filled.KeyboardArrowDown" Size="Size.Small" Class="fsh-trigger-arrow" />
22+
</MudButton>
23+
</ActivatorContent>
24+
<ChildContent>
25+
<div class="fsh-account-dropdown">
26+
<!-- User profile header -->
27+
<div class="fsh-dropdown-header">
28+
<MudAvatar Size="Size.Large" Class="fsh-header-avatar">
29+
@if (!string.IsNullOrEmpty(AvatarUrl))
30+
{
31+
<MudImage Src="@AvatarUrl" Alt="@UserName" />
32+
}
33+
else
34+
{
35+
@GetInitials(UserName)
36+
}
37+
</MudAvatar>
38+
<div class="fsh-header-info">
39+
<span class="fsh-header-name">@UserName</span>
40+
<span class="fsh-header-email">@UserEmail</span>
41+
@if (!string.IsNullOrEmpty(UserRole))
42+
{
43+
<MudChip T="string" Size="Size.Small" Color="Color.Primary" Variant="Variant.Outlined" Class="fsh-header-role">@UserRole</MudChip>
44+
}
45+
</div>
46+
</div>
47+
48+
<MudDivider Class="my-0" />
49+
50+
<!-- Menu items -->
51+
<div class="fsh-dropdown-menu">
52+
<MudMenuItem Icon="@Icons.Material.Outlined.Person" OnClick="@HandleProfileClick" Class="fsh-menu-item">
53+
<div class="fsh-menu-item-content">
54+
<span class="fsh-menu-item-text">Profile</span>
55+
<span class="fsh-menu-item-desc">View and edit your profile</span>
56+
</div>
57+
</MudMenuItem>
58+
<MudMenuItem Icon="@Icons.Material.Outlined.History" OnClick="@HandleAuditingClick" Class="fsh-menu-item">
59+
<div class="fsh-menu-item-content">
60+
<span class="fsh-menu-item-text">Activity Log</span>
61+
<span class="fsh-menu-item-desc">View your recent activity</span>
62+
</div>
63+
</MudMenuItem>
64+
</div>
65+
66+
<MudDivider Class="my-0" />
67+
68+
<!-- Sign out -->
69+
<div class="fsh-dropdown-footer">
70+
<MudMenuItem Icon="@Icons.Material.Outlined.Logout" OnClick="@HandleLogoutClick" Class="fsh-menu-item fsh-menu-item-danger">
71+
Sign out
72+
</MudMenuItem>
73+
</div>
74+
</div>
75+
</ChildContent>
76+
</MudMenu>
77+
</div>
78+
79+
@code {
80+
[Parameter, EditorRequired]
81+
public string UserName { get; set; } = "User";
82+
83+
[Parameter]
84+
public string? UserEmail { get; set; }
85+
86+
[Parameter]
87+
public string? UserRole { get; set; }
88+
89+
[Parameter]
90+
public string? AvatarUrl { get; set; }
91+
92+
[Parameter]
93+
public EventCallback OnProfileClick { get; set; }
94+
95+
[Parameter]
96+
public EventCallback OnAuditingClick { get; set; }
97+
98+
[Parameter]
99+
public EventCallback OnLogoutClick { get; set; }
100+
101+
private static string GetInitials(string? name)
102+
{
103+
if (string.IsNullOrWhiteSpace(name))
104+
return "U";
105+
106+
var parts = name.Split(' ', StringSplitOptions.RemoveEmptyEntries);
107+
if (parts.Length >= 2)
108+
return $"{parts[0][0]}{parts[1][0]}".ToUpperInvariant();
109+
110+
return name.Length >= 2 ? name[..2].ToUpperInvariant() : name.ToUpperInvariant();
111+
}
112+
113+
private async Task HandleProfileClick()
114+
{
115+
if (OnProfileClick.HasDelegate)
116+
await OnProfileClick.InvokeAsync();
117+
else
118+
Navigation.NavigateTo("/profile");
119+
}
120+
121+
private async Task HandleAuditingClick()
122+
{
123+
if (OnAuditingClick.HasDelegate)
124+
await OnAuditingClick.InvokeAsync();
125+
else
126+
Navigation.NavigateTo("/audits");
127+
}
128+
129+
private async Task HandleLogoutClick()
130+
{
131+
if (OnLogoutClick.HasDelegate)
132+
await OnLogoutClick.InvokeAsync();
133+
}
134+
}

0 commit comments

Comments
 (0)