2026-01-16 22:03:22 +01:00
namespace PlanTempus.Application.Features.Services.Components ;
/// <summary>
/// Shared catalog for service detail data.
/// Used by all ServiceDetail* ViewComponents.
/// </summary>
public static class ServiceDetailCatalog
{
private static readonly Dictionary < string , ServiceDetailRecord > Services = new ( )
{
["service-1"] = new ServiceDetailRecord
{
Key = "service-1" ,
Name = "Klip & Farve" ,
Category = "Kombi-behandlinger" ,
CalendarColor = "deep-orange" ,
IsActive = true ,
DurationRange = "60-120" ,
FromPrice = "795 kr" ,
EmployeeCount = "4" ,
BookingsThisYear = "156" ,
Tags = new ( ) { new ( "Populær" , "popular" ) , new ( "Kombi" , "combo" ) , new ( "Farve" , "color" ) } ,
InternalNotes = "Komplet farvebehandling med klip. Husk konsultation ved første besøg. Anbefal Olaplex til kemisk behandlet hår." ,
CanBookAsMain = true ,
CanBookAsAddon = false ,
ShowInOnlineBooking = true ,
IsFeatured = false ,
2026-01-17 01:21:00 +01:00
Description = "Forkæl dig selv med en komplet forvandling! Vores Klip & Farve behandling inkluderer professionel farverådgivning, farvning tilpasset din hudtone, præcisionsklip og styling. Perfekt til dig der ønsker et helt nyt look." ,
// Priser
PriceMode = PriceMode . Matrix ,
PriceMatrix = new ( )
{
new ( "Junior" , "795" , "895" , "995" , "1.095" ) ,
new ( "Senior" , "895" , "995" , "1.095" , "1.195" ) ,
new ( "Master" , "995" , "1.095" , "1.195" , "1.295" )
} ,
VatRate = "25" ,
ProductCost = "85 kr" ,
Commission = "standard" ,
MemberDiscount = true ,
GiftCardPayment = true ,
LoyaltyPoints = true ,
// Varighed
DurationVariants = new ( )
{
new ( "Kort hår" , 60 ) ,
new ( "Mellem hår" , 90 ) ,
new ( "Langt hår" , 120 ) ,
new ( "Ekstra langt hår" , 150 )
} ,
BufferBefore = "15" ,
BufferAfter = "10" ,
CleanupTime = "5" ,
// Regler
MinNotice = "24" ,
MaxAdvanceBooking = "3" ,
CancellationDeadline = "24" ,
NoShowFee = "50" ,
RequiresConsultation = false ,
RequiresPatchTest = true ,
AgeRestriction = false ,
ShowInOnlineBookingRules = true ,
AllowEmployeeSelection = true ,
ShowPrice = true ,
2026-01-17 15:36:15 +01:00
ShowDuration = true ,
// Medarbejdere
Employees = new ( )
{
new ( "emp-1" , "Anna Sørensen" , "AS" , "Master Stylist" , "master" , true , "Standard" ) ,
new ( "emp-2" , "Mette Jensen" , "MJ" , "Senior Stylist" , "senior" , true , "+15 min" ) ,
new ( "emp-3" , "Louise Nielsen" , "LN" , "Senior Stylist" , "senior" , true , "Standard" ) ,
new ( "emp-4" , "Katrine Pedersen" , "KP" , "Stylist" , "junior" , true , "+15 min" ) ,
new ( "emp-5" , "Sofie Andersen" , "SA" , "Junior Stylist" , "junior" , false , "—" , "Ikke certificeret" )
} ,
Availability = new ( )
{
new ( "Mandag" , true , "08:00" , "18:00" ) ,
new ( "Tirsdag" , true , "08:00" , "18:00" ) ,
new ( "Onsdag" , true , "08:00" , "18:00" ) ,
new ( "Torsdag" , true , "08:00" , "12:00" ) ,
new ( "Fredag" , true , "08:00" , "18:00" ) ,
new ( "Lørdag" , false , "08:00" , "18:00" ) ,
new ( "Søndag" , false , "08:00" , "18:00" )
} ,
// Tilvalg
Addons = new ( )
{
new ( "addon-1" , "Olaplex Behandling" , "+250 kr" , "+15 min" , "Valgfri" , true ) ,
new ( "addon-2" , "Kerastase Hårkur" , "+195 kr" , "+10 min" , "Valgfri" , true ) ,
new ( "addon-3" , "Styling / Curls" , "+150 kr" , "+20 min" , "Valgfri" , true ) ,
new ( "addon-4" , "Hovedbundsmassage" , "+75 kr" , "+5 min" , "Valgfri" , true ) ,
new ( "addon-5" , "Patch Test" , "Gratis" , "48t før" , "Påkrævet (nye)" , false , true )
}
2026-01-16 22:03:22 +01:00
} ,
["service-2"] = new ServiceDetailRecord
{
Key = "service-2" ,
Name = "Herreklip" ,
Category = "Klip" ,
CalendarColor = "blue" ,
IsActive = true ,
DurationRange = "30" ,
FromPrice = "295 kr" ,
EmployeeCount = "6" ,
BookingsThisYear = "312" ,
Tags = new ( ) { new ( "Populær" , "popular" ) } ,
InternalNotes = "Standard herreklip. Inkluderer vask og styling." ,
CanBookAsMain = true ,
CanBookAsAddon = false ,
ShowInOnlineBooking = true ,
IsFeatured = true ,
Description = "Klassisk herreklip med vask, klip og styling. Vores erfarne stylister sikrer dig et skarpt og velplejet look."
} ,
["service-3"] = new ServiceDetailRecord
{
Key = "service-3" ,
Name = "Dameklip" ,
Category = "Klip" ,
CalendarColor = "teal" ,
IsActive = true ,
DurationRange = "45-60" ,
FromPrice = "395 kr" ,
EmployeeCount = "5" ,
BookingsThisYear = "248" ,
Tags = new ( ) { new ( "Populær" , "popular" ) } ,
InternalNotes = "Standard dameklip. Altid konsultation først." ,
CanBookAsMain = true ,
CanBookAsAddon = false ,
ShowInOnlineBooking = true ,
IsFeatured = true ,
Description = "Professionel dameklip tilpasset din ansigtsform og ønsker. Inkluderer vask, klip og føn."
} ,
["service-4"] = new ServiceDetailRecord
{
Key = "service-4" ,
Name = "Balayage" ,
Category = "Farve" ,
CalendarColor = "purple" ,
IsActive = true ,
DurationRange = "120-180" ,
FromPrice = "1.295 kr" ,
EmployeeCount = "3" ,
BookingsThisYear = "89" ,
Tags = new ( ) { new ( "Farve" , "color" ) , new ( "Premium" , "popular" ) } ,
InternalNotes = "Avanceret farveteknik. Kun certificerede stylister. Kræver tid til konsultation." ,
CanBookAsMain = true ,
CanBookAsAddon = false ,
ShowInOnlineBooking = true ,
IsFeatured = false ,
Description = "Smuk, naturlig farveeffekt med håndmalede highlights. Perfekt til dig der ønsker et solkysset look med lavt vedligehold."
} ,
["service-5"] = new ServiceDetailRecord
{
Key = "service-5" ,
Name = "Olaplex Behandling" ,
Category = "Behandlinger" ,
CalendarColor = "green" ,
IsActive = true ,
DurationRange = "30" ,
FromPrice = "295 kr" ,
EmployeeCount = "6" ,
BookingsThisYear = "134" ,
Tags = new ( ) { new ( "Tilvalg" , "combo" ) } ,
InternalNotes = "Kan tilføjes til alle farvebehandlinger. Anbefales ved kemisk behandlet hår." ,
CanBookAsMain = false ,
CanBookAsAddon = true ,
ShowInOnlineBooking = true ,
IsFeatured = false ,
Description = "Intensiv hårbehandling der reparerer og styrker håret. Ideel som tilvalg til farvebehandlinger."
} ,
["service-6"] = new ServiceDetailRecord
{
Key = "service-6" ,
Name = "Bryllupsfrisure" ,
Category = "Styling" ,
CalendarColor = "amber" ,
IsActive = false ,
DurationRange = "90-120" ,
FromPrice = "895 kr" ,
EmployeeCount = "2" ,
BookingsThisYear = "24" ,
Tags = new ( ) { new ( "Premium" , "popular" ) , new ( "Sæson" , "combo" ) } ,
InternalNotes = "Kun Maria og Anna kan bookes til dette. Kræver prøve-session 2 uger før." ,
CanBookAsMain = true ,
CanBookAsAddon = false ,
ShowInOnlineBooking = false ,
IsFeatured = false ,
Description = "Eksklusiv bryllupsfrisure med forudgående konsultation og prøvesession. Vi skaber din drømmefrisure til den store dag."
}
} ;
public static ServiceDetailRecord Get ( string key )
{
if ( ! Services . TryGetValue ( key , out var service ) )
throw new KeyNotFoundException ( $"Service with key '{key}' not found" ) ;
return service ;
}
public static IEnumerable < string > AllKeys = > Services . Keys ;
}
/// <summary>
/// Complete service detail record used across all detail ViewComponents.
/// </summary>
public record ServiceDetailRecord
{
// Identity
public required string Key { get ; init ; }
public required string Name { get ; init ; }
public required string Category { get ; init ; }
public required string CalendarColor { get ; init ; }
public required bool IsActive { get ; init ; }
// Stats (header)
public required string DurationRange { get ; init ; }
public required string FromPrice { get ; init ; }
public required string EmployeeCount { get ; init ; }
public required string BookingsThisYear { get ; init ; }
// Tags
public List < ServiceTag > Tags { get ; init ; } = new ( ) ;
// Generelt tab - Grundlæggende
public required string InternalNotes { get ; init ; }
// Generelt tab - Bookingtype
public required bool CanBookAsMain { get ; init ; }
public required bool CanBookAsAddon { get ; init ; }
// Generelt tab - Online booking
public required bool ShowInOnlineBooking { get ; init ; }
public required bool IsFeatured { get ; init ; }
public required string Description { get ; init ; }
2026-01-17 01:21:00 +01:00
// Priser tab
public PriceMode PriceMode { get ; init ; } = PriceMode . Simple ;
public string SimplePrice { get ; init ; } = "995 kr" ;
public List < PriceMatrixRow > PriceMatrix { get ; init ; } = new ( ) ;
public string VatRate { get ; init ; } = "25" ;
public string ProductCost { get ; init ; } = "85 kr" ;
public string Commission { get ; init ; } = "standard" ;
public bool MemberDiscount { get ; init ; } = true ;
public bool GiftCardPayment { get ; init ; } = true ;
public bool LoyaltyPoints { get ; init ; } = true ;
// Varighed tab
public List < DurationVariant > DurationVariants { get ; init ; } = new ( ) ;
public string BufferBefore { get ; init ; } = "15" ;
public string BufferAfter { get ; init ; } = "10" ;
public string CleanupTime { get ; init ; } = "5" ;
// Regler tab
public string MinNotice { get ; init ; } = "24" ;
public string MaxAdvanceBooking { get ; init ; } = "3" ;
public string CancellationDeadline { get ; init ; } = "24" ;
public string NoShowFee { get ; init ; } = "50" ;
public bool RequiresConsultation { get ; init ; } = false ;
public bool RequiresPatchTest { get ; init ; } = false ;
public bool AgeRestriction { get ; init ; } = false ;
public bool ShowInOnlineBookingRules { get ; init ; } = true ;
public bool AllowEmployeeSelection { get ; init ; } = true ;
public bool ShowPrice { get ; init ; } = true ;
public bool ShowDuration { get ; init ; } = true ;
2026-01-17 15:36:15 +01:00
// Medarbejdere tab
public List < ServiceEmployee > Employees { get ; init ; } = new ( ) ;
public List < ServiceAvailability > Availability { get ; init ; } = new ( ) ;
// Tilvalg tab
public List < ServiceAddon > Addons { get ; init ; } = new ( ) ;
2026-01-16 22:03:22 +01:00
}
2026-01-17 01:21:00 +01:00
public enum PriceMode { Simple , Matrix }
public record PriceMatrixRow ( string Level , string ShortHair , string MediumHair , string LongHair , string ExtraLongHair ) ;
public record DurationVariant ( string Name , int Minutes ) ;
2026-01-16 22:03:22 +01:00
public record ServiceTag ( string Text , string CssClass ) ;
2026-01-17 15:36:15 +01:00
public record ServiceEmployee (
string Id ,
string Name ,
string Initials ,
string Level ,
string LevelCssClass ,
bool Selected ,
string OverrideValue ,
string? Warning = null ) ;
public record ServiceAddon (
string Id ,
string Name ,
string Price ,
string Duration ,
string Type ,
bool Selected ,
bool Required = false ) ;
public record ServiceAvailability (
string Day ,
bool Enabled ,
string StartTime ,
string EndTime ) ;