Dashboard & Mitarbeiterverwaltung
This commit is contained in:
@@ -1,19 +0,0 @@
|
||||
@page "/counter"
|
||||
|
||||
|
||||
<PageTitle>Counter</PageTitle>
|
||||
|
||||
<MudText Typo="Typo.h3" GutterBottom="true">Counter</MudText>
|
||||
|
||||
<MudText Class="mb-4">Current count: @currentCount</MudText>
|
||||
|
||||
<MudButton Color="Color.Primary" Variant="Variant.Filled" @onclick="IncrementCount">Click me</MudButton>
|
||||
|
||||
@code {
|
||||
private int currentCount = 0;
|
||||
|
||||
private void IncrementCount()
|
||||
{
|
||||
currentCount++;
|
||||
}
|
||||
}
|
||||
216
OnProfNext.Client/Pages/EmployeeManagement.razor
Normal file
216
OnProfNext.Client/Pages/EmployeeManagement.razor
Normal file
@@ -0,0 +1,216 @@
|
||||
@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;
|
||||
}
|
||||
}
|
||||
147
OnProfNext.Client/Pages/ManagerDashboard.razor
Normal file
147
OnProfNext.Client/Pages/ManagerDashboard.razor
Normal file
@@ -0,0 +1,147 @@
|
||||
@page "/manager-dashboard"
|
||||
@using MudBlazor
|
||||
|
||||
<PageTitle>Team-Dashboard | OnProf</PageTitle>
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="mt-8">
|
||||
<div class="d-flex justify-space-between align-center mb-6">
|
||||
<MudText Typo="Typo.h4" Class="fw-bold">Team-Dashboard</MudText>
|
||||
<MudButton Variant="Variant.Outlined" Color="Color.Primary" StartIcon="@Icons.Material.Filled.FileDownload">Als PDF exportieren</MudButton>
|
||||
</div>
|
||||
|
||||
<MudGrid>
|
||||
<!-- Top KPI Cards -->
|
||||
<MudItem xs="12" sm="6" md="3">
|
||||
<MudPaper Elevation="2" Class="pa-4" Style="height: 120px; border-left: 6px solid var(--mud-palette-primary);">
|
||||
<MudText Typo="Typo.subtitle2" Color="Color.Secondary">Team-Stunden (Aktueller Monat)</MudText>
|
||||
<div class="d-flex align-end justify-space-between mt-2">
|
||||
<MudText Typo="Typo.h3">850 <small style="font-size: 1rem">h</small></MudText>
|
||||
<MudIcon Icon="@Icons.Material.Filled.Group" Color="Color.Primary" Size="Size.Large" />
|
||||
</div>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
|
||||
<MudItem xs="12" sm="6" md="3">
|
||||
<MudPaper Elevation="2" Class="pa-4" Style="height: 120px; border-left: 6px solid var(--mud-palette-success);">
|
||||
<MudText Typo="Typo.subtitle2" Color="Color.Secondary">Auslastung (Durchschnitt)</MudText>
|
||||
<MudText Typo="Typo.h3">92 <small style="font-size: 1rem">%</small></MudText>
|
||||
<MudProgressLinear Color="Color.Success" Value="92" Class="mt-2" />
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
|
||||
<MudItem xs="12" sm="6" md="3">
|
||||
<MudPaper Elevation="2" Class="pa-4" Style="height: 120px; border-left: 6px solid var(--mud-palette-info);">
|
||||
<MudText Typo="Typo.subtitle2" Color="Color.Secondary">Aktive Auftragsprojekte</MudText>
|
||||
<div class="d-flex align-end justify-space-between mt-2">
|
||||
<MudText Typo="Typo.h3">14</MudText>
|
||||
<MudIcon Icon="@Icons.Material.Filled.Domain" Color="Color.Info" Size="Size.Large" />
|
||||
</div>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
|
||||
<MudItem xs="12" sm="6" md="3">
|
||||
<MudPaper Elevation="2" Class="pa-4" Style="height: 120px; border-left: 6px solid var(--mud-palette-warning);">
|
||||
<MudText Typo="Typo.subtitle2" Color="Color.Secondary">Überstundenkonto gesamt</MudText>
|
||||
<div class="d-flex align-end justify-space-between mt-2">
|
||||
<MudText Typo="Typo.h3">185 <small style="font-size: 1rem">h</small></MudText>
|
||||
<MudIcon Icon="@Icons.Material.Filled.Warning" Color="Color.Warning" Size="Size.Large" />
|
||||
</div>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
|
||||
<!-- Charts Row -->
|
||||
<MudItem xs="12" md="8">
|
||||
<MudPaper Elevation="2" Class="pa-6" Style="height: 400px; display: flex; flex-direction: column;">
|
||||
<MudText Typo="Typo.h6" Class="mb-4">Gebuchte Stunden der letzten 5 Wochen</MudText>
|
||||
<div class="flex-grow-1">
|
||||
<MudChart T="double" ChartType="ChartType.Bar" ChartSeries="@_barSeries" XAxisLabels="@_xAxisLabels" Width="100%" Height="280px" />
|
||||
</div>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
|
||||
<MudItem xs="12" md="4">
|
||||
<MudPaper Elevation="2" Class="pa-6" Style="height: 400px; display: flex; flex-direction: column;">
|
||||
<MudText Typo="Typo.h6" Class="mb-4">Projektverteilung gesamt</MudText>
|
||||
<div class="flex-grow-1 d-flex justify-center align-center">
|
||||
<MudChart T="double" ChartType="ChartType.Donut" InputData="@_donutData" InputLabels="@_donutLabels" Width="200px" Height="200px" />
|
||||
</div>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
|
||||
<!-- Top Mitarbeiter Table -->
|
||||
<MudItem xs="12">
|
||||
<MudPaper Elevation="2" Class="pa-6 mt-2">
|
||||
<MudText Typo="Typo.h6" Class="mb-4">Performance der Mitarbeiter im aktuellen Monat</MudText>
|
||||
<MudDataGrid T="EmployeeStat" Items="@_employees" Hover="true" Bordered="false" Striped="true" Dense="true" Elevation="0">
|
||||
<Columns>
|
||||
<TemplateColumn T="EmployeeStat" Title="Mitarbeiter" SortBy="@(x => x.Name)">
|
||||
<CellTemplate>
|
||||
<div class="d-flex align-center">
|
||||
<MudAvatar Size="Size.Small" Color="Color.Primary" Class="mr-3">
|
||||
@context.Item.Name.Substring(0, 1)
|
||||
</MudAvatar>
|
||||
<MudText Typo="Typo.body2"><b>@context.Item.Name</b></MudText>
|
||||
</div>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
<PropertyColumn Property="x => x.Role" Title="Rolle" />
|
||||
<PropertyColumn Property="x => x.ProjectCount" Title="Aktive Projekte" />
|
||||
<TemplateColumn T="EmployeeStat" Title="Stunden (Monat)" SortBy="@(x => x.HoursBooked)">
|
||||
<CellTemplate>
|
||||
<MudText Typo="Typo.body2"><b>@context.Item.HoursBooked</b> <small class="mud-text-secondary ml-1">h</small></MudText>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
<TemplateColumn T="EmployeeStat" Title="Auslastung" SortBy="@(x => x.Utilization)">
|
||||
<CellTemplate>
|
||||
<div class="d-flex align-center">
|
||||
<MudProgressLinear Color="@GetUtilizationColor(context.Item.Utilization)" Value="@context.Item.Utilization" Class="mr-2" Style="width: 100px; min-width: 60px;" />
|
||||
<MudText Typo="Typo.caption" Color="@GetUtilizationColor(context.Item.Utilization)"><b>@context.Item.Utilization%</b></MudText>
|
||||
</div>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
</Columns>
|
||||
</MudDataGrid>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
|
||||
</MudGrid>
|
||||
</MudContainer>
|
||||
|
||||
@code {
|
||||
public class EmployeeStat
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Role { get; set; } = string.Empty;
|
||||
public int ProjectCount { get; set; }
|
||||
public double HoursBooked { get; set; }
|
||||
public double Utilization { get; set; }
|
||||
}
|
||||
|
||||
private List<EmployeeStat> _employees = new()
|
||||
{
|
||||
new EmployeeStat { Name = "Marc Mustermann", Role = "Entwickler", ProjectCount = 3, HoursBooked = 160, Utilization = 100 },
|
||||
new EmployeeStat { Name = "Anna Schmidt", Role = "Projektleiterin", ProjectCount = 5, HoursBooked = 145, Utilization = 90 },
|
||||
new EmployeeStat { Name = "John Doe", Role = "Entwickler", ProjectCount = 4, HoursBooked = 175, Utilization = 110 },
|
||||
new EmployeeStat { Name = "Maria Mayer", Role = "Testerin", ProjectCount = 2, HoursBooked = 150, Utilization = 95 },
|
||||
new EmployeeStat { Name = "Peter Parker", Role = "Designer", ProjectCount = 2, HoursBooked = 80, Utilization = 50 },
|
||||
};
|
||||
|
||||
private string[] _xAxisLabels = { "KW 08", "KW 09", "KW 10", "KW 11", "KW 12" };
|
||||
|
||||
private List<ChartSeries<double>> _barSeries = new()
|
||||
{
|
||||
new ChartSeries<double>() { Name = "Kundenaufträge", Data = new double[] { 300, 320, 280, 350, 400 } },
|
||||
new ChartSeries<double>() { Name = "Intern", Data = new double[] { 60, 40, 50, 30, 20 } },
|
||||
new ChartSeries<double>() { Name = "Gleitzeit / Urlaub", Data = new double[] { 40, 50, 60, 45, 30 } },
|
||||
};
|
||||
|
||||
private double[] _donutData = { 65, 15, 20 };
|
||||
private string[] _donutLabels = { "Kundenaufträge", "Intern", "Gleitzeit / Urlaub" };
|
||||
|
||||
private Color GetUtilizationColor(double utilization)
|
||||
{
|
||||
if (utilization > 105) return Color.Warning;
|
||||
if (utilization < 75) return Color.Error;
|
||||
return Color.Success;
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
@page "/weather"
|
||||
|
||||
|
||||
<PageTitle>Weather</PageTitle>
|
||||
|
||||
<MudText Typo="Typo.h3" GutterBottom="true">Weather forecast</MudText>
|
||||
<MudText Typo="Typo.body1" Class="mb-8">This component demonstrates fetching data from the server.</MudText>
|
||||
|
||||
@if (Forecasts == null)
|
||||
{
|
||||
<MudProgressCircular Color="Color.Default" Indeterminate="true" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudTable Items="Forecasts" Hover="true" SortLabel="Sort By" Elevation="0" AllowUnsorted="false">
|
||||
<HeaderContent>
|
||||
<MudTh><MudTableSortLabel InitialDirection="SortDirection.Ascending" SortBy="new Func<WeatherForecast, object>(x=>x.Date)">Date</MudTableSortLabel></MudTh>
|
||||
<MudTh><MudTableSortLabel SortBy="new Func<WeatherForecast, object>(x=>x.TemperatureC)">Temp. (C)</MudTableSortLabel></MudTh>
|
||||
<MudTh><MudTableSortLabel SortBy="new Func<WeatherForecast, object>(x=>x.TemperatureF)">Temp. (F)</MudTableSortLabel></MudTh>
|
||||
<MudTh><MudTableSortLabel SortBy="new Func<WeatherForecast, object>(x=>x.Summary!)">Summary</MudTableSortLabel></MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Date">@context.Date</MudTd>
|
||||
<MudTd DataLabel="Temp. (C)">@context.TemperatureC</MudTd>
|
||||
<MudTd DataLabel="Temp. (F)">@context.TemperatureF</MudTd>
|
||||
<MudTd DataLabel="Summary">@context.Summary</MudTd>
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager PageSizeOptions="new int[]{50, 100}" />
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
}
|
||||
|
||||
@code {
|
||||
[PersistentState(AllowUpdates = true)]
|
||||
public WeatherForecast[]? Forecasts { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (Forecasts is null)
|
||||
{
|
||||
// Simulate asynchronous loading to demonstrate a loading indicator
|
||||
await Task.Delay(500);
|
||||
|
||||
var startDate = DateOnly.FromDateTime(DateTime.Now);
|
||||
var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" };
|
||||
Forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||
{
|
||||
Date = startDate.AddDays(index),
|
||||
TemperatureC = Random.Shared.Next(-20, 55),
|
||||
Summary = summaries[Random.Shared.Next(summaries.Length)]
|
||||
}).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public class WeatherForecast
|
||||
{
|
||||
public DateOnly Date { get; set; }
|
||||
public int TemperatureC { get; set; }
|
||||
public string? Summary { get; set; }
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user