{"version":3,"sources":["lib/models.ts","lib/HolidayCalculator.ts","lib/Calculator.ts","lib/DayKindFormatter.ts","components/ResultInfo.tsx","components/App.tsx","index.tsx"],"names":["DayKind","HolidayCalculator","extraHolidays","date","holiday","this","calculateHolidays","getFullYear","find","d","isSameDay","kind","isWeekend","Weekend","Weekday","year","easter","calculateEaster","holidays","NewYearsDay","Date","MaundyThursday","addDays","GoodFriday","EasterSunday","EasterMonday","GreatPrayerDay","AscensionDay","PentecostSunday","PentecostMonday","ChristmasDay","SecondChristmasDay","includes","MayFirst","push","ConstitutionDay","ChristmasEve","NewYearsEve","a","b","Math","floor","c","e","f","h","l","m","month","Calculator","holidayCalculator","end","numberOfDays","getBusinessDays","start","base","direction","days","currentDate","numberOfDaysReached","day","getDayDefinition","resultingDate","inputDate","DayKindFormatter","kindFormatter","ResultInfo","result","listItems","map","isHoliday","className","toLocaleDateString","format","toISOString","formatter","optionalExtraHolidays","App","useState","startOfToday","setInputDate","setNumberOfDays","mode","setMode","setExtraHolidays","calculationResult","setCalculationResult","onSubmit","preventDefault","numberOfDaysAsNumber","parseInt","isNaN","calculator","getBusinessDaysAfter","getBusinessDaysBefore","calculate","htmlFor","type","id","required","value","onChange","target","min","name","checked","filter","x","toggleExtraHoliday","ReactDOM","render","StrictMode","document","getElementById"],"mappings":"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","file":"static/js/main.9fc06d69.chunk.js","sourcesContent":["export enum DayKind {\n Weekday,\n Weekend,\n NewYearsDay,\n MaundyThursday,\n GoodFriday,\n EasterSunday,\n EasterMonday,\n MayFirst,\n GreatPrayerDay,\n AscensionDay,\n PentecostSunday,\n PentecostMonday,\n ConstitutionDay,\n ChristmasEve,\n ChristmasDay,\n SecondChristmasDay,\n NewYearsEve,\n}\n\nexport interface DayDefinition {\n date: Date;\n kind: DayKind;\n}\n\nexport interface CalculationResult {\n resultingDate: Date;\n days: DayDefinition[];\n inputDate: Date;\n direction: \"before\" | \"after\";\n numberOfDays: number;\n}\n","import { addDays, isSameDay, isWeekend } from \"date-fns\";\nimport { DayDefinition, DayKind } from \"./models\";\n\nexport class HolidayCalculator {\n constructor(private readonly extraHolidays: DayKind[] = []) {}\n\n getDayDefinition(date: Date): DayDefinition {\n const holidays = this.calculateHolidays(date.getFullYear());\n const holiday = holidays.find((d) => isSameDay(d.date, date));\n\n if (holiday) {\n return holiday;\n }\n\n return {\n date,\n kind: isWeekend(date) ? DayKind.Weekend : DayKind.Weekday,\n };\n }\n\n calculateHolidays(year: number): DayDefinition[] {\n const easter = this.calculateEaster(year);\n const holidays = [\n {\n kind: DayKind.NewYearsDay,\n date: new Date(year, 0, 1),\n },\n {\n kind: DayKind.MaundyThursday,\n date: addDays(easter, -3),\n },\n {\n kind: DayKind.GoodFriday,\n date: addDays(easter, -2),\n },\n {\n kind: DayKind.EasterSunday,\n date: easter,\n },\n {\n kind: DayKind.EasterMonday,\n date: addDays(easter, 1),\n },\n {\n kind: DayKind.GreatPrayerDay,\n date: addDays(easter, 4 * 7 - 2),\n },\n {\n kind: DayKind.AscensionDay,\n date: addDays(easter, 6 * 7 - 3),\n },\n {\n kind: DayKind.PentecostSunday,\n date: addDays(easter, 7 * 7),\n },\n {\n kind: DayKind.PentecostMonday,\n date: addDays(easter, 7 * 7 + 1),\n },\n {\n kind: DayKind.ChristmasDay,\n date: new Date(year, 11, 25),\n },\n {\n kind: DayKind.SecondChristmasDay,\n date: new Date(year, 11, 26),\n },\n ];\n\n if (this.extraHolidays.includes(DayKind.MayFirst)) {\n holidays.push({\n kind: DayKind.MayFirst,\n date: new Date(year, 4, 1),\n });\n }\n if (this.extraHolidays.includes(DayKind.ConstitutionDay)) {\n holidays.push({\n kind: DayKind.ConstitutionDay,\n date: new Date(year, 5, 5),\n });\n }\n if (this.extraHolidays.includes(DayKind.ChristmasEve)) {\n holidays.push({\n kind: DayKind.ChristmasEve,\n date: new Date(year, 11, 24),\n });\n }\n if (this.extraHolidays.includes(DayKind.NewYearsEve)) {\n holidays.push({\n kind: DayKind.NewYearsEve,\n date: new Date(year, 11, 31),\n });\n }\n\n return holidays;\n }\n\n private calculateEaster(year: number): Date {\n const a = year % 19;\n const b = Math.floor(year / 100);\n const c = year % 100;\n const d = Math.floor(b / 4);\n const e = b % 4;\n const f = Math.floor((b + 8) / 25);\n const g = Math.floor((b - f + 1) / 3);\n const h = (19 * a + b - d - g + 15) % 30;\n const i = Math.floor(c / 4);\n const k = c % 4;\n const l = (32 + 2 * e + 2 * i - h - k) % 7;\n const m = Math.floor((a + 11 * h + 22 * l) / 451);\n const month = Math.floor((h + l - 7 * m + 114) / 31);\n const dayOfMonth = ((h + l - 7 * m + 114) % 31) + 1;\n return new Date(year, month - 1, dayOfMonth);\n }\n}\n","import { addDays } from \"date-fns\";\nimport { HolidayCalculator } from \"./HolidayCalculator\";\nimport { CalculationResult, DayDefinition, DayKind } from \"./models\";\n\nexport class Calculator {\n private readonly holidayCalculator: HolidayCalculator;\n\n constructor(extraHolidays: DayKind[] = []) {\n this.holidayCalculator = new HolidayCalculator(extraHolidays);\n }\n\n getBusinessDaysBefore(end: Date, numberOfDays: number) {\n return this.getBusinessDays(end, numberOfDays, -1);\n }\n\n getBusinessDaysAfter(start: Date, numberOfDays: number) {\n return this.getBusinessDays(start, numberOfDays, 1);\n }\n\n private getBusinessDays(\n base: Date,\n numberOfDays: number,\n direction: -1 | 1\n ): CalculationResult {\n const days: DayDefinition[] = [];\n let currentDate = base;\n let numberOfDaysReached = 0;\n\n while (true) {\n const day = this.holidayCalculator.getDayDefinition(currentDate);\n days.push(day);\n\n if (day.kind === DayKind.Weekday) {\n numberOfDaysReached++;\n }\n\n if (numberOfDaysReached === numberOfDays) {\n break;\n }\n\n currentDate = addDays(currentDate, direction);\n }\n\n return {\n days,\n resultingDate: currentDate,\n numberOfDays,\n direction: direction === -1 ? \"before\" : \"after\",\n inputDate: base,\n };\n }\n}\n","import { DayKind } from \"./models\";\n\nexport class DayKindFormatter {\n format(kind: DayKind): string {\n switch (kind) {\n case DayKind.Weekday:\n return \"Hverdag\";\n case DayKind.Weekend:\n return \"Weekend\";\n case DayKind.AscensionDay:\n return \"Kristi himmelfartsdag\";\n case DayKind.GreatPrayerDay:\n return \"Store bededag\";\n case DayKind.ChristmasDay:\n return \"1. juledag\";\n case DayKind.SecondChristmasDay:\n return \"2. juledag\";\n case DayKind.ChristmasEve:\n return \"Juleaftensdag\";\n case DayKind.ConstitutionDay:\n return \"Grundlovsdag\";\n case DayKind.EasterSunday:\n return \"Påskedag\";\n case DayKind.EasterMonday:\n return \"2. påskedag\";\n case DayKind.MaundyThursday:\n return \"Skærtorsdag\";\n case DayKind.GoodFriday:\n return \"Langfredag\";\n case DayKind.MayFirst:\n return \"1. maj\";\n case DayKind.NewYearsDay:\n return \"Nytårsdag\";\n case DayKind.NewYearsEve:\n return \"Nytårsaftensdag\";\n case DayKind.PentecostSunday:\n return \"Pinsedag\";\n case DayKind.PentecostMonday:\n return \"2. pinsedag\";\n default:\n return \"Ukendt\";\n }\n }\n}\n","import { isSameDay } from \"date-fns\";\nimport { DayKindFormatter } from \"../lib/DayKindFormatter\";\nimport { CalculationResult, DayKind } from \"../lib/models\";\n\nconst kindFormatter = new DayKindFormatter();\n\ninterface Props {\n result: CalculationResult;\n}\n\nfunction ResultInfo({ result }: Props) {\n const listItems = result.days.map((day) => {\n const isHoliday =\n day.kind !== DayKind.Weekday && day.kind !== DayKind.Weekend;\n\n let className = \"\";\n if (isSameDay(day.date, result.resultingDate)) {\n className = \"fw-bold\";\n } else if (day.kind !== DayKind.Weekday) {\n className = \"text-danger\";\n }\n\n return (\n
\n {result.numberOfDays} hverdage{\" \"}\n {result.direction === \"before\" ? \"før\" : \"efter\"}{\" \"}\n {result.inputDate.toLocaleDateString()} er{\" \"}\n \n {result.resultingDate.toLocaleDateString()}\n \n
\n