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
117 lines
4 KiB
C#
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; }
|
|
}
|