Refactors UI components with new card header structure

Replaces `swp-section-label` with standardized `swp-card-header` and `swp-card-title`

Improves component consistency across multiple features:
- Adds structured card headers
- Introduces more semantic HTML elements
- Enhances layout and readability of card components

Updates CSS and component styles to support new structure
This commit is contained in:
Janus C. H. Knudsen 2026-01-19 14:23:41 +01:00
parent 33c338345e
commit c1d2df9327
31 changed files with 250 additions and 149 deletions

View file

@ -1,5 +1,7 @@
<swp-card class="invoice-history"> <swp-card class="invoice-history">
<swp-section-label localize="account.invoices.title">Faktura-historik</swp-section-label> <swp-card-header>
<swp-card-title localize="account.invoices.title">Faktura-historik</swp-card-title>
</swp-card-header>
<swp-data-table> <swp-data-table>
<swp-data-table-header> <swp-data-table-header>
<swp-data-table-cell localize="account.invoices.date">Dato</swp-data-table-cell> <swp-data-table-cell localize="account.invoices.date">Dato</swp-data-table-cell>

View file

@ -1,5 +1,7 @@
<swp-card> <swp-card>
<swp-section-label localize="cash.approval.title">Afslut dagen</swp-section-label> <swp-card-header>
<swp-card-title localize="cash.approval.title">Afslut dagen</swp-card-title>
</swp-card-header>
<swp-card-content> <swp-card-content>
<swp-approval-grid> <swp-approval-grid>
<swp-form-field> <swp-form-field>

View file

@ -1,5 +1,7 @@
<swp-card> <swp-card>
<swp-section-label localize="cash.balance.title">Kontanter i kassen</swp-section-label> <swp-card-header>
<swp-card-title localize="cash.balance.title">Kontanter i kassen</swp-card-title>
</swp-card-header>
<swp-card-content> <swp-card-content>
<swp-calc-row> <swp-calc-row>
<swp-calc-label> <swp-calc-label>

View file

@ -1,5 +1,7 @@
<swp-card> <swp-card>
<swp-section-label localize="cash.period.title">Periodeoplysninger</swp-section-label> <swp-card-header>
<swp-card-title localize="cash.period.title">Periodeoplysninger</swp-card-title>
</swp-card-header>
<swp-card-content> <swp-card-content>
<swp-period-display> <swp-period-display>
<swp-period-label localize="cash.period.dateRange">Periode</swp-period-label> <swp-period-label localize="cash.period.dateRange">Periode</swp-period-label>

View file

@ -1,5 +1,7 @@
<swp-card> <swp-card>
<swp-section-label localize="cash.revenue.title">Periodens omsætning</swp-section-label> <swp-card-header>
<swp-card-title localize="cash.revenue.title">Periodens omsætning</swp-card-title>
</swp-card-header>
<swp-card-content> <swp-card-content>
<swp-data-table> <swp-data-table>
<swp-data-header> <swp-data-header>

View file

@ -1,5 +1,7 @@
<swp-card> <swp-card>
<swp-section-label localize="cash.note.title">Note til afstemning</swp-section-label> <swp-card-header>
<swp-card-title localize="cash.note.title">Note til afstemning</swp-card-title>
</swp-card-header>
<swp-card-content> <swp-card-content>
<swp-note-field> <swp-note-field>
<textarea placeholder="Beskriv evt. årsag til difference..."></textarea> <textarea placeholder="Beskriv evt. årsag til difference..."></textarea>

View file

@ -1,5 +1,5 @@
<!-- Action Bar --> <!-- Action Bar -->
<swp-action-bar> <swp-action-bar class="grid-top">
<swp-selection-info> <swp-selection-info>
<span id="selectionCount" localize="cash.table.noneSelected">0 valgt</span> <span id="selectionCount" localize="cash.table.noneSelected">0 valgt</span>
</swp-selection-info> </swp-selection-info>

View file

@ -74,19 +74,19 @@
<!-- Tab Content: Kasseafstemning --> <!-- Tab Content: Kasseafstemning -->
<swp-tab-content data-tab="afstemning"> <swp-tab-content data-tab="afstemning">
<swp-page-container> <swp-page-container>
<swp-cash-grid> <swp-two-column-grid>
<swp-cash-column> <swp-card-column>
@await Component.InvokeAsync("PeriodRevenue") @await Component.InvokeAsync("PeriodRevenue")
@await Component.InvokeAsync("CashBalance") @await Component.InvokeAsync("CashBalance")
@await Component.InvokeAsync("CashDifference") @await Component.InvokeAsync("CashDifference")
</swp-cash-column> </swp-card-column>
<swp-cash-column> <swp-card-column>
@await Component.InvokeAsync("PeriodInfo") @await Component.InvokeAsync("PeriodInfo")
@await Component.InvokeAsync("ReconciliationNote") @await Component.InvokeAsync("ReconciliationNote")
@await Component.InvokeAsync("CashApproval") @await Component.InvokeAsync("CashApproval")
</swp-cash-column> </swp-card-column>
</swp-cash-grid> </swp-two-column-grid>
<swp-system-note localize="cash.systemNote">Systemet gemmer hvornår og af hvem der er godkendt enkelt kontrolspor.</swp-system-note> <swp-system-note localize="cash.systemNote">Systemet gemmer hvornår og af hvem der er godkendt enkelt kontrolspor.</swp-system-note>
</swp-page-container> </swp-page-container>

