Calendar/wwwroot/poc-customer-detail.html
Janus C. H. Knudsen 7965e8e753 Revamps Journal and Activity UI with new components
Introduces comprehensive styling and interaction for:
- Journal mini-tabs and entry layouts
- New activity timeline and filtering
- Responsive and visually enhanced UI components

Improves customer detail page with modern design patterns
2025-12-22 18:19:36 +01:00

3054 lines
88 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>Kundedetaljer - Sofie Nielsen</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 {
/* Colors */
--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: #ffb300;
--color-purple: #8b5cf6;
--color-green: #43a047;
/* Typography */
--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 img {
width: 16px;
height: 16px;
opacity: 0.6;
}
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);
}
/* ==========================================
STICKY HEADER
========================================== */
swp-customer-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-customer-avatar {
width: 80px;
height: 80px;
border-radius: 50%;
background: linear-gradient(135deg, var(--color-teal) 0%, #00695c 100%);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 28px;
font-weight: 600;
flex-shrink: 0;
}
swp-customer-info {
flex: 1;
display: flex;
flex-direction: column;
gap: 8px;
}
swp-customer-name-row {
display: flex;
align-items: center;
gap: 16px;
}
swp-customer-name {
font-size: 24px;
font-weight: 600;
color: var(--color-text);
}
swp-customer-name[contenteditable="true"] {
outline: none;
border-bottom: 1px dashed var(--color-border);
padding-bottom: 2px;
}
swp-customer-name[contenteditable="true"]:focus {
border-bottom-color: var(--color-teal);
}
/* Tags Editor */
swp-tags-editor {
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.vip {
background: color-mix(in srgb, var(--color-amber) 20%, white);
color: #b8860b;
}
swp-tag.stamkunde {
background: color-mix(in srgb, var(--color-teal) 15%, white);
color: var(--color-teal);
}
swp-tag.ny {
background: color-mix(in srgb, var(--color-blue) 15%, white);
color: var(--color-blue);
}
swp-tag.allergi {
background: color-mix(in srgb, var(--color-red) 15%, white);
color: var(--color-red);
}
swp-tag.sensitiv {
background: color-mix(in srgb, var(--color-purple) 15%, white);
color: var(--color-purple);
}
swp-tag .remove {
cursor: pointer;
opacity: 0.6;
margin-left: 2px;
}
swp-tag .remove:hover {
opacity: 1;
}
swp-tag-add {
display: inline-flex;
align-items: center;
padding: 4px 10px;
font-size: 11px;
font-weight: 500;
color: var(--color-text-secondary);
border: 1px dashed var(--color-border);
border-radius: 4px;
cursor: pointer;
transition: all 150ms ease;
}
swp-tag-add:hover {
border-color: var(--color-teal);
color: var(--color-teal);
}
/* Booking Exclusion Toggle */
swp-booking-exclusion {
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-booking-exclusion[data-excluded="false"] {
background: var(--color-background);
color: var(--color-text-secondary);
border: 1px solid var(--color-border);
}
swp-booking-exclusion[data-excluded="true"] {
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-booking-exclusion .icon {
font-size: 14px;
}
/* Customer Group Selector */
swp-customer-group {
display: inline-flex;
align-items: center;
gap: 8px;
position: relative;
}
swp-customer-group-label {
font-size: 12px;
color: var(--color-text-secondary);
}
swp-customer-group-select {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 5px 10px;
font-size: 13px;
font-weight: 500;
color: var(--color-text);
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 6px;
cursor: pointer;
transition: all 150ms ease;
}
swp-customer-group-select:hover {
border-color: var(--color-teal);
}
swp-customer-group-select .arrow {
font-size: 10px;
color: var(--color-text-secondary);
}
swp-customer-group-dropdown {
position: absolute;
top: 100%;
left: 0;
margin-top: 4px;
min-width: 180px;
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
z-index: 200;
display: none;
}
swp-customer-group-dropdown.open {
display: block;
}
swp-customer-group-option {
display: block;
padding: 10px 14px;
font-size: 13px;
color: var(--color-text);
cursor: pointer;
transition: background 100ms ease;
}
swp-customer-group-option:first-child {
border-radius: 7px 7px 0 0;
}
swp-customer-group-option:last-child {
border-radius: 0 0 7px 7px;
}
swp-customer-group-option:hover {
background: var(--color-background);
}
swp-customer-group-option.selected {
background: color-mix(in srgb, var(--color-teal) 10%, white);
color: var(--color-teal);
font-weight: 500;
}
/* Relation Items */
swp-relations-list {
display: flex;
flex-direction: column;
gap: 8px;
}
swp-relation-item {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 12px;
background: var(--color-background-alt);
border: 1px solid var(--color-border);
border-radius: 6px;
}
swp-relation-avatar {
width: 36px;
height: 36px;
border-radius: 50%;
background: var(--color-purple);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-size: 13px;
font-weight: 600;
flex-shrink: 0;
}
swp-relation-info {
flex: 1;
}
swp-relation-name {
display: block;
font-size: 14px;
font-weight: 500;
color: var(--color-text);
}
swp-relation-type {
display: block;
font-size: 12px;
color: var(--color-text-secondary);
}
swp-relation-actions {
display: flex;
gap: 8px;
}
swp-relation-link {
font-size: 12px;
color: var(--color-teal);
cursor: pointer;
}
swp-relation-link:hover {
text-decoration: underline;
}
swp-relation-remove {
font-size: 14px;
color: var(--color-text-secondary);
cursor: pointer;
opacity: 0.6;
}
swp-relation-remove:hover {
opacity: 1;
color: var(--color-red);
}
swp-add-relation {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 12px;
border: 1px dashed var(--color-border);
border-radius: 6px;
color: var(--color-text-secondary);
font-size: 13px;
cursor: pointer;
transition: all 150ms ease;
}
swp-add-relation:hover {
border-color: var(--color-teal);
color: var(--color-teal);
}
/* Customer Group in Card */
swp-customer-group-row {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 16px;
padding-bottom: 16px;
border-bottom: 1px solid var(--color-border);
}
/* Contact Line */
swp-contact-line {
display: flex;
align-items: center;
gap: 16px;
font-size: 13px;
color: var(--color-text-secondary);
}
swp-contact-line a {
color: var(--color-teal);
text-decoration: none;
}
swp-contact-line a:hover {
text-decoration: underline;
}
swp-contact-line span.separator {
color: var(--color-border);
}
/* Fact Boxes Inline */
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);
}
/* ==========================================
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: 193px;
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;
}
/* ==========================================
COMMON COMPONENTS
========================================== */
/* Section Label */
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: 12px;
}
/* Card */
swp-card {
display: block;
background: var(--color-surface);
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
padding: 20px;
margin-bottom: 20px;
}
/* Grid Layouts */
.grid-2 {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.grid-4 {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
}
/* Edit Section */
swp-edit-section {
display: flex;
flex-direction: column;
gap: 12px;
}
swp-edit-row {
display: grid;
grid-template-columns: 120px 1fr;
align-items: center;
gap: 12px;
}
swp-edit-label {
font-size: 13px;
color: var(--color-text-secondary);
}
swp-edit-value {
font-size: 14px;
color: var(--color-text);
padding: 8px 12px;
border: 1px solid transparent;
border-radius: 6px;
cursor: text;
transition: all 150ms ease;
}
swp-edit-value:hover {
background: var(--color-background-alt);
}
swp-edit-value:focus {
outline: none;
border-color: var(--color-teal);
background: var(--color-surface);
}
swp-edit-value[contenteditable="true"] {
cursor: text;
}
/* Toggle Slider (Ja/Nej) */
swp-toggle-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 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-slider {
display: flex;
position: relative;
background: var(--color-background);
border-radius: 6px;
padding: 3px;
gap: 0;
}
swp-toggle-slider::before {
content: '';
position: absolute;
top: 3px;
left: 3px;
width: calc(50% - 3px);
height: calc(100% - 6px);
background: color-mix(in srgb, var(--color-green) 18%, white);
border-radius: 4px;
transition: transform 200ms ease, background 200ms ease;
z-index: 0;
}
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 200ms 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;
}
/* Profile Boxes */
swp-profile-boxes {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}
swp-profile-box {
padding: 12px 14px;
background: var(--color-background-alt);
border-radius: 6px;
border: 1px solid var(--color-border);
}
swp-profile-box.warning {
background: color-mix(in srgb, var(--color-red) 8%, white);
border-color: color-mix(in srgb, var(--color-red) 30%, white);
}
swp-profile-box.full-width {
grid-column: span 2;
}
swp-profile-box-label {
display: block;
font-size: 11px;
color: var(--color-text-secondary);
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 4px;
}
swp-profile-box-value {
font-size: 14px;
color: var(--color-text);
}
swp-profile-box.warning swp-profile-box-value {
color: var(--color-red);
}
/* Stat Cards */
swp-stat-card {
background: var(--color-surface);
border-radius: 8px;
padding: 16px 20px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
text-align: center;
}
swp-stat-value {
display: block;
font-size: 24px;
font-weight: 600;
color: var(--color-text);
font-family: var(--font-mono);
}
swp-stat-card.highlight swp-stat-value {
color: var(--color-teal);
}
swp-stat-label {
display: block;
font-size: 12px;
color: var(--color-text-secondary);
margin-top: 4px;
}
/* Chart Container */
swp-chart-container {
display: block;
background: var(--color-background-alt);
border-radius: 8px;
border: 1px solid var(--color-border);
min-height: 200px;
}
swp-chart-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
}
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);
}
/* Table */
swp-table {
display: block;
width: 100%;
}
swp-table-header {
display: grid;
padding: 12px 16px;
background: var(--color-background);
border-radius: 6px 6px 0 0;
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--color-text-secondary);
}
swp-table-row {
display: grid;
padding: 12px 16px;
border-bottom: 1px solid var(--color-border);
font-size: 13px;
align-items: center;
}
swp-table-row:last-child {
border-bottom: none;
}
swp-table-row:hover {
background: var(--color-background-alt);
}
/* Journal Entry */
swp-journal-entry {
display: block;
padding: 16px;
background: var(--color-surface);
border-radius: 8px;
border: 1px solid var(--color-border);
margin-bottom: 12px;
}
swp-journal-entry:last-child {
margin-bottom: 0;
}
swp-journal-meta {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
swp-journal-type {
display: inline-block;
padding: 3px 8px;
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.3px;
border-radius: 4px;
}
swp-journal-type.farveformel {
background: color-mix(in srgb, var(--color-teal) 15%, white);
color: var(--color-teal);
}
swp-journal-type.analyse {
background: color-mix(in srgb, var(--color-purple) 15%, white);
color: var(--color-purple);
}
swp-journal-type.note {
background: color-mix(in srgb, var(--color-blue) 15%, white);
color: var(--color-blue);
}
swp-journal-type.advarsel {
background: color-mix(in srgb, var(--color-red) 15%, white);
color: var(--color-red);
}
swp-journal-date {
font-size: 12px;
color: var(--color-text-secondary);
}
swp-journal-content {
font-size: 14px;
color: var(--color-text);
line-height: 1.6;
}
swp-journal-author {
font-size: 12px;
color: var(--color-text-secondary);
margin-top: 8px;
}
/* Appointment Card */
swp-appointment-card {
display: block;
padding: 16px;
background: color-mix(in srgb, var(--color-teal) 5%, white);
border: 1px solid color-mix(in srgb, var(--color-teal) 20%, white);
border-radius: 8px;
margin-bottom: 12px;
}
swp-appointment-date {
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
font-weight: 600;
color: var(--color-teal);
margin-bottom: 6px;
}
swp-appointment-details {
font-size: 13px;
color: var(--color-text);
margin-bottom: 12px;
}
swp-appointment-actions {
display: flex;
gap: 8px;
}
swp-appointment-actions swp-btn {
padding: 6px 12px;
font-size: 12px;
}
/* Giftcard */
swp-giftcard {
display: block;
padding: 16px;
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
margin-bottom: 12px;
}
swp-giftcard-header {
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
font-weight: 600;
color: var(--color-text);
margin-bottom: 8px;
}
swp-giftcard-balance {
font-size: 13px;
color: var(--color-text);
margin-bottom: 4px;
}
swp-giftcard-balance strong {
font-family: var(--font-mono);
color: var(--color-teal);
}
swp-giftcard-expires {
font-size: 12px;
color: var(--color-text-secondary);
}
/* Progress Bar */
swp-progress-bar {
display: block;
height: 8px;
background: var(--color-background);
border-radius: 4px;
overflow: hidden;
margin: 8px 0;
}
swp-progress-fill {
display: block;
height: 100%;
background: var(--color-teal);
border-radius: 4px;
transition: width 300ms ease;
}
/* See All Link */
swp-see-all {
display: inline-block;
margin-top: 12px;
font-size: 13px;
color: var(--color-teal);
cursor: pointer;
}
swp-see-all:hover {
text-decoration: underline;
}
/* Add Button */
swp-add-btn {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 10px 16px;
font-size: 13px;
font-weight: 500;
color: var(--color-teal);
background: color-mix(in srgb, var(--color-teal) 10%, white);
border: 1px solid color-mix(in srgb, var(--color-teal) 30%, white);
border-radius: 6px;
cursor: pointer;
transition: all 150ms ease;
margin-bottom: 16px;
}
swp-add-btn:hover {
background: color-mix(in srgb, var(--color-teal) 15%, white);
}
/* Empty State */
swp-empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40px;
text-align: center;
color: var(--color-text-secondary);
}
swp-empty-state p {
font-size: 14px;
}
/* ==========================================
STAT CARD VARIANTS
========================================== */
swp-stat-card.warning swp-stat-value {
color: var(--color-amber);
}
swp-stat-card.danger swp-stat-value {
color: var(--color-red);
}
swp-stat-card.success swp-stat-value {
color: var(--color-green);
}
/* ==========================================
KEY-VALUE LIST
========================================== */
swp-kv-list {
display: flex;
flex-direction: column;
}
swp-kv-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 0;
border-bottom: 1px solid var(--color-border);
}
swp-kv-row:last-child {
border-bottom: none;
}
swp-kv-label {
font-size: 13px;
color: var(--color-text-secondary);
}
swp-kv-value {
font-size: 14px;
font-weight: 500;
font-family: var(--font-mono);
color: var(--color-text);
}
/* ==========================================
RATIO BAR
========================================== */
swp-ratio-container {
display: block;
margin-top: 16px;
}
swp-ratio-labels {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
font-size: 12px;
color: var(--color-text-secondary);
}
swp-ratio-bar {
display: flex;
height: 10px;
border-radius: 5px;
overflow: hidden;
background: var(--color-background);
}
swp-ratio-segment {
height: 100%;
transition: width 300ms ease;
}
swp-ratio-segment.services {
background: var(--color-teal);
}
swp-ratio-segment.products {
background: var(--color-blue);
}
/* ==========================================
RISK INDICATOR
========================================== */
swp-risk-indicator {
display: inline-flex;
align-items: center;
gap: 6px;
}
swp-risk-dot {
width: 10px;
height: 10px;
border-radius: 50%;
}
swp-risk-dot.low {
background: var(--color-green);
}
swp-risk-dot.medium {
background: var(--color-amber);
}
swp-risk-dot.high {
background: var(--color-red);
}
swp-risk-text {
font-size: 14px;
font-weight: 500;
}
swp-risk-text.low {
color: var(--color-green);
}
swp-risk-text.medium {
color: var(--color-amber);
}
swp-risk-text.high {
color: var(--color-red);
}
/* ==========================================
TOP LIST
========================================== */
swp-top-list {
display: flex;
flex-direction: column;
gap: 8px;
}
swp-top-item {
display: flex;
align-items: center;
gap: 12px;
font-size: 13px;
}
swp-top-rank {
width: 24px;
height: 24px;
border-radius: 50%;
background: var(--color-background);
color: var(--color-text-secondary);
display: flex;
align-items: center;
justify-content: center;
font-size: 11px;
font-weight: 600;
}
swp-top-item:first-child swp-top-rank {
background: color-mix(in srgb, var(--color-teal) 15%, white);
color: var(--color-teal);
}
swp-top-name {
flex: 1;
color: var(--color-text);
}
swp-top-count {
font-family: var(--font-mono);
font-size: 12px;
color: var(--color-text-secondary);
}
/* ==========================================
ATTENDANCE BAR
========================================== */
swp-attendance-bar {
display: flex;
height: 24px;
border-radius: 6px;
overflow: hidden;
margin-top: 12px;
}
swp-attendance-segment {
display: flex;
align-items: center;
justify-content: center;
font-size: 11px;
font-weight: 600;
color: white;
}
swp-attendance-segment.attended {
background: var(--color-teal);
}
swp-attendance-segment.cancelled {
background: var(--color-amber);
}
swp-attendance-segment.noshow {
background: var(--color-red);
}
/* ==========================================
JOURNAL - NEW LAYOUT
========================================== */
/* Journal Mini Tabs */
swp-journal-mini-tabs {
display: flex;
gap: 8px;
margin-bottom: 20px;
}
swp-journal-mini-tab {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 16px;
font-size: 13px;
font-weight: 500;
color: var(--color-text-secondary);
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
cursor: pointer;
transition: all 150ms ease;
}
swp-journal-mini-tab:hover {
border-color: var(--color-text-secondary);
}
swp-journal-mini-tab.active {
border-color: var(--color-teal);
color: var(--color-teal);
background: color-mix(in srgb, var(--color-teal) 5%, white);
}
swp-journal-mini-tab .tab-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
swp-journal-mini-tab .tab-dot.blue { background: var(--color-blue); }
swp-journal-mini-tab .tab-dot.amber { background: var(--color-amber); }
swp-journal-mini-tab .tab-dot.purple { background: var(--color-purple); }
swp-journal-mini-tab .tab-count {
font-size: 11px;
padding: 2px 6px;
background: var(--color-background);
border-radius: 10px;
color: var(--color-text-secondary);
}
/* Journal Columns */
swp-journal-columns {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
swp-journal-column {
display: flex;
flex-direction: column;
}
swp-journal-column-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
padding-bottom: 12px;
border-bottom: 1px solid var(--color-border);
}
swp-journal-column-title {
display: flex;
align-items: center;
gap: 8px;
font-size: 13px;
font-weight: 600;
color: var(--color-text);
}
swp-journal-column-title .col-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
swp-journal-column-title .col-dot.amber { background: var(--color-amber); }
swp-journal-column-title .col-dot.purple { background: var(--color-purple); }
swp-journal-column-add {
font-size: 12px;
color: var(--color-teal);
cursor: pointer;
}
swp-journal-column-add:hover {
text-decoration: underline;
}
/* Journal Entry - New Style */
swp-journal-entry-new {
display: block;
padding: 14px;
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
margin-bottom: 10px;
transition: border-color 150ms ease;
}
swp-journal-entry-new:hover {
border-color: var(--color-text-secondary);
}
swp-journal-entry-new:last-child {
margin-bottom: 0;
}
swp-journal-entry-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
}
swp-journal-entry-type-new {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 10px;
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.3px;
border-radius: 4px;
}
swp-journal-entry-type-new.farveformel {
background: color-mix(in srgb, var(--color-amber) 15%, white);
color: #b8860b;
}
swp-journal-entry-type-new.analyse {
background: color-mix(in srgb, var(--color-purple) 15%, white);
color: var(--color-purple);
}
swp-journal-entry-type-new.note {
background: color-mix(in srgb, var(--color-blue) 15%, white);
color: var(--color-blue);
}
swp-journal-entry-type-new.advarsel {
background: color-mix(in srgb, var(--color-red) 15%, white);
color: var(--color-red);
}
swp-journal-entry-tags-new {
display: flex;
gap: 6px;
}
swp-journal-tag-new {
display: inline-block;
padding: 3px 8px;
font-size: 10px;
font-weight: 500;
border-radius: 4px;
background: var(--color-background);
color: var(--color-text-secondary);
}
swp-journal-tag-new.sensitiv {
background: color-mix(in srgb, var(--color-purple) 12%, white);
color: var(--color-purple);
}
swp-journal-tag-new.allergi {
background: color-mix(in srgb, var(--color-red) 12%, white);
color: var(--color-red);
}
swp-journal-entry-delete-new {
font-size: 14px;
color: var(--color-text-secondary);
cursor: pointer;
opacity: 0;
transition: opacity 150ms ease;
}
swp-journal-entry-new:hover swp-journal-entry-delete-new {
opacity: 0.6;
}
swp-journal-entry-delete-new:hover {
opacity: 1;
color: var(--color-red);
}
swp-journal-entry-body {
font-size: 13px;
line-height: 1.6;
color: var(--color-text);
}
swp-journal-entry-body .mono {
font-family: var(--font-mono);
font-size: 12px;
background: var(--color-background);
padding: 1px 4px;
border-radius: 3px;
}
swp-journal-entry-body .label {
color: var(--color-text-secondary);
}
swp-journal-entry-footer-new {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 12px;
padding-top: 10px;
border-top: 1px solid var(--color-border);
}
swp-journal-entry-date-new {
font-size: 12px;
color: var(--color-text-secondary);
}
swp-journal-entry-icons-new {
display: flex;
align-items: center;
gap: 12px;
}
swp-journal-entry-icon {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 11px;
color: var(--color-text-secondary);
}
swp-journal-entry-icon img {
width: 14px;
height: 14px;
opacity: 0.5;
}
swp-journal-entry-icon.warning {
color: var(--color-amber);
}
swp-journal-entry-icon.warning img {
opacity: 1;
}
/* Noter Section (full width above columns) */
swp-journal-noter-section {
display: block;
margin-bottom: 24px;
}
swp-journal-noter-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}
/* Kundeprofil i Journal */
swp-journal-profile {
display: block;
margin-top: 24px;
padding-top: 20px;
border-top: 1px solid var(--color-border);
}
swp-journal-profile-header {
display: flex;
align-items: center;
gap: 8px;
font-size: 12px;
font-weight: 600;
color: var(--color-text-secondary);
margin-bottom: 12px;
cursor: pointer;
}
swp-journal-profile-header .arrow {
transition: transform 150ms ease;
}
swp-journal-profile-header.collapsed .arrow {
transform: rotate(-90deg);
}
swp-journal-profile swp-profile-boxes {
transition: all 200ms ease;
}
swp-journal-profile swp-profile-boxes.collapsed {
display: none;
}
/* ==========================================
ACTIVITY / AUDIT LOG
========================================== */
/* Activity Filters */
swp-activity-filters {
display: flex;
gap: 8px;
margin-bottom: 20px;
flex-wrap: wrap;
}
swp-activity-filter {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
font-size: 12px;
font-weight: 500;
color: var(--color-text-secondary);
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 20px;
cursor: pointer;
transition: all 150ms ease;
}
swp-activity-filter:hover {
border-color: var(--color-text-secondary);
}
swp-activity-filter.active {
background: var(--color-teal);
color: white;
border-color: var(--color-teal);
}
swp-activity-filter .filter-icon {
font-size: 11px;
}
/* Activity Timeline */
swp-activity-timeline {
display: block;
position: relative;
}
/* Date Group */
swp-activity-date-group {
display: block;
margin-bottom: 24px;
}
swp-activity-date-header {
display: flex;
align-items: center;
gap: 12px;
margin-bottom: 12px;
font-size: 12px;
font-weight: 600;
color: var(--color-text-secondary);
text-transform: uppercase;
letter-spacing: 0.5px;
}
swp-activity-date-header::after {
content: '';
flex: 1;
height: 1px;
background: var(--color-border);
}
/* Activity Item */
swp-activity-item {
display: flex;
gap: 12px;
padding: 12px 0;
border-bottom: 1px solid var(--color-border);
}
swp-activity-item:last-child {
border-bottom: none;
}
swp-activity-icon {
width: 32px;
height: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
flex-shrink: 0;
}
swp-activity-icon.system {
background: var(--color-background);
color: var(--color-text-secondary);
}
swp-activity-icon.customer {
background: color-mix(in srgb, var(--color-blue) 15%, white);
color: var(--color-blue);
}
swp-activity-icon.employee {
background: color-mix(in srgb, var(--color-teal) 15%, white);
color: var(--color-teal);
}
swp-activity-icon.booking {
background: color-mix(in srgb, var(--color-purple) 15%, white);
color: var(--color-purple);
}
swp-activity-icon.communication {
background: color-mix(in srgb, var(--color-amber) 15%, white);
color: #b8860b;
}
swp-activity-icon.payment {
background: color-mix(in srgb, var(--color-green) 15%, white);
color: var(--color-green);
}
swp-activity-icon.warning {
background: color-mix(in srgb, var(--color-red) 15%, white);
color: var(--color-red);
}
swp-activity-content {
flex: 1;
min-width: 0;
}
swp-activity-title {
display: block;
font-size: 13px;
color: var(--color-text);
margin-bottom: 2px;
}
swp-activity-title strong {
font-weight: 600;
}
swp-activity-title .highlight {
color: var(--color-teal);
font-weight: 500;
}
swp-activity-title .old-value {
color: var(--color-text-secondary);
text-decoration: line-through;
}
swp-activity-title .new-value {
color: var(--color-teal);
}
swp-activity-meta {
display: flex;
align-items: center;
gap: 8px;
font-size: 11px;
color: var(--color-text-secondary);
}
swp-activity-time {
font-family: var(--font-mono);
}
swp-activity-actor {
display: inline-flex;
align-items: center;
gap: 4px;
}
swp-activity-actor::before {
content: '·';
}
swp-activity-badge {
display: inline-block;
padding: 2px 6px;
font-size: 9px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.3px;
border-radius: 3px;
margin-left: 6px;
}
swp-activity-badge.auto {
background: var(--color-background);
color: var(--color-text-secondary);
}
swp-activity-badge.online {
background: color-mix(in srgb, var(--color-blue) 15%, white);
color: var(--color-blue);
}
swp-activity-badge.manual {
background: color-mix(in srgb, var(--color-teal) 15%, white);
color: var(--color-teal);
}
/* Activity Details (expandable) */
swp-activity-details {
display: block;
margin-top: 8px;
padding: 10px 12px;
background: var(--color-background-alt);
border-radius: 6px;
font-size: 12px;
color: var(--color-text-secondary);
}
swp-activity-details code {
font-family: var(--font-mono);
font-size: 11px;
background: var(--color-background);
padding: 1px 4px;
border-radius: 3px;
}
/* Load More */
swp-activity-load-more {
display: block;
text-align: center;
padding: 16px;
font-size: 13px;
color: var(--color-teal);
cursor: pointer;
border-top: 1px solid var(--color-border);
margin-top: 12px;
}
swp-activity-load-more:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<!-- Topbar -->
<swp-topbar>
<swp-topbar-left>
<swp-back-link onclick="history.back()">
<img src="icons/angle-small-left.svg" alt="">
Tilbage til kunder
</swp-back-link>
</swp-topbar-left>
<swp-topbar-actions>
<swp-btn class="secondary">Slet kunde</swp-btn>
<swp-btn class="primary" id="saveBtn">Gem</swp-btn>
</swp-topbar-actions>
</swp-topbar>
<!-- Sticky Header -->
<swp-customer-header>
<swp-customer-avatar>SN</swp-customer-avatar>
<swp-customer-info>
<swp-customer-name-row>
<swp-customer-name contenteditable="true">Sofie Nielsen</swp-customer-name>
<swp-tags-editor>
<swp-tag class="vip">VIP <span class="remove">×</span></swp-tag>
<swp-tag-add>+ Tilføj tag</swp-tag-add>
</swp-tags-editor>
<swp-booking-exclusion data-excluded="false" id="bookingExclusion">
<span class="icon"></span>
<span class="text">Booking tilladt</span>
</swp-booking-exclusion>
</swp-customer-name-row>
<swp-contact-line>
<a href="tel:+4523456789">+45 23 45 67 89</a>
<span class="separator">|</span>
<a href="mailto:sofie@email.dk">sofie@email.dk</a>
<span class="separator">|</span>
<span>Kunde siden marts 2024</span>
</swp-contact-line>
<swp-fact-boxes-inline>
<swp-fact-inline>
<swp-fact-inline-value>14</swp-fact-inline-value>
<swp-fact-inline-label>besøg</swp-fact-inline-label>
</swp-fact-inline>
<swp-fact-inline>
<swp-fact-inline-value>32</swp-fact-inline-value>
<swp-fact-inline-label>dage interval</swp-fact-inline-label>
</swp-fact-inline>
<swp-fact-inline>
<swp-fact-inline-value>Emma L.</swp-fact-inline-value>
<swp-fact-inline-label>foretrukken frisør</swp-fact-inline-label>
</swp-fact-inline>
<swp-fact-inline>
<swp-fact-inline-value>12.450 kr</swp-fact-inline-value>
<swp-fact-inline-label>total omsætning</swp-fact-inline-label>
</swp-fact-inline>
</swp-fact-boxes-inline>
</swp-customer-info>
</swp-customer-header>
<!-- Tab Bar -->
<swp-tab-bar>
<swp-tab class="active" data-tab="overview">Oversigt</swp-tab>
<swp-tab data-tab="economy">Økonomi</swp-tab>
<swp-tab data-tab="statistics">Statistik</swp-tab>
<swp-tab data-tab="journal">Journal</swp-tab>
<swp-tab data-tab="appointments">Aftaler</swp-tab>
<swp-tab data-tab="giftcards">Gavekort</swp-tab>
<swp-tab data-tab="activity">Aktivitet</swp-tab>
</swp-tab-bar>
<!-- Tab Contents -->
<!-- OVERSIGT TAB -->
<swp-tab-content class="active" data-tab="overview">
<div class="grid-2">
<!-- Left Column -->
<div>
<swp-card>
<swp-section-label>Kontaktoplysninger</swp-section-label>
<swp-edit-section>
<swp-edit-row>
<swp-edit-label>Telefon</swp-edit-label>
<swp-edit-value contenteditable="true">+45 23 45 67 89</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Email</swp-edit-label>
<swp-edit-value contenteditable="true">sofie@email.dk</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Adresse</swp-edit-label>
<swp-edit-value contenteditable="true">Hovedgaden 12</swp-edit-value>
</swp-edit-row>
<swp-edit-row>
<swp-edit-label>Postnr + By</swp-edit-label>
<swp-edit-value contenteditable="true">2100 København Ø</swp-edit-value>
</swp-edit-row>
</swp-edit-section>
</swp-card>
<swp-card>
<swp-section-label>Profil</swp-section-label>
<swp-profile-boxes>
<swp-profile-box>
<swp-profile-box-label>Hårtype</swp-profile-box-label>
<swp-profile-box-value>Medium · Bølget</swp-profile-box-value>
</swp-profile-box>
<swp-profile-box>
<swp-profile-box-label>Porøsitet</swp-profile-box-label>
<swp-profile-box-value>Medium</swp-profile-box-value>
</swp-profile-box>
<swp-profile-box>
<swp-profile-box-label>Hovedbund</swp-profile-box-label>
<swp-profile-box-value>Normal</swp-profile-box-value>
</swp-profile-box>
<swp-profile-box>
<swp-profile-box-label>Naturlig farve</swp-profile-box-label>
<swp-profile-box-value>Mørkblond (6)</swp-profile-box-value>
</swp-profile-box>
</swp-profile-boxes>
</swp-card>
</div>
<!-- Right Column -->
<div>
<swp-card>
<swp-section-label>Marketing</swp-section-label>
<swp-toggle-row>
<swp-toggle-label>Email marketing</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>SMS marketing</swp-toggle-label>
<swp-toggle-slider data-value="no">
<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>Præferencer</swp-section-label>
<swp-profile-boxes>
<swp-profile-box>
<swp-profile-box-label>Foretrukken frisør</swp-profile-box-label>
<swp-profile-box-value>Emma L.</swp-profile-box-value>
</swp-profile-box>
<swp-profile-box>
<swp-profile-box-label>Foretrukken dag</swp-profile-box-label>
<swp-profile-box-value>Tirsdag/Torsdag</swp-profile-box-value>
</swp-profile-box>
<swp-profile-box class="full-width">
<swp-profile-box-label>Specielle ønsker</swp-profile-box-label>
<swp-profile-box-value>Foretrækker kold tone, ikke for mørk</swp-profile-box-value>
</swp-profile-box>
</swp-profile-boxes>
</swp-card>
<swp-card>
<swp-section-label>Advarsler</swp-section-label>
<swp-profile-boxes>
<swp-profile-box class="warning full-width">
<swp-profile-box-label>Allergier / Følsomhed</swp-profile-box-label>
<swp-profile-box-value>Parfumeallergi - brug uparfumerede produkter</swp-profile-box-value>
</swp-profile-box>
</swp-profile-boxes>
</swp-card>
<swp-card>
<swp-section-label>Kundegruppe & Relationer</swp-section-label>
<swp-customer-group-row>
<swp-customer-group-label>Kundegruppe:</swp-customer-group-label>
<swp-customer-group>
<swp-customer-group-select id="customerGroupSelect">
<span class="value">Standard</span>
<span class="arrow"></span>
</swp-customer-group-select>
<swp-customer-group-dropdown id="customerGroupDropdown">
<swp-customer-group-option class="selected" data-value="standard">Standard</swp-customer-group-option>
<swp-customer-group-option data-value="premium">Premium</swp-customer-group-option>
<swp-customer-group-option data-value="erhverv">Erhverv</swp-customer-group-option>
<swp-customer-group-option data-value="medarbejder">Medarbejder</swp-customer-group-option>
<swp-customer-group-option data-value="familie">Familie & Venner</swp-customer-group-option>
</swp-customer-group-dropdown>
</swp-customer-group>
</swp-customer-group-row>
<swp-relations-list>
<swp-relation-item>
<swp-relation-avatar>EN</swp-relation-avatar>
<swp-relation-info>
<swp-relation-name>Emil Nielsen</swp-relation-name>
<swp-relation-type>Barn</swp-relation-type>
</swp-relation-info>
<swp-relation-actions>
<swp-relation-link>Åbn</swp-relation-link>
<swp-relation-remove>×</swp-relation-remove>
</swp-relation-actions>
</swp-relation-item>
<swp-relation-item>
<swp-relation-avatar>LN</swp-relation-avatar>
<swp-relation-info>
<swp-relation-name>Luna Nielsen</swp-relation-name>
<swp-relation-type>Barn</swp-relation-type>
</swp-relation-info>
<swp-relation-actions>
<swp-relation-link>Åbn</swp-relation-link>
<swp-relation-remove>×</swp-relation-remove>
</swp-relation-actions>
</swp-relation-item>
<swp-add-relation>
<span>+</span> Tilføj relation
</swp-add-relation>
</swp-relations-list>
</swp-card>
</div>
</div>
</swp-tab-content>
<!-- ØKONOMI TAB -->
<swp-tab-content data-tab="economy">
<div class="grid-4" style="margin-bottom: 24px;">
<swp-stat-card class="highlight">
<swp-stat-value>12.450 kr</swp-stat-value>
<swp-stat-label>I år (2025)</swp-stat-label>
</swp-stat-card>
<swp-stat-card>
<swp-stat-value>9.800 kr</swp-stat-value>
<swp-stat-label>Sidste år</swp-stat-label>
</swp-stat-card>
<swp-stat-card>
<swp-stat-value>889 kr</swp-stat-value>
<swp-stat-label>Gns. pr. besøg</swp-stat-label>
</swp-stat-card>
<swp-stat-card>
<swp-stat-value>1.038 kr</swp-stat-value>
<swp-stat-label>Gns. pr. måned</swp-stat-label>
</swp-stat-card>
</div>
<swp-card>
<swp-chart-header>
<swp-section-label style="margin-bottom: 0;">Omsætning over tid</swp-section-label>
<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"></swp-chart-container>
</swp-card>
<swp-card>
<swp-section-label>Købshistorik</swp-section-label>
<swp-table>
<swp-table-header style="grid-template-columns: 100px 80px 1fr 100px;">
<span>Dato</span>
<span>Type</span>
<span>Beskrivelse</span>
<span style="text-align: right;">Beløb</span>
</swp-table-header>
<swp-table-row style="grid-template-columns: 100px 80px 1fr 100px;">
<span>9. dec 2025</span>
<span><swp-journal-type class="farveformel" style="font-size: 9px;">Service</swp-journal-type></span>
<span>Klip + Farve</span>
<span style="text-align: right; font-family: var(--font-mono);">1.450 kr</span>
</swp-table-row>
<swp-table-row style="grid-template-columns: 100px 80px 1fr 100px;">
<span>9. dec 2025</span>
<span><swp-journal-type class="analyse" style="font-size: 9px;">Produkt</swp-journal-type></span>
<span>Olaplex No. 3</span>
<span style="text-align: right; font-family: var(--font-mono);">349 kr</span>
</swp-table-row>
<swp-table-row style="grid-template-columns: 100px 80px 1fr 100px;">
<span>12. nov 2025</span>
<span><swp-journal-type class="farveformel" style="font-size: 9px;">Service</swp-journal-type></span>
<span>Farve</span>
<span style="text-align: right; font-family: var(--font-mono);">1.200 kr</span>
</swp-table-row>
<swp-table-row style="grid-template-columns: 100px 80px 1fr 100px;">
<span>15. okt 2025</span>
<span><swp-journal-type class="farveformel" style="font-size: 9px;">Service</swp-journal-type></span>
<span>Klip</span>
<span style="text-align: right; font-family: var(--font-mono);">550 kr</span>
</swp-table-row>
</swp-table>
<swp-see-all>Se alle transaktioner →</swp-see-all>
</swp-card>
</swp-tab-content>
<!-- STATISTIK TAB -->
<swp-tab-content data-tab="statistics">
<!-- Fremmøde & Pålidelighed -->
<swp-card>
<swp-section-label>Fremmøde & Pålidelighed</swp-section-label>
<div class="grid-4">
<swp-stat-card class="highlight">
<swp-stat-value>47</swp-stat-value>
<swp-stat-label>Fremmøder</swp-stat-label>
</swp-stat-card>
<swp-stat-card class="warning">
<swp-stat-value>3</swp-stat-value>
<swp-stat-label>Aflysninger</swp-stat-label>
</swp-stat-card>
<swp-stat-card class="danger">
<swp-stat-value>1</swp-stat-value>
<swp-stat-label>No-shows</swp-stat-label>
</swp-stat-card>
<swp-stat-card class="success">
<swp-stat-value>92%</swp-stat-value>
<swp-stat-label>Pålidelighed</swp-stat-label>
</swp-stat-card>
</div>
<swp-attendance-bar>
<swp-attendance-segment class="attended" style="width: 92%;">47</swp-attendance-segment>
<swp-attendance-segment class="cancelled" style="width: 6%;">3</swp-attendance-segment>
<swp-attendance-segment class="noshow" style="width: 2%;">1</swp-attendance-segment>
</swp-attendance-bar>
</swp-card>
<div class="grid-2">
<!-- Booking-adfærd -->
<swp-card>
<swp-section-label>Booking-adfærd</swp-section-label>
<swp-kv-list>
<swp-kv-row>
<swp-kv-label>Gns. bookingvarsel</swp-kv-label>
<swp-kv-value>5 dage</swp-kv-value>
</swp-kv-row>
<swp-kv-row>
<swp-kv-label>Foretrukken dag</swp-kv-label>
<swp-kv-value>Tirsdag</swp-kv-value>
</swp-kv-row>
<swp-kv-row>
<swp-kv-label>Foretrukken tid</swp-kv-label>
<swp-kv-value>10:00 - 12:00</swp-kv-value>
</swp-kv-row>
<swp-kv-row>
<swp-kv-label>Online booking rate</swp-kv-label>
<swp-kv-value>78%</swp-kv-value>
</swp-kv-row>
<swp-kv-row>
<swp-kv-label>Gns. aflysningsvarsel</swp-kv-label>
<swp-kv-value>2 dage</swp-kv-value>
</swp-kv-row>
</swp-kv-list>
</swp-card>
<!-- Loyalitet -->
<swp-card>
<swp-section-label>Loyalitet</swp-section-label>
<div class="grid-2" style="gap: 12px;">
<swp-stat-card>
<swp-stat-value style="font-size: 20px;">1,8 år</swp-stat-value>
<swp-stat-label>Kunde siden</swp-stat-label>
</swp-stat-card>
<swp-stat-card class="success">
<swp-stat-value style="font-size: 20px;">13</swp-stat-value>
<swp-stat-label>Dage siden sidst</swp-stat-label>
</swp-stat-card>
<swp-stat-card>
<swp-stat-value style="font-size: 20px;">
<swp-risk-indicator>
<swp-risk-dot class="low"></swp-risk-dot>
<swp-risk-text class="low">Lav</swp-risk-text>
</swp-risk-indicator>
</swp-stat-value>
<swp-stat-label>Churn-risiko</swp-stat-label>
</swp-stat-card>
<swp-stat-card>
<swp-stat-value style="font-size: 20px;">32 dage</swp-stat-value>
<swp-stat-label>Gns. interval</swp-stat-label>
</swp-stat-card>
</div>
</swp-card>
</div>
<!-- Service-mønstre -->
<swp-card>
<swp-section-label>Service-mønstre</swp-section-label>
<div class="grid-2">
<div>
<swp-section-label style="font-size: 10px; margin-bottom: 10px;">Top 3 Services</swp-section-label>
<swp-top-list>
<swp-top-item>
<swp-top-rank>1</swp-top-rank>
<swp-top-name>Klip + Farve</swp-top-name>
<swp-top-count>12×</swp-top-count>
</swp-top-item>
<swp-top-item>
<swp-top-rank>2</swp-top-rank>
<swp-top-name>Farve</swp-top-name>
<swp-top-count>8×</swp-top-count>
</swp-top-item>
<swp-top-item>
<swp-top-rank>3</swp-top-rank>
<swp-top-name>Klip</swp-top-name>
<swp-top-count>6×</swp-top-count>
</swp-top-item>
</swp-top-list>
</div>
<div>
<swp-section-label style="font-size: 10px; margin-bottom: 10px;">Top 3 Produkter</swp-section-label>
<swp-top-list>
<swp-top-item>
<swp-top-rank>1</swp-top-rank>
<swp-top-name>Olaplex No. 3</swp-top-name>
<swp-top-count>5×</swp-top-count>
</swp-top-item>
<swp-top-item>
<swp-top-rank>2</swp-top-rank>
<swp-top-name>Shampoo</swp-top-name>
<swp-top-count>3×</swp-top-count>
</swp-top-item>
<swp-top-item>
<swp-top-rank>3</swp-top-rank>
<swp-top-name>Hårkur</swp-top-name>
<swp-top-count>2×</swp-top-count>
</swp-top-item>
</swp-top-list>
</div>
</div>
<swp-ratio-container>
<swp-ratio-labels>
<span>Services (85%)</span>
<span>Produkter (15%)</span>
</swp-ratio-labels>
<swp-ratio-bar>
<swp-ratio-segment class="services" style="width: 85%;"></swp-ratio-segment>
<swp-ratio-segment class="products" style="width: 15%;"></swp-ratio-segment>
</swp-ratio-bar>
</swp-ratio-container>
</swp-card>
</swp-tab-content>
<!-- JOURNAL TAB -->
<swp-tab-content data-tab="journal">
<!-- Mini Tabs for quick filter -->
<swp-journal-mini-tabs>
<swp-journal-mini-tab class="active">
<span class="tab-dot blue"></span>
Alle
<span class="tab-count">5</span>
</swp-journal-mini-tab>
<swp-journal-mini-tab>
<span class="tab-dot blue"></span>
Noter
<span class="tab-count">2</span>
</swp-journal-mini-tab>
<swp-journal-mini-tab>
<span class="tab-dot amber"></span>
Farveformler
<span class="tab-count">2</span>
</swp-journal-mini-tab>
<swp-journal-mini-tab>
<span class="tab-dot purple"></span>
Analyser
<span class="tab-count">1</span>
</swp-journal-mini-tab>
</swp-journal-mini-tabs>
<!-- Noter Section - full width -->
<swp-journal-noter-section>
<swp-card>
<swp-journal-column-header>
<swp-journal-column-title>
<span class="col-dot" style="background: var(--color-blue);"></span>
Noter
</swp-journal-column-title>
<swp-journal-column-add>+ Tilføj note</swp-journal-column-add>
</swp-journal-column-header>
<swp-journal-noter-grid>
<swp-journal-entry-new>
<swp-journal-entry-header>
<swp-journal-entry-type-new class="note">Note</swp-journal-entry-type-new>
<swp-journal-entry-delete-new>🗑</swp-journal-entry-delete-new>
</swp-journal-entry-header>
<swp-journal-entry-body>
Kunden foretrækker naturlige farver og ønsker lidt ekstra tid til konsultation. Husk at tjekke allergistatus inden farvebehandling.
</swp-journal-entry-body>
<swp-journal-entry-footer-new>
<swp-journal-entry-date-new>9. dec 2025 · Af: Emma</swp-journal-entry-date-new>
<swp-journal-entry-icons-new>
<swp-journal-entry-icon>
<img src="icons/eye.svg" alt="">
<span>Alle</span>
</swp-journal-entry-icon>
</swp-journal-entry-icons-new>
</swp-journal-entry-footer-new>
</swp-journal-entry-new>
<swp-journal-entry-new>
<swp-journal-entry-header>
<div style="display: flex; align-items: center; gap: 8px;">
<swp-journal-entry-type-new class="advarsel">Advarsel</swp-journal-entry-type-new>
<swp-journal-entry-tags-new>
<swp-journal-tag-new class="allergi">Allergi</swp-journal-tag-new>
</swp-journal-entry-tags-new>
</div>
<swp-journal-entry-delete-new>🗑</swp-journal-entry-delete-new>
</swp-journal-entry-header>
<swp-journal-entry-body>
<strong>PARFUMEALLERGI</strong> — Brug kun uparfumerede produkter. Havde reaktion på standard shampoo ved første besøg.
</swp-journal-entry-body>
<swp-journal-entry-footer-new>
<swp-journal-entry-date-new>15. mar 2024 · Af: Nina</swp-journal-entry-date-new>
<swp-journal-entry-icons-new>
<swp-journal-entry-icon>
<img src="icons/eye.svg" alt="">
<span>Alle</span>
</swp-journal-entry-icon>
<swp-journal-entry-icon class="warning">
<img src="icons/warning.svg" alt="">
<span>Advarsel</span>
</swp-journal-entry-icon>
</swp-journal-entry-icons-new>
</swp-journal-entry-footer-new>
</swp-journal-entry-new>
</swp-journal-noter-grid>
</swp-card>
</swp-journal-noter-section>
<!-- Two Column Layout: Farveformler + Analyser -->
<swp-journal-columns>
<!-- Farveformler Column -->
<swp-journal-column>
<swp-card style="height: 100%;">
<swp-journal-column-header>
<swp-journal-column-title>
<span class="col-dot amber"></span>
Farveformler
</swp-journal-column-title>
<swp-journal-column-add>+ Tilføj</swp-journal-column-add>
</swp-journal-column-header>
<swp-journal-entry-new>
<swp-journal-entry-header>
<swp-journal-entry-type-new class="farveformel">Farveformel</swp-journal-entry-type-new>
<swp-journal-entry-delete-new>🗑</swp-journal-entry-delete-new>
</swp-journal-entry-header>
<swp-journal-entry-body>
<span class="label">Mål/tone:</span> Kold<br>
<span class="label">Oxidant:</span> <span class="mono">6%</span><br>
<span class="label">Formel:</span> <span class="mono">7/1 + 7/0 (1:1)</span><br>
<span class="label">Virketid:</span> <span class="mono">35 min</span><br>
<span class="label">Placering:</span> Hele håret<br><br>
Resultat: Flot ensartet farve, kunden meget tilfreds
</swp-journal-entry-body>
<swp-journal-entry-footer-new>
<swp-journal-entry-date-new>12. nov 2025 · Af: Emma</swp-journal-entry-date-new>
<swp-journal-entry-icons-new>
<swp-journal-entry-icon>
<img src="icons/eye.svg" alt="">
<span>Alle</span>
</swp-journal-entry-icon>
</swp-journal-entry-icons-new>
</swp-journal-entry-footer-new>
</swp-journal-entry-new>
<swp-journal-entry-new>
<swp-journal-entry-header>
<swp-journal-entry-type-new class="farveformel">Farveformel</swp-journal-entry-type-new>
<swp-journal-entry-delete-new>🗑</swp-journal-entry-delete-new>
</swp-journal-entry-header>
<swp-journal-entry-body>
<span class="label">Mål/tone:</span> Varm<br>
<span class="label">Oxidant:</span> <span class="mono">6%</span><br>
<span class="label">Formel:</span> <span class="mono">8/0 + 7/1 (2:1)</span><br>
<span class="label">Virketid:</span> <span class="mono">30 min</span><br>
<span class="label">Placering:</span> Rødder<br><br>
Resultat: Lidt for varm, juster næste gang
</swp-journal-entry-body>
<swp-journal-entry-footer-new>
<swp-journal-entry-date-new>15. sep 2025 · Af: Emma</swp-journal-entry-date-new>
<swp-journal-entry-icons-new>
<swp-journal-entry-icon>
<img src="icons/eye.svg" alt="">
<span>Alle</span>
</swp-journal-entry-icon>
</swp-journal-entry-icons-new>
</swp-journal-entry-footer-new>
</swp-journal-entry-new>
</swp-card>
</swp-journal-column>
<!-- Analyser Column -->
<swp-journal-column>
<swp-card style="height: 100%;">
<swp-journal-column-header>
<swp-journal-column-title>
<span class="col-dot purple"></span>
Hår & Hovedbund
</swp-journal-column-title>
<swp-journal-column-add>+ Tilføj</swp-journal-column-add>
</swp-journal-column-header>
<swp-journal-entry-new>
<swp-journal-entry-header>
<div style="display: flex; align-items: center; gap: 8px;">
<swp-journal-entry-type-new class="analyse">Analyse</swp-journal-entry-type-new>
<swp-journal-entry-tags-new>
<swp-journal-tag-new class="sensitiv">Sensitiv</swp-journal-tag-new>
</swp-journal-entry-tags-new>
</div>
<swp-journal-entry-delete-new>🗑</swp-journal-entry-delete-new>
</swp-journal-entry-header>
<swp-journal-entry-body>
<span class="label">Hovedbund:</span> Normal<br>
<span class="label">Hår:</span> <span class="mono">Medium · Bølget</span><br>
<span class="label">Porøsitet:</span> <span class="mono">Medium</span><br>
<span class="label">Elasticitet:</span> <span class="mono">Normal</span><br>
<span class="label">Tilstand:</span> Let tørt i spidserne<br><br>
Anbefaling: Fugtgivende behandling hver 6. uge
</swp-journal-entry-body>
<swp-journal-entry-footer-new>
<swp-journal-entry-date-new>10. aug 2025 · Af: Nina</swp-journal-entry-date-new>
<swp-journal-entry-icons-new>
<swp-journal-entry-icon>
<img src="icons/eye.svg" alt="">
<span>Alle</span>
</swp-journal-entry-icon>
</swp-journal-entry-icons-new>
</swp-journal-entry-footer-new>
</swp-journal-entry-new>
</swp-card>
</swp-journal-column>
</swp-journal-columns>
<!-- Kundeprofil Section -->
<swp-journal-profile>
<swp-journal-profile-header onclick="this.classList.toggle('collapsed'); this.nextElementSibling.classList.toggle('collapsed');">
<span class="arrow"></span>
Vis "Kundeprofil" (hurtige facts)
</swp-journal-profile-header>
<swp-profile-boxes id="journalProfileBoxes">
<swp-profile-box>
<swp-profile-box-label>Hårtype</swp-profile-box-label>
<swp-profile-box-value>Medium · Bølget</swp-profile-box-value>
</swp-profile-box>
<swp-profile-box>
<swp-profile-box-label>Porøsitet</swp-profile-box-label>
<swp-profile-box-value>Medium</swp-profile-box-value>
</swp-profile-box>
<swp-profile-box>
<swp-profile-box-label>Præference</swp-profile-box-label>
<swp-profile-box-value>Kold tone, ikke for mørk</swp-profile-box-value>
</swp-profile-box>
<swp-profile-box class="warning">
<swp-profile-box-label>Advarsler</swp-profile-box-label>
<swp-profile-box-value>Parfumeallergi · Sensitiv hovedbund</swp-profile-box-value>
</swp-profile-box>
</swp-profile-boxes>
</swp-journal-profile>
</swp-tab-content>
<!-- AFTALER TAB -->
<swp-tab-content data-tab="appointments">
<swp-card>
<swp-section-label>Kommende aftaler</swp-section-label>
<swp-appointment-card>
<swp-appointment-date>
Tirsdag 14. januar 2026 kl. 10:00
</swp-appointment-date>
<swp-appointment-details>
Klip + Farve · Emma L. · 2 timer
</swp-appointment-details>
<swp-appointment-actions>
<swp-btn class="secondary">Flyt</swp-btn>
<swp-btn class="secondary">Aflys</swp-btn>
</swp-appointment-actions>
</swp-appointment-card>
</swp-card>
<swp-card>
<swp-section-label>Tidligere aftaler</swp-section-label>
<swp-table>
<swp-table-header style="grid-template-columns: 120px 1fr 100px 80px 100px;">
<span>Dato</span>
<span>Service</span>
<span>Frisør</span>
<span>Varighed</span>
<span style="text-align: right;">Pris</span>
</swp-table-header>
<swp-table-row style="grid-template-columns: 120px 1fr 100px 80px 100px;">
<span>9. dec 2025</span>
<span>Klip + Farve</span>
<span>Emma L.</span>
<span>2 timer</span>
<span style="text-align: right; font-family: var(--font-mono);">1.450 kr</span>
</swp-table-row>
<swp-table-row style="grid-template-columns: 120px 1fr 100px 80px 100px;">
<span>12. nov 2025</span>
<span>Farve</span>
<span>Emma L.</span>
<span>1t 30m</span>
<span style="text-align: right; font-family: var(--font-mono);">1.200 kr</span>
</swp-table-row>
<swp-table-row style="grid-template-columns: 120px 1fr 100px 80px 100px;">
<span>15. okt 2025</span>
<span>Klip</span>
<span>Emma L.</span>
<span>45 min</span>
<span style="text-align: right; font-family: var(--font-mono);">550 kr</span>
</swp-table-row>
<swp-table-row style="grid-template-columns: 120px 1fr 100px 80px 100px;">
<span>20. sep 2025</span>
<span>Klip + Behandling</span>
<span>Nina K.</span>
<span>1t 15m</span>
<span style="text-align: right; font-family: var(--font-mono);">750 kr</span>
</swp-table-row>
<swp-table-row style="grid-template-columns: 120px 1fr 100px 80px 100px;">
<span>15. aug 2025</span>
<span>Farve + Klip</span>
<span>Emma L.</span>
<span>2t 15m</span>
<span style="text-align: right; font-family: var(--font-mono);">1.600 kr</span>
</swp-table-row>
</swp-table>
<swp-see-all>Se alle aftaler →</swp-see-all>
</swp-card>
</swp-tab-content>
<!-- GAVEKORT TAB -->
<swp-tab-content data-tab="giftcards">
<swp-card>
<swp-section-label>Aktive gavekort</swp-section-label>
<swp-giftcard>
<swp-giftcard-header>
Gavekort #GK-2024-0892
</swp-giftcard-header>
<swp-giftcard-balance>
Saldo: <strong>350 kr</strong> (af 500 kr)
</swp-giftcard-balance>
<swp-progress-bar>
<swp-progress-fill style="width: 70%;"></swp-progress-fill>
</swp-progress-bar>
<swp-giftcard-expires>Udløber: 15. marts 2026</swp-giftcard-expires>
</swp-giftcard>
</swp-card>
<swp-card>
<swp-section-label>Klippekort</swp-section-label>
<swp-giftcard>
<swp-giftcard-header>
10-klip kort
</swp-giftcard-header>
<swp-giftcard-balance>
Brugt: <strong>7 af 10</strong> klip
</swp-giftcard-balance>
<swp-progress-bar>
<swp-progress-fill style="width: 70%;"></swp-progress-fill>
</swp-progress-bar>
<swp-giftcard-expires>Udløber aldrig</swp-giftcard-expires>
</swp-giftcard>
</swp-card>
<swp-card>
<swp-section-label>Udløbne / Brugte</swp-section-label>
<swp-empty-state>
<p>Ingen udløbne eller brugte kort</p>
</swp-empty-state>
</swp-card>
</swp-tab-content>
<!-- AKTIVITET TAB -->
<swp-tab-content data-tab="activity">
<!-- Filters -->
<swp-activity-filters>
<swp-activity-filter class="active">Alle</swp-activity-filter>
<swp-activity-filter><span class="filter-icon">📅</span> Bookinger</swp-activity-filter>
<swp-activity-filter><span class="filter-icon">💬</span> Kommunikation</swp-activity-filter>
<swp-activity-filter><span class="filter-icon">✏️</span> Ændringer</swp-activity-filter>
<swp-activity-filter><span class="filter-icon">💳</span> Betalinger</swp-activity-filter>
<swp-activity-filter><span class="filter-icon">🔐</span> Login</swp-activity-filter>
</swp-activity-filters>
<swp-card>
<swp-activity-timeline>
<!-- I dag -->
<swp-activity-date-group>
<swp-activity-date-header>I dag</swp-activity-date-header>
<swp-activity-item>
<swp-activity-icon class="communication">💬</swp-activity-icon>
<swp-activity-content>
<swp-activity-title>
<strong>SMS påmindelse</strong> sendt om aftale i morgen
<swp-activity-badge class="auto">Auto</swp-activity-badge>
</swp-activity-title>
<swp-activity-meta>
<swp-activity-time>14:00</swp-activity-time>
<swp-activity-actor>System</swp-activity-actor>
</swp-activity-meta>
</swp-activity-content>
</swp-activity-item>
<swp-activity-item>
<swp-activity-icon class="customer">👤</swp-activity-icon>
<swp-activity-content>
<swp-activity-title>
Kunde <strong>loggede ind</strong> via online booking
<swp-activity-badge class="online">Online</swp-activity-badge>
</swp-activity-title>
<swp-activity-meta>
<swp-activity-time>11:23</swp-activity-time>
<swp-activity-actor>Sofie Nielsen</swp-activity-actor>
</swp-activity-meta>
</swp-activity-content>
</swp-activity-item>
</swp-activity-date-group>
<!-- 9. december -->
<swp-activity-date-group>
<swp-activity-date-header>9. december 2025</swp-activity-date-header>
<swp-activity-item>
<swp-activity-icon class="payment">💳</swp-activity-icon>
<swp-activity-content>
<swp-activity-title>
<strong>Betaling modtaget</strong><span class="highlight">1.799 kr</span> (Dankort)
</swp-activity-title>
<swp-activity-meta>
<swp-activity-time>12:45</swp-activity-time>
<swp-activity-actor>Emma L.</swp-activity-actor>
</swp-activity-meta>
</swp-activity-content>
</swp-activity-item>
<swp-activity-item>
<swp-activity-icon class="booking">📅</swp-activity-icon>
<swp-activity-content>
<swp-activity-title>
<strong>Aftale gennemført</strong> — Klip + Farve hos Emma L.
</swp-activity-title>
<swp-activity-meta>
<swp-activity-time>12:30</swp-activity-time>
<swp-activity-actor>Emma L.</swp-activity-actor>
</swp-activity-meta>
</swp-activity-content>
</swp-activity-item>
<swp-activity-item>
<swp-activity-icon class="booking">📅</swp-activity-icon>
<swp-activity-content>
<swp-activity-title>
<strong>Check-in</strong> — Kunden er ankommet
</swp-activity-title>
<swp-activity-meta>
<swp-activity-time>10:02</swp-activity-time>
<swp-activity-actor>Reception</swp-activity-actor>
</swp-activity-meta>
</swp-activity-content>
</swp-activity-item>
<swp-activity-item>
<swp-activity-icon class="employee">✏️</swp-activity-icon>
<swp-activity-content>
<swp-activity-title>
<strong>Journal opdateret</strong> — Ny farveformel tilføjet
</swp-activity-title>
<swp-activity-meta>
<swp-activity-time>12:35</swp-activity-time>
<swp-activity-actor>Emma L.</swp-activity-actor>
</swp-activity-meta>
</swp-activity-content>
</swp-activity-item>
</swp-activity-date-group>
<!-- 5. december -->
<swp-activity-date-group>
<swp-activity-date-header>5. december 2025</swp-activity-date-header>
<swp-activity-item>
<swp-activity-icon class="booking">📅</swp-activity-icon>
<swp-activity-content>
<swp-activity-title>
<strong>Ny booking</strong> oprettet — 9. dec kl. 10:00, Klip + Farve
<swp-activity-badge class="online">Online</swp-activity-badge>
</swp-activity-title>
<swp-activity-meta>
<swp-activity-time>19:42</swp-activity-time>
<swp-activity-actor>Sofie Nielsen</swp-activity-actor>
</swp-activity-meta>
</swp-activity-content>
</swp-activity-item>
<swp-activity-item>
<swp-activity-icon class="customer">👤</swp-activity-icon>
<swp-activity-content>
<swp-activity-title>
Kunde <strong>loggede ind</strong> via online booking
<swp-activity-badge class="online">Online</swp-activity-badge>
</swp-activity-title>
<swp-activity-meta>
<swp-activity-time>19:40</swp-activity-time>
<swp-activity-actor>Sofie Nielsen</swp-activity-actor>
</swp-activity-meta>
</swp-activity-content>
</swp-activity-item>
</swp-activity-date-group>
<!-- 28. november -->
<swp-activity-date-group>
<swp-activity-date-header>28. november 2025</swp-activity-date-header>
<swp-activity-item>
<swp-activity-icon class="employee">✏️</swp-activity-icon>
<swp-activity-content>
<swp-activity-title>
<strong>Telefon ændret</strong><span class="old-value">+45 12 34 56 78</span><span class="new-value">+45 23 45 67 89</span>
</swp-activity-title>
<swp-activity-meta>
<swp-activity-time>14:15</swp-activity-time>
<swp-activity-actor>Emma L.</swp-activity-actor>
</swp-activity-meta>
<swp-activity-details>
Kunden oplyste nyt nummer under besøg.
</swp-activity-details>
</swp-activity-content>
</swp-activity-item>
<swp-activity-item>
<swp-activity-icon class="employee">✏️</swp-activity-icon>
<swp-activity-content>
<swp-activity-title>
<strong>Tag tilføjet</strong><span class="highlight">VIP</span>
</swp-activity-title>
<swp-activity-meta>
<swp-activity-time>14:10</swp-activity-time>
<swp-activity-actor>Emma L.</swp-activity-actor>
</swp-activity-meta>
</swp-activity-content>
</swp-activity-item>
</swp-activity-date-group>
<!-- 12. november -->
<swp-activity-date-group>
<swp-activity-date-header>12. november 2025</swp-activity-date-header>
<swp-activity-item>
<swp-activity-icon class="warning">⚠️</swp-activity-icon>
<swp-activity-content>
<swp-activity-title>
<strong>Booking aflyst</strong> — Af kunden med 2 dages varsel
</swp-activity-title>
<swp-activity-meta>
<swp-activity-time>09:15</swp-activity-time>
<swp-activity-actor>Sofie Nielsen</swp-activity-actor>
</swp-activity-meta>
<swp-activity-details>
Årsag: "Kan desværre ikke den dag alligevel"
</swp-activity-details>
</swp-activity-content>
</swp-activity-item>
<swp-activity-item>
<swp-activity-icon class="communication">💬</swp-activity-icon>
<swp-activity-content>
<swp-activity-title>
<strong>Email sendt</strong> — Booking bekræftelse
<swp-activity-badge class="auto">Auto</swp-activity-badge>
</swp-activity-title>
<swp-activity-meta>
<swp-activity-time>08:00</swp-activity-time>
<swp-activity-actor>System</swp-activity-actor>
</swp-activity-meta>
</swp-activity-content>
</swp-activity-item>
</swp-activity-date-group>
<!-- Marts 2024 -->
<swp-activity-date-group>
<swp-activity-date-header>15. marts 2024</swp-activity-date-header>
<swp-activity-item>
<swp-activity-icon class="system"></swp-activity-icon>
<swp-activity-content>
<swp-activity-title>
<strong>Kunde oprettet</strong>
</swp-activity-title>
<swp-activity-meta>
<swp-activity-time>10:30</swp-activity-time>
<swp-activity-actor>Nina K.</swp-activity-actor>
</swp-activity-meta>
<swp-activity-details>
Oprettet manuelt ved første besøg. Kilde: Walk-in
</swp-activity-details>
</swp-activity-content>
</swp-activity-item>
</swp-activity-date-group>
</swp-activity-timeline>
<swp-activity-load-more>Indlæs ældre aktivitet...</swp-activity-load-more>
</swp-card>
</swp-tab-content>
<script>
// ==========================================
// TAB SWITCHING
// ==========================================
document.querySelectorAll('swp-tab').forEach(tab => {
tab.addEventListener('click', () => {
const tabName = tab.dataset.tab;
// Update tab active state
document.querySelectorAll('swp-tab').forEach(t => t.classList.remove('active'));
tab.classList.add('active');
// Update content visibility
document.querySelectorAll('swp-tab-content').forEach(content => {
content.classList.remove('active');
if (content.dataset.tab === tabName) {
content.classList.add('active');
}
});
});
});
// ==========================================
// TOGGLE SLIDERS (Ja/Nej)
// ==========================================
document.querySelectorAll('swp-toggle-slider').forEach(slider => {
const options = slider.querySelectorAll('swp-toggle-option');
options.forEach((option, index) => {
option.addEventListener('click', () => {
slider.dataset.value = index === 0 ? 'yes' : 'no';
});
});
});
// ==========================================
// TAG REMOVAL
// ==========================================
document.querySelectorAll('swp-tag .remove').forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
btn.closest('swp-tag').remove();
});
});
// ==========================================
// BOOKING EXCLUSION TOGGLE
// ==========================================
const bookingExclusion = document.getElementById('bookingExclusion');
bookingExclusion.addEventListener('click', () => {
const isExcluded = bookingExclusion.dataset.excluded === 'true';
bookingExclusion.dataset.excluded = isExcluded ? 'false' : 'true';
const icon = bookingExclusion.querySelector('.icon');
const text = bookingExclusion.querySelector('.text');
if (isExcluded) {
icon.textContent = '✓';
text.textContent = 'Booking tilladt';
} else {
icon.textContent = '✕';
text.textContent = 'Udelukket fra booking';
}
});
// ==========================================
// CUSTOMER GROUP DROPDOWN
// ==========================================
const customerGroupSelect = document.getElementById('customerGroupSelect');
const customerGroupDropdown = document.getElementById('customerGroupDropdown');
customerGroupSelect.addEventListener('click', (e) => {
e.stopPropagation();
customerGroupDropdown.classList.toggle('open');
});
document.querySelectorAll('swp-customer-group-option').forEach(option => {
option.addEventListener('click', () => {
// Update selection
document.querySelectorAll('swp-customer-group-option').forEach(o => o.classList.remove('selected'));
option.classList.add('selected');
// Update display
customerGroupSelect.querySelector('.value').textContent = option.textContent;
// Close dropdown
customerGroupDropdown.classList.remove('open');
});
});
// Close dropdown when clicking outside
document.addEventListener('click', () => {
customerGroupDropdown.classList.remove('open');
});
// ==========================================
// RELATION REMOVE
// ==========================================
document.querySelectorAll('swp-relation-remove').forEach(btn => {
btn.addEventListener('click', () => {
btn.closest('swp-relation-item').remove();
});
});
// ==========================================
// SAVE BUTTON
// ==========================================
const saveBtn = document.getElementById('saveBtn');
saveBtn.addEventListener('click', () => {
// Simulate save
saveBtn.textContent = 'Gemt!';
saveBtn.style.background = 'var(--color-green)';
setTimeout(() => {
saveBtn.textContent = 'Gem';
saveBtn.style.background = '';
}, 2000);
});
// ==========================================
// CHART (lazy load)
// ==========================================
let chartLoaded = false;
function loadChart() {
if (chartLoaded) return;
import('https://unpkg.com/@sevenweirdpeople/swp-charting@latest/dist/index.js')
.then(module => {
const { createChart } = module;
createChart(document.getElementById('revenueChart'), {
width: 1100,
height: 200,
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec']
},
series: [
{
name: 'Services',
color: '#00897b',
data: [
{ x: 'Mar', y: 1200 },
{ x: 'Apr', y: 800 },
{ x: 'Jun', y: 1500 },
{ x: 'Aug', y: 1600 },
{ x: 'Sep', y: 750 },
{ x: 'Okt', y: 550 },
{ x: 'Nov', y: 1200 },
{ x: 'Dec', y: 1450 }
]
},
{
name: 'Produkter',
color: '#1976d2',
data: [
{ x: 'Apr', y: 250 },
{ x: 'Jun', y: 180 },
{ x: 'Sep', y: 320 },
{ x: 'Dec', y: 349 }
]
}
],
legend: false
});
chartLoaded = true;
});
}
// Load chart when Økonomi tab is shown
document.querySelector('swp-tab[data-tab="economy"]').addEventListener('click', loadChart);
// ==========================================
// JOURNAL MINI TABS
// ==========================================
document.querySelectorAll('swp-journal-mini-tab').forEach(tab => {
tab.addEventListener('click', () => {
document.querySelectorAll('swp-journal-mini-tab').forEach(t => t.classList.remove('active'));
tab.classList.add('active');
// In a real app, this would filter the entries
});
});
// ==========================================
// JOURNAL ENTRY DELETE
// ==========================================
document.querySelectorAll('swp-journal-entry-delete-new').forEach(btn => {
btn.addEventListener('click', () => {
btn.closest('swp-journal-entry-new').remove();
});
});
// ==========================================
// ACTIVITY FILTERS
// ==========================================
document.querySelectorAll('swp-activity-filter').forEach(filter => {
filter.addEventListener('click', () => {
document.querySelectorAll('swp-activity-filter').forEach(f => f.classList.remove('active'));
filter.classList.add('active');
// In a real app, this would filter the activity items
});
});
</script>
</body>
</html>