PlanTempusApp/PlanTempus.Application/Features/Customers/Components/CustomerDetailEconomy/CustomerDetailEconomyViewComponent.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

145 lines
5.7 KiB
C#

using Microsoft.AspNetCore.Mvc;
using PlanTempus.Application.Features.Localization.Services;
namespace PlanTempus.Application.Features.Customers.Components;
public class CustomerDetailEconomyViewComponent : ViewComponent
{
private readonly ILocalizationService _localization;
public CustomerDetailEconomyViewComponent(ILocalizationService localization)
{
_localization = localization;
}
public IViewComponentResult Invoke(string customerId)
{
var customer = CustomerDetailCatalog.Get(customerId);
var economy = customer.Economy;
var model = new CustomerDetailEconomyViewModel
{
HasData = economy != null,
// Stat cards
CurrentYearValue = economy != null ? $"{economy.CurrentYear.Total:N0} kr".Replace(",", ".") : "-",
CurrentYearLabel = string.Format(_localization.Get("customers.detail.economy.thisYear"), economy?.CurrentYear.Year ?? DateTime.Now.Year),
LastYearValue = economy != null ? $"{economy.LastYear.Total:N0} kr".Replace(",", ".") : "-",
LastYearLabel = _localization.Get("customers.detail.economy.lastYear"),
AvgPerVisitValue = economy != null ? $"{economy.AvgPerVisit:N0} kr".Replace(",", ".") : "-",
AvgPerVisitLabel = _localization.Get("customers.detail.economy.avgPerVisit"),
AvgPerMonthValue = economy != null ? $"{economy.AvgPerMonth:N0} kr".Replace(",", ".") : "-",
AvgPerMonthLabel = _localization.Get("customers.detail.economy.avgPerMonth"),
// Chart card
RevenueOverTimeTitle = _localization.Get("customers.detail.economy.revenueOverTime"),
ServicesLabel = _localization.Get("customers.detail.economy.services"),
ProductsLabel = _localization.Get("customers.detail.economy.products"),
ChartData = economy?.ChartData != null ? new CustomerChartDataViewModel
{
Categories = economy.ChartData.Categories,
Series = economy.ChartData.Series.Select(s => new CustomerChartSeriesViewModel
{
Name = s.Name,
Color = s.Color,
Data = s.Data.Select(d => new CustomerChartDataPointViewModel
{
X = d.X,
Y = d.Y
}).ToList()
}).ToList()
} : null,
// Purchase history
PurchaseHistoryTitle = _localization.Get("customers.detail.economy.purchaseHistory"),
Purchases = economy?.Purchases.Take(5).Select(p => new CustomerPurchaseViewModel
{
Invoice = p.Invoice,
Date = FormatDate(p.Date),
Time = p.Time,
Employee = p.Employee,
Services = p.Services,
Type = p.Type,
TypeLabel = p.Type == "service"
? _localization.Get("customers.detail.economy.services")
: _localization.Get("customers.detail.economy.products"),
Amount = $"{p.Amount:N0} kr".Replace(",", ".")
}).ToList() ?? new List<CustomerPurchaseViewModel>(),
SeeAllText = _localization.Get("customers.detail.economy.seeAll"),
// Empty state
EmptyStateText = _localization.Get("customers.detail.economy.noData")
};
return View(model);
}
private static string FormatDate(string dateStr)
{
if (DateTime.TryParse(dateStr, out var date))
{
return date.ToString("d. MMM yyyy", new System.Globalization.CultureInfo("da-DK"));
}
return dateStr;
}
}
public class CustomerDetailEconomyViewModel
{
public bool HasData { get; init; }
// Stat cards
public required string CurrentYearValue { get; init; }
public required string CurrentYearLabel { get; init; }
public required string LastYearValue { get; init; }
public required string LastYearLabel { get; init; }
public required string AvgPerVisitValue { get; init; }
public required string AvgPerVisitLabel { get; init; }
public required string AvgPerMonthValue { get; init; }
public required string AvgPerMonthLabel { get; init; }
// Chart card
public required string RevenueOverTimeTitle { get; init; }
public required string ServicesLabel { get; init; }
public required string ProductsLabel { get; init; }
public CustomerChartDataViewModel? ChartData { get; init; }
// Purchase history
public required string PurchaseHistoryTitle { get; init; }
public List<CustomerPurchaseViewModel> Purchases { get; init; } = new();
public required string SeeAllText { get; init; }
// Empty state
public required string EmptyStateText { get; init; }
}
public class CustomerPurchaseViewModel
{
public required string Invoice { get; init; }
public required string Date { get; init; }
public required string Time { get; init; }
public required string Employee { get; init; }
public required string Services { get; init; }
public required string Type { get; init; }
public required string TypeLabel { get; init; }
public required string Amount { get; init; }
}
public class CustomerChartDataViewModel
{
public List<string> Categories { get; init; } = new();
public List<CustomerChartSeriesViewModel> Series { get; init; } = new();
}
public class CustomerChartSeriesViewModel
{
public required string Name { get; init; }
public required string Color { get; init; }
public List<CustomerChartDataPointViewModel> Data { get; init; } = new();
}
public class CustomerChartDataPointViewModel
{
public required string X { get; init; }
public decimal Y { get; init; }
}