View file

@ -1,7 +1,9 @@
@model PlanTempus.Application.Features.Dashboard.Components.AttentionListViewModel @model PlanTempus.Application.Features.Dashboard.Components.AttentionListViewModel
<swp-card data-key="@Model.Key"> <swp-card data-key="@Model.Key">
<swp-section-label>@Model.Title</swp-section-label> <swp-card-header>
<swp-card-title>@Model.Title</swp-card-title>
</swp-card-header>
<swp-card-content> <swp-card-content>
<swp-attention-list> <swp-attention-list>
@foreach (var attentionKey in Model.AttentionKeys) @foreach (var attentionKey in Model.AttentionKeys)

View file

@ -1,10 +1,10 @@
@model PlanTempus.Application.Features.Dashboard.Components.BookingListViewModel @model PlanTempus.Application.Features.Dashboard.Components.BookingListViewModel
<swp-card data-key="@Model.Key"> <swp-card data-key="@Model.Key">
<swp-section-header> <swp-card-header>
<swp-section-label>@Model.Title</swp-section-label> <swp-card-title>@Model.Title</swp-card-title>
<swp-section-action localize="dashboard.bookings.viewAll">Se alle</swp-section-action> <swp-section-action localize="dashboard.bookings.viewAll">Se alle</swp-section-action>
</swp-section-header> </swp-card-header>
<swp-current-time> <swp-current-time>
<i class="ph ph-clock"></i> <i class="ph ph-clock"></i>
<span><span localize="dashboard.bookings.currentTime">Nu:</span> <swp-time>@Model.CurrentTime</swp-time></span> <span><span localize="dashboard.bookings.currentTime">Nu:</span> <swp-time>@Model.CurrentTime</swp-time></span>

View file

@ -1,10 +1,10 @@
@model PlanTempus.Application.Features.Dashboard.Components.NotificationListViewModel @model PlanTempus.Application.Features.Dashboard.Components.NotificationListViewModel
<swp-card data-key="@Model.Key"> <swp-card data-key="@Model.Key">
<swp-section-header> <swp-card-header>
<swp-section-label>@Model.Title</swp-section-label> <swp-card-title>@Model.Title</swp-card-title>
<swp-section-action>@Model.ActionText</swp-section-action> <swp-section-action>@Model.ActionText</swp-section-action>
</swp-section-header> </swp-card-header>
<swp-card-content> <swp-card-content>
<swp-notification-list> <swp-notification-list>
@foreach (var notificationKey in Model.NotificationKeys) @foreach (var notificationKey in Model.NotificationKeys)

View file

@ -1,7 +1,9 @@
@model PlanTempus.Application.Features.Dashboard.Components.QuickStatListViewModel @model PlanTempus.Application.Features.Dashboard.Components.QuickStatListViewModel
<swp-card data-key="@Model.Key"> <swp-card data-key="@Model.Key">
<swp-section-label>@Model.Title</swp-section-label> <swp-card-header>
<swp-card-title>@Model.Title</swp-card-title>
</swp-card-header>
<swp-card-content> <swp-card-content>
<swp-quick-stats> <swp-quick-stats>
@foreach (var statKey in Model.StatKeys) @foreach (var statKey in Model.StatKeys)

View file

@ -50,7 +50,9 @@
<!-- Quick Actions --> <!-- Quick Actions -->
<swp-card> <swp-card>
<swp-section-label localize="dashboard.quickActions.title">Hurtige handlinger</swp-section-label> <swp-card-header>
<swp-card-title localize="dashboard.quickActions.title">Hurtige handlinger</swp-card-title>
</swp-card-header>
<swp-card-content> <swp-card-content>
<swp-quick-actions> <swp-quick-actions>
<swp-quick-action-btn> <swp-quick-action-btn>

View file

