mirror of
https://github.com/claunia/marechai.git
synced 2025-12-16 19:14:25 +00:00
Add users management page.
This commit is contained in:
394
Marechai.App/Presentation/Views/UsersPage.xaml.cs
Normal file
394
Marechai.App/Presentation/Views/UsersPage.xaml.cs
Normal file
@@ -0,0 +1,394 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using Marechai.App.Presentation.ViewModels;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Text;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
|
||||
namespace Marechai.App.Presentation.Views;
|
||||
|
||||
/// <summary>
|
||||
/// User management page for Uberadmins
|
||||
/// </summary>
|
||||
public sealed partial class UsersPage : Page
|
||||
{
|
||||
private ContentDialog? _currentOpenDialog;
|
||||
private UsersViewModel? _currentViewModel;
|
||||
|
||||
public UsersPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
Loaded += UsersPage_Loaded;
|
||||
DataContextChanged += UsersPage_DataContextChanged;
|
||||
}
|
||||
|
||||
private void UsersPage_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
|
||||
{
|
||||
// Unsubscribe from previous ViewModel
|
||||
if(_currentViewModel != null) _currentViewModel.ShowDialogRequested -= OnShowDialogRequested;
|
||||
|
||||
// Subscribe to new ViewModel
|
||||
if(DataContext is UsersViewModel vm)
|
||||
{
|
||||
_currentViewModel = vm;
|
||||
vm.ShowDialogRequested += OnShowDialogRequested;
|
||||
|
||||
if(vm.IsUberadmin)
|
||||
{
|
||||
// Load data when DataContext is set and user is Uberadmin
|
||||
vm.LoadUsersCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UsersPage_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if(DataContext is UsersViewModel vm && vm.IsUberadmin)
|
||||
{
|
||||
// Load data when page is loaded (fallback)
|
||||
vm.LoadUsersCommand.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnShowDialogRequested(object? sender, string dialogType)
|
||||
{
|
||||
// Close any currently open dialog first
|
||||
if(_currentOpenDialog != null)
|
||||
{
|
||||
_currentOpenDialog.Hide();
|
||||
_currentOpenDialog = null;
|
||||
}
|
||||
|
||||
if(DataContext is not UsersViewModel vm) return;
|
||||
|
||||
ContentDialog? dialog = null;
|
||||
|
||||
switch(dialogType)
|
||||
{
|
||||
case "AddEdit":
|
||||
{
|
||||
var emailBox = new TextBox
|
||||
{
|
||||
Header = "Email",
|
||||
Text = vm.Email
|
||||
};
|
||||
|
||||
emailBox.TextChanged += (s, e) => vm.Email = emailBox.Text;
|
||||
|
||||
var userNameBox = new TextBox
|
||||
{
|
||||
Header = "Username",
|
||||
Text = vm.UserName
|
||||
};
|
||||
|
||||
userNameBox.TextChanged += (s, e) => vm.UserName = userNameBox.Text;
|
||||
|
||||
var phoneBox = new TextBox
|
||||
{
|
||||
Header = "Phone Number",
|
||||
Text = vm.PhoneNumber
|
||||
};
|
||||
|
||||
phoneBox.TextChanged += (s, e) => vm.PhoneNumber = phoneBox.Text;
|
||||
|
||||
var passwordBox = new PasswordBox
|
||||
{
|
||||
Header = "Password",
|
||||
Password = vm.Password,
|
||||
PlaceholderText = "Leave blank to keep current (when editing)"
|
||||
};
|
||||
|
||||
passwordBox.PasswordChanged += (s, e) => vm.Password = passwordBox.Password;
|
||||
|
||||
var confirmPasswordBox = new PasswordBox
|
||||
{
|
||||
Header = "Confirm Password",
|
||||
Password = vm.ConfirmPassword
|
||||
};
|
||||
|
||||
confirmPasswordBox.PasswordChanged += (s, e) => vm.ConfirmPassword = confirmPasswordBox.Password;
|
||||
|
||||
dialog = new ContentDialog
|
||||
{
|
||||
XamlRoot = XamlRoot,
|
||||
Title = vm.DialogTitle,
|
||||
PrimaryButtonText = "Save",
|
||||
CloseButtonText = "Cancel",
|
||||
PrimaryButtonCommand = vm.SaveUserCommand,
|
||||
CloseButtonCommand = vm.CloseDialogCommand,
|
||||
DefaultButton = ContentDialogButton.Primary,
|
||||
Content = new StackPanel
|
||||
{
|
||||
Spacing = 12,
|
||||
MinWidth = 400,
|
||||
Children =
|
||||
{
|
||||
emailBox,
|
||||
userNameBox,
|
||||
phoneBox,
|
||||
passwordBox,
|
||||
confirmPasswordBox
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "Password":
|
||||
{
|
||||
var passwordBox = new PasswordBox
|
||||
{
|
||||
Header = "New Password",
|
||||
Password = vm.Password
|
||||
};
|
||||
|
||||
passwordBox.PasswordChanged += (s, e) => vm.Password = passwordBox.Password;
|
||||
|
||||
var confirmPasswordBox = new PasswordBox
|
||||
{
|
||||
Header = "Confirm Password",
|
||||
Password = vm.ConfirmPassword
|
||||
};
|
||||
|
||||
confirmPasswordBox.PasswordChanged += (s, e) => vm.ConfirmPassword = confirmPasswordBox.Password;
|
||||
|
||||
dialog = new ContentDialog
|
||||
{
|
||||
XamlRoot = XamlRoot,
|
||||
Title = vm.DialogTitle,
|
||||
PrimaryButtonText = "Change Password",
|
||||
CloseButtonText = "Cancel",
|
||||
PrimaryButtonCommand = vm.SavePasswordCommand,
|
||||
CloseButtonCommand = vm.CloseDialogCommand,
|
||||
DefaultButton = ContentDialogButton.Primary,
|
||||
Content = new StackPanel
|
||||
{
|
||||
Spacing = 12,
|
||||
MinWidth = 400,
|
||||
Children =
|
||||
{
|
||||
passwordBox,
|
||||
confirmPasswordBox
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "Roles":
|
||||
{
|
||||
Debug.WriteLine($"Creating Roles dialog. Available roles count: {vm.AvailableRoles.Count}");
|
||||
foreach(string role in vm.AvailableRoles) Debug.WriteLine($" - Role: {role}");
|
||||
|
||||
var rolesContent = new Grid
|
||||
{
|
||||
RowSpacing = 16,
|
||||
MinWidth = 450
|
||||
};
|
||||
|
||||
rolesContent.RowDefinitions.Add(new RowDefinition
|
||||
{
|
||||
Height = GridLength.Auto
|
||||
});
|
||||
|
||||
rolesContent.RowDefinitions.Add(new RowDefinition
|
||||
{
|
||||
Height = new GridLength(1, GridUnitType.Star)
|
||||
});
|
||||
|
||||
var addRolePanel = new StackPanel
|
||||
{
|
||||
Spacing = 8
|
||||
};
|
||||
|
||||
addRolePanel.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "Add Role",
|
||||
FontWeight = FontWeights.SemiBold
|
||||
});
|
||||
|
||||
var addRoleGrid = new Grid
|
||||
{
|
||||
ColumnSpacing = 8
|
||||
};
|
||||
|
||||
addRoleGrid.ColumnDefinitions.Add(new ColumnDefinition
|
||||
{
|
||||
Width = new GridLength(1, GridUnitType.Star)
|
||||
});
|
||||
|
||||
addRoleGrid.ColumnDefinitions.Add(new ColumnDefinition
|
||||
{
|
||||
Width = GridLength.Auto
|
||||
});
|
||||
|
||||
// Use ListView with SingleSelection instead of ComboBox - ComboBox has issues with programmatic creation
|
||||
var roleListView = new ListView
|
||||
{
|
||||
SelectionMode = ListViewSelectionMode.Single,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
MaxHeight = 200,
|
||||
MinWidth = 300
|
||||
};
|
||||
|
||||
Debug.WriteLine($"Creating ListView for role selection with {vm.AvailableRoles.Count} roles");
|
||||
|
||||
// Populate the ListView
|
||||
foreach(string role in vm.AvailableRoles)
|
||||
{
|
||||
var item = new ListViewItem
|
||||
{
|
||||
Content = role
|
||||
};
|
||||
|
||||
roleListView.Items.Add(item);
|
||||
Debug.WriteLine($" Added role to ListView: {role}");
|
||||
}
|
||||
|
||||
Debug.WriteLine($"ListView Items.Count: {roleListView.Items.Count}");
|
||||
|
||||
roleListView.SelectionChanged += (s, e) =>
|
||||
{
|
||||
if(roleListView.SelectedItem is ListViewItem selectedItem &&
|
||||
selectedItem.Content is string selectedRole)
|
||||
{
|
||||
vm.SelectedRole = selectedRole;
|
||||
Debug.WriteLine($"Selected role from ListView: {selectedRole}");
|
||||
}
|
||||
};
|
||||
|
||||
Grid.SetColumn(roleListView, 0);
|
||||
addRoleGrid.Children.Add(roleListView);
|
||||
|
||||
var addButton = new Button
|
||||
{
|
||||
Content = "Add",
|
||||
Command = vm.AddRoleCommand
|
||||
};
|
||||
|
||||
Grid.SetColumn(addButton, 1);
|
||||
addRoleGrid.Children.Add(addButton);
|
||||
|
||||
addRolePanel.Children.Add(addRoleGrid);
|
||||
Grid.SetRow(addRolePanel, 0);
|
||||
rolesContent.Children.Add(addRolePanel);
|
||||
|
||||
var currentRolesPanel = new StackPanel
|
||||
{
|
||||
Spacing = 8,
|
||||
Margin = new Thickness(0, 8, 0, 0)
|
||||
};
|
||||
|
||||
currentRolesPanel.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "Current Roles",
|
||||
FontWeight = FontWeights.SemiBold
|
||||
});
|
||||
|
||||
// Create a StackPanel to display roles dynamically
|
||||
var rolesStack = new StackPanel
|
||||
{
|
||||
Spacing = 4
|
||||
};
|
||||
|
||||
// Handler to refresh the roles list
|
||||
void UpdateRolesList()
|
||||
{
|
||||
rolesStack.Children.Clear();
|
||||
|
||||
foreach(string role in vm.UserRoles)
|
||||
{
|
||||
var roleItem = new Grid
|
||||
{
|
||||
ColumnSpacing = 8,
|
||||
Margin = new Thickness(0, 4, 0, 4)
|
||||
};
|
||||
|
||||
roleItem.ColumnDefinitions.Add(new ColumnDefinition
|
||||
{
|
||||
Width = new GridLength(1, GridUnitType.Star)
|
||||
});
|
||||
|
||||
roleItem.ColumnDefinitions.Add(new ColumnDefinition
|
||||
{
|
||||
Width = GridLength.Auto
|
||||
});
|
||||
|
||||
var roleText = new TextBlock
|
||||
{
|
||||
Text = role,
|
||||
VerticalAlignment = VerticalAlignment.Center
|
||||
};
|
||||
|
||||
Grid.SetColumn(roleText, 0);
|
||||
roleItem.Children.Add(roleText);
|
||||
|
||||
var removeButton = new Button
|
||||
{
|
||||
Content = "Remove",
|
||||
Foreground = new SolidColorBrush(Colors.Red),
|
||||
CommandParameter = role
|
||||
};
|
||||
|
||||
removeButton.Click += (s, e) =>
|
||||
{
|
||||
var btn = s as Button;
|
||||
var roleToRemove = btn?.CommandParameter as string;
|
||||
|
||||
if(roleToRemove != null && vm.RemoveRoleCommand.CanExecute(roleToRemove))
|
||||
{
|
||||
vm.RemoveRoleCommand.Execute(roleToRemove);
|
||||
UpdateRolesList();
|
||||
}
|
||||
};
|
||||
|
||||
Grid.SetColumn(removeButton, 1);
|
||||
roleItem.Children.Add(removeButton);
|
||||
|
||||
rolesStack.Children.Add(roleItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Listen to collection changes
|
||||
vm.UserRoles.CollectionChanged += (s, e) => UpdateRolesList();
|
||||
|
||||
// Initial population
|
||||
UpdateRolesList();
|
||||
|
||||
var scrollViewer = new ScrollViewer
|
||||
{
|
||||
MaxHeight = 200,
|
||||
Content = rolesStack
|
||||
};
|
||||
|
||||
currentRolesPanel.Children.Add(scrollViewer);
|
||||
|
||||
Grid.SetRow(currentRolesPanel, 1);
|
||||
rolesContent.Children.Add(currentRolesPanel);
|
||||
|
||||
dialog = new ContentDialog
|
||||
{
|
||||
XamlRoot = XamlRoot,
|
||||
Title = vm.DialogTitle,
|
||||
CloseButtonText = "Close",
|
||||
CloseButtonCommand = vm.CloseDialogCommand,
|
||||
DefaultButton = ContentDialogButton.Close,
|
||||
Content = rolesContent
|
||||
};
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(dialog != null)
|
||||
{
|
||||
_currentOpenDialog = dialog;
|
||||
await dialog.ShowAsync();
|
||||
_currentOpenDialog = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user