PlanTempusApp/PlanTempus.Application/Features/Customers/Components/CustomerDetailActivity/CustomerDetailActivityViewComponent.cs
Janus C. H. Knudsen 1b25978d9b Adds comprehensive customer detail view components
Implements full customer detail page with multiple feature-rich components including overview, economy, statistics, journal, appointments, giftcards, and activity sections

Creates reusable ViewComponents for different customer detail aspects with robust data modeling and presentation logic
2026-01-25 01:55:41 +01:00

117 lines
4 KiB
C#

using Microsoft.AspNetCore.Mvc;
using PlanTempus.Application.Features.Localization.Services;
using System.Globalization;
namespace PlanTempus.Application.Features.Customers.Components;
public class CustomerDetailActivityViewComponent : ViewComponent
{
private readonly ILocalizationService _localization;
public CustomerDetailActivityViewComponent(ILocalizationService localization)
{
_localization = localization;
}
public IViewComponentResult Invoke(string customerId)
{
var customer = CustomerDetailCatalog.Get(customerId);
var culture = new CultureInfo("da-DK");
var today = DateTime.Today;
// Group activities by date
var groupedActivities = customer.Activity
.OrderByDescending(a => DateTime.Parse(a.Date))
.ThenByDescending(a => a.Time)
.GroupBy(a => a.Date)
.Select(g =>
{
var date = DateTime.Parse(g.Key);
string dateHeader;
if (date.Date == today)
{
dateHeader = "I dag";
}
else if (date.Date == today.AddDays(-1))
{
dateHeader = "I gar";
}
else
{
dateHeader = date.ToString("d. MMMM yyyy", culture);
}
return new ActivityDateGroupViewModel
{
DateHeader = dateHeader,
Items = g.Select(a => new ActivityItemViewModel
{
Time = a.Time,
Type = a.Type,
Icon = a.Icon,
Title = a.Title,
Actor = a.Actor,
Badges = a.Badges.Select(b => new ActivityBadgeViewModel
{
Text = char.ToUpper(b[0]) + b[1..],
CssClass = b.ToLowerInvariant()
}).ToList()
}).ToList()
};
})
.ToList();
var model = new CustomerDetailActivityViewModel
{
DateGroups = groupedActivities,
Filters = new List<ActivityFilterViewModel>
{
new() { Label = "Alle", Type = null, Icon = null, IsActive = true },
new() { Label = "Bookinger", Type = "booking", Icon = "calendar" },
new() { Label = "Kommunikation", Type = "communication", Icon = "envelope" },
new() { Label = "Ændringer", Type = "edit", Icon = "pencil-simple" },
new() { Label = "Betalinger", Type = "payment", Icon = "credit-card" },
new() { Label = "Advarsler", Type = "warning", Icon = "warning" },
new() { Label = "Kunde", Type = "customer", Icon = "user" }
}
};
return View(model);
}
}
public class CustomerDetailActivityViewModel
{
public List<ActivityDateGroupViewModel> DateGroups { get; init; } = new();
public List<ActivityFilterViewModel> Filters { get; init; } = new();
}
public class ActivityFilterViewModel
{
public required string Label { get; init; }
public string? Type { get; init; }
public string? Icon { get; init; }
public bool IsActive { get; init; }
}
public class ActivityDateGroupViewModel
{
public required string DateHeader { get; init; }
public List<ActivityItemViewModel> Items { get; init; } = new();
}
public class ActivityItemViewModel
{
public required string Time { get; init; }
public required string Type { get; init; }
public required string Icon { get; init; }
public required string Title { get; init; }
public string? Actor { get; init; }
public List<ActivityBadgeViewModel> Badges { get; init; } = new();
}
public class ActivityBadgeViewModel
{
public required string Text { get; init; }
public required string CssClass { get; init; }
}