@ -2,10 +2,12 @@
<swp-detail-grid> <swp-detail-grid>
<!-- Left column --> <!-- Left column -->
<div> <swp-card-column>
<!-- Contact Card --> <!-- Contact Card -->
<swp-card> <swp-card>
<swp-section-label>@Model.LabelContact</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelContact</swp-card-title>
</swp-card-header>
<swp-edit-section> <swp-edit-section>
<swp-edit-row> <swp-edit-row>
<swp-edit-label>@Model.LabelFullName</swp-edit-label> <swp-edit-label>@Model.LabelFullName</swp-edit-label>
@ -32,7 +34,9 @@
<!-- Personal Card --> <!-- Personal Card -->
<swp-card> <swp-card>
<swp-section-label>@Model.LabelPersonal</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelPersonal</swp-card-title>
</swp-card-header>
<swp-edit-section> <swp-edit-section>
<swp-edit-row> <swp-edit-row>
<swp-edit-label>@Model.LabelBirthDate</swp-edit-label> <swp-edit-label>@Model.LabelBirthDate</swp-edit-label>
@ -48,13 +52,15 @@
</swp-edit-row> </swp-edit-row>
</swp-edit-section> </swp-edit-section>
</swp-card> </swp-card>
</div> </swp-card-column>
<!-- Right column --> <!-- Right column -->
<div> <swp-card-column>
<!-- Employment Card --> <!-- Employment Card -->
<swp-card> <swp-card>
<swp-section-label>@Model.LabelEmployment</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelEmployment</swp-card-title>
</swp-card-header>
<swp-edit-section> <swp-edit-section>
<swp-edit-row> <swp-edit-row>
<swp-edit-label>@Model.LabelEmploymentDate</swp-edit-label> <swp-edit-label>@Model.LabelEmploymentDate</swp-edit-label>
@ -77,7 +83,9 @@
<!-- Settings Card --> <!-- Settings Card -->
<swp-card> <swp-card>
<swp-section-label>@Model.LabelSettings</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelSettings</swp-card-title>
</swp-card-header>
<swp-toggle-row> <swp-toggle-row>
<div> <div>
<swp-toggle-label>@Model.SettingShowInBooking</swp-toggle-label> <swp-toggle-label>@Model.SettingShowInBooking</swp-toggle-label>
@ -102,7 +110,9 @@
<!-- Notifications Card --> <!-- Notifications Card -->
<swp-card> <swp-card>
<swp-section-label>@Model.LabelNotifications</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelNotifications</swp-card-title>
</swp-card-header>
<swp-notification-intro>@Model.NotificationsIntro</swp-notification-intro> <swp-notification-intro>@Model.NotificationsIntro</swp-notification-intro>
<swp-toggle-row> <swp-toggle-row>
<swp-toggle-label>@Model.SettingSmsReminders</swp-toggle-label> <swp-toggle-label>@Model.SettingSmsReminders</swp-toggle-label>
@ -147,5 +157,5 @@
</swp-toggle-slider> </swp-toggle-slider>
</swp-toggle-row> </swp-toggle-row>
</swp-card> </swp-card>
</div> </swp-card-column>
</swp-detail-grid> </swp-detail-grid>

View file

