Introduces new analysis functionality for hair and scalp tracking Adds dynamic preview, form interactions, and styling for analysis entries Enables users to log detailed hair and scalp condition assessments
3452 lines
109 KiB
HTML
3452 lines
109 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="da">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Detail Drawer POC</title>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
<style>
|
|
/* Import design tokens fra calendar-base.css */
|
|
:root {
|
|
--hour-height: 64px;
|
|
--time-axis-width: 60px;
|
|
--header-height: 70px;
|
|
|
|
/* Colors - UI */
|
|
--color-border: #e0e0e0;
|
|
--color-surface: #fff;
|
|
--color-background: #f5f5f5;
|
|
--color-background-hover: #f0f0f0;
|
|
--color-background-alt: #fafafa;
|
|
--color-text: #333333;
|
|
--color-text-secondary: #666;
|
|
--color-primary: #1976d2;
|
|
|
|
/* Named color palette */
|
|
--b-color-blue: #1e88e5;
|
|
--b-color-green: #43a047;
|
|
--b-color-red: #e53935;
|
|
--b-color-amber: #ffb300;
|
|
--b-color-purple: #8e24aa;
|
|
--b-color-teal: #00897b;
|
|
--b-mix: #fff;
|
|
|
|
/* Checkout style tokens */
|
|
--color-teal: #00897b;
|
|
--font-mono: 'JetBrains Mono', monospace;
|
|
|
|
/* Shadows */
|
|
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
|
|
/* Transitions */
|
|
--transition-fast: 150ms ease;
|
|
}
|
|
|
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
background: var(--color-background);
|
|
}
|
|
|
|
/* Demo layout */
|
|
.demo-container {
|
|
padding: 16px;
|
|
}
|
|
|
|
.demo-buttons {
|
|
display: flex;
|
|
gap: 8px;
|
|
margin-bottom: 16px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.demo-btn {
|
|
padding: 6px 12px;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
background: var(--color-surface);
|
|
font-size: 12px;
|
|
transition: background var(--transition-fast);
|
|
}
|
|
|
|
.demo-btn:hover {
|
|
background: var(--color-background-hover);
|
|
}
|
|
|
|
.demo-btn-primary {
|
|
background: var(--color-primary);
|
|
color: white;
|
|
border-color: var(--color-primary);
|
|
}
|
|
|
|
.demo-btn-primary:hover {
|
|
background: #1565c0;
|
|
}
|
|
|
|
/* Calendar mock */
|
|
.calendar-mock {
|
|
background: var(--color-surface);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 4px;
|
|
height: 500px;
|
|
display: grid;
|
|
grid-template-columns: repeat(5, 1fr);
|
|
}
|
|
|
|
.calendar-mock-column {
|
|
border-right: 1px solid var(--color-border);
|
|
padding: 8px;
|
|
}
|
|
|
|
.calendar-mock-column:last-child {
|
|
border-right: none;
|
|
}
|
|
|
|
.mock-event {
|
|
--b-primary: var(--b-color-blue);
|
|
background-color: color-mix(in srgb, var(--b-primary) 10%, var(--b-mix));
|
|
border-left: 4px solid var(--b-primary);
|
|
padding: 4px 6px;
|
|
margin-bottom: 8px;
|
|
border-radius: 3px;
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
transition: background-color 200ms ease;
|
|
}
|
|
|
|
.mock-event:hover {
|
|
background-color: color-mix(in srgb, var(--b-primary) 15%, var(--b-mix));
|
|
}
|
|
|
|
.mock-event-time {
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.mock-event-title {
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
/* ==========================================
|
|
DETAIL DRAWER
|
|
========================================== */
|
|
|
|
swp-detail-drawer-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
background: rgba(0, 0, 0, 0.2);
|
|
opacity: 0;
|
|
visibility: hidden;
|
|
transition: opacity 200ms ease, visibility 200ms ease;
|
|
z-index: 900;
|
|
}
|
|
|
|
swp-detail-drawer-overlay.open {
|
|
opacity: 1;
|
|
visibility: visible;
|
|
}
|
|
|
|
swp-detail-drawer {
|
|
position: fixed;
|
|
top: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
width: 340px;
|
|
background: var(--color-surface);
|
|
border-left: 1px solid var(--color-border);
|
|
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
|
|
transform: translateX(100%);
|
|
transition: transform 200ms ease;
|
|
display: flex;
|
|
flex-direction: column;
|
|
z-index: 1000; /* Drawer 1 - top */
|
|
}
|
|
|
|
swp-detail-drawer.open {
|
|
transform: translateX(0);
|
|
}
|
|
|
|
/* Drawer header */
|
|
swp-drawer-header {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2px;
|
|
padding: 0;
|
|
border-bottom: 1px solid var(--color-border);
|
|
}
|
|
|
|
swp-drawer-title {
|
|
display: flex;
|
|
justify-content: center;
|
|
padding: 14px 16px;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
background: var(--color-background);
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
swp-drawer-title.source-web {
|
|
--b-primary: var(--b-color-blue);
|
|
background: color-mix(in srgb, var(--b-primary) 15%, var(--b-mix));
|
|
color: var(--b-primary);
|
|
}
|
|
|
|
swp-drawer-title.source-recurring {
|
|
--b-primary: var(--b-color-purple);
|
|
background: color-mix(in srgb, var(--b-primary) 15%, var(--b-mix));
|
|
color: var(--b-primary);
|
|
}
|
|
|
|
swp-drawer-title.source-manual {
|
|
--b-primary: var(--b-color-teal);
|
|
background: color-mix(in srgb, var(--b-primary) 15%, var(--b-mix));
|
|
color: var(--b-primary);
|
|
}
|
|
|
|
swp-created-date {
|
|
font-size: 10px;
|
|
color: var(--color-text-secondary);
|
|
opacity: 0.8;
|
|
padding: 4px 16px 8px;
|
|
text-align: right;
|
|
background: var(--color-background-alt);
|
|
}
|
|
|
|
/* Drawer content */
|
|
swp-drawer-content {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: 16px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 16px;
|
|
}
|
|
|
|
/* Section styling */
|
|
swp-drawer-section {
|
|
display: block;
|
|
}
|
|
|
|
swp-section-label {
|
|
display: block;
|
|
font-size: 11px;
|
|
font-weight: 400;
|
|
color: var(--color-text-secondary);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
/* Event time/date */
|
|
swp-event-info {
|
|
display: block;
|
|
padding-bottom: 16px;
|
|
border-bottom: 1px solid var(--color-border);
|
|
}
|
|
|
|
swp-event-time-display {
|
|
display: block;
|
|
font-size: 20px;
|
|
font-weight: 500;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
swp-event-date-display {
|
|
display: block;
|
|
font-size: 14px;
|
|
color: var(--color-text-secondary);
|
|
margin-top: 2px;
|
|
}
|
|
|
|
/* Customer section */
|
|
swp-customer-info {
|
|
display: block;
|
|
}
|
|
|
|
swp-customer-row {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 12px;
|
|
}
|
|
|
|
swp-customer-name {
|
|
font-size: 18px;
|
|
font-weight: 500;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
swp-customer-phone {
|
|
font-size: 14px;
|
|
color: var(--color-teal);
|
|
}
|
|
|
|
swp-customer-phone a {
|
|
color: var(--color-teal);
|
|
text-decoration: none;
|
|
}
|
|
|
|
swp-customer-phone a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
swp-customer-details-link {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
font-size: 13px;
|
|
color: var(--color-text-secondary);
|
|
cursor: pointer;
|
|
margin-top: 6px;
|
|
transition: color 150ms ease;
|
|
}
|
|
|
|
swp-customer-details-link:hover {
|
|
color: var(--color-teal);
|
|
}
|
|
|
|
/* Chevron icon styling */
|
|
.link-chevron {
|
|
width: 18px;
|
|
height: 18px;
|
|
transition: transform 200ms ease;
|
|
filter: invert(45%) sepia(0%) saturate(0%) brightness(90%);
|
|
}
|
|
|
|
swp-customer-details-link:hover .link-chevron,
|
|
swp-journal-details-link:hover .link-chevron {
|
|
filter: invert(32%) sepia(98%) saturate(1234%) hue-rotate(152deg) brightness(93%) contrast(92%);
|
|
}
|
|
|
|
swp-customer-details-link.panel-open .link-chevron,
|
|
swp-journal-details-link.panel-open .link-chevron {
|
|
transform: rotate(90deg);
|
|
}
|
|
|
|
/* Status */
|
|
swp-status-row {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 10px 12px;
|
|
background: var(--color-background-alt);
|
|
border-radius: 4px;
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
|
|
swp-status-label {
|
|
font-size: 14px;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
swp-status-dot {
|
|
width: 6px;
|
|
height: 6px;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
/* Status variants - using color-mix like events */
|
|
.status-badge.status-created {
|
|
--b-primary: var(--b-color-purple);
|
|
background: color-mix(in srgb, var(--b-primary) 15%, var(--b-mix));
|
|
color: var(--b-primary);
|
|
}
|
|
.status-badge.status-created swp-status-dot { background: var(--b-color-purple); }
|
|
|
|
.status-badge.status-arrived {
|
|
--b-primary: var(--b-color-green);
|
|
background: color-mix(in srgb, var(--b-primary) 15%, var(--b-mix));
|
|
color: var(--b-primary);
|
|
}
|
|
.status-badge.status-arrived swp-status-dot { background: var(--b-color-green); }
|
|
|
|
.status-badge.status-paid {
|
|
--b-primary: var(--b-color-blue);
|
|
background: color-mix(in srgb, var(--b-primary) 15%, var(--b-mix));
|
|
color: var(--b-primary);
|
|
}
|
|
.status-badge.status-paid swp-status-dot { background: var(--b-color-blue); }
|
|
|
|
.status-badge.status-noshow {
|
|
--b-primary: var(--b-color-red);
|
|
background: color-mix(in srgb, var(--b-primary) 15%, var(--b-mix));
|
|
color: var(--b-primary);
|
|
}
|
|
.status-badge.status-noshow swp-status-dot { background: var(--b-color-red); }
|
|
|
|
.status-badge.status-cancelled {
|
|
background: var(--color-background-alt);
|
|
color: var(--color-text-secondary);
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
.status-badge.status-cancelled swp-status-dot { background: var(--color-text-secondary); }
|
|
|
|
/* Services list */
|
|
swp-services-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
swp-service-item {
|
|
--b-primary: var(--b-color-blue);
|
|
display: block;
|
|
padding: 10px 12px;
|
|
background: color-mix(in srgb, var(--b-primary) 5%, var(--b-mix));
|
|
border-left: 3px solid var(--b-primary);
|
|
border-radius: 3px;
|
|
}
|
|
|
|
swp-service-name {
|
|
display: block;
|
|
font-size: 15px;
|
|
font-weight: 500;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
swp-service-details {
|
|
display: block;
|
|
font-size: 13px;
|
|
color: var(--color-text-secondary);
|
|
margin-top: 2px;
|
|
}
|
|
|
|
swp-service-price {
|
|
font-family: var(--font-mono);
|
|
font-weight: 500;
|
|
}
|
|
|
|
swp-service-resource {
|
|
display: block;
|
|
font-size: 13px;
|
|
color: var(--color-text-secondary);
|
|
margin-top: 4px;
|
|
opacity: 0.8;
|
|
}
|
|
|
|
/* Total */
|
|
swp-total-row {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 12px 0;
|
|
border-top: 1px solid var(--color-border);
|
|
border-bottom: 1px solid var(--color-border);
|
|
margin-top: 4px;
|
|
}
|
|
|
|
swp-total-label {
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
swp-total-amount {
|
|
font-family: var(--font-mono);
|
|
font-size: 24px;
|
|
font-weight: 700;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
/* Notes */
|
|
swp-notes-box {
|
|
display: block;
|
|
padding: 10px 12px;
|
|
background: color-mix(in srgb, var(--b-color-amber) 10%, var(--b-mix));
|
|
border-left: 3px solid var(--b-color-amber);
|
|
border-radius: 3px;
|
|
font-size: 14px;
|
|
color: var(--color-text);
|
|
font-style: italic;
|
|
}
|
|
|
|
/* Journal link */
|
|
swp-journal-link {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
padding: 12px;
|
|
background: var(--color-surface);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
transition: all var(--transition-fast);
|
|
}
|
|
|
|
swp-journal-link:hover {
|
|
background: var(--color-background-hover);
|
|
border-color: var(--color-teal);
|
|
}
|
|
|
|
swp-journal-icon {
|
|
width: 20px;
|
|
height: 20px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
swp-journal-icon img {
|
|
width: 20px;
|
|
height: 20px;
|
|
filter: invert(22%) sepia(14%) saturate(1042%) hue-rotate(164deg) brightness(102%) contrast(85%);
|
|
transition: filter 150ms ease;
|
|
}
|
|
|
|
swp-journal-link:hover swp-journal-icon img {
|
|
filter: invert(32%) sepia(98%) saturate(1234%) hue-rotate(196deg) brightness(93%) contrast(92%);
|
|
}
|
|
|
|
swp-journal-link.no-journal swp-journal-icon img {
|
|
filter: invert(45%) sepia(8%) saturate(0%) hue-rotate(0deg) brightness(95%) contrast(90%);
|
|
}
|
|
|
|
swp-journal-link.no-journal:hover swp-journal-icon img {
|
|
filter: invert(32%) sepia(98%) saturate(1234%) hue-rotate(196deg) brightness(93%) contrast(92%);
|
|
}
|
|
|
|
swp-journal-text {
|
|
flex: 1;
|
|
font-size: 14px;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
swp-journal-arrow {
|
|
font-size: 14px;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
/* Journal not created state */
|
|
swp-journal-link.no-journal {
|
|
border-style: dashed;
|
|
background: var(--color-background-alt);
|
|
}
|
|
|
|
swp-journal-link.no-journal swp-journal-text {
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
swp-journal-link.no-journal:hover {
|
|
background: var(--color-surface);
|
|
border-color: var(--color-teal);
|
|
border-style: solid;
|
|
}
|
|
|
|
/* Journal Panel - slides out from left of drawer */
|
|
swp-journal-panel {
|
|
position: fixed;
|
|
top: 0;
|
|
right: 340px;
|
|
bottom: 0;
|
|
width: 440px;
|
|
background: var(--color-surface);
|
|
border-left: 1px solid var(--color-border);
|
|
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
|
|
transform: translateX(100%);
|
|
opacity: 0;
|
|
transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1),
|
|
opacity 200ms ease;
|
|
display: flex;
|
|
flex-direction: column;
|
|
z-index: 990; /* Drawer 2 - middle */
|
|
}
|
|
|
|
swp-journal-panel.open {
|
|
transform: translateX(0);
|
|
opacity: 1;
|
|
}
|
|
|
|
swp-journal-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 16px 20px;
|
|
border-bottom: 1px solid var(--color-border);
|
|
background: var(--color-background-alt);
|
|
}
|
|
|
|
swp-journal-header-title {
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
swp-journal-close {
|
|
background: none;
|
|
border: none;
|
|
font-size: 18px;
|
|
color: var(--color-text-secondary);
|
|
cursor: pointer;
|
|
padding: 4px 8px;
|
|
border-radius: 4px;
|
|
transition: background 150ms ease;
|
|
}
|
|
|
|
swp-journal-close:hover {
|
|
background: var(--color-background-hover);
|
|
}
|
|
|
|
/* Journal Tabs - Traditional style */
|
|
swp-journal-tabs {
|
|
display: flex;
|
|
padding: 0 20px;
|
|
background: var(--color-background-alt);
|
|
border-bottom: 1px solid var(--color-border);
|
|
}
|
|
|
|
swp-journal-tab {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 14px 18px;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
color: var(--color-text-secondary);
|
|
background: transparent;
|
|
border: none;
|
|
border-bottom: 2px solid transparent;
|
|
margin-bottom: -1px;
|
|
cursor: pointer;
|
|
transition: all 150ms ease;
|
|
}
|
|
|
|
swp-journal-tab:hover:not(.disabled) {
|
|
color: var(--color-text);
|
|
background: var(--color-background-hover);
|
|
}
|
|
|
|
swp-journal-tab.active {
|
|
color: var(--color-text);
|
|
background: var(--color-surface);
|
|
border-bottom-color: var(--color-teal);
|
|
}
|
|
|
|
swp-journal-tab.disabled {
|
|
opacity: 0.5;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.tab-indicator {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 2px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.tab-indicator.blue {
|
|
background: var(--b-color-blue);
|
|
}
|
|
|
|
.tab-indicator.amber {
|
|
background: var(--b-color-amber);
|
|
}
|
|
|
|
.tab-indicator.gray {
|
|
background: var(--color-text-secondary);
|
|
}
|
|
|
|
.tab-indicator.purple {
|
|
background: #8b5cf6;
|
|
}
|
|
|
|
/* Tab Content Container */
|
|
swp-journal-tab-content {
|
|
display: none;
|
|
flex-direction: column;
|
|
flex: 1;
|
|
overflow: hidden;
|
|
}
|
|
|
|
swp-journal-tab-content.active {
|
|
display: flex;
|
|
}
|
|
|
|
/* Tab Content Header */
|
|
swp-journal-tab-header {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
padding: 16px 20px;
|
|
border-bottom: 1px solid var(--color-border);
|
|
}
|
|
|
|
swp-journal-tab-title {
|
|
font-size: 15px;
|
|
font-weight: 600;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
swp-journal-tab-title span {
|
|
font-weight: 400;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
swp-journal-tab-desc {
|
|
font-size: 12px;
|
|
color: var(--color-text-secondary);
|
|
line-height: 1.4;
|
|
}
|
|
|
|
swp-journal-add-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
padding: 8px 14px;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
color: white;
|
|
background: var(--color-teal);
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
margin-top: 4px;
|
|
align-self: flex-start;
|
|
transition: background 150ms ease;
|
|
}
|
|
|
|
swp-journal-add-btn:hover {
|
|
background: #00796b;
|
|
}
|
|
|
|
/* Journal Content */
|
|
swp-journal-content {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: 16px 20px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
}
|
|
|
|
/* Journal Entry Card */
|
|
swp-journal-entry {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
padding: 14px 16px;
|
|
background: var(--color-background-alt);
|
|
border-radius: 8px;
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
|
|
swp-journal-entry-meta {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
swp-journal-entry-type {
|
|
padding: 4px 10px;
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
color: var(--b-color-blue);
|
|
background: color-mix(in srgb, var(--b-color-blue) 15%, var(--b-mix));
|
|
border-radius: 4px;
|
|
}
|
|
|
|
swp-journal-entry-type.farveformel {
|
|
color: var(--color-teal);
|
|
background: color-mix(in srgb, var(--color-teal) 15%, var(--b-mix));
|
|
}
|
|
|
|
swp-journal-entry-type.analyse {
|
|
color: #7c3aed;
|
|
background: color-mix(in srgb, #8b5cf6 15%, var(--b-mix));
|
|
}
|
|
|
|
swp-journal-entry-date {
|
|
font-size: 12px;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
swp-journal-entry-author {
|
|
font-size: 12px;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
swp-journal-entry-tags {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 6px;
|
|
margin-left: auto;
|
|
}
|
|
|
|
swp-journal-tag {
|
|
padding: 3px 10px;
|
|
font-size: 11px;
|
|
color: var(--color-text-secondary);
|
|
background: var(--color-surface);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 12px;
|
|
}
|
|
|
|
/* Tag Colors - Journal Panel */
|
|
swp-journal-tag.tag-note,
|
|
swp-journal-tag:contains('Fri note') {
|
|
background: color-mix(in srgb, var(--b-color-blue) 15%, var(--b-mix));
|
|
border-color: var(--b-color-blue);
|
|
color: var(--b-color-blue);
|
|
}
|
|
swp-journal-tag.tag-sensitiv {
|
|
background: color-mix(in srgb, #8b5cf6 15%, var(--b-mix));
|
|
border-color: #8b5cf6;
|
|
color: #7c3aed;
|
|
}
|
|
swp-journal-tag.tag-allergi {
|
|
background: color-mix(in srgb, var(--b-color-red) 15%, var(--b-mix));
|
|
border-color: var(--b-color-red);
|
|
color: var(--b-color-red);
|
|
}
|
|
swp-journal-tag.tag-praference {
|
|
background: color-mix(in srgb, var(--color-teal) 15%, var(--b-mix));
|
|
border-color: var(--color-teal);
|
|
color: var(--color-teal);
|
|
}
|
|
swp-journal-tag.tag-anbefaling {
|
|
background: color-mix(in srgb, var(--b-color-amber) 15%, var(--b-mix));
|
|
border-color: var(--b-color-amber);
|
|
color: #b45309;
|
|
}
|
|
|
|
/* Farveformel Tags */
|
|
swp-journal-tag.tag-farveformel {
|
|
background: color-mix(in srgb, var(--color-teal) 15%, var(--b-mix));
|
|
border-color: var(--color-teal);
|
|
color: var(--color-teal);
|
|
}
|
|
swp-journal-tag.tag-kold-tone {
|
|
background: color-mix(in srgb, var(--b-color-blue) 15%, var(--b-mix));
|
|
border-color: var(--b-color-blue);
|
|
color: var(--b-color-blue);
|
|
}
|
|
swp-journal-tag.tag-toning {
|
|
background: color-mix(in srgb, #8b5cf6 15%, var(--b-mix));
|
|
border-color: #8b5cf6;
|
|
color: #7c3aed;
|
|
}
|
|
swp-journal-tag.tag-balayage {
|
|
background: color-mix(in srgb, var(--b-color-amber) 15%, var(--b-mix));
|
|
border-color: var(--b-color-amber);
|
|
color: #b45309;
|
|
}
|
|
|
|
swp-journal-entry-delete {
|
|
padding: 4px 6px;
|
|
font-size: 14px;
|
|
color: var(--color-text-secondary);
|
|
cursor: pointer;
|
|
border-radius: 4px;
|
|
transition: all 150ms ease;
|
|
opacity: 0.6;
|
|
}
|
|
|
|
swp-journal-entry-delete:hover {
|
|
color: var(--b-color-red);
|
|
background: color-mix(in srgb, var(--b-color-red) 10%, var(--b-mix));
|
|
opacity: 1;
|
|
}
|
|
|
|
swp-journal-entry-text {
|
|
font-size: 13px;
|
|
color: var(--color-text);
|
|
line-height: 1.5;
|
|
white-space: pre-line;
|
|
}
|
|
|
|
swp-journal-entry-text .mono {
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
/* Entry Footer - Dato, Synlighed & Markering */
|
|
swp-journal-entry-footer {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-top: 10px;
|
|
padding-top: 10px;
|
|
border-top: 1px solid var(--color-border);
|
|
}
|
|
|
|
swp-journal-entry-footer swp-journal-entry-date {
|
|
font-size: 12px;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
swp-journal-entry-icons {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
|
|
swp-journal-entry-visibility,
|
|
swp-journal-entry-marking {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
font-size: 11px;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
swp-journal-entry-visibility .entry-icon,
|
|
swp-journal-entry-marking .entry-icon {
|
|
width: 18px;
|
|
height: 18px;
|
|
filter: invert(22%) sepia(14%) saturate(1042%) hue-rotate(164deg) brightness(102%) contrast(85%);
|
|
}
|
|
|
|
swp-journal-entry-marking.hidden {
|
|
display: none;
|
|
}
|
|
|
|
/* Preview Entry */
|
|
swp-journal-entry.preview {
|
|
border: 2px dashed var(--color-teal);
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
transition: opacity 200ms ease, transform 200ms ease, max-height 300ms ease;
|
|
max-height: 2000px;
|
|
}
|
|
|
|
swp-journal-entry.preview.hidden {
|
|
opacity: 0;
|
|
transform: translateY(-20px);
|
|
max-height: 0;
|
|
margin: 0;
|
|
padding: 0;
|
|
overflow: hidden;
|
|
border: none;
|
|
}
|
|
|
|
/* Journal Profile Section */
|
|
swp-journal-profile-section {
|
|
padding: 16px 20px;
|
|
border-top: 1px solid var(--color-border);
|
|
background: var(--color-surface);
|
|
}
|
|
|
|
swp-journal-profile-toggle {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
font-size: 13px;
|
|
color: var(--color-teal);
|
|
cursor: pointer;
|
|
transition: color 150ms ease;
|
|
}
|
|
|
|
swp-journal-profile-toggle:hover {
|
|
color: #00796b;
|
|
}
|
|
|
|
swp-journal-profile-toggle .toggle-arrow {
|
|
font-size: 10px;
|
|
transition: transform 200ms ease;
|
|
}
|
|
|
|
swp-journal-profile-toggle.collapsed .toggle-arrow {
|
|
transform: rotate(-90deg);
|
|
}
|
|
|
|
swp-journal-profile-boxes {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 8px;
|
|
margin-top: 12px;
|
|
max-height: 200px;
|
|
overflow: hidden;
|
|
transition: max-height 200ms ease, margin-top 200ms ease, opacity 200ms ease;
|
|
}
|
|
|
|
swp-journal-profile-boxes.collapsed {
|
|
max-height: 0;
|
|
margin-top: 0;
|
|
opacity: 0;
|
|
}
|
|
|
|
/* Customer Details Panel - double width drawer, slides under like journal */
|
|
swp-customer-panel {
|
|
position: fixed;
|
|
top: 0;
|
|
right: 340px;
|
|
bottom: 0;
|
|
width: 680px;
|
|
background: var(--color-surface);
|
|
border-left: 1px solid var(--color-border);
|
|
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
|
|
transform: translateX(100%);
|
|
opacity: 0;
|
|
transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1),
|
|
opacity 200ms ease;
|
|
display: flex;
|
|
flex-direction: column;
|
|
z-index: 1000;
|
|
overflow: hidden;
|
|
}
|
|
|
|
swp-customer-panel.open {
|
|
transform: translateX(0);
|
|
opacity: 1;
|
|
}
|
|
|
|
swp-customer-panel-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 20px 24px;
|
|
border-bottom: 1px solid var(--color-border);
|
|
background: var(--color-background-alt);
|
|
}
|
|
|
|
swp-customer-panel-title {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
.panel-header-icon {
|
|
width: 20px;
|
|
height: 20px;
|
|
filter: invert(22%) sepia(14%) saturate(1042%) hue-rotate(164deg) brightness(102%) contrast(85%);
|
|
}
|
|
|
|
swp-customer-panel-close {
|
|
background: none;
|
|
border: none;
|
|
font-size: 20px;
|
|
color: var(--color-text-secondary);
|
|
cursor: pointer;
|
|
padding: 4px 8px;
|
|
border-radius: 4px;
|
|
transition: background 150ms ease;
|
|
}
|
|
|
|
swp-customer-panel-close:hover {
|
|
background: var(--color-background-hover);
|
|
}
|
|
|
|
swp-customer-panel-content {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
overflow-x: hidden;
|
|
padding: 24px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 24px;
|
|
min-height: 0;
|
|
}
|
|
|
|
/* Customer info header */
|
|
swp-customer-header-section {
|
|
display: flex;
|
|
gap: 24px;
|
|
padding-bottom: 20px;
|
|
border-bottom: 1px solid var(--color-border);
|
|
}
|
|
|
|
swp-customer-avatar {
|
|
width: 80px;
|
|
height: 80px;
|
|
border-radius: 50%;
|
|
background: linear-gradient(135deg, var(--color-teal), #4db6ac);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 32px;
|
|
font-weight: 600;
|
|
color: white;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
swp-customer-header-info {
|
|
flex: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
}
|
|
|
|
swp-customer-header-top {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
swp-customer-header-left {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
}
|
|
|
|
swp-customer-header-name {
|
|
font-size: 24px;
|
|
font-weight: 600;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
swp-customer-header-contact {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
align-items: flex-end;
|
|
}
|
|
|
|
swp-customer-header-contact-item {
|
|
font-size: 14px;
|
|
}
|
|
|
|
swp-customer-header-contact-item a {
|
|
color: var(--color-teal);
|
|
text-decoration: none;
|
|
}
|
|
|
|
swp-customer-header-contact-item a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
swp-customer-since {
|
|
font-size: 12px;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
/* Fact boxes grid */
|
|
swp-fact-boxes {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
gap: 16px;
|
|
}
|
|
|
|
swp-fact-box {
|
|
padding: 16px;
|
|
background: var(--color-background-alt);
|
|
border-radius: 8px;
|
|
border: 1px solid var(--color-border);
|
|
text-align: center;
|
|
}
|
|
|
|
swp-fact-box-value {
|
|
display: block;
|
|
font-family: var(--font-mono);
|
|
font-size: 20px;
|
|
font-weight: 700;
|
|
color: var(--color-text);
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
swp-fact-box-label {
|
|
display: block;
|
|
font-size: 11px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
swp-fact-box.highlight {
|
|
background: linear-gradient(135deg, rgba(0, 137, 123, 0.1), rgba(0, 137, 123, 0.05));
|
|
border-color: var(--color-teal);
|
|
}
|
|
|
|
swp-fact-box.highlight swp-fact-box-value {
|
|
color: var(--color-teal);
|
|
}
|
|
|
|
/* Chart section */
|
|
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;
|
|
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(--b-color-blue);
|
|
}
|
|
|
|
swp-chart-container {
|
|
display: block;
|
|
background: var(--color-background-alt);
|
|
border-radius: 8px;
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
|
|
/* Products list */
|
|
swp-products-section {
|
|
display: block;
|
|
}
|
|
|
|
swp-products-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
swp-product-item {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 12px 14px;
|
|
background: var(--color-background-alt);
|
|
border-radius: 6px;
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
|
|
swp-product-info {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2px;
|
|
}
|
|
|
|
swp-product-name {
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
swp-product-date {
|
|
font-size: 12px;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
swp-product-price {
|
|
font-family: var(--font-mono);
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
/* Preferences section */
|
|
swp-preferences-section {
|
|
display: block;
|
|
}
|
|
|
|
swp-preferences-grid {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 12px;
|
|
}
|
|
|
|
swp-preference-item {
|
|
padding: 12px 14px;
|
|
background: var(--color-background-alt);
|
|
border-radius: 6px;
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
|
|
swp-preference-label {
|
|
display: block;
|
|
font-size: 11px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
color: var(--color-text-secondary);
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
swp-preference-value {
|
|
font-size: 14px;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
/* Customer stats */
|
|
swp-stats-grid {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 8px;
|
|
}
|
|
|
|
swp-stat-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding: 10px 12px;
|
|
background: var(--color-background-alt);
|
|
border-radius: 4px;
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
|
|
swp-stat-value {
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
swp-stat-value.mono {
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
swp-stat-label {
|
|
font-size: 11px;
|
|
color: var(--color-text-secondary);
|
|
margin-top: 2px;
|
|
}
|
|
|
|
/* Profile boxes */
|
|
swp-profile-boxes {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 8px;
|
|
}
|
|
|
|
swp-profile-box {
|
|
padding: 10px 12px;
|
|
background: var(--color-background-alt);
|
|
border-radius: 4px;
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
|
|
swp-profile-box.warning {
|
|
background: color-mix(in srgb, var(--b-color-amber) 10%, var(--b-mix));
|
|
border-color: var(--b-color-amber);
|
|
}
|
|
|
|
swp-profile-box-label {
|
|
display: block;
|
|
font-size: 10px;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
color: var(--color-text-secondary);
|
|
margin-bottom: 3px;
|
|
}
|
|
|
|
swp-profile-box.warning swp-profile-box-label {
|
|
color: #b8860b;
|
|
}
|
|
|
|
swp-profile-box-value {
|
|
display: block;
|
|
font-size: 12px;
|
|
color: var(--color-text);
|
|
line-height: 1.3;
|
|
}
|
|
|
|
swp-journal-details-link {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
font-size: 13px;
|
|
color: var(--color-text-secondary);
|
|
cursor: pointer;
|
|
margin-top: 10px;
|
|
transition: color 150ms ease;
|
|
}
|
|
|
|
swp-journal-details-link:hover {
|
|
color: var(--color-teal);
|
|
}
|
|
|
|
swp-journal-details-link.no-journal {
|
|
color: var(--color-teal);
|
|
}
|
|
|
|
/* Drawer footer */
|
|
swp-drawer-footer {
|
|
display: flex;
|
|
gap: 8px;
|
|
padding: 16px;
|
|
border-top: 1px solid var(--color-border);
|
|
background: var(--color-surface);
|
|
}
|
|
|
|
swp-footer-btn {
|
|
flex: 1;
|
|
padding: 12px 16px;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 4px;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
cursor: pointer;
|
|
transition: all var(--transition-fast);
|
|
text-align: center;
|
|
}
|
|
|
|
swp-footer-btn.btn-primary {
|
|
background: var(--color-teal);
|
|
color: white;
|
|
border-color: var(--color-teal);
|
|
}
|
|
|
|
swp-footer-btn.btn-primary:hover {
|
|
background: #00796b;
|
|
}
|
|
|
|
swp-footer-btn.btn-secondary {
|
|
background: var(--color-surface);
|
|
color: var(--color-text);
|
|
}
|
|
|
|
swp-footer-btn.btn-secondary:hover {
|
|
background: var(--color-background-hover);
|
|
}
|
|
|
|
/* Footer states based on booking status */
|
|
swp-drawer-footer.status-paid swp-footer-btn.btn-primary {
|
|
background: var(--color-teal);
|
|
border-color: var(--color-teal);
|
|
opacity: 0.7;
|
|
cursor: default;
|
|
}
|
|
|
|
swp-drawer-footer.status-cancelled swp-footer-btn.btn-primary,
|
|
swp-drawer-footer.status-noshow swp-footer-btn.btn-primary {
|
|
background: var(--color-text-secondary);
|
|
border-color: var(--color-text-secondary);
|
|
cursor: not-allowed;
|
|
opacity: 0.6;
|
|
}
|
|
|
|
/* ==========================================
|
|
STATUS DROPDOWN (Popover API)
|
|
========================================== */
|
|
|
|
swp-status-row {
|
|
position: relative;
|
|
anchor-name: --status-row;
|
|
}
|
|
|
|
.status-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 3px 8px;
|
|
border: none;
|
|
border-radius: 3px;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
font-family: inherit;
|
|
cursor: pointer;
|
|
transition: transform var(--transition-fast);
|
|
}
|
|
|
|
.status-badge:hover {
|
|
transform: scale(1.02);
|
|
}
|
|
|
|
#statusText {
|
|
margin-top: -2px;
|
|
}
|
|
|
|
swp-status-dropdown {
|
|
margin: 0;
|
|
padding: 4px;
|
|
background: var(--color-surface);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 4px;
|
|
box-shadow: var(--shadow-md);
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 2px;
|
|
|
|
/* Animation */
|
|
opacity: 0;
|
|
transform: translateY(-8px);
|
|
transition: opacity 150ms ease, transform 150ms ease, display 150ms ease allow-discrete;
|
|
}
|
|
|
|
swp-status-dropdown:popover-open {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
|
|
@starting-style {
|
|
swp-status-dropdown:popover-open {
|
|
opacity: 0;
|
|
transform: translateY(-8px);
|
|
}
|
|
}
|
|
|
|
swp-status-option {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
padding: 6px 10px;
|
|
border-radius: 3px;
|
|
cursor: pointer;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
opacity: 0;
|
|
transform: translateX(10px);
|
|
transition: background var(--transition-fast), opacity 150ms ease, transform 150ms ease;
|
|
}
|
|
|
|
swp-status-dropdown:popover-open swp-status-option {
|
|
opacity: 1;
|
|
transform: translateX(0);
|
|
}
|
|
|
|
/* Stagger animation delays */
|
|
swp-status-dropdown:popover-open swp-status-option:nth-child(1) { transition-delay: 0ms; }
|
|
swp-status-dropdown:popover-open swp-status-option:nth-child(2) { transition-delay: 30ms; }
|
|
swp-status-dropdown:popover-open swp-status-option:nth-child(3) { transition-delay: 60ms; }
|
|
swp-status-dropdown:popover-open swp-status-option:nth-child(4) { transition-delay: 90ms; }
|
|
swp-status-dropdown:popover-open swp-status-option:nth-child(5) { transition-delay: 120ms; }
|
|
|
|
swp-status-option:hover {
|
|
background: var(--color-background-hover);
|
|
}
|
|
|
|
swp-status-option swp-status-dot {
|
|
width: 8px;
|
|
height: 8px;
|
|
}
|
|
|
|
swp-status-option swp-status-check {
|
|
margin-left: auto;
|
|
font-size: 12px;
|
|
opacity: 0;
|
|
}
|
|
|
|
swp-status-option.selected swp-status-check {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* Status option colors */
|
|
swp-status-option.opt-created { color: var(--b-color-purple); }
|
|
swp-status-option.opt-created swp-status-dot { background: var(--b-color-purple); }
|
|
|
|
swp-status-option.opt-arrived { color: var(--b-color-green); }
|
|
swp-status-option.opt-arrived swp-status-dot { background: var(--b-color-green); }
|
|
|
|
swp-status-option.opt-paid { color: var(--b-color-blue); }
|
|
swp-status-option.opt-paid swp-status-dot { background: var(--b-color-blue); }
|
|
|
|
swp-status-option.opt-noshow { color: var(--b-color-red); }
|
|
swp-status-option.opt-noshow swp-status-dot { background: var(--b-color-red); }
|
|
|
|
swp-status-option.opt-cancelled { color: var(--color-text-secondary); }
|
|
swp-status-option.opt-cancelled swp-status-dot { background: var(--color-text-secondary); }
|
|
|
|
/* ==========================================
|
|
ADD NOTE PANEL
|
|
========================================== */
|
|
swp-add-note-panel {
|
|
position: fixed;
|
|
top: 0;
|
|
right: 340px; /* Same as journal - starts behind it */
|
|
bottom: 0;
|
|
width: 440px;
|
|
background: var(--color-surface);
|
|
border-left: 1px solid var(--color-border);
|
|
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
|
|
transform: translateX(0); /* Behind journal panel */
|
|
visibility: hidden;
|
|
transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1),
|
|
visibility 0ms 250ms;
|
|
display: flex;
|
|
flex-direction: column;
|
|
z-index: 980; /* Drawer 3 - bottom */
|
|
}
|
|
|
|
swp-add-note-panel.open {
|
|
transform: translateX(-100%); /* Slide out to the left */
|
|
visibility: visible;
|
|
transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1),
|
|
visibility 0ms 0ms;
|
|
}
|
|
|
|
swp-add-note-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 16px 20px;
|
|
border-bottom: 1px solid var(--color-border);
|
|
background: var(--color-background-alt);
|
|
}
|
|
|
|
swp-add-note-title {
|
|
font-size: 16px;
|
|
font-weight: 600;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
swp-add-note-close {
|
|
cursor: pointer;
|
|
padding: 4px 8px;
|
|
border-radius: 4px;
|
|
font-size: 18px;
|
|
color: var(--color-text-secondary);
|
|
transition: background 150ms ease;
|
|
}
|
|
|
|
swp-add-note-close:hover {
|
|
background: var(--color-background-hover);
|
|
}
|
|
|
|
swp-add-note-content {
|
|
flex: 1;
|
|
overflow-y: auto;
|
|
padding: 20px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 20px;
|
|
}
|
|
|
|
swp-add-note-desc {
|
|
font-size: 13px;
|
|
color: var(--color-text-secondary);
|
|
line-height: 1.4;
|
|
}
|
|
|
|
swp-add-note-field {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
swp-add-note-label {
|
|
font-size: 12px;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
/* Tags */
|
|
swp-add-note-tags {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 8px;
|
|
}
|
|
|
|
swp-add-note-tag-option {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
padding: 6px 14px;
|
|
font-size: 13px;
|
|
border-radius: 16px;
|
|
border: 1px solid var(--color-border);
|
|
cursor: pointer;
|
|
transition: all 150ms ease;
|
|
}
|
|
|
|
swp-add-note-tag-option::before {
|
|
content: '';
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
border: 1px solid var(--color-border);
|
|
transition: all 150ms ease;
|
|
}
|
|
|
|
swp-add-note-tag-option:hover {
|
|
background: var(--color-background-hover);
|
|
}
|
|
|
|
swp-add-note-tag-option.selected {
|
|
background: color-mix(in srgb, var(--b-color-blue) 12%, var(--b-mix));
|
|
border-color: var(--b-color-blue);
|
|
}
|
|
|
|
/* Tag Colors - Add Note Panel */
|
|
swp-add-note-tag-option[data-tag="note"].selected {
|
|
background: color-mix(in srgb, var(--b-color-blue) 15%, var(--b-mix));
|
|
border-color: var(--b-color-blue);
|
|
color: var(--b-color-blue);
|
|
}
|
|
swp-add-note-tag-option[data-tag="sensitiv"].selected {
|
|
background: color-mix(in srgb, #8b5cf6 15%, var(--b-mix));
|
|
border-color: #8b5cf6;
|
|
color: #7c3aed;
|
|
}
|
|
swp-add-note-tag-option[data-tag="allergi"].selected {
|
|
background: color-mix(in srgb, var(--b-color-red) 15%, var(--b-mix));
|
|
border-color: var(--b-color-red);
|
|
color: var(--b-color-red);
|
|
}
|
|
swp-add-note-tag-option[data-tag="praference"].selected {
|
|
background: color-mix(in srgb, var(--color-teal) 15%, var(--b-mix));
|
|
border-color: var(--color-teal);
|
|
color: var(--color-teal);
|
|
}
|
|
swp-add-note-tag-option[data-tag="anbefaling"].selected {
|
|
background: color-mix(in srgb, var(--b-color-amber) 15%, var(--b-mix));
|
|
border-color: var(--b-color-amber);
|
|
color: #b45309;
|
|
}
|
|
/* Farveformel tags */
|
|
swp-add-note-tag-option[data-tag="farveformel"].selected {
|
|
background: color-mix(in srgb, var(--color-teal) 15%, var(--b-mix));
|
|
border-color: var(--color-teal);
|
|
color: var(--color-teal);
|
|
}
|
|
swp-add-note-tag-option[data-tag="kold-tone"].selected {
|
|
background: color-mix(in srgb, var(--b-color-blue) 15%, var(--b-mix));
|
|
border-color: var(--b-color-blue);
|
|
color: var(--b-color-blue);
|
|
}
|
|
swp-add-note-tag-option[data-tag="toning"].selected {
|
|
background: color-mix(in srgb, #8b5cf6 15%, var(--b-mix));
|
|
border-color: #8b5cf6;
|
|
color: #7c3aed;
|
|
}
|
|
swp-add-note-tag-option[data-tag="balayage"].selected {
|
|
background: color-mix(in srgb, var(--b-color-amber) 15%, var(--b-mix));
|
|
border-color: var(--b-color-amber);
|
|
color: #b45309;
|
|
}
|
|
|
|
swp-add-note-tag-option.selected::before {
|
|
background: var(--b-color-blue);
|
|
border-color: var(--b-color-blue);
|
|
}
|
|
swp-add-note-tag-option[data-tag="note"].selected::before {
|
|
background: var(--b-color-blue);
|
|
border-color: var(--b-color-blue);
|
|
}
|
|
swp-add-note-tag-option[data-tag="sensitiv"].selected::before {
|
|
background: #8b5cf6;
|
|
border-color: #8b5cf6;
|
|
}
|
|
swp-add-note-tag-option[data-tag="allergi"].selected::before {
|
|
background: var(--b-color-red);
|
|
border-color: var(--b-color-red);
|
|
}
|
|
swp-add-note-tag-option[data-tag="praference"].selected::before {
|
|
background: var(--color-teal);
|
|
border-color: var(--color-teal);
|
|
}
|
|
swp-add-note-tag-option[data-tag="anbefaling"].selected::before {
|
|
background: var(--b-color-amber);
|
|
border-color: var(--b-color-amber);
|
|
}
|
|
/* Farveformel tags ::before */
|
|
swp-add-note-tag-option[data-tag="farveformel"].selected::before {
|
|
background: var(--color-teal);
|
|
border-color: var(--color-teal);
|
|
}
|
|
swp-add-note-tag-option[data-tag="kold-tone"].selected::before {
|
|
background: var(--b-color-blue);
|
|
border-color: var(--b-color-blue);
|
|
}
|
|
swp-add-note-tag-option[data-tag="toning"].selected::before {
|
|
background: #8b5cf6;
|
|
border-color: #8b5cf6;
|
|
}
|
|
swp-add-note-tag-option[data-tag="balayage"].selected::before {
|
|
background: var(--b-color-amber);
|
|
border-color: var(--b-color-amber);
|
|
}
|
|
|
|
swp-add-note-tip {
|
|
font-size: 11px;
|
|
color: var(--color-teal);
|
|
font-style: italic;
|
|
}
|
|
|
|
/* Textarea */
|
|
swp-add-note-content textarea {
|
|
width: 100%;
|
|
min-height: 120px;
|
|
padding: 12px;
|
|
font-family: inherit;
|
|
font-size: 13px;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 6px;
|
|
resize: vertical;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
swp-add-note-content textarea:focus {
|
|
outline: none;
|
|
border-color: var(--color-teal);
|
|
}
|
|
|
|
/* Dropdowns */
|
|
swp-add-note-dropdowns {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 16px;
|
|
}
|
|
|
|
swp-add-note-dropdown-group {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
}
|
|
|
|
swp-add-note-dropdown-group select {
|
|
padding: 10px 12px;
|
|
font-size: 13px;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 6px;
|
|
background: var(--color-surface);
|
|
cursor: pointer;
|
|
}
|
|
|
|
swp-add-note-dropdown-group select:focus {
|
|
outline: none;
|
|
border-color: var(--color-teal);
|
|
}
|
|
|
|
swp-add-note-help {
|
|
font-size: 11px;
|
|
color: var(--color-teal);
|
|
}
|
|
|
|
/* Footer */
|
|
swp-add-note-footer {
|
|
display: flex;
|
|
gap: 8px;
|
|
padding: 16px 20px;
|
|
border-top: 1px solid var(--color-border);
|
|
}
|
|
|
|
swp-add-note-btn {
|
|
flex: 1;
|
|
padding: 10px 16px;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
text-align: center;
|
|
transition: all 150ms ease;
|
|
}
|
|
|
|
swp-add-note-btn.primary {
|
|
background: var(--color-teal);
|
|
color: white;
|
|
border: none;
|
|
}
|
|
|
|
swp-add-note-btn.primary:hover {
|
|
background: #00796b;
|
|
}
|
|
|
|
swp-add-note-btn.secondary {
|
|
background: var(--color-surface);
|
|
border: 1px solid var(--color-border);
|
|
color: var(--color-text);
|
|
}
|
|
|
|
swp-add-note-btn.secondary:hover {
|
|
background: var(--color-background-hover);
|
|
}
|
|
|
|
/* ==========================================
|
|
FARVEFORMEL PANEL (extends add-note styles)
|
|
========================================== */
|
|
swp-farveformel-panel {
|
|
position: fixed;
|
|
top: 0;
|
|
right: 340px;
|
|
bottom: 0;
|
|
width: 440px;
|
|
background: var(--color-surface);
|
|
border-left: 1px solid var(--color-border);
|
|
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
|
|
transform: translateX(0);
|
|
visibility: hidden;
|
|
transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1),
|
|
visibility 0ms 250ms;
|
|
display: flex;
|
|
flex-direction: column;
|
|
z-index: 980;
|
|
}
|
|
|
|
swp-farveformel-panel.open {
|
|
transform: translateX(-100%);
|
|
visibility: visible;
|
|
transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1),
|
|
visibility 0ms 0ms;
|
|
}
|
|
|
|
/* Farveformel-specific: 2-column grid layout */
|
|
swp-add-note-row {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 16px;
|
|
}
|
|
|
|
swp-add-note-field.full-width {
|
|
grid-column: 1 / -1;
|
|
}
|
|
|
|
/* Input styling for farveformel */
|
|
swp-farveformel-panel input[type="text"] {
|
|
padding: 10px 12px;
|
|
font-size: 13px;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 6px;
|
|
background: var(--color-surface);
|
|
}
|
|
|
|
/* Monospace for formula fields */
|
|
swp-farveformel-panel input#ffFormel,
|
|
swp-farveformel-panel input#ffBlandingsforhold {
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
swp-farveformel-panel input[type="text"]:focus {
|
|
outline: none;
|
|
border-color: var(--color-teal);
|
|
}
|
|
|
|
swp-farveformel-panel select {
|
|
padding: 10px 12px;
|
|
font-size: 13px;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 6px;
|
|
background: var(--color-surface);
|
|
cursor: pointer;
|
|
}
|
|
|
|
swp-farveformel-panel select:focus {
|
|
outline: none;
|
|
border-color: var(--color-teal);
|
|
}
|
|
|
|
swp-farveformel-panel textarea {
|
|
width: 100%;
|
|
min-height: 100px;
|
|
padding: 12px;
|
|
font-family: inherit;
|
|
font-size: 13px;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 6px;
|
|
background: var(--color-surface);
|
|
resize: vertical;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
swp-farveformel-panel textarea:focus {
|
|
outline: none;
|
|
border-color: var(--color-teal);
|
|
}
|
|
|
|
/* ==========================================
|
|
ANALYSE PANEL (extends add-note styles)
|
|
========================================== */
|
|
swp-analyse-panel {
|
|
position: fixed;
|
|
top: 0;
|
|
right: 340px;
|
|
bottom: 0;
|
|
width: 440px;
|
|
background: var(--color-surface);
|
|
border-left: 1px solid var(--color-border);
|
|
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1);
|
|
transform: translateX(0);
|
|
visibility: hidden;
|
|
transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1),
|
|
visibility 0ms 250ms;
|
|
display: flex;
|
|
flex-direction: column;
|
|
z-index: 980;
|
|
}
|
|
|
|
swp-analyse-panel.open {
|
|
transform: translateX(-100%);
|
|
visibility: visible;
|
|
transition: transform 250ms cubic-bezier(0.4, 0, 0.2, 1),
|
|
visibility 0ms 0ms;
|
|
}
|
|
|
|
swp-analyse-panel input[type="text"] {
|
|
padding: 10px 12px;
|
|
font-size: 13px;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 6px;
|
|
background: var(--color-surface);
|
|
}
|
|
|
|
swp-analyse-panel input[type="text"]:focus {
|
|
outline: none;
|
|
border-color: #8b5cf6;
|
|
}
|
|
|
|
swp-analyse-panel select {
|
|
padding: 10px 12px;
|
|
font-size: 13px;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 6px;
|
|
background: var(--color-surface);
|
|
cursor: pointer;
|
|
}
|
|
|
|
swp-analyse-panel select:focus {
|
|
outline: none;
|
|
border-color: #8b5cf6;
|
|
}
|
|
|
|
swp-analyse-panel textarea {
|
|
width: 100%;
|
|
min-height: 80px;
|
|
padding: 12px;
|
|
font-family: inherit;
|
|
font-size: 13px;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 6px;
|
|
background: var(--color-surface);
|
|
resize: vertical;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
swp-analyse-panel textarea:focus {
|
|
outline: none;
|
|
border-color: #8b5cf6;
|
|
}
|
|
|
|
/* Analyse tags */
|
|
swp-add-note-tag-option[data-tag="analyse"].selected {
|
|
background: color-mix(in srgb, #8b5cf6 15%, var(--b-mix));
|
|
border-color: #8b5cf6;
|
|
color: #7c3aed;
|
|
}
|
|
swp-add-note-tag-option[data-tag="hovedbund"].selected {
|
|
background: color-mix(in srgb, var(--b-color-amber) 15%, var(--b-mix));
|
|
border-color: var(--b-color-amber);
|
|
color: #b45309;
|
|
}
|
|
swp-add-note-tag-option[data-tag="analyse"].selected::before {
|
|
background: #8b5cf6;
|
|
border-color: #8b5cf6;
|
|
}
|
|
swp-add-note-tag-option[data-tag="hovedbund"].selected::before {
|
|
background: var(--b-color-amber);
|
|
border-color: var(--b-color-amber);
|
|
}
|
|
|
|
/* Journal tag for analyse */
|
|
swp-journal-tag.tag-analyse {
|
|
background: color-mix(in srgb, #8b5cf6 15%, var(--b-mix));
|
|
border-color: #8b5cf6;
|
|
color: #7c3aed;
|
|
}
|
|
swp-journal-tag.tag-hovedbund {
|
|
background: color-mix(in srgb, var(--b-color-amber) 15%, var(--b-mix));
|
|
border-color: var(--b-color-amber);
|
|
color: #b45309;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="demo-container">
|
|
<p style="font-size: 12px; color: var(--color-text-secondary); margin-bottom: 12px;">
|
|
Dobbeltklik på en event eller brug knapperne
|
|
</p>
|
|
|
|
<div class="demo-buttons">
|
|
<button class="demo-btn demo-btn-primary" onclick="openDrawer('arrived', 'web', true)">Online + journal</button>
|
|
<button class="demo-btn" onclick="openDrawer('created', 'manual', false)">Manuel</button>
|
|
<button class="demo-btn" onclick="openDrawer('paid', 'recurring', true)">Recurring</button>
|
|
<button class="demo-btn" onclick="openDrawer('noshow', 'web', false)">No-show</button>
|
|
<button class="demo-btn" onclick="openDrawer('cancelled', 'manual', true)">Cancelled</button>
|
|
</div>
|
|
|
|
<div class="calendar-mock">
|
|
<div class="calendar-mock-column">
|
|
<div class="mock-event" ondblclick="openDrawer('arrived')">
|
|
<div class="mock-event-time">10:00 - 11:00</div>
|
|
<div class="mock-event-title">Sofie Nielsen</div>
|
|
</div>
|
|
<div class="mock-event" ondblclick="openDrawer('created')">
|
|
<div class="mock-event-time">14:00 - 15:30</div>
|
|
<div class="mock-event-title">Lars Pedersen</div>
|
|
</div>
|
|
</div>
|
|
<div class="calendar-mock-column">
|
|
<div class="mock-event" ondblclick="openDrawer('paid')">
|
|
<div class="mock-event-time">09:00 - 10:00</div>
|
|
<div class="mock-event-title">Marie Hansen</div>
|
|
</div>
|
|
</div>
|
|
<div class="calendar-mock-column">
|
|
<div class="mock-event" ondblclick="openDrawer('noshow')">
|
|
<div class="mock-event-time">11:00 - 12:00</div>
|
|
<div class="mock-event-title">Peter Jensen</div>
|
|
</div>
|
|
</div>
|
|
<div class="calendar-mock-column"></div>
|
|
<div class="calendar-mock-column"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Overlay -->
|
|
<swp-detail-drawer-overlay id="drawerOverlay" onclick="closeDrawer()"></swp-detail-drawer-overlay>
|
|
|
|
<!-- Journal Panel -->
|
|
<swp-journal-panel id="journalPanel">
|
|
<swp-journal-header>
|
|
<swp-journal-header-title>Journal</swp-journal-header-title>
|
|
<swp-journal-close onclick="closeJournal()">✕</swp-journal-close>
|
|
</swp-journal-header>
|
|
|
|
<!-- Tabs -->
|
|
<swp-journal-tabs>
|
|
<swp-journal-tab class="active" data-tab="noter" onclick="switchJournalTab('noter')"><span class="tab-indicator blue"></span>Noter</swp-journal-tab>
|
|
<swp-journal-tab data-tab="farveformler" onclick="switchJournalTab('farveformler')"><span class="tab-indicator amber"></span>Farveformler</swp-journal-tab>
|
|
<swp-journal-tab data-tab="analyse" onclick="switchJournalTab('analyse')"><span class="tab-indicator purple"></span>Analyse</swp-journal-tab>
|
|
</swp-journal-tabs>
|
|
|
|
<!-- Tab: Noter -->
|
|
<swp-journal-tab-content id="tabNoter" class="active">
|
|
<swp-journal-tab-header>
|
|
<swp-journal-tab-title>Kunde-journal <span>(langsigtet)</span></swp-journal-tab-title>
|
|
<swp-journal-tab-desc>Private noter om hår, reaktioner og anbefalinger. Kunden ser det ikke.</swp-journal-tab-desc>
|
|
<swp-journal-add-btn onclick="openAddNote()">+ Tilføj note</swp-journal-add-btn>
|
|
</swp-journal-tab-header>
|
|
|
|
<swp-journal-content>
|
|
<!-- Preview Entry for Notes -->
|
|
<swp-journal-entry id="previewEntry" class="preview hidden">
|
|
<swp-journal-entry-meta>
|
|
<swp-journal-entry-type>Note</swp-journal-entry-type>
|
|
<swp-journal-entry-tags id="previewTags"></swp-journal-entry-tags>
|
|
</swp-journal-entry-meta>
|
|
<swp-journal-entry-text id="previewText">(Tom note)</swp-journal-entry-text>
|
|
<swp-journal-entry-footer>
|
|
<swp-journal-entry-date id="previewDate">I dag</swp-journal-entry-date>
|
|
<swp-journal-entry-icons>
|
|
<swp-journal-entry-visibility id="previewVisibility">
|
|
<img src="icons/eye.svg" class="entry-icon" alt="">
|
|
<span>Alle</span>
|
|
</swp-journal-entry-visibility>
|
|
<swp-journal-entry-marking id="previewMarking" class="hidden"></swp-journal-entry-marking>
|
|
</swp-journal-entry-icons>
|
|
</swp-journal-entry-footer>
|
|
</swp-journal-entry>
|
|
|
|
<swp-journal-entry>
|
|
<swp-journal-entry-meta>
|
|
<swp-journal-entry-type>Note</swp-journal-entry-type>
|
|
<swp-journal-entry-tags>
|
|
<swp-journal-tag class="tag-allergi">Hovedbund</swp-journal-tag>
|
|
<swp-journal-tag class="tag-sensitiv">Sensitiv</swp-journal-tag>
|
|
</swp-journal-entry-tags>
|
|
<swp-journal-entry-delete title="Slet">🗑</swp-journal-entry-delete>
|
|
</swp-journal-entry-meta>
|
|
<swp-journal-entry-text>
|
|
Let irritation ved hårgrænsen. Anbefalet parfumefri shampoo + mild kur.<br>
|
|
Kunden reagerer på stærk parfume.
|
|
</swp-journal-entry-text>
|
|
<swp-journal-entry-footer>
|
|
<swp-journal-entry-date>2. sep 2025 · Af: Nina</swp-journal-entry-date>
|
|
<swp-journal-entry-icons>
|
|
<swp-journal-entry-visibility>
|
|
<img src="icons/eye.svg" class="entry-icon" alt="">
|
|
<span>Alle</span>
|
|
</swp-journal-entry-visibility>
|
|
</swp-journal-entry-icons>
|
|
</swp-journal-entry-footer>
|
|
</swp-journal-entry>
|
|
</swp-journal-content>
|
|
</swp-journal-tab-content>
|
|
|
|
<!-- Tab: Farveformler -->
|
|
<swp-journal-tab-content id="tabFarveformler">
|
|
<swp-journal-tab-header>
|
|
<swp-journal-tab-title>Farveformler <span>(historik)</span></swp-journal-tab-title>
|
|
<swp-journal-tab-desc>Gemte farveformler for denne kunde. Nem genbrug og konsistens.</swp-journal-tab-desc>
|
|
<swp-journal-add-btn onclick="openFarveformel()">+ Tilføj farveformel</swp-journal-add-btn>
|
|
</swp-journal-tab-header>
|
|
|
|
<swp-journal-content>
|
|
<!-- Preview Entry for Farveformler -->
|
|
<swp-journal-entry id="previewEntryFarveformel" class="preview hidden">
|
|
<swp-journal-entry-meta>
|
|
<swp-journal-entry-type class="farveformel">Farveformel</swp-journal-entry-type>
|
|
<swp-journal-entry-tags id="previewTagsFarveformel"></swp-journal-entry-tags>
|
|
</swp-journal-entry-meta>
|
|
<swp-journal-entry-text id="previewTextFarveformel">(Udfyld felter...)</swp-journal-entry-text>
|
|
<swp-journal-entry-footer>
|
|
<swp-journal-entry-date>I dag</swp-journal-entry-date>
|
|
<swp-journal-entry-icons>
|
|
<swp-journal-entry-visibility>
|
|
<img src="icons/eye.svg" class="entry-icon" alt="">
|
|
<span>Alle</span>
|
|
</swp-journal-entry-visibility>
|
|
</swp-journal-entry-icons>
|
|
</swp-journal-entry-footer>
|
|
</swp-journal-entry>
|
|
|
|
<swp-journal-entry>
|
|
<swp-journal-entry-meta>
|
|
<swp-journal-entry-type class="farveformel">Farveformel</swp-journal-entry-type>
|
|
<swp-journal-entry-delete title="Slet">🗑</swp-journal-entry-delete>
|
|
</swp-journal-entry-meta>
|
|
<swp-journal-entry-text>
|
|
• Mål/tone: Kold<br>
|
|
• Oxidant: <span class="mono">1.9%</span><br>
|
|
• Formel: <span class="mono">7/1 + 7/0 (1:1)</span><br>
|
|
• Virketid: <span class="mono">15 min</span><br>
|
|
• Placering: Hele håret<br><br>
|
|
Resultat: neutral/kold, god glans. Undgå varme toner næste gang.
|
|
</swp-journal-entry-text>
|
|
<swp-journal-entry-footer>
|
|
<swp-journal-entry-date>12. nov 2025 · Af: Maja</swp-journal-entry-date>
|
|
<swp-journal-entry-icons>
|
|
<swp-journal-entry-visibility>
|
|
<img src="icons/eye.svg" class="entry-icon" alt="">
|
|
<span>Alle</span>
|
|
</swp-journal-entry-visibility>
|
|
</swp-journal-entry-icons>
|
|
</swp-journal-entry-footer>
|
|
</swp-journal-entry>
|
|
|
|
<swp-journal-entry>
|
|
<swp-journal-entry-meta>
|
|
<swp-journal-entry-type class="farveformel">Farveformel</swp-journal-entry-type>
|
|
<swp-journal-entry-delete title="Slet">🗑</swp-journal-entry-delete>
|
|
</swp-journal-entry-meta>
|
|
<swp-journal-entry-text>
|
|
• Mål/tone: Neutral<br>
|
|
• Oxidant: <span class="mono">3%</span><br>
|
|
• Formel: <span class="mono">6/0 + 7/1 (2:1)</span><br>
|
|
• Virketid: <span class="mono">20 min</span><br>
|
|
• Placering: Rødder<br><br>
|
|
Første besøg. Kunden ønskede naturlig look.
|
|
</swp-journal-entry-text>
|
|
<swp-journal-entry-footer>
|
|
<swp-journal-entry-date>15. aug 2025 · Af: Maja</swp-journal-entry-date>
|
|
<swp-journal-entry-icons>
|
|
<swp-journal-entry-visibility>
|
|
<img src="icons/eye.svg" class="entry-icon" alt="">
|
|
<span>Alle</span>
|
|
</swp-journal-entry-visibility>
|
|
</swp-journal-entry-icons>
|
|
</swp-journal-entry-footer>
|
|
</swp-journal-entry>
|
|
</swp-journal-content>
|
|
</swp-journal-tab-content>
|
|
|
|
<!-- Tab: Analyse -->
|
|
<swp-journal-tab-content id="tabAnalyse">
|
|
<swp-journal-tab-header>
|
|
<swp-journal-tab-title>Hår & hovedbund <span>(analyse)</span></swp-journal-tab-title>
|
|
<swp-journal-tab-desc>Struktureret analyse af hår og hovedbund. Kan blive til advarsel.</swp-journal-tab-desc>
|
|
<swp-journal-add-btn onclick="openAnalyse()">+ Tilføj analyse</swp-journal-add-btn>
|
|
</swp-journal-tab-header>
|
|
|
|
<swp-journal-content>
|
|
<!-- Preview Entry for Analyse -->
|
|
<swp-journal-entry id="previewEntryAnalyse" class="preview hidden">
|
|
<swp-journal-entry-meta>
|
|
<swp-journal-entry-type class="analyse">Analyse</swp-journal-entry-type>
|
|
<swp-journal-entry-tags id="previewTagsAnalyse"></swp-journal-entry-tags>
|
|
</swp-journal-entry-meta>
|
|
<swp-journal-entry-text id="previewTextAnalyse">(Udfyld felter...)</swp-journal-entry-text>
|
|
<swp-journal-entry-footer>
|
|
<swp-journal-entry-date>I dag</swp-journal-entry-date>
|
|
<swp-journal-entry-icons>
|
|
<swp-journal-entry-visibility>
|
|
<img src="icons/eye.svg" class="entry-icon" alt="">
|
|
<span>Alle</span>
|
|
</swp-journal-entry-visibility>
|
|
</swp-journal-entry-icons>
|
|
</swp-journal-entry-footer>
|
|
</swp-journal-entry>
|
|
|
|
<swp-journal-entry>
|
|
<swp-journal-entry-meta>
|
|
<swp-journal-entry-type class="analyse">Analyse</swp-journal-entry-type>
|
|
<swp-journal-entry-tags>
|
|
<swp-journal-tag class="tag-analyse">Hovedbund</swp-journal-tag>
|
|
<swp-journal-tag class="tag-sensitiv">Sensitiv</swp-journal-tag>
|
|
</swp-journal-entry-tags>
|
|
<swp-journal-entry-delete title="Slet">🗑</swp-journal-entry-delete>
|
|
</swp-journal-entry-meta>
|
|
<swp-journal-entry-text>
|
|
• Hovedbund: Let irriteret<br>
|
|
• Hår: <span class="mono">Medium · Bølget</span><br>
|
|
• Porøsitet: <span class="mono">Medium</span><br>
|
|
• Kemisk beh.: Nej<br><br>
|
|
Let rødme ved hårgrænsen. Anbefalet parfumefri shampoo.
|
|
</swp-journal-entry-text>
|
|
<swp-journal-entry-footer>
|
|
<swp-journal-entry-date>2. sep 2025 · Af: Nina</swp-journal-entry-date>
|
|
<swp-journal-entry-icons>
|
|
<swp-journal-entry-visibility>
|
|
<img src="icons/eye.svg" class="entry-icon" alt="">
|
|
<span>Alle</span>
|
|
</swp-journal-entry-visibility>
|
|
<swp-journal-entry-marking class="warning">
|
|
<img src="icons/warning.svg" class="entry-icon" alt="">
|
|
<span>Advarsel</span>
|
|
</swp-journal-entry-marking>
|
|
</swp-journal-entry-icons>
|
|
</swp-journal-entry-footer>
|
|
</swp-journal-entry>
|
|
</swp-journal-content>
|
|
</swp-journal-tab-content>
|
|
|
|
<!-- Kundeprofil Toggle -->
|
|
<swp-journal-profile-section>
|
|
<swp-journal-profile-toggle onclick="toggleJournalProfile()">
|
|
<span class="toggle-arrow">▼</span> Vis "Kundeprofil" (hurtige facts)
|
|
</swp-journal-profile-toggle>
|
|
<swp-journal-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>Parfume-allergi • Sensitiv hovedbund</swp-profile-box-value>
|
|
</swp-profile-box>
|
|
</swp-journal-profile-boxes>
|
|
</swp-journal-profile-section>
|
|
</swp-journal-panel>
|
|
|
|
<!-- Add Note Panel -->
|
|
<swp-add-note-panel id="addNotePanel">
|
|
<swp-add-note-header>
|
|
<swp-add-note-title>Opret ny note</swp-add-note-title>
|
|
<swp-add-note-close onclick="closeAddNote()">✕</swp-add-note-close>
|
|
</swp-add-note-header>
|
|
|
|
<swp-add-note-content>
|
|
<swp-add-note-desc>God til observationer, præferencer, reaktioner og næste gang-plan.</swp-add-note-desc>
|
|
|
|
<!-- Tags -->
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Tags (klik for at tilføje)</swp-add-note-label>
|
|
<swp-add-note-tags>
|
|
<swp-add-note-tag-option class="selected" data-tag="note">Fri note</swp-add-note-tag-option>
|
|
<swp-add-note-tag-option data-tag="sensitiv">Sensitiv</swp-add-note-tag-option>
|
|
<swp-add-note-tag-option data-tag="allergi">Allergi</swp-add-note-tag-option>
|
|
<swp-add-note-tag-option data-tag="praference">Præference</swp-add-note-tag-option>
|
|
<swp-add-note-tag-option data-tag="anbefaling">Anbefaling</swp-add-note-tag-option>
|
|
</swp-add-note-tags>
|
|
<swp-add-note-tip>Tip: I et rigtigt system kan tags være søgbare/standardiserede.</swp-add-note-tip>
|
|
</swp-add-note-field>
|
|
|
|
<!-- Note Textarea -->
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Note</swp-add-note-label>
|
|
<textarea placeholder="Fx: Kunden vil have kold tone og ikke for mørk. Reagerer på parfume. Næste gang: kortere pandehår."></textarea>
|
|
</swp-add-note-field>
|
|
|
|
<!-- Dropdowns -->
|
|
<swp-add-note-dropdowns>
|
|
<swp-add-note-dropdown-group>
|
|
<swp-add-note-label>Synlighed</swp-add-note-label>
|
|
<select>
|
|
<option>Hele salonen</option>
|
|
<option>Kun mig</option>
|
|
</select>
|
|
<swp-add-note-help>Hvis I er flere frisører, kan "Kun mig" være nyttigt.</swp-add-note-help>
|
|
</swp-add-note-dropdown-group>
|
|
<swp-add-note-dropdown-group>
|
|
<swp-add-note-label>Markering</swp-add-note-label>
|
|
<select>
|
|
<option>Ingen</option>
|
|
<option>Vigtigt</option>
|
|
<option>Advarsel</option>
|
|
</select>
|
|
<swp-add-note-help>"Advarsel" kan vise ikon på kundekortet.</swp-add-note-help>
|
|
</swp-add-note-dropdown-group>
|
|
</swp-add-note-dropdowns>
|
|
</swp-add-note-content>
|
|
|
|
<swp-add-note-footer>
|
|
<swp-add-note-btn class="secondary" onclick="closeAddNote()">Annuller</swp-add-note-btn>
|
|
<swp-add-note-btn class="primary">Gem note</swp-add-note-btn>
|
|
</swp-add-note-footer>
|
|
</swp-add-note-panel>
|
|
|
|
<!-- Farveformel Panel -->
|
|
<swp-farveformel-panel id="farveformelPanel">
|
|
<swp-add-note-header>
|
|
<swp-add-note-title>Farveformel</swp-add-note-title>
|
|
<swp-add-note-close onclick="closeFarveformel()">✕</swp-add-note-close>
|
|
</swp-add-note-header>
|
|
|
|
<swp-add-note-content>
|
|
<swp-add-note-desc>Struktureret nok til at kunne genskabes. Gemmes som journalnote.</swp-add-note-desc>
|
|
|
|
<!-- Row 1: Mål/tone + Oxidant -->
|
|
<swp-add-note-row>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Mål / tone</swp-add-note-label>
|
|
<select id="ffMaalTone">
|
|
<option value="">Vælg...</option>
|
|
<option value="Kold">Kold</option>
|
|
<option value="Varm">Varm</option>
|
|
<option value="Neutral">Neutral</option>
|
|
</select>
|
|
</swp-add-note-field>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Oxidant / styrke</swp-add-note-label>
|
|
<select id="ffOxidant">
|
|
<option value="">Vælg...</option>
|
|
<option value="1.9%">1.9%</option>
|
|
<option value="3%">3%</option>
|
|
<option value="6%">6%</option>
|
|
<option value="9%">9%</option>
|
|
<option value="12%">12%</option>
|
|
</select>
|
|
</swp-add-note-field>
|
|
</swp-add-note-row>
|
|
|
|
<!-- Row 2: Formel + Blandingsforhold -->
|
|
<swp-add-note-row>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Formel (skriv som du vil)</swp-add-note-label>
|
|
<input type="text" id="ffFormel" placeholder="Fx: 7/1 + 7/0 (1:1)">
|
|
<swp-add-note-tip>Monospace gør formler nemmere at læse.</swp-add-note-tip>
|
|
</swp-add-note-field>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Blandingsforhold</swp-add-note-label>
|
|
<input type="text" id="ffBlandingsforhold" placeholder="Fx: 1:2">
|
|
</swp-add-note-field>
|
|
</swp-add-note-row>
|
|
|
|
<!-- Row 3: Virketid + Placering -->
|
|
<swp-add-note-row>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Virketid</swp-add-note-label>
|
|
<input type="text" id="ffVirketid" placeholder="Fx: 15 min">
|
|
</swp-add-note-field>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Placering</swp-add-note-label>
|
|
<select id="ffPlacering">
|
|
<option value="">Vælg...</option>
|
|
<option value="Hele håret">Hele håret</option>
|
|
<option value="Rødder">Rødder</option>
|
|
<option value="Længder">Længder</option>
|
|
<option value="Spidser">Spidser</option>
|
|
</select>
|
|
</swp-add-note-field>
|
|
</swp-add-note-row>
|
|
|
|
<!-- Resultat / note -->
|
|
<swp-add-note-field class="full-width">
|
|
<swp-add-note-label>Resultat / note</swp-add-note-label>
|
|
<textarea id="ffResultat" placeholder="Fx: Resultat kold/neutral, god glans. Undgå varme toner næste gang."></textarea>
|
|
</swp-add-note-field>
|
|
|
|
</swp-add-note-content>
|
|
|
|
<swp-add-note-footer>
|
|
<swp-add-note-btn class="secondary" onclick="closeFarveformel()">Annuller</swp-add-note-btn>
|
|
<swp-add-note-btn class="primary" onclick="saveFarveformel()">Gem farveformel</swp-add-note-btn>
|
|
</swp-add-note-footer>
|
|
</swp-farveformel-panel>
|
|
|
|
<!-- Analyse Panel -->
|
|
<swp-analyse-panel id="analysePanel">
|
|
<swp-add-note-header>
|
|
<swp-add-note-title>Shampoo & hovedbund-analyse</swp-add-note-title>
|
|
<swp-add-note-close onclick="closeAnalyse()">✕</swp-add-note-close>
|
|
</swp-add-note-header>
|
|
|
|
<swp-add-note-content>
|
|
<swp-add-note-desc>Hurtige valg + bemærkning. Kan blive til "sticky warning".</swp-add-note-desc>
|
|
|
|
<!-- Row 1: Hovedbund + Irritation -->
|
|
<swp-add-note-row>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Hovedbund (tilstand)</swp-add-note-label>
|
|
<select id="anHovedbund">
|
|
<option value="">Vælg...</option>
|
|
<option value="Normal">Normal</option>
|
|
<option value="Tør">Tør</option>
|
|
<option value="Fedtet">Fedtet</option>
|
|
<option value="Let irriteret">Let irriteret</option>
|
|
<option value="Irriteret">Irriteret</option>
|
|
</select>
|
|
</swp-add-note-field>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Irritation</swp-add-note-label>
|
|
<select id="anIrritation">
|
|
<option value="">Vælg...</option>
|
|
<option value="Ingen">Ingen</option>
|
|
<option value="Let">Let</option>
|
|
<option value="Moderat">Moderat</option>
|
|
<option value="Kraftig">Kraftig</option>
|
|
</select>
|
|
</swp-add-note-field>
|
|
</swp-add-note-row>
|
|
|
|
<!-- Row 2: Hår tykkelse + struktur -->
|
|
<swp-add-note-row>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Hår (tykkelse)</swp-add-note-label>
|
|
<select id="anHaarTykkelse">
|
|
<option value="">Vælg...</option>
|
|
<option value="Fint">Fint</option>
|
|
<option value="Medium">Medium</option>
|
|
<option value="Tykt">Tykt</option>
|
|
</select>
|
|
</swp-add-note-field>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Hår (struktur)</swp-add-note-label>
|
|
<select id="anHaarStruktur">
|
|
<option value="">Vælg...</option>
|
|
<option value="Glat">Glat</option>
|
|
<option value="Bølget">Bølget</option>
|
|
<option value="Krøllet">Krøllet</option>
|
|
</select>
|
|
</swp-add-note-field>
|
|
</swp-add-note-row>
|
|
|
|
<!-- Row 3: Porøsitet + Kemisk behandling -->
|
|
<swp-add-note-row>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Porøsitet</swp-add-note-label>
|
|
<select id="anPorositet">
|
|
<option value="">Vælg...</option>
|
|
<option value="Lav">Lav</option>
|
|
<option value="Medium">Medium</option>
|
|
<option value="Høj">Høj</option>
|
|
</select>
|
|
</swp-add-note-field>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Tidligere kemisk behandling?</swp-add-note-label>
|
|
<select id="anKemisk">
|
|
<option value="">Vælg...</option>
|
|
<option value="Nej">Nej</option>
|
|
<option value="Ja">Ja</option>
|
|
</select>
|
|
</swp-add-note-field>
|
|
</swp-add-note-row>
|
|
|
|
<!-- Row 4: Shampoo + Hjemmepleje -->
|
|
<swp-add-note-row>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Anvendt shampoo</swp-add-note-label>
|
|
<input type="text" id="anShampoo" placeholder="Fx: Kerastase Bain">
|
|
</swp-add-note-field>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Anbefalet hjemmepleje</swp-add-note-label>
|
|
<input type="text" id="anHjemmepleje" placeholder="Fx: Parfumefri shampoo">
|
|
</swp-add-note-field>
|
|
</swp-add-note-row>
|
|
|
|
<!-- Bemærkning -->
|
|
<swp-add-note-field class="full-width">
|
|
<swp-add-note-label>Bemærkning</swp-add-note-label>
|
|
<textarea id="anBemaerkning" placeholder="Fx: Let rødme ved hårgrænsen. Undgå parfume og stærke sulfater."></textarea>
|
|
</swp-add-note-field>
|
|
|
|
<!-- Row 5: Advarsel + Tags -->
|
|
<swp-add-note-row>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Gør til advarsel på kundekort?</swp-add-note-label>
|
|
<select id="anAdvarsel">
|
|
<option value="Nej">Nej</option>
|
|
<option value="Ja">Ja</option>
|
|
</select>
|
|
<swp-add-note-help>Brug "Ja" ved fx allergi/sensitivitet.</swp-add-note-help>
|
|
</swp-add-note-field>
|
|
<swp-add-note-field>
|
|
<swp-add-note-label>Tags</swp-add-note-label>
|
|
<swp-add-note-tags>
|
|
<swp-add-note-tag-option class="selected" data-tag="analyse">Analyse</swp-add-note-tag-option>
|
|
<swp-add-note-tag-option data-tag="hovedbund">Hovedbund</swp-add-note-tag-option>
|
|
<swp-add-note-tag-option data-tag="sensitiv">Sensitiv</swp-add-note-tag-option>
|
|
<swp-add-note-tag-option data-tag="allergi">Allergi</swp-add-note-tag-option>
|
|
</swp-add-note-tags>
|
|
</swp-add-note-field>
|
|
</swp-add-note-row>
|
|
</swp-add-note-content>
|
|
|
|
<swp-add-note-footer>
|
|
<swp-add-note-btn class="secondary" onclick="closeAnalyse()">Annuller</swp-add-note-btn>
|
|
<swp-add-note-btn class="primary" onclick="saveAnalyse()">Gem analyse</swp-add-note-btn>
|
|
</swp-add-note-footer>
|
|
</swp-analyse-panel>
|
|
|
|
<!-- Customer Details Panel -->
|
|
<swp-customer-panel id="customerPanel">
|
|
<swp-customer-panel-header>
|
|
<swp-customer-panel-title><img src="icons/user.svg" class="panel-header-icon" alt="">Kundedetaljer</swp-customer-panel-title>
|
|
<swp-customer-panel-close onclick="closeCustomerPanel()">✕</swp-customer-panel-close>
|
|
</swp-customer-panel-header>
|
|
<swp-customer-panel-content>
|
|
<!-- Customer header with avatar -->
|
|
<swp-customer-header-section>
|
|
<swp-customer-avatar>SN</swp-customer-avatar>
|
|
<swp-customer-header-info>
|
|
<swp-customer-header-top>
|
|
<swp-customer-header-left>
|
|
<swp-customer-header-name>Sofie Nielsen</swp-customer-header-name>
|
|
<swp-customer-since>Kunde siden marts 2024</swp-customer-since>
|
|
</swp-customer-header-left>
|
|
<swp-customer-header-contact>
|
|
<swp-customer-header-contact-item>
|
|
<a href="tel:+4523456789">+45 23 45 67 89</a>
|
|
</swp-customer-header-contact-item>
|
|
<swp-customer-header-contact-item>
|
|
<a href="mailto:sofie@email.dk">sofie@email.dk</a>
|
|
</swp-customer-header-contact-item>
|
|
</swp-customer-header-contact>
|
|
</swp-customer-header-top>
|
|
</swp-customer-header-info>
|
|
</swp-customer-header-section>
|
|
|
|
<!-- Fact boxes -->
|
|
<swp-fact-boxes>
|
|
<swp-fact-box class="highlight">
|
|
<swp-fact-box-value>12.450 kr</swp-fact-box-value>
|
|
<swp-fact-box-label>Total omsætning</swp-fact-box-label>
|
|
</swp-fact-box>
|
|
<swp-fact-box>
|
|
<swp-fact-box-value>14</swp-fact-box-value>
|
|
<swp-fact-box-label>Besøg</swp-fact-box-label>
|
|
</swp-fact-box>
|
|
<swp-fact-box>
|
|
<swp-fact-box-value>889 kr</swp-fact-box-value>
|
|
<swp-fact-box-label>Gns. pr. besøg</swp-fact-box-label>
|
|
</swp-fact-box>
|
|
<swp-fact-box>
|
|
<swp-fact-box-value>32 dage</swp-fact-box-value>
|
|
<swp-fact-box-label>Gns. interval</swp-fact-box-label>
|
|
</swp-fact-box>
|
|
</swp-fact-boxes>
|
|
|
|
<!-- Chart -->
|
|
<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="customerRevenueChart"></swp-chart-container>
|
|
</swp-chart-section>
|
|
|
|
<!-- Last 5 products -->
|
|
<swp-products-section>
|
|
<swp-section-label>Seneste produktkøb</swp-section-label>
|
|
<swp-products-list>
|
|
<swp-product-item>
|
|
<swp-product-info>
|
|
<swp-product-name>Olaplex No. 3</swp-product-name>
|
|
<swp-product-date>9. dec 2025</swp-product-date>
|
|
</swp-product-info>
|
|
<swp-product-price>300 kr</swp-product-price>
|
|
</swp-product-item>
|
|
<swp-product-item>
|
|
<swp-product-info>
|
|
<swp-product-name>Kevin Murphy Hydrate-Me Wash</swp-product-name>
|
|
<swp-product-date>12. nov 2025</swp-product-date>
|
|
</swp-product-info>
|
|
<swp-product-price>275 kr</swp-product-price>
|
|
</swp-product-item>
|
|
<swp-product-item>
|
|
<swp-product-info>
|
|
<swp-product-name>Olaplex No. 4 Bond Shampoo</swp-product-name>
|
|
<swp-product-date>18. okt 2025</swp-product-date>
|
|
</swp-product-info>
|
|
<swp-product-price>320 kr</swp-product-price>
|
|
</swp-product-item>
|
|
<swp-product-item>
|
|
<swp-product-info>
|
|
<swp-product-name>Moroccanoil Treatment</swp-product-name>
|
|
<swp-product-date>5. sep 2025</swp-product-date>
|
|
</swp-product-info>
|
|
<swp-product-price>399 kr</swp-product-price>
|
|
</swp-product-item>
|
|
<swp-product-item>
|
|
<swp-product-info>
|
|
<swp-product-name>Olaplex No. 5 Conditioner</swp-product-name>
|
|
<swp-product-date>12. aug 2025</swp-product-date>
|
|
</swp-product-info>
|
|
<swp-product-price>320 kr</swp-product-price>
|
|
</swp-product-item>
|
|
</swp-products-list>
|
|
</swp-products-section>
|
|
|
|
<!-- Preferences -->
|
|
<swp-preferences-section>
|
|
<swp-section-label>Præferencer & noter</swp-section-label>
|
|
<swp-preferences-grid>
|
|
<swp-preference-item>
|
|
<swp-preference-label>Foretrukken frisør</swp-preference-label>
|
|
<swp-preference-value>Emma Larsen</swp-preference-value>
|
|
</swp-preference-item>
|
|
<swp-preference-item>
|
|
<swp-preference-label>Hårtype</swp-preference-label>
|
|
<swp-preference-value>Fint, medium tykkelse</swp-preference-value>
|
|
</swp-preference-item>
|
|
<swp-preference-item>
|
|
<swp-preference-label>Farvehistorik</swp-preference-label>
|
|
<swp-preference-value>7.3 + 7.4 blanding</swp-preference-value>
|
|
</swp-preference-item>
|
|
<swp-preference-item>
|
|
<swp-preference-label>Allergier</swp-preference-label>
|
|
<swp-preference-value>Ingen kendte</swp-preference-value>
|
|
</swp-preference-item>
|
|
</swp-preferences-grid>
|
|
</swp-preferences-section>
|
|
</swp-customer-panel-content>
|
|
</swp-customer-panel>
|
|
|
|
<!-- Detail Drawer -->
|
|
<swp-detail-drawer id="detailDrawer">
|
|
<swp-drawer-header>
|
|
<swp-drawer-title id="drawerTitle" class="source-web">Online Booking</swp-drawer-title>
|
|
<swp-created-date>oprettet 5. aug 2025, 14:32</swp-created-date>
|
|
</swp-drawer-header>
|
|
|
|
<swp-drawer-content>
|
|
<!-- Event time/date -->
|
|
<swp-event-info>
|
|
<swp-event-time-display>10:00 - 11:00</swp-event-time-display>
|
|
<swp-event-date-display>Mandag 9. december 2025</swp-event-date-display>
|
|
</swp-event-info>
|
|
|
|
<!-- Customer -->
|
|
<swp-drawer-section>
|
|
<swp-section-label>Kunde</swp-section-label>
|
|
<swp-customer-info>
|
|
<swp-customer-row>
|
|
<swp-customer-name>Sofie Nielsen</swp-customer-name>
|
|
<swp-customer-phone><a href="tel:+4523456789">+45 23 45 67 89</a></swp-customer-phone>
|
|
</swp-customer-row>
|
|
<swp-customer-details-link id="customerDetailsLink" onclick="openCustomerPanel()">Vis detaljer <img src="icons/angle-small-right.svg" class="link-chevron" alt=""></swp-customer-details-link>
|
|
</swp-customer-info>
|
|
</swp-drawer-section>
|
|
|
|
<!-- Status -->
|
|
<swp-drawer-section>
|
|
<swp-status-row>
|
|
<swp-status-label>Status</swp-status-label>
|
|
<button class="status-badge status-arrived" id="statusBadge" popovertarget="statusDropdown">
|
|
<swp-status-dot></swp-status-dot>
|
|
<span id="statusText">Ankommet</span>
|
|
</button>
|
|
<swp-status-dropdown id="statusDropdown" popover>
|
|
<swp-status-option class="opt-created" data-status="created" onclick="selectStatus('created')">
|
|
<swp-status-dot></swp-status-dot>
|
|
<span>Oprettet</span>
|
|
<swp-status-check>✓</swp-status-check>
|
|
</swp-status-option>
|
|
<swp-status-option class="opt-arrived" data-status="arrived" onclick="selectStatus('arrived')">
|
|
<swp-status-dot></swp-status-dot>
|
|
<span>Ankommet</span>
|
|
<swp-status-check>✓</swp-status-check>
|
|
</swp-status-option>
|
|
<swp-status-option class="opt-paid" data-status="paid" onclick="selectStatus('paid')">
|
|
<swp-status-dot></swp-status-dot>
|
|
<span>Betalt</span>
|
|
<swp-status-check>✓</swp-status-check>
|
|
</swp-status-option>
|
|
<swp-status-option class="opt-noshow" data-status="noshow" onclick="selectStatus('noshow')">
|
|
<swp-status-dot></swp-status-dot>
|
|
<span>Udeblevet</span>
|
|
<swp-status-check>✓</swp-status-check>
|
|
</swp-status-option>
|
|
<swp-status-option class="opt-cancelled" data-status="cancelled" onclick="selectStatus('cancelled')">
|
|
<swp-status-dot></swp-status-dot>
|
|
<span>Aflyst</span>
|
|
<swp-status-check>✓</swp-status-check>
|
|
</swp-status-option>
|
|
</swp-status-dropdown>
|
|
</swp-status-row>
|
|
</swp-drawer-section>
|
|
|
|
<!-- Services -->
|
|
<swp-drawer-section>
|
|
<swp-section-label>Services</swp-section-label>
|
|
<swp-services-list>
|
|
<swp-service-item>
|
|
<swp-service-name>Klipning og styling</swp-service-name>
|
|
<swp-service-details>60 min · <swp-service-price>500 kr</swp-service-price></swp-service-details>
|
|
<swp-service-resource>Emma (EMP001)</swp-service-resource>
|
|
</swp-service-item>
|
|
<swp-service-item>
|
|
<swp-service-name>Bundfarve</swp-service-name>
|
|
<swp-service-details>90 min · <swp-service-price>800 kr</swp-service-price></swp-service-details>
|
|
<swp-service-resource>Emma (EMP001)</swp-service-resource>
|
|
</swp-service-item>
|
|
</swp-services-list>
|
|
</swp-drawer-section>
|
|
|
|
<!-- Total -->
|
|
<swp-drawer-section>
|
|
<swp-total-row>
|
|
<swp-total-label>Total</swp-total-label>
|
|
<swp-total-amount>1.300 kr</swp-total-amount>
|
|
</swp-total-row>
|
|
</swp-drawer-section>
|
|
|
|
<!-- Notes -->
|
|
<swp-drawer-section>
|
|
<swp-section-label>Noter</swp-section-label>
|
|
<swp-notes-box>
|
|
Kunden foretrækker naturlige farver og ønsker lidt ekstra tid til konsultation
|
|
</swp-notes-box>
|
|
</swp-drawer-section>
|
|
|
|
<!-- Customer profile boxes -->
|
|
<swp-drawer-section>
|
|
<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>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>Parfume-allergi • Sensitiv hovedbund</swp-profile-box-value>
|
|
</swp-profile-box>
|
|
</swp-profile-boxes>
|
|
<swp-journal-details-link id="journalLink" onclick="toggleJournal()">Se journal <img src="icons/angle-small-right.svg" class="link-chevron" alt=""></swp-journal-details-link>
|
|
</swp-drawer-section>
|
|
|
|
</swp-drawer-content>
|
|
|
|
<swp-drawer-footer id="drawerFooter">
|
|
<swp-footer-btn class="btn-primary" id="payBtn">Gå til betaling</swp-footer-btn>
|
|
</swp-drawer-footer>
|
|
</swp-detail-drawer>
|
|
|
|
<script>
|
|
const statusLabels = {
|
|
created: 'Oprettet',
|
|
arrived: 'Ankommet',
|
|
paid: 'Betalt',
|
|
noshow: 'Udeblevet',
|
|
cancelled: 'Aflyst'
|
|
};
|
|
|
|
const sourceTitles = {
|
|
manual: 'Manuel Booking',
|
|
web: 'Online Booking',
|
|
recurring: 'Gentagende Booking'
|
|
};
|
|
|
|
function openDrawer(status = 'arrived', source = 'web', hasJournal = true) {
|
|
document.getElementById('drawerOverlay').classList.add('open');
|
|
document.getElementById('detailDrawer').classList.add('open');
|
|
|
|
// Update current status for dropdown
|
|
currentStatus = status;
|
|
|
|
// Update status badge
|
|
const badge = document.getElementById('statusBadge');
|
|
const text = document.getElementById('statusText');
|
|
badge.className = 'status-badge status-' + status;
|
|
text.textContent = statusLabels[status];
|
|
|
|
// Update drawer title based on source
|
|
const title = document.getElementById('drawerTitle');
|
|
title.textContent = sourceTitles[source];
|
|
title.className = 'source-' + source;
|
|
|
|
// Update journal link
|
|
const journalLink = document.getElementById('journalLink');
|
|
const chevronImg = '<img src="icons/angle-small-right.svg" class="link-chevron" alt="">';
|
|
|
|
if (hasJournal) {
|
|
journalLink.classList.remove('no-journal');
|
|
journalLink.innerHTML = 'Se journal ' + chevronImg;
|
|
} else {
|
|
journalLink.classList.add('no-journal');
|
|
journalLink.innerHTML = '+ Opret journal';
|
|
}
|
|
|
|
// Update footer based on status
|
|
const footer = document.getElementById('drawerFooter');
|
|
const payBtn = document.getElementById('payBtn');
|
|
footer.className = 'status-' + status;
|
|
|
|
const btnLabels = {
|
|
created: 'Gå til betaling',
|
|
arrived: 'Gå til betaling',
|
|
paid: 'Betalt ✓',
|
|
noshow: 'Udeblevet',
|
|
cancelled: 'Aflyst'
|
|
};
|
|
payBtn.textContent = btnLabels[status];
|
|
}
|
|
|
|
function closeDrawer() {
|
|
document.getElementById('drawerOverlay').classList.remove('open');
|
|
document.getElementById('detailDrawer').classList.remove('open');
|
|
document.getElementById('journalPanel').classList.remove('open');
|
|
document.getElementById('customerPanel').classList.remove('open');
|
|
document.getElementById('addNotePanel').classList.remove('open');
|
|
document.getElementById('journalLink').classList.remove('panel-open');
|
|
document.getElementById('customerDetailsLink').classList.remove('panel-open');
|
|
}
|
|
|
|
function toggleJournal() {
|
|
const journalLink = document.getElementById('journalLink');
|
|
// Don't open journal if it's the "create" state
|
|
if (journalLink.classList.contains('no-journal')) {
|
|
// Could show create journal flow here
|
|
return;
|
|
}
|
|
const journalPanel = document.getElementById('journalPanel');
|
|
journalPanel.classList.toggle('open');
|
|
journalLink.classList.toggle('panel-open', journalPanel.classList.contains('open'));
|
|
}
|
|
|
|
function closeJournal() {
|
|
document.getElementById('journalPanel').classList.remove('open');
|
|
document.getElementById('journalLink').classList.remove('panel-open');
|
|
closeAddNote();
|
|
closeFarveformel();
|
|
closeAnalyse();
|
|
}
|
|
|
|
function switchJournalTab(tabName) {
|
|
// Update tab buttons
|
|
document.querySelectorAll('swp-journal-tab[data-tab]').forEach(tab => {
|
|
tab.classList.toggle('active', tab.dataset.tab === tabName);
|
|
});
|
|
// Update tab content
|
|
document.getElementById('tabNoter').classList.toggle('active', tabName === 'noter');
|
|
document.getElementById('tabFarveformler').classList.toggle('active', tabName === 'farveformler');
|
|
document.getElementById('tabAnalyse').classList.toggle('active', tabName === 'analyse');
|
|
// Close any open panels
|
|
closeAddNote();
|
|
closeFarveformel();
|
|
closeAnalyse();
|
|
}
|
|
|
|
function openAddNote() {
|
|
document.getElementById('addNotePanel').classList.add('open');
|
|
}
|
|
|
|
function closeAddNote() {
|
|
document.getElementById('addNotePanel').classList.remove('open');
|
|
hidePreview();
|
|
resetAddNoteForm();
|
|
}
|
|
|
|
function toggleJournalProfile() {
|
|
const toggle = document.querySelector('swp-journal-profile-toggle');
|
|
const boxes = document.getElementById('journalProfileBoxes');
|
|
toggle.classList.toggle('collapsed');
|
|
boxes.classList.toggle('collapsed');
|
|
}
|
|
|
|
function openCustomerPanel() {
|
|
const panel = document.getElementById('customerPanel');
|
|
const link = document.getElementById('customerDetailsLink');
|
|
const isOpen = panel.classList.contains('open');
|
|
|
|
if (isOpen) {
|
|
panel.classList.remove('open');
|
|
link.classList.remove('panel-open');
|
|
} else {
|
|
panel.classList.add('open');
|
|
link.classList.add('panel-open');
|
|
}
|
|
}
|
|
|
|
function closeCustomerPanel() {
|
|
document.getElementById('customerPanel').classList.remove('open');
|
|
document.getElementById('customerDetailsLink').classList.remove('panel-open');
|
|
}
|
|
|
|
document.addEventListener('keydown', (e) => {
|
|
if (e.key === 'Escape') closeDrawer();
|
|
});
|
|
|
|
// Status dropdown (Popover API)
|
|
let currentStatus = 'arrived';
|
|
const dropdown = document.getElementById('statusDropdown');
|
|
const badge = document.getElementById('statusBadge');
|
|
|
|
// Update selection when popover is about to open
|
|
dropdown.addEventListener('beforetoggle', (e) => {
|
|
if (e.newState === 'open') {
|
|
updateDropdownSelection();
|
|
}
|
|
});
|
|
|
|
// Position after popover opens
|
|
dropdown.addEventListener('toggle', (e) => {
|
|
if (e.newState === 'open') {
|
|
const rect = badge.getBoundingClientRect();
|
|
dropdown.style.position = 'fixed';
|
|
dropdown.style.top = `${rect.bottom + 4}px`;
|
|
dropdown.style.left = `${rect.right - dropdown.offsetWidth}px`;
|
|
}
|
|
});
|
|
|
|
function updateDropdownSelection() {
|
|
const options = document.querySelectorAll('swp-status-option');
|
|
options.forEach(opt => {
|
|
opt.classList.toggle('selected', opt.dataset.status === currentStatus);
|
|
});
|
|
}
|
|
|
|
function selectStatus(status) {
|
|
currentStatus = status;
|
|
|
|
// Update badge
|
|
const badge = document.getElementById('statusBadge');
|
|
const text = document.getElementById('statusText');
|
|
badge.className = 'status-badge status-' + status;
|
|
text.textContent = statusLabels[status];
|
|
|
|
// Update footer
|
|
const footer = document.getElementById('drawerFooter');
|
|
const payBtn = document.getElementById('payBtn');
|
|
footer.className = 'status-' + status;
|
|
|
|
const btnLabels = {
|
|
created: 'Gå til betaling',
|
|
arrived: 'Gå til betaling',
|
|
paid: 'Betalt ✓',
|
|
noshow: 'Udeblevet',
|
|
cancelled: 'Aflyst'
|
|
};
|
|
payBtn.textContent = btnLabels[status];
|
|
|
|
// Close popover
|
|
dropdown.hidePopover();
|
|
}
|
|
|
|
// Add note tags: multi-select (toggle) + update preview
|
|
document.querySelectorAll('swp-add-note-tag-option').forEach(tag => {
|
|
tag.onclick = () => {
|
|
tag.classList.toggle('selected');
|
|
updatePreviewTags();
|
|
};
|
|
});
|
|
|
|
// Live Preview Logic
|
|
const addNoteTextarea = document.querySelector('swp-add-note-content textarea');
|
|
const previewEntry = document.getElementById('previewEntry');
|
|
const previewText = document.getElementById('previewText');
|
|
const previewTags = document.getElementById('previewTags');
|
|
const previewVisibility = document.getElementById('previewVisibility');
|
|
const previewMarking = document.getElementById('previewMarking');
|
|
const visibilitySelect = document.querySelector('swp-add-note-dropdown-group:nth-child(1) select');
|
|
const markingSelect = document.querySelector('swp-add-note-dropdown-group:nth-child(2) select');
|
|
|
|
// Show preview on textarea focus
|
|
addNoteTextarea.addEventListener('focus', showPreview);
|
|
|
|
// Update visibility in preview
|
|
visibilitySelect.addEventListener('change', updatePreviewVisibility);
|
|
|
|
// Update marking in preview
|
|
markingSelect.addEventListener('change', updatePreviewMarking);
|
|
|
|
// Update preview text in real-time
|
|
addNoteTextarea.addEventListener('input', () => {
|
|
previewText.textContent = addNoteTextarea.value || '(Tom note)';
|
|
});
|
|
|
|
function showPreview() {
|
|
previewEntry.classList.remove('hidden');
|
|
updatePreviewTags();
|
|
}
|
|
|
|
function hidePreview() {
|
|
previewEntry.classList.add('hidden');
|
|
}
|
|
|
|
function updatePreviewTags() {
|
|
const selectedTags = document.querySelectorAll('swp-add-note-tag-option.selected');
|
|
previewTags.innerHTML = '';
|
|
selectedTags.forEach(tag => {
|
|
const tagEl = document.createElement('swp-journal-tag');
|
|
tagEl.textContent = tag.textContent;
|
|
tagEl.classList.add('tag-' + tag.dataset.tag);
|
|
previewTags.appendChild(tagEl);
|
|
});
|
|
}
|
|
|
|
function updatePreviewVisibility() {
|
|
const value = visibilitySelect.value;
|
|
const text = value === 'Kun mig' ? 'Kun dig' : 'Alle';
|
|
previewVisibility.querySelector('span').textContent = text;
|
|
}
|
|
|
|
function updatePreviewMarking() {
|
|
const value = markingSelect.value;
|
|
previewMarking.className = '';
|
|
|
|
if (value === 'Ingen') {
|
|
previewMarking.classList.add('hidden');
|
|
previewMarking.innerHTML = '';
|
|
} else if (value === 'Vigtigt') {
|
|
previewMarking.classList.add('important');
|
|
previewMarking.innerHTML = '<img src="icons/exclamation.svg" class="entry-icon" alt=""><span>Vigtigt</span>';
|
|
} else if (value === 'Advarsel') {
|
|
previewMarking.classList.add('warning');
|
|
previewMarking.innerHTML = '<img src="icons/warning.svg" class="entry-icon" alt=""><span>Advarsel</span>';
|
|
}
|
|
}
|
|
|
|
function resetAddNoteForm() {
|
|
addNoteTextarea.value = '';
|
|
previewText.textContent = '(Tom note)';
|
|
document.querySelectorAll('swp-add-note-tag-option').forEach(tag => {
|
|
if (tag.textContent === 'Fri note') {
|
|
tag.classList.add('selected');
|
|
} else {
|
|
tag.classList.remove('selected');
|
|
}
|
|
});
|
|
visibilitySelect.value = 'Hele salonen';
|
|
markingSelect.value = 'Ingen';
|
|
updatePreviewTags();
|
|
updatePreviewVisibility();
|
|
updatePreviewMarking();
|
|
}
|
|
|
|
// ==========================================
|
|
// FARVEFORMEL PANEL
|
|
// ==========================================
|
|
let activePanel = null; // 'note' or 'farveformel'
|
|
|
|
// Farveformel elements
|
|
const ffMaalTone = document.getElementById('ffMaalTone');
|
|
const ffOxidant = document.getElementById('ffOxidant');
|
|
const ffFormel = document.getElementById('ffFormel');
|
|
const ffBlandingsforhold = document.getElementById('ffBlandingsforhold');
|
|
const ffVirketid = document.getElementById('ffVirketid');
|
|
const ffPlacering = document.getElementById('ffPlacering');
|
|
const ffResultat = document.getElementById('ffResultat');
|
|
const previewType = document.querySelector('#previewEntry swp-journal-entry-type');
|
|
|
|
// Farveformel preview elements (in farveformler tab)
|
|
const previewEntryFarveformel = document.getElementById('previewEntryFarveformel');
|
|
const previewTextFarveformel = document.getElementById('previewTextFarveformel');
|
|
|
|
function openFarveformel() {
|
|
document.getElementById('farveformelPanel').classList.add('open');
|
|
activePanel = 'farveformel';
|
|
showFarveformelPreview();
|
|
}
|
|
|
|
function closeFarveformel() {
|
|
document.getElementById('farveformelPanel').classList.remove('open');
|
|
hideFarveformelPreview();
|
|
resetFarveformelForm();
|
|
activePanel = null;
|
|
}
|
|
|
|
function showFarveformelPreview() {
|
|
previewEntryFarveformel.classList.remove('hidden');
|
|
updateFarveformelPreview();
|
|
}
|
|
|
|
function hideFarveformelPreview() {
|
|
previewEntryFarveformel.classList.add('hidden');
|
|
}
|
|
|
|
function updateFarveformelPreview() {
|
|
const lines = [];
|
|
|
|
if (ffMaalTone.value) {
|
|
lines.push(`• Mål/tone: ${ffMaalTone.value}`);
|
|
}
|
|
if (ffOxidant.value) {
|
|
lines.push(`• Oxidant: <span class="mono">${ffOxidant.value}</span>`);
|
|
}
|
|
if (ffFormel.value) {
|
|
lines.push(`• Formel: <span class="mono">${ffFormel.value}</span>`);
|
|
} else {
|
|
lines.push(`• Formel: <span class="mono">(ikke angivet)</span>`);
|
|
}
|
|
if (ffBlandingsforhold.value) {
|
|
lines.push(`• Blanding: <span class="mono">${ffBlandingsforhold.value}</span>`);
|
|
}
|
|
if (ffVirketid.value) {
|
|
lines.push(`• Virketid: <span class="mono">${ffVirketid.value}</span>`);
|
|
}
|
|
if (ffPlacering.value) {
|
|
lines.push(`• Placering: ${ffPlacering.value}`);
|
|
}
|
|
if (ffResultat.value) {
|
|
lines.push(`<br>${ffResultat.value}`);
|
|
}
|
|
|
|
previewTextFarveformel.innerHTML = lines.length > 0 ? lines.join('<br>') : '(Udfyld felter...)';
|
|
}
|
|
|
|
function resetFarveformelForm() {
|
|
ffMaalTone.value = '';
|
|
ffOxidant.value = '';
|
|
ffFormel.value = '';
|
|
ffBlandingsforhold.value = '';
|
|
ffVirketid.value = '';
|
|
ffPlacering.value = '';
|
|
ffResultat.value = '';
|
|
}
|
|
|
|
function saveFarveformel() {
|
|
// In a real app, this would save to backend
|
|
alert('Farveformel gemt!');
|
|
closeFarveformel();
|
|
}
|
|
|
|
// Add event listeners for farveformel fields
|
|
[ffMaalTone, ffOxidant, ffFormel, ffBlandingsforhold, ffVirketid, ffPlacering, ffResultat].forEach(el => {
|
|
el.addEventListener('input', () => {
|
|
if (activePanel === 'farveformel') {
|
|
updateFarveformelPreview();
|
|
}
|
|
});
|
|
el.addEventListener('change', () => {
|
|
if (activePanel === 'farveformel') {
|
|
updateFarveformelPreview();
|
|
}
|
|
});
|
|
});
|
|
|
|
// Update original openAddNote to track active panel
|
|
const originalOpenAddNote = openAddNote;
|
|
openAddNote = function() {
|
|
originalOpenAddNote();
|
|
activePanel = 'note';
|
|
};
|
|
|
|
// Update original closeAddNote to clear active panel
|
|
const originalCloseAddNote = closeAddNote;
|
|
closeAddNote = function() {
|
|
originalCloseAddNote();
|
|
activePanel = null;
|
|
};
|
|
|
|
// ==========================================
|
|
// ANALYSE PANEL
|
|
// ==========================================
|
|
|
|
// Analyse form elements
|
|
const anHovedbund = document.getElementById('anHovedbund');
|
|
const anIrritation = document.getElementById('anIrritation');
|
|
const anHaarTykkelse = document.getElementById('anHaarTykkelse');
|
|
const anHaarStruktur = document.getElementById('anHaarStruktur');
|
|
const anPorositet = document.getElementById('anPorositet');
|
|
const anKemisk = document.getElementById('anKemisk');
|
|
const anShampoo = document.getElementById('anShampoo');
|
|
const anHjemmepleje = document.getElementById('anHjemmepleje');
|
|
const anBemaerkning = document.getElementById('anBemaerkning');
|
|
const anAdvarsel = document.getElementById('anAdvarsel');
|
|
|
|
// Analyse preview elements
|
|
const previewEntryAnalyse = document.getElementById('previewEntryAnalyse');
|
|
const previewTextAnalyse = document.getElementById('previewTextAnalyse');
|
|
const previewTagsAnalyse = document.getElementById('previewTagsAnalyse');
|
|
|
|
function openAnalyse() {
|
|
document.getElementById('analysePanel').classList.add('open');
|
|
activePanel = 'analyse';
|
|
showAnalysePreview();
|
|
}
|
|
|
|
function closeAnalyse() {
|
|
document.getElementById('analysePanel').classList.remove('open');
|
|
hideAnalysePreview();
|
|
resetAnalyseForm();
|
|
activePanel = null;
|
|
}
|
|
|
|
function showAnalysePreview() {
|
|
previewEntryAnalyse.classList.remove('hidden');
|
|
updateAnalysePreview();
|
|
updateAnalysePreviewTags();
|
|
}
|
|
|
|
function hideAnalysePreview() {
|
|
previewEntryAnalyse.classList.add('hidden');
|
|
}
|
|
|
|
function updateAnalysePreview() {
|
|
const lines = [];
|
|
|
|
if (anHovedbund.value) {
|
|
lines.push(`• Hovedbund: ${anHovedbund.value}`);
|
|
}
|
|
if (anIrritation.value) {
|
|
lines.push(`• Irritation: ${anIrritation.value}`);
|
|
}
|
|
if (anHaarTykkelse.value || anHaarStruktur.value) {
|
|
const haarParts = [];
|
|
if (anHaarTykkelse.value) haarParts.push(anHaarTykkelse.value);
|
|
if (anHaarStruktur.value) haarParts.push(anHaarStruktur.value);
|
|
lines.push(`• Hår: <span class="mono">${haarParts.join(' · ')}</span>`);
|
|
}
|
|
if (anPorositet.value) {
|
|
lines.push(`• Porøsitet: <span class="mono">${anPorositet.value}</span>`);
|
|
}
|
|
if (anKemisk.value) {
|
|
lines.push(`• Kemisk beh.: ${anKemisk.value}`);
|
|
}
|
|
if (anShampoo.value) {
|
|
lines.push(`• Shampoo: ${anShampoo.value}`);
|
|
}
|
|
if (anHjemmepleje.value) {
|
|
lines.push(`• Hjemmepleje: ${anHjemmepleje.value}`);
|
|
}
|
|
if (anBemaerkning.value) {
|
|
lines.push(`<br>${anBemaerkning.value}`);
|
|
}
|
|
|
|
previewTextAnalyse.innerHTML = lines.length > 0 ? lines.join('<br>') : '(Udfyld felter...)';
|
|
}
|
|
|
|
function updateAnalysePreviewTags() {
|
|
const analysePanelTags = document.querySelectorAll('#analysePanel swp-add-note-tag-option.selected');
|
|
previewTagsAnalyse.innerHTML = '';
|
|
analysePanelTags.forEach(tag => {
|
|
const tagEl = document.createElement('swp-journal-tag');
|
|
tagEl.textContent = tag.textContent;
|
|
tagEl.classList.add('tag-' + tag.dataset.tag);
|
|
previewTagsAnalyse.appendChild(tagEl);
|
|
});
|
|
}
|
|
|
|
function resetAnalyseForm() {
|
|
anHovedbund.value = '';
|
|
anIrritation.value = '';
|
|
anHaarTykkelse.value = '';
|
|
anHaarStruktur.value = '';
|
|
anPorositet.value = '';
|
|
anKemisk.value = '';
|
|
anShampoo.value = '';
|
|
anHjemmepleje.value = '';
|
|
anBemaerkning.value = '';
|
|
anAdvarsel.value = 'Nej';
|
|
|
|
// Reset tags - only "Analyse" selected by default
|
|
document.querySelectorAll('#analysePanel swp-add-note-tag-option').forEach(tag => {
|
|
if (tag.dataset.tag === 'analyse') {
|
|
tag.classList.add('selected');
|
|
} else {
|
|
tag.classList.remove('selected');
|
|
}
|
|
});
|
|
}
|
|
|
|
function saveAnalyse() {
|
|
// In a real app, this would save to backend
|
|
alert('Analyse gemt!');
|
|
closeAnalyse();
|
|
}
|
|
|
|
// Add event listeners for analyse form fields
|
|
[anHovedbund, anIrritation, anHaarTykkelse, anHaarStruktur, anPorositet, anKemisk, anShampoo, anHjemmepleje, anBemaerkning, anAdvarsel].forEach(el => {
|
|
el.addEventListener('input', () => {
|
|
if (activePanel === 'analyse') {
|
|
updateAnalysePreview();
|
|
}
|
|
});
|
|
el.addEventListener('change', () => {
|
|
if (activePanel === 'analyse') {
|
|
updateAnalysePreview();
|
|
}
|
|
});
|
|
});
|
|
|
|
// Add tag toggle listeners for analyse panel
|
|
document.querySelectorAll('#analysePanel swp-add-note-tag-option').forEach(tag => {
|
|
tag.onclick = () => {
|
|
tag.classList.toggle('selected');
|
|
updateAnalysePreviewTags();
|
|
};
|
|
});
|
|
</script>
|
|
|
|
<!-- Chart initialization -->
|
|
<script type="module">
|
|
import { createChart } from 'https://unpkg.com/@sevenweirdpeople/swp-charting@latest/dist/index.js';
|
|
|
|
// Initialize chart when customer panel opens
|
|
let chartInitialized = false;
|
|
|
|
const originalOpenCustomerPanel = window.openCustomerPanel;
|
|
window.openCustomerPanel = function() {
|
|
originalOpenCustomerPanel();
|
|
|
|
if (!chartInitialized) {
|
|
setTimeout(() => {
|
|
createChart(document.getElementById('customerRevenueChart'), {
|
|
width: 620,
|
|
height: 215,
|
|
xAxis: {
|
|
categories: ['Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec']
|
|
},
|
|
series: [
|
|
{
|
|
name: 'Services',
|
|
color: '#00897b',
|
|
data: [
|
|
{ x: 'Jul', y: 1200 },
|
|
{ x: 'Sep', y: 1500 },
|
|
{ x: 'Okt', y: 2800 },
|
|
{ x: 'Dec', y: 1800 }
|
|
]
|
|
},
|
|
{
|
|
name: 'Produkter',
|
|
color: '#1e88e5',
|
|
data: [
|
|
{ x: 'Aug', y: 800 },
|
|
{ x: 'Okt', y: 900 },
|
|
{ x: 'Nov', y: 700 },
|
|
{ x: 'Dec', y: 950 }
|
|
]
|
|
}
|
|
],
|
|
legend: true
|
|
});
|
|
chartInitialized = true;
|
|
}, 100);
|
|
}
|
|
};
|
|
</script>
|
|
</body>
|
|
</html>
|