Calendar/wwwroot/poc-employee.html
Janus C. H. Knudsen e86948a984 Upgrades charting library and adds employee details page
Updates @sevenweirdpeople/swp-charting package to latest version (0.1.7)

Adds comprehensive employee details page with multiple tabs and interactive components including:
- Detailed employee profile information
- Work schedule and availability tracking
- Services and specialties management
- Salary and performance statistics

Integrates advanced charting capabilities for visualizing employee data
2025-12-26 14:05:56 +01:00

2157 lines
64 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="da">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Medarbejder Detaljer - Anna Sørensen</title>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
/* ==========================================
CSS VARIABLES (Design System)
========================================== */
:root {
--color-surface: #fff;
--color-background: #f5f5f5;
--color-background-hover: #f0f0f0;
--color-background-alt: #fafafa;
--color-border: #e0e0e0;
--color-text: #333;
--color-text-secondary: #666;
--color-teal: #00897b;
--color-blue: #1976d2;
--color-red: #e53935;
--color-amber: #f59e0b;
--color-purple: #8b5cf6;
--color-green: #43a047;
--font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
--font-mono: 'JetBrains Mono', monospace;
}
/* ==========================================
RESET & BASE
========================================== */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: var(--font-family);
font-size: 14px;
color: var(--color-text);
background: var(--color-background);
line-height: 1.5;
}
/* ==========================================
TOPBAR
========================================== */
swp-topbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 24px;
background: var(--color-surface);
border-bottom: 1px solid var(--color-border);
position: sticky;
top: 0;
z-index: 100;
}
swp-topbar-left {
display: flex;
align-items: center;
gap: 16px;
}
swp-back-link {
display: flex;
align-items: center;
gap: 6px;
color: var(--color-text-secondary);
text-decoration: none;
font-size: 13px;
cursor: pointer;
transition: color 150ms ease;
}
swp-back-link:hover {
color: var(--color-teal);
}
swp-back-link svg {
width: 16px;
height: 16px;
fill: currentColor;
}
swp-topbar-title {
font-size: 16px;
font-weight: 600;
color: var(--color-text);
}
swp-topbar-actions {
display: flex;
align-items: center;
gap: 12px;
}
swp-btn {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 8px 16px;
font-size: 13px;
font-weight: 500;
border-radius: 6px;
border: none;
cursor: pointer;
transition: all 150ms ease;
}
swp-btn.primary {
background: var(--color-teal);
color: white;
}
swp-btn.primary:hover {
background: #00796b;
}
swp-btn.secondary {
background: var(--color-surface);
color: var(--color-text);
border: 1px solid var(--color-border);
}
swp-btn.secondary:hover {
background: var(--color-background);
}
/* ==========================================
EMPLOYEE HEADER
========================================== */
swp-employee-header {
display: flex;
gap: 24px;
padding: 24px;
background: var(--color-surface);
border-bottom: 1px solid var(--color-border);
position: sticky;
top: 49px;
z-index: 90;
}
swp-employee-avatar-large {
width: 80px;
height: 80px;
border-radius: 50%;
background: linear-gradient(135deg, var(--color-teal) 0%, #00695c 100%);
display: flex;
align-items: center;
justify-content: center;
font-size: 28px;
font-weight: 600;
color: white;
flex-shrink: 0;
position: relative;
cursor: pointer;
overflow: hidden;
}
swp-employee-avatar-large img {
width: 100%;
height: 100%;
object-fit: cover;
}
swp-employee-avatar-large swp-avatar-initials {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
swp-employee-avatar-large.has-image swp-avatar-initials {
display: none;
}
swp-avatar-overlay {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 2px;
opacity: 0;
transition: opacity 150ms ease;
border-radius: 50%;
}
swp-employee-avatar-large:hover swp-avatar-overlay {
opacity: 1;
}
swp-avatar-overlay svg {
width: 24px;
height: 24px;
fill: white;
}
swp-avatar-overlay span {
font-size: 9px;
font-weight: 500;
color: white;
text-transform: uppercase;
letter-spacing: 0.3px;
}
swp-avatar-overlay .upload-text { display: block; }
swp-avatar-overlay .change-text { display: none; }
swp-employee-avatar-large.has-image swp-avatar-overlay .upload-text { display: none; }
swp-employee-avatar-large.has-image swp-avatar-overlay .change-text { display: block; }
swp-avatar-remove {
position: absolute;
top: -4px;
right: -4px;
width: 20px;
height: 20px;
background: var(--color-red);
border-radius: 50%;
display: none;
align-items: center;
justify-content: center;
color: white;
font-size: 12px;
font-weight: 600;
cursor: pointer;
z-index: 2;
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
transition: transform 150ms ease;
}
swp-employee-avatar-large.has-image:hover swp-avatar-remove {
display: flex;
}
swp-avatar-remove:hover {
transform: scale(1.1);
}
swp-avatar-upload-input {
display: none;
}
/* ==========================================
CHECKBOX ROW
========================================== */
swp-checkbox-list {
display: flex;
flex-direction: column;
gap: 4px;
}
swp-checkbox-row {
display: flex;
align-items: flex-start;
gap: 12px;
padding: 10px 12px;
border-radius: 6px;
cursor: pointer;
transition: background 150ms ease;
}
swp-checkbox-row:hover {
background: var(--color-background-alt);
}
swp-checkbox-box {
width: 18px;
height: 18px;
border: 2px solid var(--color-border);
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
margin-top: 1px;
transition: all 150ms ease;
}
swp-checkbox-row.checked swp-checkbox-box {
background: var(--color-teal);
border-color: var(--color-teal);
}
swp-checkbox-box svg {
width: 12px;
height: 12px;
fill: white;
opacity: 0;
transition: opacity 150ms ease;
}
swp-checkbox-row.checked swp-checkbox-box svg {
opacity: 1;
}
swp-checkbox-text {
font-size: 14px;
color: var(--color-text);
line-height: 1.4;
}
/* ==========================================
SCHEDULE TABLE (read-only, single employee)
Matches poc-arbejdstidsplan.html styling
========================================== */
swp-schedule-grid {
display: grid;
grid-template-columns: 120px repeat(7, minmax(80px, 1fr));
border-radius: 8px;
overflow: hidden;
border: 1px solid var(--color-border);
background: var(--color-surface);
}
swp-schedule-grid swp-cell {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 12px 16px;
min-height: 60px;
border-right: 1px solid var(--color-border);
border-bottom: 1px solid var(--color-border);
background: var(--color-surface);
}
swp-schedule-grid swp-cell:nth-child(8n) {
border-right: none;
}
swp-schedule-grid swp-cell:nth-last-child(-n+8) {
border-bottom: none;
}
swp-schedule-grid swp-cell.header {
background: var(--color-background-alt);
font-weight: 500;
font-size: 13px;
color: var(--color-text-secondary);
min-height: 48px;
text-align: center;
}
swp-schedule-grid swp-cell.header swp-day-name {
font-weight: 500;
color: var(--color-text);
}
swp-schedule-grid swp-cell.header swp-day-date {
font-size: 12px;
color: var(--color-text-secondary);
font-weight: 400;
}
swp-schedule-grid swp-cell.header.week-col {
font-size: 13px;
font-weight: 600;
color: var(--color-text);
}
swp-schedule-grid swp-cell.week-label {
font-size: 14px;
font-weight: 500;
color: var(--color-text);
background: var(--color-background-alt);
justify-content: center;
align-items: flex-start;
padding-left: 16px;
}
swp-schedule-grid swp-cell.week-label swp-week-hours {
font-size: 12px;
font-weight: 400;
color: var(--color-text-secondary);
font-family: var(--font-mono);
margin-top: 2px;
}
swp-time-badge {
font-family: var(--font-mono);
font-size: 12px;
font-weight: 500;
padding: 4px 8px;
border-radius: 4px;
background: color-mix(in srgb, var(--color-teal) 10%, white);
color: var(--color-text);
white-space: nowrap;
min-width: 90px;
text-align: center;
display: inline-block;
}
swp-time-badge.off {
background: transparent;
color: var(--color-text-secondary);
}
swp-time-badge.vacation {
background: color-mix(in srgb, var(--color-amber) 15%, white);
color: #b45309;
}
swp-time-badge.sick {
background: color-mix(in srgb, var(--color-red) 15%, white);
color: var(--color-red);
}
swp-schedule-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16px;
}
swp-schedule-header swp-section-label {
margin-bottom: 0;
}
swp-edit-link {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 13px;
color: var(--color-teal);
text-decoration: none;
cursor: pointer;
transition: color 150ms ease;
}
swp-edit-link:hover {
color: #00695c;
}
swp-edit-link svg {
width: 14px;
height: 14px;
fill: currentColor;
}
swp-employee-info {
flex: 1;
display: flex;
flex-direction: column;
gap: 8px;
}
swp-employee-name-row {
display: flex;
align-items: center;
gap: 16px;
}
swp-employee-name {
font-size: 24px;
font-weight: 600;
color: var(--color-text);
}
swp-tags-row {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
swp-tag {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 4px 10px;
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.3px;
border-radius: 4px;
background: var(--color-background);
color: var(--color-text-secondary);
}
swp-tag.master {
background: color-mix(in srgb, var(--color-purple) 15%, white);
color: var(--color-purple);
}
swp-tag.senior {
background: color-mix(in srgb, var(--color-blue) 15%, white);
color: var(--color-blue);
}
swp-tag.junior {
background: color-mix(in srgb, var(--color-amber) 15%, white);
color: #b45309;
}
swp-tag.cert {
background: color-mix(in srgb, var(--color-teal) 15%, white);
color: var(--color-teal);
}
swp-employee-status {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
font-size: 12px;
font-weight: 500;
border-radius: 6px;
cursor: pointer;
transition: all 150ms ease;
margin-left: auto;
}
swp-employee-status[data-active="true"] {
background: color-mix(in srgb, var(--color-green) 15%, white);
color: var(--color-green);
border: 1px solid color-mix(in srgb, var(--color-green) 30%, white);
}
swp-employee-status[data-active="false"] {
background: color-mix(in srgb, var(--color-red) 12%, white);
color: var(--color-red);
border: 1px solid color-mix(in srgb, var(--color-red) 30%, white);
}
swp-employee-status .icon {
font-size: 14px;
}
swp-fact-boxes-inline {
display: flex;
gap: 24px;
margin-top: 4px;
}
swp-fact-inline {
display: flex;
align-items: baseline;
gap: 6px;
}
swp-fact-inline-value {
font-size: 18px;
font-weight: 600;
font-family: var(--font-mono);
color: var(--color-text);
}
swp-fact-inline-label {
font-size: 12px;
color: var(--color-text-secondary);
}
.stars {
color: var(--color-amber);
}
/* ==========================================
TAB BAR
========================================== */
swp-tab-bar {
display: flex;
gap: 0;
background: var(--color-surface);
border-bottom: 1px solid var(--color-border);
padding: 0 24px;
position: sticky;
top: 178px;
z-index: 80;
}
swp-tab {
padding: 14px 24px;
font-size: 14px;
font-weight: 500;
color: var(--color-text-secondary);
cursor: pointer;
border-bottom: 2px solid transparent;
margin-bottom: -1px;
transition: all 150ms ease;
}
swp-tab:hover {
color: var(--color-text);
background: var(--color-background-alt);
}
swp-tab.active {
color: var(--color-teal);
border-bottom-color: var(--color-teal);
}
/* ==========================================
TAB CONTENT
========================================== */
swp-tab-content {
display: none;
padding: 24px;
max-width: 1200px;
margin: 0 auto;
}
swp-tab-content.active {
display: block;
}
/* ==========================================
LAYOUT GRID
========================================== */
.grid-2 {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
}
.grid-4 {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
}
@media (max-width: 900px) {
.grid-2 { grid-template-columns: 1fr; }
.grid-4 { grid-template-columns: repeat(2, 1fr); }
}
/* ==========================================
CARDS
========================================== */
swp-card {
display: block;
background: var(--color-surface);
border-radius: 8px;
padding: 20px;
border: 1px solid var(--color-border);
margin-bottom: 16px;
}
swp-card:last-child {
margin-bottom: 0;
}
swp-section-label {
display: block;
font-size: 11px;
font-weight: 600;
color: var(--color-text-secondary);
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 16px;
}
/* ==========================================
STAT CARDS
========================================== */
swp-stat-card {
background: var(--color-surface);
border-radius: 8px;
padding: 20px;
text-align: center;
border: 1px solid var(--color-border);
}
swp-stat-value {
display: block;
font-size: 28px;
font-weight: 600;
font-family: var(--font-mono);
color: var(--color-text);
}
swp-stat-label {
display: block;
font-size: 12px;
color: var(--color-text-secondary);
margin-top: 4px;
}
swp-stat-card.highlight swp-stat-value {
color: var(--color-teal);
}
/* ==========================================
EDIT SECTION
========================================== */
swp-edit-section {
display: flex;
flex-direction: column;
gap: 12px;
}
swp-edit-row {
display: grid;
grid-template-columns: 140px 1fr;
align-items: center;
gap: 12px;
}
swp-edit-label {
font-size: 13px;
color: var(--color-text-secondary);
}
swp-edit-value {
font-size: 14px;
padding: 8px 12px;
border-radius: 4px;
background: var(--color-background-alt);
border: 1px solid transparent;
transition: all 150ms ease;
cursor: text;
}
swp-edit-value:hover {
background: var(--color-background);
}
swp-edit-value:focus {
outline: none;
background: var(--color-surface);
border-color: var(--color-teal);
}
swp-edit-value.masked {
letter-spacing: 1px;
}
swp-edit-select select {
width: 100%;
font-size: 14px;
font-family: inherit;
padding: 8px 12px;
border-radius: 4px;
background: var(--color-background-alt);
border: 1px solid transparent;
cursor: pointer;
transition: all 150ms ease;
}
swp-edit-select select:hover {
background: var(--color-background);
}
swp-edit-select select:focus {
outline: none;
background: var(--color-surface);
border-color: var(--color-teal);
}
/* ==========================================
TOGGLE SLIDER
========================================== */
swp-toggle-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 0;
border-bottom: 1px solid var(--color-border);
}
swp-toggle-row:last-child {
border-bottom: none;
}
swp-toggle-label {
font-size: 14px;
color: var(--color-text);
}
swp-toggle-description {
display: block;
font-size: 12px;
color: var(--color-text-secondary);
margin-top: 2px;
}
swp-toggle-slider {
display: inline-flex;
width: fit-content;
background: var(--color-background);
border-radius: 6px;
border: 1px solid var(--color-border);
overflow: hidden;
position: relative;
}
swp-toggle-slider::before {
content: '';
position: absolute;
top: 2px;
left: 2px;
width: calc(50% - 4px);
height: calc(100% - 4px);
background: color-mix(in srgb, var(--color-green) 18%, white);
border-radius: 4px;
transition: transform 200ms ease, background 200ms ease;
}
swp-toggle-slider[data-value="no"]::before {
transform: translateX(100%);
background: color-mix(in srgb, var(--color-red) 18%, white);
}
swp-toggle-option {
position: relative;
z-index: 1;
padding: 5px 16px;
font-size: 12px;
font-weight: 500;
color: var(--color-text-secondary);
cursor: pointer;
transition: color 150ms ease;
user-select: none;
}
swp-toggle-slider[data-value="yes"] swp-toggle-option:first-child {
color: var(--color-green);
font-weight: 600;
}
swp-toggle-slider[data-value="no"] swp-toggle-option:last-child {
color: var(--color-red);
font-weight: 600;
}
/* ==========================================
AVAILABILITY LIST
========================================== */
swp-availability-list {
display: flex;
flex-direction: column;
}
swp-availability-row {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 16px;
padding: 12px 0;
border-bottom: 1px solid var(--color-border);
}
swp-availability-row:last-child {
border-bottom: none;
}
swp-availability-row[data-enabled="false"] {
opacity: 0.5;
}
swp-availability-day {
width: 80px;
font-size: 14px;
font-weight: 500;
color: var(--color-text);
}
swp-availability-time {
flex: 1;
display: flex;
flex-direction: column;
gap: 4px;
}
swp-time-range {
display: flex;
align-items: center;
gap: 12px;
}
swp-time-range-slider {
position: relative;
flex: 1;
height: 20px;
display: flex;
align-items: center;
}
swp-time-range-track {
position: absolute;
width: 100%;
height: 4px;
background: var(--color-border);
border-radius: 2px;
}
swp-time-range-fill {
position: absolute;
height: 4px;
background: var(--color-teal);
border-radius: 2px;
cursor: grab;
}
swp-time-range-slider input[type="range"] {
position: absolute;
width: 100%;
height: 4px;
-webkit-appearance: none;
appearance: none;
background: transparent;
pointer-events: none;
margin: 0;
}
swp-time-range-slider input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 14px;
height: 14px;
background: var(--color-teal);
border: 2px solid white;
border-radius: 50%;
cursor: pointer;
pointer-events: auto;
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}
swp-time-range-label {
font-size: 12px;
font-family: var(--font-mono);
color: var(--color-text);
min-width: 90px;
text-align: center;
background: var(--color-background-alt);
padding: 3px 8px;
border-radius: 4px;
}
/* ==========================================
VACATION LIST
========================================== */
swp-vacation-list {
display: flex;
flex-direction: column;
gap: 8px;
}
swp-vacation-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
background: var(--color-background-alt);
border-radius: 6px;
border: 1px solid var(--color-border);
}
swp-vacation-dates {
flex: 1;
font-size: 14px;
font-family: var(--font-mono);
}
swp-vacation-type {
font-size: 12px;
padding: 3px 10px;
border-radius: 12px;
font-weight: 500;
}
swp-vacation-type.ferie {
background: color-mix(in srgb, var(--color-amber) 15%, white);
color: #b45309;
}
swp-vacation-type.fri {
background: color-mix(in srgb, var(--color-purple) 15%, white);
color: var(--color-purple);
}
swp-vacation-type.syg {
background: color-mix(in srgb, var(--color-red) 15%, white);
color: var(--color-red);
}
swp-vacation-delete {
padding: 4px 8px;
color: var(--color-text-secondary);
cursor: pointer;
border-radius: 4px;
transition: all 150ms ease;
}
swp-vacation-delete:hover {
color: var(--color-red);
background: color-mix(in srgb, var(--color-red) 10%, white);
}
/* ==========================================
SERVICE LIST
========================================== */
swp-service-list {
display: flex;
flex-direction: column;
gap: 8px;
}
swp-service-item {
display: flex;
align-items: center;
gap: 16px;
padding: 16px;
background: var(--color-background-alt);
border-radius: 6px;
border: 1px solid var(--color-border);
cursor: pointer;
transition: border-color 0.15s ease;
}
swp-service-item:hover {
border-color: var(--color-teal);
}
swp-service-item.selected {
border-color: var(--color-teal);
background: color-mix(in srgb, var(--color-teal) 5%, var(--color-background-alt));
}
swp-service-checkbox {
width: 20px;
height: 20px;
border: 2px solid var(--color-border);
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
transition: all 0.15s ease;
}
swp-service-item.selected swp-service-checkbox {
background: var(--color-teal);
border-color: var(--color-teal);
color: white;
}
swp-service-checkbox svg {
width: 14px;
height: 14px;
fill: currentColor;
opacity: 0;
}
swp-service-item.selected swp-service-checkbox svg {
opacity: 1;
}
swp-service-color {
width: 4px;
height: 40px;
border-radius: 2px;
flex-shrink: 0;
}
swp-service-info {
flex: 1;
}
swp-service-name {
font-weight: 500;
color: var(--color-text);
}
swp-service-meta {
font-size: 12px;
color: var(--color-text-secondary);
margin-top: 2px;
}
swp-service-override {
font-size: 13px;
color: var(--color-text-secondary);
}
swp-service-override-value {
color: var(--color-text);
font-weight: 500;
}
/* ==========================================
SPECIALTY TAGS
========================================== */
swp-specialty-tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
swp-specialty-tag {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 8px 14px;
font-size: 13px;
border-radius: 20px;
border: 1px solid var(--color-border);
cursor: pointer;
transition: all 150ms ease;
}
swp-specialty-tag:hover {
background: var(--color-background-hover);
}
swp-specialty-tag.selected {
background: color-mix(in srgb, var(--color-teal) 12%, white);
border-color: var(--color-teal);
color: var(--color-teal);
}
swp-specialty-tag::before {
content: '';
width: 8px;
height: 8px;
border-radius: 50%;
border: 1px solid var(--color-border);
transition: all 150ms ease;
}
swp-specialty-tag.selected::before {
background: var(--color-teal);
border-color: var(--color-teal);
}
/* ==========================================
CERTIFICATION LIST
========================================== */
swp-cert-list {
display: flex;
flex-direction: column;
gap: 8px;
}
swp-cert-item {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px;
background: var(--color-background-alt);
border-radius: 6px;
border: 1px solid var(--color-border);
}
swp-cert-icon {
width: 36px;
height: 36px;
background: color-mix(in srgb, var(--color-teal) 15%, white);
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
}
swp-cert-info {
flex: 1;
}
swp-cert-name {
font-weight: 500;
color: var(--color-text);
}
swp-cert-dates {
font-size: 12px;
color: var(--color-text-secondary);
margin-top: 2px;
}
swp-cert-status {
font-size: 11px;
font-weight: 600;
padding: 4px 10px;
border-radius: 12px;
}
swp-cert-status.valid {
background: color-mix(in srgb, var(--color-green) 15%, white);
color: var(--color-green);
}
swp-cert-status.expiring {
background: color-mix(in srgb, var(--color-amber) 15%, white);
color: #b45309;
}
swp-cert-status.expired {
background: color-mix(in srgb, var(--color-red) 15%, white);
color: var(--color-red);
}
/* ==========================================
SALARY TABLE
========================================== */
swp-salary-history {
display: block;
margin-top: 16px;
}
swp-salary-history table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}
swp-salary-history th,
swp-salary-history td {
padding: 10px 12px;
text-align: left;
border-bottom: 1px solid var(--color-border);
}
swp-salary-history th {
font-size: 11px;
font-weight: 600;
color: var(--color-text-secondary);
text-transform: uppercase;
letter-spacing: 0.3px;
background: var(--color-background-alt);
}
swp-salary-history td {
color: var(--color-text);
}
swp-salary-history td.mono {
font-family: var(--font-mono);
}
/* ==========================================
BOOKING TABLE
========================================== */
swp-booking-table {
display: block;
margin-top: 16px;
}
swp-booking-table table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}
swp-booking-table th,
swp-booking-table td {
padding: 12px 16px;
text-align: left;
border-bottom: 1px solid var(--color-border);
}
swp-booking-table th {
font-size: 11px;
font-weight: 600;
color: var(--color-text-secondary);
text-transform: uppercase;
letter-spacing: 0.3px;
background: var(--color-background-alt);
}
swp-booking-table td {
color: var(--color-text);
}
swp-booking-table .customer {
font-weight: 500;
}
swp-booking-table .date {
font-family: var(--font-mono);
font-size: 12px;
color: var(--color-text-secondary);
}
swp-booking-table .amount {
font-family: var(--font-mono);
font-weight: 500;
}
/* ==========================================
CHART SECTION (matches poc-detail-drawer.html)
========================================== */
swp-chart-section {
display: block;
}
swp-chart-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16px;
}
swp-chart-title {
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--color-text-secondary);
}
swp-chart-legend {
display: flex;
gap: 16px;
}
swp-chart-legend-item {
display: flex;
align-items: center;
gap: 6px;
font-size: 12px;
color: var(--color-text-secondary);
}
swp-chart-legend-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
swp-chart-legend-dot.services {
background: var(--color-teal);
}
swp-chart-legend-dot.products {
background: var(--color-blue);
}
swp-chart-container {
display: block;
background: var(--color-background-alt);
border-radius: 8px;
border: 1px solid var(--color-border);
padding: 16px;
}
/* ==========================================
ADD BUTTON
========================================== */
swp-add-button {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 12px;
border: 2px dashed var(--color-border);
border-radius: 6px;
color: var(--color-text-secondary);
font-size: 13px;
cursor: pointer;
transition: all 150ms ease;
margin-top: 12px;
}
swp-add-button:hover {
border-color: var(--color-teal);
color: var(--color-teal);
background: color-mix(in srgb, var(--color-teal) 5%, white);
}
</style>
</head>
<body>
<!-- Topbar -->
<swp-topbar>
<swp-topbar-left>
<swp-back-link>
<svg viewBox="0 0 24 24"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg>
Tilbage til medarbejdere
</swp-back-link>
<swp-topbar-title>Medarbejder detaljer</swp-topbar-title>
</swp-topbar-left>
<swp-topbar-actions>
<swp-btn class="secondary">Slet medarbejder</swp-btn>
<swp-btn class="primary">Gem ændringer</swp-btn>
</swp-topbar-actions>
</swp-topbar>
<!-- Employee Header -->
<swp-employee-header>
<swp-employee-avatar-large id="avatarUpload">
<swp-avatar-initials>AS</swp-avatar-initials>
<swp-avatar-overlay>
<svg viewBox="0 0 24 24"><path d="M12 15.2c1.77 0 3.2-1.43 3.2-3.2 0-1.77-1.43-3.2-3.2-3.2-1.77 0-3.2 1.43-3.2 3.2 0 1.77 1.43 3.2 3.2 3.2zm8-10.2h-3.17L15 3H9L7.17 5H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-8 13c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"/></svg>
<span class="upload-text">Upload</span>
<span class="change-text">Skift</span>
</swp-avatar-overlay>
<swp-avatar-remove id="avatarRemove" title="Fjern billede"></swp-avatar-remove>
<input type="file" accept="image/*" id="avatarInput" style="display: none;">
</swp-employee-avatar-large>
<swp-employee-info>
<swp-employee-name-row>
<swp-employee-name contenteditable="true">Anna Sørensen</swp-employee-name>
<swp-tags-row>
<swp-tag class="master">Master Stylist</swp-tag>
<swp-tag class="cert">Farvecertificeret</swp-tag>
<swp-tag class="cert">Balayage</swp-tag>
</swp-tags-row>
<swp-employee-status data-active="true">
<span class="icon"></span>
<span class="text">Aktiv</span>
</swp-employee-status>
</swp-employee-name-row>
<swp-fact-boxes-inline>
<swp-fact-inline>
<swp-fact-inline-value>248</swp-fact-inline-value>
<swp-fact-inline-label>bookinger i år</swp-fact-inline-label>
</swp-fact-inline>
<swp-fact-inline>
<swp-fact-inline-value>186.450 kr</swp-fact-inline-value>
<swp-fact-inline-label>omsætning i år</swp-fact-inline-label>
</swp-fact-inline>
<swp-fact-inline>
<swp-fact-inline-value class="stars">★★★★★</swp-fact-inline-value>
<swp-fact-inline-label>4.9 rating</swp-fact-inline-label>
</swp-fact-inline>
<swp-fact-inline>
<swp-fact-inline-value>2019</swp-fact-inline-value>
<swp-fact-inline-label>ansat siden</swp-fact-inline-label>
</swp-fact-inline>
</swp-fact-boxes-inline>
</swp-employee-info>
</swp-employee-header>
<!-- Tab Bar -->
<swp-tab-bar>
<swp-tab class="active" data-tab="general">Generelt</swp-tab>
<swp-tab data-tab="hours">Arbejdstid</swp-tab>
<swp-tab data-tab="services">Services</swp-tab>
<swp-tab data-tab="salary">Løn</swp-tab>
<swp-tab data-tab="stats">Statistik</swp-tab>
</swp-tab-bar>
<!-- ==========================================
GENERELT TAB
========================================== -->
<swp-tab-content class="active" data-tab="general">
<div class="grid-2">
<div>
<swp-card>
<swp-section-label>Kontaktoplysninger</swp-section-label>
<swp-edit-section>
<swp-edit-row>
<swp-edit-label>Fulde navn</swp-edit-label>
<swp-edit-value contenteditable="true">Anna Sørensen</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>E-mail</swp-edit-label>
<swp-edit-value contenteditable="true">anna@salon.dk</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Telefon</swp-edit-label>
<swp-edit-value contenteditable="true">+45 12 34 56 78</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Adresse</swp-edit-label>
<swp-edit-value contenteditable="true">Vestergade 15, 3. tv</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Postnr. & By</swp-edit-label>
<swp-edit-value contenteditable="true">8000 Aarhus C</swp-edit-value>
</swp-edit-row>
</swp-edit-section>
</swp-card>
<swp-card>
<swp-section-label>Personlige oplysninger</swp-section-label>
<swp-edit-section>
<swp-edit-row>
<swp-edit-label>Fødselsdato</swp-edit-label>
<swp-edit-value contenteditable="true">15. marts 1992</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>CPR-nummer</swp-edit-label>
<swp-edit-value class="masked" contenteditable="true">150392-****</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Nødkontakt</swp-edit-label>
<swp-edit-value contenteditable="true">Peter Sørensen (ægtefælle)</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Nødkontakt tlf.</swp-edit-label>
<swp-edit-value contenteditable="true">+45 87 65 43 21</swp-edit-value>
</swp-edit-row>
</swp-edit-section>
</swp-card>
</div>
<div>
<swp-card>
<swp-section-label>Ansættelse</swp-section-label>
<swp-edit-section>
<swp-edit-row>
<swp-edit-label>Ansættelsesdato</swp-edit-label>
<swp-edit-value contenteditable="true">1. august 2019</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Stilling</swp-edit-label>
<swp-edit-select>
<select>
<option>Junior Stylist</option>
<option>Stylist</option>
<option>Senior Stylist</option>
<option selected>Master Stylist</option>
</select>
</swp-edit-select>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Ansættelsestype</swp-edit-label>
<swp-edit-select>
<select>
<option selected>Fuldtid</option>
<option>Deltid</option>
<option>Vikar</option>
<option>Elev</option>
</select>
</swp-edit-select>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Timer/uge</swp-edit-label>
<swp-edit-value contenteditable="true">37</swp-edit-value>
</swp-edit-row>
</swp-edit-section>
</swp-card>
<swp-card>
<swp-section-label>Indstillinger</swp-section-label>
<swp-toggle-row>
<div>
<swp-toggle-label>Vis i online booking</swp-toggle-label>
<swp-toggle-description>Kunder kan vælge denne medarbejder</swp-toggle-description>
</div>
<swp-toggle-slider data-value="yes">
<swp-toggle-option>Ja</swp-toggle-option>
<swp-toggle-option>Nej</swp-toggle-option>
</swp-toggle-slider>
</swp-toggle-row>
<swp-toggle-row>
<div>
<swp-toggle-label>Modtag SMS-påmindelser</swp-toggle-label>
<swp-toggle-description>Få besked om nye bookinger</swp-toggle-description>
</div>
<swp-toggle-slider data-value="yes">
<swp-toggle-option>Ja</swp-toggle-option>
<swp-toggle-option>Nej</swp-toggle-option>
</swp-toggle-slider>
</swp-toggle-row>
<swp-toggle-row>
<div>
<swp-toggle-label>Kan redigere egen kalender</swp-toggle-label>
<swp-toggle-description>Tillad ændringer i egne bookinger</swp-toggle-description>
</div>
<swp-toggle-slider data-value="yes">
<swp-toggle-option>Ja</swp-toggle-option>
<swp-toggle-option>Nej</swp-toggle-option>
</swp-toggle-slider>
</swp-toggle-row>
</swp-card>
<swp-card>
<swp-section-label>Notifikationer</swp-section-label>
<p style="font-size: 13px; color: var(--color-text-secondary); margin-bottom: 16px;">
Vælg hvilke email-notifikationer medarbejderen skal modtage.
</p>
<swp-checkbox-list>
<swp-checkbox-row class="checked">
<swp-checkbox-box>
<svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
</swp-checkbox-box>
<swp-checkbox-text>Modtag email ved online booking</swp-checkbox-text>
</swp-checkbox-row>
<swp-checkbox-row class="checked">
<swp-checkbox-box>
<svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
</swp-checkbox-box>
<swp-checkbox-text>Modtag email ved manuel booking</swp-checkbox-text>
</swp-checkbox-row>
<swp-checkbox-row>
<swp-checkbox-box>
<svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
</swp-checkbox-box>
<swp-checkbox-text>Modtag email ved aflysning</swp-checkbox-text>
</swp-checkbox-row>
<swp-checkbox-row>
<swp-checkbox-box>
<svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
</swp-checkbox-box>
<swp-checkbox-text>Modtag email ved opskrivning til venteliste</swp-checkbox-text>
</swp-checkbox-row>
<swp-checkbox-row class="checked">
<swp-checkbox-box>
<svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
</swp-checkbox-box>
<swp-checkbox-text>Modtag daglig oversigt over morgendagens bookinger</swp-checkbox-text>
</swp-checkbox-row>
</swp-checkbox-list>
</swp-card>
</div>
</div>
</swp-tab-content>
<!-- ==========================================
ARBEJDSTID TAB
========================================== -->
<swp-tab-content data-tab="hours">
<swp-card>
<swp-schedule-header>
<swp-section-label>Arbejdstidsplan</swp-section-label>
<swp-edit-link href="poc-arbejdstidsplan.html">
<svg viewBox="0 0 24 24"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></svg>
Rediger i arbejdstidsplan
</swp-edit-link>
</swp-schedule-header>
<swp-schedule-grid>
<!-- Header row -->
<swp-cell class="header week-col"></swp-cell>
<swp-cell class="header"><swp-day-name>Mandag</swp-day-name></swp-cell>
<swp-cell class="header"><swp-day-name>Tirsdag</swp-day-name></swp-cell>
<swp-cell class="header"><swp-day-name>Onsdag</swp-day-name></swp-cell>
<swp-cell class="header"><swp-day-name>Torsdag</swp-day-name></swp-cell>
<swp-cell class="header"><swp-day-name>Fredag</swp-day-name></swp-cell>
<swp-cell class="header"><swp-day-name>Lørdag</swp-day-name></swp-cell>
<swp-cell class="header"><swp-day-name>Søndag</swp-day-name></swp-cell>
<!-- Uge 51 -->
<swp-cell class="week-label">Uge 51<swp-week-hours>38 timer</swp-week-hours></swp-cell>
<swp-cell><swp-time-badge>09:00 - 17:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>09:00 - 17:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>10:00 - 18:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>09:00 - 17:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>09:00 - 15:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="off"></swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="off"></swp-time-badge></swp-cell>
<!-- Uge 52 -->
<swp-cell class="week-label">Uge 52<swp-week-hours>20 timer</swp-week-hours></swp-cell>
<swp-cell><swp-time-badge>09:00 - 17:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>09:00 - 13:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="vacation">Ferie</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="vacation">Ferie</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="vacation">Ferie</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="vacation">Ferie</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="vacation">Ferie</swp-time-badge></swp-cell>
<!-- Uge 1 -->
<swp-cell class="week-label">Uge 1<swp-week-hours>0 timer</swp-week-hours></swp-cell>
<swp-cell><swp-time-badge class="vacation">Ferie</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="vacation">Ferie</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="off"></swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="off"></swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="off"></swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="off"></swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="off"></swp-time-badge></swp-cell>
<!-- Uge 2 -->
<swp-cell class="week-label">Uge 2<swp-week-hours>38 timer</swp-week-hours></swp-cell>
<swp-cell><swp-time-badge>09:00 - 17:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>09:00 - 17:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>10:00 - 18:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>09:00 - 17:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>09:00 - 15:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="off"></swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="off"></swp-time-badge></swp-cell>
<!-- Uge 3 -->
<swp-cell class="week-label">Uge 3<swp-week-hours>38 timer</swp-week-hours></swp-cell>
<swp-cell><swp-time-badge>09:00 - 17:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>09:00 - 17:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>10:00 - 18:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>09:00 - 17:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>09:00 - 15:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="off"></swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="off"></swp-time-badge></swp-cell>
<!-- Uge 4 -->
<swp-cell class="week-label">Uge 4<swp-week-hours>38 timer</swp-week-hours></swp-cell>
<swp-cell><swp-time-badge>09:00 - 17:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>09:00 - 17:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>10:00 - 18:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>09:00 - 17:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge>09:00 - 15:00</swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="off"></swp-time-badge></swp-cell>
<swp-cell><swp-time-badge class="off"></swp-time-badge></swp-cell>
</swp-schedule-grid>
</swp-card>
<div class="grid-2" style="margin-top: 24px;">
<swp-card>
<swp-section-label>Planlagt fravær</swp-section-label>
<swp-vacation-list>
<swp-vacation-item>
<swp-vacation-dates>23. dec 2. jan 2026</swp-vacation-dates>
<swp-vacation-type class="ferie">Ferie</swp-vacation-type>
</swp-vacation-item>
<swp-vacation-item>
<swp-vacation-dates>14. feb 2025</swp-vacation-dates>
<swp-vacation-type class="fri">Fri</swp-vacation-type>
</swp-vacation-item>
<swp-vacation-item>
<swp-vacation-dates>7. apr 11. apr 2025</swp-vacation-dates>
<swp-vacation-type class="ferie">Ferie</swp-vacation-type>
</swp-vacation-item>
</swp-vacation-list>
</swp-card>
<swp-card>
<swp-section-label>Ferie-saldo</swp-section-label>
<swp-edit-section>
<swp-edit-row>
<swp-edit-label>Optjente feriedage</swp-edit-label>
<swp-edit-value>25 dage</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Brugte feriedage</swp-edit-label>
<swp-edit-value>12 dage</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Resterende</swp-edit-label>
<swp-edit-value style="font-weight: 600; color: var(--color-teal);">13 dage</swp-edit-value>
</swp-edit-row>
</swp-edit-section>
</swp-card>
</div>
</swp-tab-content>
<!-- ==========================================
SERVICES TAB
========================================== -->
<swp-tab-content data-tab="services">
<div class="grid-2">
<swp-card>
<swp-section-label>Services medarbejderen kan udføre</swp-section-label>
<swp-service-list>
<swp-service-item class="selected">
<swp-service-checkbox>
<svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
</swp-service-checkbox>
<swp-service-color style="background: #f4511e;"></swp-service-color>
<swp-service-info>
<swp-service-name>Klip & Farve</swp-service-name>
<swp-service-meta>60-120 min · fra 795 kr</swp-service-meta>
</swp-service-info>
<swp-service-override>Varighed: <swp-service-override-value>Standard</swp-service-override-value></swp-service-override>
</swp-service-item>
<swp-service-item class="selected">
<swp-service-checkbox>
<svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
</swp-service-checkbox>
<swp-service-color style="background: #8e24aa;"></swp-service-color>
<swp-service-info>
<swp-service-name>Balayage</swp-service-name>
<swp-service-meta>90-150 min · fra 1.295 kr</swp-service-meta>
</swp-service-info>
<swp-service-override>Varighed: <swp-service-override-value>Standard</swp-service-override-value></swp-service-override>
</swp-service-item>
<swp-service-item class="selected">
<swp-service-checkbox>
<svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
</swp-service-checkbox>
<swp-service-color style="background: #1e88e5;"></swp-service-color>
<swp-service-info>
<swp-service-name>Dameklip</swp-service-name>
<swp-service-meta>45 min · fra 395 kr</swp-service-meta>
</swp-service-info>
<swp-service-override>Varighed: <swp-service-override-value>-10 min</swp-service-override-value></swp-service-override>
</swp-service-item>
<swp-service-item class="selected">
<swp-service-checkbox>
<svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
</swp-service-checkbox>
<swp-service-color style="background: #00897b;"></swp-service-color>
<swp-service-info>
<swp-service-name>Herreklip</swp-service-name>
<swp-service-meta>30 min · fra 295 kr</swp-service-meta>
</swp-service-info>
<swp-service-override>Varighed: <swp-service-override-value>Standard</swp-service-override-value></swp-service-override>
</swp-service-item>
<swp-service-item>
<swp-service-checkbox>
<svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
</swp-service-checkbox>
<swp-service-color style="background: #ffb300;"></swp-service-color>
<swp-service-info>
<swp-service-name>Extensions</swp-service-name>
<swp-service-meta>120-180 min · fra 2.500 kr</swp-service-meta>
</swp-service-info>
<swp-service-override>Varighed: <swp-service-override-value></swp-service-override-value></swp-service-override>
</swp-service-item>
<swp-service-item class="selected">
<swp-service-checkbox>
<svg viewBox="0 0 24 24"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
</swp-service-checkbox>
<swp-service-color style="background: #43a047;"></swp-service-color>
<swp-service-info>
<swp-service-name>Olaplex Behandling</swp-service-name>
<swp-service-meta>45 min · 350 kr</swp-service-meta>
</swp-service-info>
<swp-service-override>Varighed: <swp-service-override-value>Standard</swp-service-override-value></swp-service-override>
</swp-service-item>
</swp-service-list>
</swp-card>
<swp-card>
<swp-section-label>Specialer</swp-section-label>
<swp-specialty-tags>
<swp-specialty-tag class="selected">Farve</swp-specialty-tag>
<swp-specialty-tag class="selected">Balayage</swp-specialty-tag>
<swp-specialty-tag class="selected">Highlights</swp-specialty-tag>
<swp-specialty-tag>Extensions</swp-specialty-tag>
<swp-specialty-tag class="selected">Olaplex</swp-specialty-tag>
<swp-specialty-tag>Permanent</swp-specialty-tag>
<swp-specialty-tag>Brude-styling</swp-specialty-tag>
<swp-specialty-tag class="selected">Kort hår</swp-specialty-tag>
</swp-specialty-tags>
</swp-card>
</div>
</swp-tab-content>
<!-- ==========================================
LØN TAB
========================================== -->
<swp-tab-content data-tab="salary">
<div class="grid-2">
<div>
<swp-card>
<swp-section-label>Grundløn</swp-section-label>
<swp-edit-section>
<swp-edit-row>
<swp-edit-label>Timeløn</swp-edit-label>
<swp-edit-value contenteditable="true">185 kr/time</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Overarbejde</swp-edit-label>
<swp-edit-value contenteditable="true">150%</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Weekendtillæg</swp-edit-label>
<swp-edit-value contenteditable="true">25%</swp-edit-value>
</swp-edit-row>
</swp-edit-section>
<swp-toggle-row style="margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--color-border);">
<swp-toggle-label>ATP-bidrag</swp-toggle-label>
<swp-toggle-slider data-value="yes">
<swp-toggle-option>Ja</swp-toggle-option>
<swp-toggle-option>Nej</swp-toggle-option>
</swp-toggle-slider>
</swp-toggle-row>
<swp-toggle-row>
<swp-toggle-label>Pension (arbejdsgiver)</swp-toggle-label>
<swp-toggle-slider data-value="yes">
<swp-toggle-option>Ja</swp-toggle-option>
<swp-toggle-option>Nej</swp-toggle-option>
</swp-toggle-slider>
</swp-toggle-row>
</swp-card>
<swp-card>
<swp-section-label>Provision</swp-section-label>
<swp-edit-section>
<swp-edit-row>
<swp-edit-label>På services</swp-edit-label>
<swp-edit-value contenteditable="true">12%</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>På produktsalg</swp-edit-label>
<swp-edit-value contenteditable="true">8%</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Bonus ved mål</swp-edit-label>
<swp-edit-value contenteditable="true">2.500 kr/md</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Månedligt mål</swp-edit-label>
<swp-edit-value contenteditable="true">45.000 kr</swp-edit-value>
</swp-edit-row>
</swp-edit-section>
</swp-card>
</div>
<swp-card>
<swp-section-label>Lønhistorik</swp-section-label>
<swp-salary-history>
<table>
<thead>
<tr>
<th>Dato</th>
<th>Ændring</th>
<th>Ny værdi</th>
</tr>
</thead>
<tbody>
<tr>
<td class="mono">01.01.2025</td>
<td>Lønforhøjelse</td>
<td class="mono">185 kr/time</td>
</tr>
<tr>
<td class="mono">01.01.2024</td>
<td>Lønforhøjelse</td>
<td class="mono">175 kr/time</td>
</tr>
<tr>
<td class="mono">01.07.2023</td>
<td>Provision ændret</td>
<td class="mono">12%</td>
</tr>
<tr>
<td class="mono">01.01.2023</td>
<td>Lønforhøjelse</td>
<td class="mono">165 kr/time</td>
</tr>
<tr>
<td class="mono">01.08.2019</td>
<td>Ansættelse</td>
<td class="mono">145 kr/time</td>
</tr>
</tbody>
</table>
</swp-salary-history>
</swp-card>
</div>
</swp-tab-content>
<!-- ==========================================
STATISTIK TAB
========================================== -->
<swp-tab-content data-tab="stats">
<div class="grid-4" style="margin-bottom: 24px;">
<swp-stat-card class="highlight">
<swp-stat-value>42</swp-stat-value>
<swp-stat-label>Bookinger denne måned</swp-stat-label>
</swp-stat-card>
<swp-stat-card>
<swp-stat-value>28.450 kr</swp-stat-value>
<swp-stat-label>Omsætning denne måned</swp-stat-label>
</swp-stat-card>
<swp-stat-card>
<swp-stat-value>4.9</swp-stat-value>
<swp-stat-label>Gns. kundetilfredshed</swp-stat-label>
</swp-stat-card>
<swp-stat-card>
<swp-stat-value>68%</swp-stat-value>
<swp-stat-label>Gengangere</swp-stat-label>
</swp-stat-card>
</div>
<div class="grid-2">
<swp-card>
<swp-chart-section>
<swp-chart-header>
<swp-chart-title>Omsætning (sidste 6 mdr)</swp-chart-title>
<swp-chart-legend>
<swp-chart-legend-item>
<swp-chart-legend-dot class="services"></swp-chart-legend-dot>
<span>Services</span>
</swp-chart-legend-item>
<swp-chart-legend-item>
<swp-chart-legend-dot class="products"></swp-chart-legend-dot>
<span>Produkter</span>
</swp-chart-legend-item>
</swp-chart-legend>
</swp-chart-header>
<swp-chart-container id="revenueChart" style="height: 220px;"></swp-chart-container>
</swp-chart-section>
</swp-card>
<swp-card>
<swp-section-label>Seneste bookinger</swp-section-label>
<swp-booking-table>
<table>
<thead>
<tr>
<th>Kunde</th>
<th>Service</th>
<th>Dato</th>
<th>Beløb</th>
</tr>
</thead>
<tbody>
<tr>
<td class="customer">Maria Hansen</td>
<td>Klip & Farve</td>
<td class="date">23. dec 2024</td>
<td class="amount">995 kr</td>
</tr>
<tr>
<td class="customer">Louise Nielsen</td>
<td>Balayage</td>
<td class="date">22. dec 2024</td>
<td class="amount">1.495 kr</td>
</tr>
<tr>
<td class="customer">Sofie Andersen</td>
<td>Dameklip</td>
<td class="date">22. dec 2024</td>
<td class="amount">425 kr</td>
</tr>
<tr>
<td class="customer">Karen Pedersen</td>
<td>Klip & Farve</td>
<td class="date">21. dec 2024</td>
<td class="amount">1.095 kr</td>
</tr>
<tr>
<td class="customer">Emma Larsen</td>
<td>Olaplex</td>
<td class="date">21. dec 2024</td>
<td class="amount">350 kr</td>
</tr>
</tbody>
</table>
</swp-booking-table>
</swp-card>
</div>
</swp-tab-content>
<script type="module">
// Tab switching
document.querySelectorAll('swp-tab').forEach(tab => {
tab.addEventListener('click', () => {
document.querySelectorAll('swp-tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('swp-tab-content').forEach(c => c.classList.remove('active'));
tab.classList.add('active');
document.querySelector(`swp-tab-content[data-tab="${tab.dataset.tab}"]`).classList.add('active');
});
});
// Toggle sliders
document.querySelectorAll('swp-toggle-slider').forEach(slider => {
slider.addEventListener('click', () => {
slider.dataset.value = slider.dataset.value === 'yes' ? 'no' : 'yes';
});
});
// Service item selection
document.querySelectorAll('swp-service-item').forEach(item => {
item.addEventListener('click', () => {
item.classList.toggle('selected');
});
});
// Specialty tag selection
document.querySelectorAll('swp-specialty-tag').forEach(tag => {
tag.addEventListener('click', () => {
tag.classList.toggle('selected');
});
});
// Checkbox rows
document.querySelectorAll('swp-checkbox-row').forEach(row => {
row.addEventListener('click', () => {
row.classList.toggle('checked');
});
});
// Employee status toggle
const statusEl = document.querySelector('swp-employee-status');
statusEl.addEventListener('click', () => {
const isActive = statusEl.dataset.active === 'true';
statusEl.dataset.active = isActive ? 'false' : 'true';
statusEl.querySelector('.text').textContent = isActive ? 'Inaktiv' : 'Aktiv';
});
// Avatar upload
const avatarUpload = document.getElementById('avatarUpload');
const avatarInput = document.getElementById('avatarInput');
avatarUpload.addEventListener('click', () => {
avatarInput.click();
});
avatarInput.addEventListener('change', (e) => {
const file = e.target.files[0];
if (file && file.type.startsWith('image/')) {
const reader = new FileReader();
reader.onload = (event) => {
// Check if image already exists
let img = avatarUpload.querySelector('img');
if (!img) {
img = document.createElement('img');
avatarUpload.insertBefore(img, avatarUpload.firstChild);
}
img.src = event.target.result;
avatarUpload.classList.add('has-image');
};
reader.readAsDataURL(file);
}
});
// Avatar remove
const avatarRemove = document.getElementById('avatarRemove');
avatarRemove.addEventListener('click', (e) => {
e.stopPropagation();
const img = avatarUpload.querySelector('img');
if (img) {
img.remove();
}
avatarUpload.classList.remove('has-image');
avatarInput.value = '';
});
// Revenue chart - line (Services + Produkter)
import { createChart } from 'https://unpkg.com/@sevenweirdpeople/swp-charting@latest/dist/index.js';
createChart(document.getElementById('revenueChart'), {
xAxis: { categories: ['Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'] },
series: [
{
name: 'Services',
color: '#00897b',
data: [
{ x: 'Jul', y: 22000 },
{ x: 'Aug', y: 28500 },
{ x: 'Sep', y: 26200 },
{ x: 'Okt', y: 30500 },
{ x: 'Nov', y: 27100 },
{ x: 'Dec', y: 26000 },
],
showArea: true,
area: { gradient: { startOpacity: 0.3, endOpacity: 0.05 } }
},
{
name: 'Produkter',
color: '#1976d2',
data: [
{ x: 'Jul', y: 2500 },
{ x: 'Aug', y: 2700 },
{ x: 'Sep', y: 2600 },
{ x: 'Okt', y: 2600 },
{ x: 'Nov', y: 2500 },
{ x: 'Dec', y: 2450 },
],
showArea: true,
area: { gradient: { startOpacity: 0.3, endOpacity: 0.05 } }
}
],
yAxis: { format: (v) => (v/1000).toFixed(0) + 'k' },
height: 200,
legend: false
});
</script>
</body>
</html>