@ -2,11 +2,12 @@
<swp-detail-grid> <swp-detail-grid>
<!-- Left column --> <!-- Left column -->
<div> <swp-card-column>
<!-- Contract & Documents --> <!-- Contract & Documents -->
<swp-card> <swp-card>
<swp-section-label>@Model.LabelContractDocuments</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelContractDocuments</swp-card-title>
</swp-card-header>
<swp-edit-section> <swp-edit-section>
<swp-edit-row> <swp-edit-row>
<swp-edit-label>@Model.LabelContractType</swp-edit-label> <swp-edit-label>@Model.LabelContractType</swp-edit-label>
@ -57,7 +58,9 @@
<!-- Planned absence --> <!-- Planned absence -->
<swp-card> <swp-card>
<swp-section-label>@Model.LabelPlannedAbsence</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelPlannedAbsence</swp-card-title>
</swp-card-header>
<swp-simple-list> <swp-simple-list>
@foreach (var absence in Model.PlannedAbsences) @foreach (var absence in Model.PlannedAbsences)
{ {
@ -69,13 +72,15 @@
</swp-simple-list> </swp-simple-list>
<swp-add-button>+ @Model.LabelAddAbsence</swp-add-button> <swp-add-button>+ @Model.LabelAddAbsence</swp-add-button>
</swp-card> </swp-card>
</div> </swp-card-column>
<!-- Right column --> <!-- Right column -->
<div> <swp-card-column>
<!-- Certifications --> <!-- Certifications -->
<swp-card> <swp-card>
<swp-section-label>@Model.LabelCertifications</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelCertifications</swp-card-title>
</swp-card-header>
<swp-document-list> <swp-document-list>
@foreach (var cert in Model.Certifications) @foreach (var cert in Model.Certifications)
{ {
@ -96,8 +101,9 @@
<!-- Courses --> <!-- Courses -->
<swp-card> <swp-card>
<swp-section-label>@Model.LabelCourses</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelCourses</swp-card-title>
</swp-card-header>
<swp-subsection> <swp-subsection>
<swp-subsection-title>@Model.LabelCompletedCourses</swp-subsection-title> <swp-subsection-title>@Model.LabelCompletedCourses</swp-subsection-title>
<swp-document-list> <swp-document-list>
@ -136,13 +142,15 @@
<swp-add-button>+ @Model.LabelAddCourse</swp-add-button> <swp-add-button>+ @Model.LabelAddCourse</swp-add-button>
</swp-card> </swp-card>
</div> </swp-card-column>
</swp-detail-grid> </swp-detail-grid>
<!-- Vacation & Absence section --> <!-- Vacation & Absence section -->
<swp-detail-grid style="margin-top: var(--spacing-8);"> <swp-detail-grid style="margin-top: var(--spacing-8);">
<swp-card> <swp-card>
<swp-section-label>@Model.LabelVacationBalance</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelVacationBalance</swp-card-title>
</swp-card-header>
<swp-edit-section> <swp-edit-section>
<swp-edit-row> <swp-edit-row>
<swp-edit-label>@Model.LabelVacationEarned</swp-edit-label> <swp-edit-label>@Model.LabelVacationEarned</swp-edit-label>
@ -160,7 +168,9 @@
</swp-card> </swp-card>
<swp-card> <swp-card>
<swp-section-label>@Model.LabelAbsenceSickness</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelAbsenceSickness</swp-card-title>
</swp-card-header>
<swp-edit-section> <swp-edit-section>
<swp-edit-row> <swp-edit-row>
<swp-edit-label>@Model.LabelSickDays2025</swp-edit-label> <swp-edit-label>@Model.LabelSickDays2025</swp-edit-label>

View file

@ -1,13 +1,13 @@
@model PlanTempus.Application.Features.Employees.Components.EmployeeDetailSalaryViewModel @model PlanTempus.Application.Features.Employees.Components.EmployeeDetailSalaryViewModel
<swp-detail-grid> <swp-detail-grid>
<div> <swp-card-column>
<!-- Satser (Grundsatser) --> <!-- Satser (Grundsatser) -->
<swp-card> <swp-card>
<swp-section-header> <swp-card-header>
<swp-section-label>@Model.LabelRates</swp-section-label> <swp-card-title>@Model.LabelRates</swp-card-title>
<swp-section-action data-drawer-trigger="rates-drawer">@Model.LabelEdit</swp-section-action> <swp-section-action data-drawer-trigger="rates-drawer">@Model.LabelEdit</swp-section-action>
</swp-section-header> </swp-card-header>
<swp-edit-section> <swp-edit-section>
<swp-edit-row id="card-normal"> <swp-edit-row id="card-normal">
<swp-edit-label>@Model.LabelNormalRate</swp-edit-label> <swp-edit-label>@Model.LabelNormalRate</swp-edit-label>
@ -54,7 +54,9 @@
<!-- Tillæg --> <!-- Tillæg -->
<swp-card> <swp-card>
<swp-section-label>@Model.LabelSupplements</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelSupplements</swp-card-title>
</swp-card-header>
<swp-edit-section> <swp-edit-section>
<swp-edit-row id="card-weekday"> <swp-edit-row id="card-weekday">
<swp-edit-label>@Model.LabelWeekdaySupplement</swp-edit-label> <swp-edit-label>@Model.LabelWeekdaySupplement</swp-edit-label>
@ -73,7 +75,9 @@
<!-- Provision --> <!-- Provision -->
<swp-card> <swp-card>
<swp-section-label>@Model.LabelCommission</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelCommission</swp-card-title>
</swp-card-header>
<swp-edit-section> <swp-edit-section>
<swp-edit-row id="card-productcommission"> <swp-edit-row id="card-productcommission">
<swp-edit-label>@Model.LabelProductCommission</swp-edit-label> <swp-edit-label>@Model.LabelProductCommission</swp-edit-label>
@ -85,10 +89,12 @@
</swp-edit-row> </swp-edit-row>
</swp-edit-section> </swp-edit-section>
</swp-card> </swp-card>
</div> </swp-card-column>
<swp-card class="salary-history"> <swp-card class="salary-history">
<swp-section-label>@Model.LabelSalaryHistory</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelSalaryHistory</swp-card-title>
</swp-card-header>
<swp-data-table> <swp-data-table>
<swp-data-table-header> <swp-data-table-header>
<swp-data-table-cell>@Model.LabelPeriod</swp-data-table-cell> <swp-data-table-cell>@Model.LabelPeriod</swp-data-table-cell>

View file

@ -2,7 +2,9 @@
<swp-detail-grid> <swp-detail-grid>
<swp-card> <swp-card>
<swp-section-label>@Model.LabelAssignedServices</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelAssignedServices</swp-card-title>
</swp-card-header>
<swp-service-list> <swp-service-list>
<swp-service-item> <swp-service-item>
<swp-service-name>Dameklip</swp-service-name> <swp-service-name>Dameklip</swp-service-name>

View file

@ -2,7 +2,9 @@
<swp-detail-grid> <swp-detail-grid>
<swp-card> <swp-card>
<swp-section-label>@Model.LabelPerformance</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelPerformance</swp-card-title>
</swp-card-header>
<swp-stats-row> <swp-stats-row>
<swp-stat-card class="teal"> <swp-stat-card class="teal">
<swp-stat-value>@Model.BookingsThisYear</swp-stat-value> <swp-stat-value>@Model.BookingsThisYear</swp-stat-value>
@ -24,7 +26,9 @@
</swp-card> </swp-card>
<swp-card class="stats-bookings"> <swp-card class="stats-bookings">
<swp-section-label>@Model.LabelCompletedBookings</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelCompletedBookings</swp-card-title>
</swp-card-header>
<swp-data-table> <swp-data-table>
<swp-data-table-header> <swp-data-table-header>
<swp-data-table-cell>@Model.LabelDate</swp-data-table-cell> <swp-data-table-cell>@Model.LabelDate</swp-data-table-cell>

View file

@ -1,8 +1,9 @@
@model PlanTempus.Application.Features.Services.Components.ServiceDetailAddonsViewModel @model PlanTempus.Application.Features.Services.Components.ServiceDetailAddonsViewModel
<swp-card> <swp-card>
<swp-section-label>@Model.LabelAddonsForService</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelAddonsForService</swp-card-title>
</swp-card-header>
<swp-selectable-list> <swp-selectable-list>
@foreach (var addon in Model.Addons) @foreach (var addon in Model.Addons)
{ {

View file

@ -2,8 +2,9 @@
<swp-detail-grid> <swp-detail-grid>
<swp-card> <swp-card>
<swp-section-label>@Model.LabelDurationVariants</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelDurationVariants</swp-card-title>
</swp-card-header>
<swp-duration-list> <swp-duration-list>
@foreach (var variant in Model.DurationVariants) @foreach (var variant in Model.DurationVariants)
{ {
@ -27,7 +28,9 @@
</swp-card> </swp-card>
<swp-card> <swp-card>
<swp-section-label>@Model.LabelBufferTimes</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelBufferTimes</swp-card-title>
</swp-card-header>
<swp-edit-section> <swp-edit-section>
<swp-edit-row> <swp-edit-row>
<swp-edit-label>@Model.LabelBufferBefore</swp-edit-label> <swp-edit-label>@Model.LabelBufferBefore</swp-edit-label>

View file

@ -1,10 +1,11 @@
@model PlanTempus.Application.Features.Services.Components.ServiceDetailEmployeesViewModel @model PlanTempus.Application.Features.Services.Components.ServiceDetailEmployeesViewModel
<swp-detail-grid> <swp-detail-grid>
<div> <swp-card-column>
<swp-card> <swp-card>
<swp-section-label>@Model.LabelEmployeesForService</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelEmployeesForService</swp-card-title>
</swp-card-header>
<swp-selectable-list> <swp-selectable-list>
@foreach (var employee in Model.Employees) @foreach (var employee in Model.Employees)
{ {
@ -32,12 +33,13 @@
<swp-see-all>@Model.LabelSelectAll</swp-see-all> <swp-see-all>@Model.LabelSelectAll</swp-see-all>
</swp-card> </swp-card>
</div> </swp-card-column>
<div> <swp-card-column>
<swp-card> <swp-card>
<swp-section-label>@Model.LabelAvailability</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelAvailability</swp-card-title>
</swp-card-header>
<swp-availability-list> <swp-availability-list>
@foreach (var day in Model.Availability) @foreach (var day in Model.Availability)
{ {
@ -62,5 +64,5 @@
} }
</swp-availability-list> </swp-availability-list>
</swp-card> </swp-card>
</div> </swp-card-column>
</swp-detail-grid> </swp-detail-grid>

View file

@ -2,10 +2,12 @@
<swp-detail-grid> <swp-detail-grid>
<!-- Left column --> <!-- Left column -->
<div> <swp-card-column>
<!-- Basic Info Card --> <!-- Basic Info Card -->
<swp-card> <swp-card>
<swp-section-label>@Model.LabelBasic</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelBasic</swp-card-title>
</swp-card-header>
<swp-edit-section> <swp-edit-section>
<swp-edit-row> <swp-edit-row>
<swp-edit-label>@Model.LabelServiceName</swp-edit-label> <swp-edit-label>@Model.LabelServiceName</swp-edit-label>
@ -70,7 +72,9 @@
<!-- Booking Type Card --> <!-- Booking Type Card -->
<swp-card> <swp-card>
<swp-section-label>@Model.LabelBookingType</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelBookingType</swp-card-title>
</swp-card-header>
<swp-toggle-row> <swp-toggle-row>
<div> <div>
<swp-toggle-label>@Model.LabelCanBookAsMain</swp-toggle-label> <swp-toggle-label>@Model.LabelCanBookAsMain</swp-toggle-label>
@ -92,13 +96,15 @@
</swp-toggle-slider> </swp-toggle-slider>
</swp-toggle-row> </swp-toggle-row>
</swp-card> </swp-card>
</div> </swp-card-column>
<!-- Right column --> <!-- Right column -->
<div> <swp-card-column>
<!-- Online Booking Card --> <!-- Online Booking Card -->
<swp-card> <swp-card>
<swp-section-label>@Model.LabelOnlineBooking</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelOnlineBooking</swp-card-title>
</swp-card-header>
<swp-toggle-row> <swp-toggle-row>
<div> <div>
<swp-toggle-label>@Model.LabelShowInOnlineBooking</swp-toggle-label> <swp-toggle-label>@Model.LabelShowInOnlineBooking</swp-toggle-label>
@ -129,5 +135,5 @@
@Model.LabelUploadImage @Model.LabelUploadImage
</swp-add-button> </swp-add-button>
</swp-card> </swp-card>
</div> </swp-card-column>
</swp-detail-grid> </swp-detail-grid>

View file

@ -1,8 +1,9 @@
@model PlanTempus.Application.Features.Services.Components.ServiceDetailPricesViewModel @model PlanTempus.Application.Features.Services.Components.ServiceDetailPricesViewModel
<swp-card> <swp-card>
<swp-section-label>@Model.LabelPriceStructure</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelPriceStructure</swp-card-title>
</swp-card-header>
<swp-price-mode> <swp-price-mode>
<swp-price-mode-btn data-mode="simple" class="@(Model.PriceMode == PlanTempus.Application.Features.Services.Components.PriceMode.Simple ? "active" : "")">@Model.LabelSimplePrice</swp-price-mode-btn> <swp-price-mode-btn data-mode="simple" class="@(Model.PriceMode == PlanTempus.Application.Features.Services.Components.PriceMode.Simple ? "active" : "")">@Model.LabelSimplePrice</swp-price-mode-btn>
<swp-price-mode-btn data-mode="matrix" class="@(Model.PriceMode == PlanTempus.Application.Features.Services.Components.PriceMode.Matrix ? "active" : "")">@Model.LabelMatrixPrice</swp-price-mode-btn> <swp-price-mode-btn data-mode="matrix" class="@(Model.PriceMode == PlanTempus.Application.Features.Services.Components.PriceMode.Matrix ? "active" : "")">@Model.LabelMatrixPrice</swp-price-mode-btn>
@ -49,7 +50,9 @@
<swp-detail-grid> <swp-detail-grid>
<swp-card> <swp-card>
<swp-section-label>@Model.LabelEconomy</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelEconomy</swp-card-title>
</swp-card-header>
<swp-edit-section> <swp-edit-section>
<swp-edit-row> <swp-edit-row>
<swp-edit-label>@Model.LabelVatRate</swp-edit-label> <swp-edit-label>@Model.LabelVatRate</swp-edit-label>
@ -86,7 +89,9 @@
</swp-card> </swp-card>
<swp-card> <swp-card>
<swp-section-label>@Model.LabelDiscounts</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelDiscounts</swp-card-title>
</swp-card-header>
<swp-toggle-row> <swp-toggle-row>
<swp-toggle-label>@Model.LabelMemberDiscount</swp-toggle-label> <swp-toggle-label>@Model.LabelMemberDiscount</swp-toggle-label>
<swp-toggle-slider data-value="@(Model.MemberDiscount ? "yes" : "no")"> <swp-toggle-slider data-value="@(Model.MemberDiscount ? "yes" : "no")">

View file

@ -2,7 +2,9 @@
<swp-detail-grid> <swp-detail-grid>
<swp-card> <swp-card>
<swp-section-label>@Model.LabelBookingRules</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelBookingRules</swp-card-title>
</swp-card-header>
<swp-edit-section> <swp-edit-section>
<swp-edit-row> <swp-edit-row>
<swp-edit-label>@Model.LabelMinNotice</swp-edit-label> <swp-edit-label>@Model.LabelMinNotice</swp-edit-label>
@ -73,7 +75,9 @@
</swp-card> </swp-card>
<swp-card> <swp-card>
<swp-section-label>@Model.LabelRequirements</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelRequirements</swp-card-title>
</swp-card-header>
<swp-toggle-row> <swp-toggle-row>
<div> <div>
<swp-toggle-label>@Model.LabelRequiresConsultation</swp-toggle-label> <swp-toggle-label>@Model.LabelRequiresConsultation</swp-toggle-label>
@ -108,7 +112,9 @@
</swp-detail-grid> </swp-detail-grid>
<swp-card> <swp-card>
<swp-section-label>@Model.LabelOnlineBookingSettings</swp-section-label> <swp-card-header>
<swp-card-title>@Model.LabelOnlineBookingSettings</swp-card-title>
</swp-card-header>
<swp-toggle-row> <swp-toggle-row>
<swp-toggle-label>@Model.LabelShowInOnlineBooking</swp-toggle-label> <swp-toggle-label>@Model.LabelShowInOnlineBooking</swp-toggle-label>
<swp-toggle-slider data-value="@(Model.ShowInOnlineBooking ? "yes" : "no")"> <swp-toggle-slider data-value="@(Model.ShowInOnlineBooking ? "yes" : "no")">

View file

@ -63,7 +63,7 @@
</swp-card> </swp-card>
<!-- Column 2: Online betaling + Gebyr --> <!-- Column 2: Online betaling + Gebyr -->
<div class="stacked-cards"> <swp-card-column>
<!-- Online betaling --> <!-- Online betaling -->
<swp-card> <swp-card>
<swp-card-header> <swp-card-header>
@ -137,5 +137,5 @@
</swp-toggle-row> </swp-toggle-row>
</swp-card-content> </swp-card-content>
</swp-card> </swp-card>
</div> </swp-card-column>
</swp-two-column-grid> </swp-two-column-grid>

View file

@ -1,10 +1,12 @@
<swp-two-column-grid> <swp-two-column-grid>
<!-- EMAIL --> <!-- EMAIL -->
<swp-card> <swp-card>
<swp-section-label> <swp-card-header>
<swp-card-title>
<i class="ph ph-envelope"></i> <i class="ph ph-envelope"></i>
Email Email
</swp-section-label> </swp-card-title>
</swp-card-header>
<swp-toggle-row> <swp-toggle-row>
<div> <div>
<swp-toggle-label>Bekræftelse</swp-toggle-label> <swp-toggle-label>Bekræftelse</swp-toggle-label>
@ -51,10 +53,12 @@
<!-- SMS --> <!-- SMS -->
<swp-card> <swp-card>
<swp-section-label> <swp-card-header>
<swp-card-title>
<i class="ph ph-chat-text"></i> <i class="ph ph-chat-text"></i>
SMS SMS
</swp-section-label> </swp-card-title>
</swp-card-header>
<swp-toggle-row> <swp-toggle-row>
<div> <div>
<swp-toggle-label>Bekræftelse online <span class="text-secondary">(0,30 kr.)</span></swp-toggle-label> <swp-toggle-label>Bekræftelse online <span class="text-secondary">(0,30 kr.)</span></swp-toggle-label>

View file

@ -75,29 +75,58 @@ Standard icon wrapper (40×40px cirkel):
| `swp-page-title` | Titel-wrapper med h1 og p | h1 + subtitle | | `swp-page-title` | Titel-wrapper med h1 og p | h1 + subtitle |
| `swp-page-actions` | Action buttons i header | Flex gap | | `swp-page-actions` | Action buttons i header | Flex gap |
| `swp-card` | Standard card wrapper | Border, padding, rounded | | `swp-card` | Standard card wrapper | Border, padding, rounded |
| `swp-section-label` | Card section label | Uppercase, 11px, border-bottom | | `swp-card-header` | Card header wrapper | Flex, space-between, border-bottom |
| `swp-section-header` | Wrapper for label + action | Flex, space-between | | `swp-card-title` | Card title med ikon | Flex, icon + text |
| `swp-section-action` | Action link i section header | Teal, clickable | | `swp-section-action` | Action link i header | Teal, clickable |
| `swp-section-label` | Subsection label (inde i card) | Uppercase, 11px, border-bottom |
| `swp-card-content` | Card indhold | Block | | `swp-card-content` | Card indhold | Block |
### Card Header Eksempler ### Card Header Eksempler
**Simpel label (uden action):** **Standard card header (ANBEFALET):**
```html ```html
<swp-card> <swp-card>
<swp-section-label>Kontakter</swp-section-label> <swp-card-header>
<swp-card-content>...</swp-card-content> <swp-card-title>Kontakter</swp-card-title>
</swp-card-header>
<!-- content -->
</swp-card> </swp-card>
``` ```
**Label med action:** **Card header med ikon:**
```html ```html
<swp-card> <swp-card>
<swp-section-header> <swp-card-header>
<swp-section-label>Dagens bookinger</swp-section-label> <swp-card-title>
<i class="ph ph-envelope"></i>
Email
</swp-card-title>
</swp-card-header>
<!-- content -->
</swp-card>
```
**Card header med action:**
```html
<swp-card>
<swp-card-header>
<swp-card-title>Dagens bookinger</swp-card-title>
<swp-section-action>Se alle</swp-section-action> <swp-section-action>Se alle</swp-section-action>
</swp-section-header> </swp-card-header>
<swp-card-content>...</swp-card-content> <!-- content -->
</swp-card>
```
**Subsection label (inde i card):**
```html
<swp-card>
<swp-card-header>
<swp-card-title>Grundlæggende</swp-card-title>
</swp-card-header>
<!-- first section content -->
<swp-section-label class="spaced">Interne noter</swp-section-label>
<!-- second section content -->
</swp-card> </swp-card>
``` ```
@ -434,7 +463,9 @@ Bruger `swp-data-table` med `.salary-history` context class.
```html ```html
<swp-card class="salary-history"> <swp-card class="salary-history">
<swp-section-label>Lønhistorik</swp-section-label> <swp-card-header>
<swp-card-title>Lønhistorik</swp-card-title>
</swp-card-header>
<swp-data-table> <swp-data-table>
<swp-data-table-header> <swp-data-table-header>
<swp-data-table-cell>Periode</swp-data-table-cell> <swp-data-table-cell>Periode</swp-data-table-cell>

View file

@ -57,15 +57,9 @@ swp-filter-spacer {
/* =========================================== /* ===========================================
ACTION BAR (Table Header) ACTION BAR (Table Header)
=========================================== */ =========================================== */
swp-action-bar { swp-action-bar.grid-top {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--spacing-6) var(--spacing-8);
background: var(--color-surface);
border: 1px solid var(--color-border);
border-bottom: none; border-bottom: none;
border-radius: var(--radius-lg) var(--radius-lg) 0 0; margin-bottom: 0;
} }
swp-selection-info { swp-selection-info {
@ -279,20 +273,6 @@ swp-row-arrow {
} }
} }
/* ===========================================
TWO-COLUMN GRID (Detail View)
=========================================== */
swp-cash-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--spacing-12);
}
swp-cash-column {
display: grid;
align-content: start;
}
/* =========================================== /* ===========================================
DATA TABLE (Dagens Tal) DATA TABLE (Dagens Tal)
=========================================== */ =========================================== */
@ -690,12 +670,6 @@ swp-system-note {
} }
} }
@media (max-width: 900px) {
swp-cash-grid {
grid-template-columns: 1fr;
}
}
@media (max-width: 768px) { @media (max-width: 768px) {
swp-filter-bar { swp-filter-bar {
flex-direction: column; flex-direction: column;

View file

@ -570,6 +570,7 @@ swp-card-title {
gap: var(--spacing-3); gap: var(--spacing-3);
font-size: var(--font-size-md); font-size: var(--font-size-md);
font-weight: var(--font-weight-semibold); font-weight: var(--font-weight-semibold);
text-transform: uppercase;
color: var(--color-text); color: var(--color-text);
& i { & i {
@ -1322,12 +1323,17 @@ swp-back-link {
swp-detail-grid { swp-detail-grid {
display: grid; display: grid;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
gap: var(--spacing-8); gap: var(--card-gap);
align-items: start;
}
> div { /* ===========================================
display: flex; CARD COLUMN (Stacked cards container)
flex-direction: column; =========================================== */
} swp-card-column {
display: grid;
gap: var(--card-gap);
align-content: start;
} }
@media (max-width: 900px) { @media (max-width: 900px) {
@ -1582,9 +1588,3 @@ swp-two-column-grid {
} }
} }
/* Stacked cards in a grid column */
.stacked-cards {
display: flex;
flex-direction: column;
gap: var(--card-gap);
}

View file

@ -12,6 +12,8 @@ swp-stats-grid {
display: grid; display: grid;
grid-template-columns: repeat(4, 1fr); grid-template-columns: repeat(4, 1fr);
gap: var(--card-gap); gap: var(--card-gap);
margin-bottom: var(--section-gap);
} }
swp-stats-row { swp-stats-row {

View file

@ -88,10 +88,31 @@ export class CashController {
toBankInput.addEventListener('input', calculate); toBankInput.addEventListener('input', calculate);
actualCashInput.addEventListener('input', calculate); actualCashInput.addEventListener('input', calculate);
// Setup Enter key navigation between fields
this.setupEnterNavigation([payoutsInput, toBankInput, actualCashInput]);
// Initial calculation // Initial calculation
calculate(); calculate();
} }
/**
* Setup Enter key to move focus to next input field
*/
private setupEnterNavigation(inputs: HTMLInputElement[]): void {
inputs.forEach((input, index) => {
input.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
e.preventDefault();
const nextIndex = index + 1;
if (nextIndex < inputs.length) {
inputs[nextIndex].focus();
inputs[nextIndex].select();
}
}
});
});
}
/** /**
* Calculate expected cash and difference * Calculate expected cash and difference
*/ */
@ -113,13 +134,13 @@ export class CashController {
} }
// Calculate and display difference // Calculate and display difference
this.updateDifference(actual, expectedCash, actualCashInput.value); this.updateDifference(actual, expectedCash);
} }
/** /**
* Update difference box with color coding * Update difference box with color coding
*/ */
private updateDifference(actual: number, expected: number, rawValue: string): void { private updateDifference(actual: number, expected: number): void {
const box = document.getElementById('differenceBox'); const box = document.getElementById('differenceBox');
const value = document.getElementById('differenceValue'); const value = document.getElementById('differenceValue');
if (!box || !value) return; if (!box || !value) return;
@ -129,11 +150,7 @@ export class CashController {
// Remove all state classes // Remove all state classes
box.classList.remove('positive', 'negative', 'neutral'); box.classList.remove('positive', 'negative', 'neutral');
if (actual === 0 && rawValue === '') { if (diff > 0) {
// No input yet
value.textContent = ' kr';
box.classList.add('neutral');
} else if (diff > 0) {
// More cash than expected // More cash than expected
value.textContent = '+' + this.formatNumber(diff) + ' kr'; value.textContent = '+' + this.formatNumber(diff) + ' kr';
box.classList.add('positive'); box.classList.add('positive');