146 lines
5.7 KiB
C#
146 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; }
|
||
|
|
}
|