Adds salary specifications with detailed accordion view

Introduces new salary specification feature with interactive accordion component

Implements detailed salary breakdown including:
- Salary specification JSON data model
- Salary specification page with printable view
- Accordion component for expanding/collapsing salary details
- Localization support for new salary labels

Enhances employee salary transparency and detail presentation
This commit is contained in:
Janus C. H. Knudsen 2026-01-23 20:03:24 +01:00
parent f3c54dde35
commit a1059adf06
14 changed files with 1613 additions and 46 deletions

View file

@ -52,7 +52,24 @@
</swp-edit-section>
</swp-card>
<!-- Tillæg -->
<!-- Provision -->
<swp-card>
<swp-card-header>
<swp-card-title>@Model.LabelCommission</swp-card-title>
</swp-card-header>
<swp-edit-section>
<swp-edit-row id="card-productcommission">
<swp-edit-label>@Model.LabelProductCommission</swp-edit-label>
<input type="text" id="value-productcommission" data-type="number" value="@Model.ProductCommission" readonly>
</swp-edit-row>
<swp-edit-row id="card-servicecommission">
<swp-edit-label>@Model.LabelServiceCommission</swp-edit-label>
<input type="text" id="value-servicecommission" data-type="number" value="@Model.ServiceCommission" readonly>
</swp-edit-row>
</swp-edit-section>
</swp-card>
<!-- Tillaeg -->
<swp-card>
<swp-card-header>
<swp-card-title>@Model.LabelSupplements</swp-card-title>
@ -72,47 +89,111 @@
</swp-edit-row>
</swp-edit-section>
</swp-card>
<!-- Provision -->
<swp-card>
<swp-card-header>
<swp-card-title>@Model.LabelCommission</swp-card-title>
</swp-card-header>
<swp-edit-section>
<swp-edit-row id="card-productcommission">
<swp-edit-label>@Model.LabelProductCommission</swp-edit-label>
<input type="text" id="value-productcommission" data-type="number" value="@Model.ProductCommission" readonly>
</swp-edit-row>
<swp-edit-row id="card-servicecommission">
<swp-edit-label>@Model.LabelServiceCommission</swp-edit-label>
<input type="text" id="value-servicecommission" data-type="number" value="@Model.ServiceCommission" readonly>
</swp-edit-row>
</swp-edit-section>
</swp-card>
</swp-card-column>
<swp-card class="salary-history">
<swp-card-header>
<swp-card-title>@Model.LabelSalaryHistory</swp-card-title>
</swp-card-header>
<swp-data-table>
<swp-data-table-header>
<swp-data-table-cell>@Model.LabelPeriod</swp-data-table-cell>
<swp-data-table-cell>@Model.LabelGrossSalary</swp-data-table-cell>
<swp-data-table-cell></swp-data-table-cell>
</swp-data-table-header>
@foreach (var item in Model.SalaryHistory)
{
<swp-data-table-row>
<swp-data-table-cell>@item.Period</swp-data-table-cell>
<swp-data-table-cell class="mono">@item.GrossSalary</swp-data-table-cell>
<swp-data-table-cell><i class="ph ph-caret-right"></i></swp-data-table-cell>
</swp-data-table-row>
}
</swp-data-table>
</swp-card>
</swp-detail-grid>
<!-- Loenspecifikationer (full width accordion) -->
<swp-card class="salary-specifications">
<swp-card-header>
<swp-card-title>@Model.LabelSpecifications</swp-card-title>
</swp-card-header>
<swp-accordion id="salary-specifications-accordion">
@foreach (var spec in Model.Specifications)
{
<swp-accordion-item data-period="@spec.PeriodKey">
<swp-accordion-header>
<swp-accordion-info>
<swp-accordion-title>@spec.Period</swp-accordion-title>
<swp-accordion-meta>@spec.Weeks.Sum(w => w.NormalHours + w.OvertimeHours)t</swp-accordion-meta>
</swp-accordion-info>
<swp-accordion-summary>
<swp-summary-item>
<swp-summary-value>@spec.GrossSalaryFormatted</swp-summary-value>
<swp-summary-label>@Model.LabelTotal</swp-summary-label>
</swp-summary-item>
<swp-accordion-toggle>
<i class="ph ph-caret-down"></i>
</swp-accordion-toggle>
</swp-accordion-summary>
</swp-accordion-header>
<swp-accordion-content>
<!-- Config row -->
<swp-config-row>
<swp-config-item>
<swp-config-label>@Model.LabelNormalRate:</swp-config-label>
<swp-config-value class="mono">@spec.Config.HourlyRateFormatted</swp-config-value>
</swp-config-item>
<swp-config-item>
<swp-config-label>@Model.LabelWeeklyNorm:</swp-config-label>
<swp-config-value>@spec.Config.WeeklyHoursFormatted</swp-config-value>
</swp-config-item>
<swp-config-item>
<swp-config-label>@Model.LabelOvertimeMultiplier:</swp-config-label>
<swp-config-value>@spec.Config.OvertimeFormatted</swp-config-value>
</swp-config-item>
<swp-config-item>
<swp-config-label>@Model.LabelMinimum:</swp-config-label>
<swp-config-value class="mono">@spec.Config.MinimumFormatted</swp-config-value>
</swp-config-item>
<swp-config-item>
<swp-config-label>@Model.LabelProvision:</swp-config-label>
<swp-config-value>@spec.Config.CommissionFormatted</swp-config-value>
</swp-config-item>
</swp-config-row>
<!-- Weeks table -->
<swp-accordion-table>
<swp-data-table class="specification-weeks">
<swp-data-table-header>
<swp-data-table-cell>@Model.LabelWeek</swp-data-table-cell>
<swp-data-table-cell>Timer</swp-data-table-cell>
<swp-data-table-cell>Overtid</swp-data-table-cell>
<swp-data-table-cell>Ferie</swp-data-table-cell>
<swp-data-table-cell>Services</swp-data-table-cell>
<swp-data-table-cell>Produkter</swp-data-table-cell>
<swp-data-table-cell>Minimum</swp-data-table-cell>
<swp-data-table-cell>Provision</swp-data-table-cell>
<swp-data-table-cell>I alt</swp-data-table-cell>
</swp-data-table-header>
@foreach (var week in spec.Weeks)
{
<swp-data-table-row>
<swp-data-table-cell>Uge @week.WeekNumber</swp-data-table-cell>
<swp-data-table-cell class="mono">@week.NormalHoursFormatted</swp-data-table-cell>
<swp-data-table-cell class="mono @(week.HasOvertime ? "warning" : "")">@week.OvertimeHoursFormatted</swp-data-table-cell>
<swp-data-table-cell class="mono">@week.VacationDaysFormatted</swp-data-table-cell>
<swp-data-table-cell class="mono">@week.ServiceRevenueFormatted</swp-data-table-cell>
<swp-data-table-cell class="mono">@week.ProductRevenueFormatted</swp-data-table-cell>
<swp-data-table-cell class="mono">@week.MinimumThresholdFormatted</swp-data-table-cell>
<swp-data-table-cell class="mono @(week.HasCommission ? "highlight" : "")">@week.CommissionFormatted</swp-data-table-cell>
<swp-data-table-cell class="mono">@week.TotalPayFormatted</swp-data-table-cell>
</swp-data-table-row>
}
<swp-data-table-footer>
<swp-data-table-cell>TOTAL</swp-data-table-cell>
<swp-data-table-cell class="mono">@(spec.Weeks.Sum(w => w.NormalHours))t</swp-data-table-cell>
<swp-data-table-cell class="mono">@(spec.Weeks.Sum(w => w.OvertimeHours))t</swp-data-table-cell>
<swp-data-table-cell class="mono">@(spec.Weeks.Sum(w => w.VacationDays)) dg</swp-data-table-cell>
<swp-data-table-cell class="mono">@(spec.Weeks.Sum(w => w.ServiceRevenue).ToString("N0", System.Globalization.CultureInfo.GetCultureInfo("da-DK"))) kr</swp-data-table-cell>
<swp-data-table-cell class="mono">@(spec.Weeks.Sum(w => w.ProductRevenue).ToString("N0", System.Globalization.CultureInfo.GetCultureInfo("da-DK"))) kr</swp-data-table-cell>
<swp-data-table-cell class="mono">-</swp-data-table-cell>
<swp-data-table-cell class="mono">@(spec.Weeks.Sum(w => w.Commission).ToString("N2", System.Globalization.CultureInfo.GetCultureInfo("da-DK"))) kr</swp-data-table-cell>
<swp-data-table-cell class="mono">@(spec.Weeks.Sum(w => w.TotalPay).ToString("N2", System.Globalization.CultureInfo.GetCultureInfo("da-DK"))) kr</swp-data-table-cell>
</swp-data-table-footer>
</swp-data-table>
</swp-accordion-table>
<swp-accordion-footer>
<a href="/medarbejdere/loenspecifikation/@spec.PeriodKey" target="_blank" class="swp-btn secondary">
<i class="ph ph-file-text"></i>
Se lønberegning
</a>
</swp-accordion-footer>
</swp-accordion-content>
</swp-accordion-item>
}
</swp-accordion>
</swp-card>
<!-- Rates drawer -->
<div id="rates-drawer" data-drawer="lg">
<swp-drawer-header>
@ -177,7 +258,7 @@
</swp-data-row>
</swp-data-table>
<!-- Tillæg -->
<!-- Tillaeg -->
<swp-data-section>
<swp-section-label>@Model.LabelSupplements</swp-section-label>
<swp-data-table>