216 lines
10 KiB
Plaintext
216 lines
10 KiB
Plaintext
@page "/employee-management"
|
|
@using MudBlazor
|
|
@inject ISnackbar Snackbar
|
|
|
|
<PageTitle>Mitarbeiterverwaltung | OnProf</PageTitle>
|
|
|
|
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="mt-8">
|
|
<div class="d-flex justify-space-between align-center mb-6">
|
|
<div>
|
|
<MudText Typo="Typo.h4" Class="fw-bold">Mitarbeiterverwaltung</MudText>
|
|
<MudText Typo="Typo.body1" Color="Color.Secondary" Class="mt-1">Verwalte Rollen, Mandanten und Arbeitszeiten deiner Mitarbeiter.</MudText>
|
|
</div>
|
|
<div class="d-flex gap-4">
|
|
<MudButton Variant="Variant.Outlined" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Sync" OnClick="SyncWithAzureAd">AAD Sync</MudButton>
|
|
<MudButton Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Add" OnClick="OpenAddModal">Neuer Mitarbeiter</MudButton>
|
|
</div>
|
|
</div>
|
|
|
|
<MudPaper Elevation="2" Class="pa-4">
|
|
<MudDataGrid T="Employee" Items="@_employees" Hover="true" Bordered="false" Striped="true" QuickFilter="@_quickFilter" Dense="false">
|
|
<ToolBarContent>
|
|
<MudTextField @bind-Value="_searchString" Placeholder="Suchen..." Adornment="Adornment.Start" Immediate="true"
|
|
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"
|
|
Variant="Variant.Outlined" Margin="Margin.Dense" Style="max-width: 300px;"></MudTextField>
|
|
<MudSpacer />
|
|
</ToolBarContent>
|
|
<Columns>
|
|
<TemplateColumn T="Employee" Title="Mitarbeiter" SortBy="@(x => x.Name)">
|
|
<CellTemplate>
|
|
<div class="d-flex align-center">
|
|
<MudAvatar Size="Size.Medium" Color="Color.Primary" Class="mr-3">
|
|
@(string.IsNullOrWhiteSpace(context.Item.Name) ? "?" : context.Item.Name[0].ToString().ToUpper())
|
|
</MudAvatar>
|
|
<div>
|
|
<MudText Typo="Typo.body1"><b>@context.Item.Name</b></MudText>
|
|
<MudText Typo="Typo.caption" Color="Color.Secondary">@context.Item.Email</MudText>
|
|
</div>
|
|
</div>
|
|
</CellTemplate>
|
|
</TemplateColumn>
|
|
<TemplateColumn T="Employee" Title="Mandant" SortBy="@(x => x.Tenant)">
|
|
<CellTemplate>
|
|
<MudChip T="string" Color="Color.Secondary" Size="Size.Small" Variant="Variant.Text">@context.Item.Tenant</MudChip>
|
|
</CellTemplate>
|
|
</TemplateColumn>
|
|
<PropertyColumn Property="x => x.Role" Title="Rolle" />
|
|
<TemplateColumn T="Employee" Title="Tägl. Arbeitszeit" SortBy="@(x => x.DailyWorkHours)">
|
|
<CellTemplate>
|
|
<div class="d-flex align-center gap-2">
|
|
<MudIcon Icon="@Icons.Material.Filled.Schedule" Size="Size.Small" Color="Color.Default" />
|
|
<MudText><b>@context.Item.DailyWorkHours</b> <small>h / Tag</small></MudText>
|
|
</div>
|
|
</CellTemplate>
|
|
</TemplateColumn>
|
|
<TemplateColumn T="Employee" Title="AAD Status">
|
|
<CellTemplate>
|
|
@if (context.Item.IsAadSynced)
|
|
{
|
|
<MudTooltip Text="Mit Azure AD synchronisiert">
|
|
<MudIcon Icon="@Icons.Material.Filled.CloudSync" Color="Color.Success" Size="Size.Small" />
|
|
</MudTooltip>
|
|
}
|
|
else
|
|
{
|
|
<MudTooltip Text="Lokal angelegt">
|
|
<MudIcon Icon="@Icons.Material.Filled.PersonOutline" Color="Color.Warning" Size="Size.Small" />
|
|
</MudTooltip>
|
|
}
|
|
</CellTemplate>
|
|
</TemplateColumn>
|
|
<TemplateColumn T="Employee" CellClass="d-flex justify-end pr-4">
|
|
<CellTemplate>
|
|
<MudIconButton Size="@Size.Small" Icon="@Icons.Material.Filled.Edit" Color="Color.Primary" OnClick="() => EditEmployee(context.Item)" />
|
|
</CellTemplate>
|
|
</TemplateColumn>
|
|
</Columns>
|
|
<PagerContent>
|
|
<MudDataGridPager T="Employee" RowsPerPageString="Einträge pro Seite:" />
|
|
</PagerContent>
|
|
</MudDataGrid>
|
|
</MudPaper>
|
|
</MudContainer>
|
|
|
|
<MudDialog @bind-Visible="_isModalOpen" Options="new DialogOptions { MaxWidth = MaxWidth.Small, FullWidth = true }">
|
|
<TitleContent>
|
|
<MudText Typo="Typo.h6">@(_isEditing ? "Mitarbeiter bearbeiten" : "Neuen Mitarbeiter anlegen")</MudText>
|
|
</TitleContent>
|
|
<DialogContent>
|
|
<MudTextField @bind-Value="_currentEmployee.Name" Label="Name" Variant="Variant.Outlined" Margin="Margin.Dense" Class="mb-3" Required="true"
|
|
Disabled="@(_isEditing && _currentEmployee.IsAadSynced)" HelperText="@(_isEditing && _currentEmployee.IsAadSynced ? "Wird durch AAD verwaltet" : "")" />
|
|
<MudTextField @bind-Value="_currentEmployee.Email" Label="E-Mail" Variant="Variant.Outlined" Margin="Margin.Dense" Class="mb-3" Required="true"
|
|
Disabled="@(_isEditing && _currentEmployee.IsAadSynced)" />
|
|
|
|
<MudSelect @bind-Value="_currentEmployee.Tenant" Label="Mandant" Variant="Variant.Outlined" Margin="Margin.Dense" Class="mb-3">
|
|
@foreach (var tenant in _availableTenants)
|
|
{
|
|
<MudSelectItem Value="@tenant">@tenant</MudSelectItem>
|
|
}
|
|
</MudSelect>
|
|
|
|
<MudSelect @bind-Value="_currentEmployee.Role" Label="Rolle" Variant="Variant.Outlined" Margin="Margin.Dense" Class="mb-3">
|
|
@foreach (var role in _availableRoles)
|
|
{
|
|
<MudSelectItem Value="@role">@role</MudSelectItem>
|
|
}
|
|
</MudSelect>
|
|
|
|
<MudNumericField @bind-Value="_currentEmployee.DailyWorkHours" Label="Tägliche Arbeitszeit (Stunden)" Variant="Variant.Outlined" Margin="Margin.Dense" Step="0.5" Min="1" Max="24" />
|
|
</DialogContent>
|
|
<DialogActions>
|
|
<MudButton OnClick="CloseModal">Abbrechen</MudButton>
|
|
<MudButton Color="Color.Primary" Variant="Variant.Filled" OnClick="SaveEmployee">Speichern</MudButton>
|
|
</DialogActions>
|
|
</MudDialog>
|
|
|
|
@code {
|
|
private string _searchString = "";
|
|
private bool _isModalOpen = false;
|
|
private bool _isEditing = false;
|
|
private Employee _currentEmployee = new();
|
|
|
|
// Listen für Dropdowns
|
|
private List<string> _availableTenants = new() { "OnProf GmbH", "SubCorp AG", "Freelancer Network" };
|
|
private List<string> _availableRoles = new() { "Teamleiter", "Entwickler", "Projektleiter", "Designer", "Tester", "Administrator" };
|
|
|
|
public class Employee
|
|
{
|
|
public Guid Id { get; set; } = Guid.NewGuid();
|
|
public string Name { get; set; } = string.Empty;
|
|
public string Email { get; set; } = string.Empty;
|
|
public string Tenant { get; set; } = string.Empty;
|
|
public string Role { get; set; } = string.Empty;
|
|
public double DailyWorkHours { get; set; } = 8.0;
|
|
public bool IsAadSynced { get; set; } = false;
|
|
}
|
|
|
|
private List<Employee> _employees = new()
|
|
{
|
|
new Employee { Name = "Marc Mustermann", Email = "marc@onprof.de", Tenant = "OnProf GmbH", Role = "Entwickler", DailyWorkHours = 8.0, IsAadSynced = true },
|
|
new Employee { Name = "Anna Schmidt", Email = "anna@onprof.de", Tenant = "OnProf GmbH", Role = "Projektleiter", DailyWorkHours = 8.0, IsAadSynced = true },
|
|
new Employee { Name = "John Doe", Email = "john@subcorp.com", Tenant = "SubCorp AG", Role = "Entwickler", DailyWorkHours = 4.0, IsAadSynced = false },
|
|
new Employee { Name = "Maria Mayer", Email = "maria@onprof.de", Tenant = "OnProf GmbH", Role = "Tester", DailyWorkHours = 6.0, IsAadSynced = true },
|
|
new Employee { Name = "Peter Parker", Email = "peter@freelance.net", Tenant = "Freelancer Network", Role = "Designer", DailyWorkHours = 8.0, IsAadSynced = false },
|
|
};
|
|
|
|
private Func<Employee, bool> _quickFilter => x =>
|
|
{
|
|
if (string.IsNullOrWhiteSpace(_searchString)) return true;
|
|
if (x.Name.Contains(_searchString, StringComparison.OrdinalIgnoreCase)) return true;
|
|
if (x.Email.Contains(_searchString, StringComparison.OrdinalIgnoreCase)) return true;
|
|
if (x.Role.Contains(_searchString, StringComparison.OrdinalIgnoreCase)) return true;
|
|
if (x.Tenant.Contains(_searchString, StringComparison.OrdinalIgnoreCase)) return true;
|
|
return false;
|
|
};
|
|
|
|
private void SyncWithAzureAd()
|
|
{
|
|
Snackbar.Add("Synchronisation mit Azure AD wird gestartet (Mock)...", Severity.Info);
|
|
// Hier käme später die MS Graph API Integration hin
|
|
}
|
|
|
|
private void OpenAddModal()
|
|
{
|
|
_isEditing = false;
|
|
_currentEmployee = new Employee { Tenant = _availableTenants.First(), Role = _availableRoles.First() };
|
|
_isModalOpen = true;
|
|
}
|
|
|
|
private void EditEmployee(Employee employee)
|
|
{
|
|
_isEditing = true;
|
|
// Deep Copy für die Bearbeitung, um direkte Listen-Updates bei Abbruch zu vermeiden
|
|
_currentEmployee = new Employee
|
|
{
|
|
Id = employee.Id,
|
|
Name = employee.Name,
|
|
Email = employee.Email,
|
|
Tenant = employee.Tenant,
|
|
Role = employee.Role,
|
|
DailyWorkHours = employee.DailyWorkHours,
|
|
IsAadSynced = employee.IsAadSynced
|
|
};
|
|
_isModalOpen = true;
|
|
}
|
|
|
|
private void SaveEmployee()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(_currentEmployee.Name) || string.IsNullOrWhiteSpace(_currentEmployee.Email))
|
|
{
|
|
Snackbar.Add("Name und E-Mail sind Pflichtfelder.", Severity.Error);
|
|
return;
|
|
}
|
|
|
|
if (_isEditing)
|
|
{
|
|
var index = _employees.FindIndex(e => e.Id == _currentEmployee.Id);
|
|
if (index != -1)
|
|
{
|
|
_employees[index] = _currentEmployee;
|
|
Snackbar.Add("Änderungen gespeichert.", Severity.Success);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_employees.Add(_currentEmployee);
|
|
Snackbar.Add("Neuer Mitarbeiter angelegt.", Severity.Success);
|
|
}
|
|
|
|
CloseModal();
|
|
}
|
|
|
|
private void CloseModal()
|
|
{
|
|
_isModalOpen = false;
|
|
}
|
|
} |