@using TaskTrackingSystem.WebApp.Components.Shared.Charts
@if (!Items.Any() || Items.Sum(item => item.Value) <= 0)
{
@EmptyText
}
else
{
@if (ShowLegend)
{
@foreach (var item in Items)
{
@item.Label
@AppLocalization.Number(item.Value, ValueFormat)
}
}
}
@code {
[Parameter] public IReadOnlyList Items { get; set; } = Array.Empty();
[Parameter] public bool ShowLegend { get; set; } = true;
[Parameter] public string EmptyText { get; set; } = AppLocalization.Text("report.noChartData", "No data available.");
[Parameter] public string ValueFormat { get; set; } = "0";
[Parameter] public string WrapperClass { get; set; } = string.Empty;
private IReadOnlyList Slices => BuildSlices();
private IReadOnlyList BuildSlices()
{
const double center = 95;
const double radius = 72;
var total = Items.Sum(item => Math.Max(0, item.Value));
var startAngle = -90.0;
var slices = new List();
foreach (var item in Items)
{
var value = Math.Max(0, item.Value);
if (value <= 0 || total <= 0)
{
continue;
}
var sweep = 360 * value / total;
var endAngle = startAngle + sweep;
if (sweep >= 359.999)
{
slices.Add(new Slice(item.Color, string.Empty, true));
startAngle = endAngle;
continue;
}
var start = PointOnCircle(center, center, radius, startAngle);
var end = PointOnCircle(center, center, radius, endAngle);
var largeArc = sweep > 180 ? 1 : 0;
var path = $"M {center:0.##} {center:0.##} L {start.X:0.##} {start.Y:0.##} A {radius:0.##} {radius:0.##} 0 {largeArc} 1 {end.X:0.##} {end.Y:0.##} Z";
slices.Add(new Slice(item.Color, path, false));
startAngle = endAngle;
}
return slices;
}
private static (double X, double Y) PointOnCircle(double centerX, double centerY, double radius, double angleDegrees)
{
var radians = angleDegrees * Math.PI / 180;
return (centerX + radius * Math.Cos(radians), centerY + radius * Math.Sin(radians));
}
private sealed record Slice(string Color, string Path, bool IsFullCircle);
}