Aggiunta componente progress pareto semaforico

This commit is contained in:
Samuele Locatelli
2026-05-04 12:25:04 +02:00
parent 4d7632b64a
commit bad3deff3a
4 changed files with 129 additions and 0 deletions
+1
View File
@@ -13,6 +13,7 @@ namespace EgwCoreLib.BlazorTest.Data
{"TestBarcodeReader", "Test Barcode Read"},
{"TestCalendario", "Test Calendario"},
{"TestProgress", "Test Progress"},
{"TestParetoProgress", "Test Pareto ProgressBar"},
{"TestLoading", "Test Loading"},
{"TestComponenti", "Test Componenti"},
{"TestSvgDraw", "Test SVG draw"},
@@ -0,0 +1,41 @@
@page "/TestParetoProgress"
<div class="card">
<div class="card-header">
<h3>Test Pareto ProgressBar</h3>
</div>
<div class="card-body py-1">
<div class="row">
@foreach (var dataSet in ListParetoTime)
{
<div class="col-4">
<ParetoProgress ParetoData="@dataSet" Title="Demo Progress" />
</div>
}
</div>
</div>
</div>
@code {
private List<Dictionary<string, int>> ListParetoTime = new();
private Random rnd = new();
protected override void OnInitialized()
{
base.OnInitialized();
ListParetoTime = new();
// simulazione...
for (int i = 0; i < 9; i++)
{
Dictionary<string, int> currSet = new();
currSet.Add("success", rnd.Next(2, 10));
currSet.Add("warning", rnd.Next(0, 10));
currSet.Add("danger", rnd.Next(1, 10));
ListParetoTime.Add(currSet);
}
// fatto!
}
}
+4
View File
@@ -107,4 +107,8 @@
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="ChartJS\" />
</ItemGroup>
</Project>
+83
View File
@@ -0,0 +1,83 @@
@using System.Collections.Generic
@using System.Globalization
<div class="mb-3">
@if (!string.IsNullOrWhiteSpace(Title))
{
<div class="d-flex justify-content-between align-items-center mb-1">
<strong>@Title</strong>
@if (Total > 0)
{
<span class="text-muted small">Totale: @Total</span>
}
</div>
}
@if (Total > 0)
{
<div class="progress" style="height: 32px;" role="progressbar" aria-label="@($"Pareto scadenze: {success} OK, {warning} Warning, {danger} Danger")">
<div class="progress-bar bg-success" style="width: @(CalcPctCss(SuccessPct))" title="@($"OK: {success} ({SuccessPct:F1}%)")" aria-valuenow="@SuccessPct" aria-valuemin="0" aria-valuemax="100">
@if (ShowIcon)
{
<span>✅ OK: </span>
}
@success
</div>
<div class="progress-bar bg-warning text-dark" style="width: @(CalcPctCss(WarningPct))" title="@($"Warning: {warning} ({WarningPct:F1}%)")" aria-valuenow="@WarningPct" aria-valuemin="0" aria-valuemax="100">
@if (ShowIcon)
{
<span>⚠️ Warning: </span>
}
@warning
</div>
<div class="progress-bar bg-danger" style="width: @(CalcPctCss(DangerPct))" title="@($"Danger: {danger} ({DangerPct:F1}%)")" aria-valuenow="@DangerPct" aria-valuemin="0" aria-valuemax="100">
@if (ShowIcon)
{
<span>🚨 Danger: </span>
}
@danger
</div>
</div>
}
else
{
<div class="text-muted py-2">Nessun record</div>
}
</div>
@code {
/// <summary>
/// Dizionario valori dussiviso tra success/warning/danger
/// </summary>
[Parameter]
public Dictionary<string, int>? ParetoData { get; set; }
/// <summary>
/// Titolo del display
/// </summary>
[Parameter]
public string Title { get; set; } = "Distribuzione";
/// <summary>
/// Indica se mostrare icona insieme al numero dentro i blocchi
/// </summary>
[Parameter]
public bool ShowIcon { get; set; } = false;
private string CalcPctCss(double currVal)
{
var dblVal = Total > 0 ? currVal / (double)Total * 100 : 0;
return $"{dblVal.ToString("F1", CultureInfo.InvariantCulture)}%";
}
// Proprietà calcolate con fallback sicuro
private int success => ParetoData?.GetValueOrDefault("success", 0) ?? 0;
private int warning => ParetoData?.GetValueOrDefault("warning", 0) ?? 0;
private int danger => ParetoData?.GetValueOrDefault("danger", 0) ?? 0;
private int Total => success + warning + danger;
private double SuccessPct => Total > 0 ? (success / (double)Total) * 100 : 0;
private double WarningPct => Total > 0 ? (warning / (double)Total) * 100 : 0;
private double DangerPct => Total > 0 ? (danger / (double)Total) * 100 : 0;
}