@using TaskTrackingSystem.WebApp.Components.Shared.Charts
@if (!Groups.Any()) {
@EmptyText
} else { @foreach (var tick in YTicks) { var y = TickToY(tick); @tick.ToString("0") } @for (var i = 0; i < Groups.Count; i++) { var group = Groups[i]; var slotWidth = (PlotRight - PlotLeft) / Groups.Count; var centerX = PlotLeft + (slotWidth * i) + (slotWidth / 2); var bars = group.Bars.Take(MaxBarsPerGroup).ToList(); var totalBarWidth = (bars.Count * BarWidth) + Math.Max(0, bars.Count - 1) * BarGap; var startX = centerX - (totalBarWidth / 2); @for (var j = 0; j < bars.Count; j++) { var bar = bars[j]; var height = ValueToHeight(bar.Value); } @group.Label } @if (ShowLegend) {
@foreach (var item in LegendItems) {
@item.Label
}
} }
@code { private const double PlotLeft = 56; private const double PlotRight = 724; private const double PlotTop = 40; private const double PlotBottom = 200; private const double BarGap = 8; [Parameter] public IReadOnlyList Groups { get; set; } = Array.Empty(); [Parameter] public string WrapperClass { get; set; } = "relative h-[280px]"; [Parameter] public string EmptyText { get; set; } = "No data available"; [Parameter] public bool ShowLegend { get; set; } = true; [Parameter] public double BarWidth { get; set; } = 18; [Parameter] public int MaxBarsPerGroup { get; set; } = 4; private double MaxValue => Math.Max(1, Groups.SelectMany(group => group.Bars).Select(bar => bar.Value).DefaultIfEmpty(0).Max()); private IReadOnlyList YTicks { get { var interval = Math.Max(1, Math.Ceiling(MaxValue / 4.0)); var highest = interval * 4; return new[] { 0, highest * 0.25, highest * 0.5, highest * 0.75, highest }; } } private IReadOnlyList LegendItems => Groups .SelectMany(group => group.Bars) .GroupBy(bar => bar.Label) .Select(group => group.First()) .ToList(); private double TickToY(double tickValue) { var chartHeight = PlotBottom - PlotTop; return PlotBottom - (Math.Min(tickValue, MaxValue) / MaxValue * chartHeight); } private double ValueToHeight(double value) { var chartHeight = PlotBottom - PlotTop; return Math.Round(Math.Min(value, MaxValue) / MaxValue * chartHeight, 2); } }