2025-12-23 09:32:49 +01:00
<!DOCTYPE html>
< html lang = "da" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< title > Service Detaljer - Klip & Farve< / title >
< link href = "https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel = "stylesheet" >
< style >
/* ==========================================
CSS VARIABLES (Design System)
========================================== */
:root {
/* Colors */
--color-surface: #fff;
--color-background: #f5f5f5;
--color-background-hover: #f0f0f0;
--color-background-alt: #fafafa;
--color-border: #e0e0e0;
--color-text: #333;
--color-text-secondary: #666;
--color-teal: #00897b;
--color-blue: #1976d2;
--color-red: #e53935;
--color-amber: #ffb300;
--color-purple: #8b5cf6;
--color-green: #43a047;
/* Calendar colors */
--b-color-red: #e53935;
--b-color-pink: #d81b60;
--b-color-magenta: #c2185b;
--b-color-purple: #8e24aa;
--b-color-violet: #7b1fa2;
--b-color-deep-purple: #5e35b1;
--b-color-indigo: #3949ab;
--b-color-blue: #1e88e5;
--b-color-light-blue: #039be5;
--b-color-cyan: #00acc1;
--b-color-teal: #00897b;
--b-color-green: #43a047;
--b-color-light-green: #7cb342;
--b-color-lime: #c0ca33;
--b-color-yellow: #fdd835;
--b-color-amber: #ffb300;
--b-color-orange: #fb8c00;
--b-color-deep-orange: #f4511e;
/* Typography */
--font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
--font-mono: 'JetBrains Mono', monospace;
}
/* ==========================================
RESET & BASE
========================================== */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: var(--font-family);
font-size: 14px;
color: var(--color-text);
background: var(--color-background);
line-height: 1.5;
}
/* ==========================================
TOPBAR
========================================== */
swp-topbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 24px;
background: var(--color-surface);
border-bottom: 1px solid var(--color-border);
position: sticky;
top: 0;
z-index: 100;
}
swp-topbar-left {
display: flex;
align-items: center;
gap: 16px;
}
swp-back-link {
display: flex;
align-items: center;
gap: 6px;
color: var(--color-text-secondary);
text-decoration: none;
font-size: 13px;
cursor: pointer;
transition: color 150ms ease;
}
swp-back-link:hover {
color: var(--color-teal);
}
swp-back-link svg {
width: 16px;
height: 16px;
fill: currentColor;
}
swp-topbar-title {
font-size: 16px;
font-weight: 600;
color: var(--color-text);
}
swp-topbar-actions {
display: flex;
align-items: center;
gap: 12px;
}
swp-btn {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 8px 16px;
font-size: 13px;
font-weight: 500;
border-radius: 6px;
border: none;
cursor: pointer;
transition: all 150ms ease;
}
swp-btn.primary {
background: var(--color-teal);
color: white;
}
swp-btn.primary:hover {
background: #00796b;
}
swp-btn.secondary {
background: var(--color-surface);
color: var(--color-text);
border: 1px solid var(--color-border);
}
swp-btn.secondary:hover {
background: var(--color-background);
}
/* ==========================================
SERVICE HEADER
========================================== */
swp-service-header {
display: flex;
gap: 24px;
padding: 24px;
background: var(--color-surface);
border-bottom: 1px solid var(--color-border);
position: sticky;
top: 49px;
z-index: 90;
}
swp-service-info {
flex: 1;
display: flex;
flex-direction: column;
gap: 8px;
}
swp-service-name-row {
display: flex;
align-items: center;
gap: 16px;
}
swp-service-name {
font-size: 24px;
font-weight: 600;
color: var(--color-text);
}
/* Tags */
swp-tags-editor {
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
swp-tag {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 4px 10px;
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.3px;
border-radius: 4px;
background: var(--color-background);
color: var(--color-text-secondary);
}
swp-tag.active {
background: color-mix(in srgb, var(--color-green) 20%, white);
color: var(--color-green);
}
swp-tag.popular {
background: color-mix(in srgb, var(--color-amber) 20%, white);
color: #b8860b;
}
swp-tag.combo {
background: color-mix(in srgb, var(--color-teal) 15%, white);
color: var(--color-teal);
}
swp-tag.color {
background: color-mix(in srgb, var(--color-purple) 15%, white);
color: var(--color-purple);
}
swp-tag .remove {
cursor: pointer;
opacity: 0.6;
margin-left: 2px;
}
swp-tag .remove:hover {
opacity: 1;
}
swp-tag-add {
display: inline-flex;
align-items: center;
padding: 4px 10px;
font-size: 11px;
font-weight: 500;
color: var(--color-text-secondary);
border: 1px dashed var(--color-border);
border-radius: 4px;
cursor: pointer;
transition: all 150ms ease;
}
swp-tag-add:hover {
border-color: var(--color-teal);
color: var(--color-teal);
}
/* Service Status Toggle (like booking exclusion) */
swp-service-status {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
font-size: 12px;
font-weight: 500;
border-radius: 6px;
cursor: pointer;
transition: all 150ms ease;
margin-left: auto;
}
swp-service-status[data-active="true"] {
background: color-mix(in srgb, var(--color-green) 15%, white);
color: var(--color-green);
border: 1px solid color-mix(in srgb, var(--color-green) 30%, white);
}
swp-service-status[data-active="false"] {
background: color-mix(in srgb, var(--color-red) 12%, white);
color: var(--color-red);
border: 1px solid color-mix(in srgb, var(--color-red) 30%, white);
}
swp-service-status .icon {
font-size: 14px;
}
/* Fact Boxes Inline (same as customer detail) */
swp-fact-boxes-inline {
display: flex;
gap: 24px;
margin-top: 4px;
}
swp-fact-inline {
display: flex;
align-items: baseline;
gap: 6px;
}
swp-fact-inline-value {
font-size: 18px;
font-weight: 600;
font-family: var(--font-mono);
color: var(--color-text);
}
swp-fact-inline-label {
font-size: 12px;
color: var(--color-text-secondary);
}
/* ==========================================
TAB BAR
========================================== */
swp-tab-bar {
display: flex;
gap: 0;
background: var(--color-surface);
border-bottom: 1px solid var(--color-border);
padding: 0 24px;
position: sticky;
top: 178px;
z-index: 80;
}
swp-tab {
padding: 14px 24px;
font-size: 14px;
font-weight: 500;
color: var(--color-text-secondary);
cursor: pointer;
border-bottom: 2px solid transparent;
margin-bottom: -1px;
transition: all 150ms ease;
}
swp-tab:hover {
color: var(--color-text);
background: var(--color-background-alt);
}
swp-tab.active {
color: var(--color-teal);
border-bottom-color: var(--color-teal);
}
/* ==========================================
TAB CONTENT
========================================== */
swp-tab-content {
display: none;
padding: 24px;
max-width: 1200px;
margin: 0 auto;
}
swp-tab-content.active {
display: block;
}
/* ==========================================
LAYOUT GRID
========================================== */
.grid-2 {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
}
.grid-4 {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
}
@media (max-width: 900px) {
.grid-2 {
grid-template-columns: 1fr;
}
.grid-4 {
grid-template-columns: repeat(2, 1fr);
}
}
/* ==========================================
CARDS
========================================== */
swp-card {
display: block;
background: var(--color-surface);
border-radius: 8px;
padding: 20px;
border: 1px solid var(--color-border);
margin-bottom: 16px;
}
swp-card:last-child {
margin-bottom: 0;
}
/* Section Label */
swp-section-label {
display: block;
font-size: 11px;
font-weight: 600;
color: var(--color-text-secondary);
text-transform: uppercase;
letter-spacing: 0.5px;
margin-bottom: 16px;
}
/* ==========================================
STAT CARDS
========================================== */
swp-stat-card {
background: var(--color-surface);
border-radius: 8px;
padding: 20px;
text-align: center;
border: 1px solid var(--color-border);
}
swp-stat-value {
display: block;
font-size: 28px;
font-weight: 600;
font-family: var(--font-mono);
color: var(--color-text);
}
swp-stat-label {
display: block;
font-size: 12px;
color: var(--color-text-secondary);
margin-top: 4px;
}
swp-stat-card.highlight swp-stat-value {
color: var(--color-teal);
}
/* ==========================================
EDIT SECTION
========================================== */
swp-edit-section {
display: flex;
flex-direction: column;
gap: 12px;
}
swp-edit-row {
display: grid;
grid-template-columns: 140px 1fr;
align-items: center;
gap: 12px;
}
swp-edit-label {
font-size: 13px;
color: var(--color-text-secondary);
}
swp-edit-value {
font-size: 14px;
padding: 8px 12px;
border-radius: 4px;
background: var(--color-background-alt);
border: 1px solid transparent;
transition: all 150ms ease;
cursor: text;
}
swp-edit-value:hover {
background: var(--color-background);
}
swp-edit-value:focus {
outline: none;
background: var(--color-surface);
border-color: var(--color-teal);
}
swp-edit-value[contenteditable="true"] {
cursor: text;
}
/* Select dropdown styling */
swp-edit-select {
display: block;
}
swp-edit-select select {
width: 100%;
font-size: 14px;
font-family: inherit;
padding: 8px 12px;
border-radius: 4px;
background: var(--color-background-alt);
border: 1px solid transparent;
cursor: pointer;
transition: all 150ms ease;
}
swp-edit-select select:hover {
background: var(--color-background);
}
swp-edit-select select:focus {
outline: none;
background: var(--color-surface);
border-color: var(--color-teal);
}
/* Textarea styling */
swp-edit-textarea {
display: block;
width: 100%;
min-height: 80px;
font-size: 14px;
font-family: inherit;
padding: 12px;
border-radius: 4px;
background: var(--color-background-alt);
border: 1px solid transparent;
resize: vertical;
transition: all 150ms ease;
}
swp-edit-textarea:hover {
background: var(--color-background);
}
swp-edit-textarea:focus {
outline: none;
background: var(--color-surface);
border-color: var(--color-teal);
}
/* ==========================================
TOGGLE SLIDER (Ja/Nej)
========================================== */
swp-toggle-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 0;
border-bottom: 1px solid var(--color-border);
}
swp-toggle-row:last-child {
border-bottom: none;
}
swp-toggle-label {
font-size: 14px;
color: var(--color-text);
}
swp-toggle-description {
display: block;
font-size: 12px;
color: var(--color-text-secondary);
margin-top: 2px;
}
swp-toggle-slider {
display: inline-flex;
width: fit-content;
background: var(--color-background);
border-radius: 6px;
border: 1px solid var(--color-border);
overflow: hidden;
position: relative;
}
swp-toggle-slider::before {
content: '';
position: absolute;
top: 2px;
left: 2px;
width: calc(50% - 4px);
height: calc(100% - 4px);
background: color-mix(in srgb, var(--color-green) 18%, white);
border-radius: 4px;
transition: transform 200ms ease, background 200ms ease;
}
swp-toggle-slider[data-value="no"]::before {
transform: translateX(100%);
background: color-mix(in srgb, var(--color-red) 18%, white);
}
swp-toggle-option {
position: relative;
z-index: 1;
padding: 5px 16px;
font-size: 12px;
font-weight: 500;
color: var(--color-text-secondary);
cursor: pointer;
transition: color 150ms ease;
user-select: none;
}
swp-toggle-slider[data-value="yes"] swp-toggle-option:first-child {
color: var(--color-green);
font-weight: 600;
}
swp-toggle-slider[data-value="no"] swp-toggle-option:last-child {
color: var(--color-red);
font-weight: 600;
}
/* ==========================================
PRICE MATRIX
========================================== */
swp-price-matrix {
display: block;
overflow-x: auto;
margin-top: 16px;
}
swp-price-matrix table {
width: 100%;
border-collapse: collapse;
font-size: 14px;
}
swp-price-matrix th,
swp-price-matrix td {
padding: 12px 16px;
text-align: center;
border: 1px solid var(--color-border);
}
swp-price-matrix th {
background: var(--color-background);
font-weight: 600;
color: var(--color-text-secondary);
font-size: 12px;
text-transform: uppercase;
letter-spacing: 0.3px;
}
swp-price-matrix th:first-child,
swp-price-matrix td:first-child {
text-align: left;
}
swp-price-matrix td:first-child {
font-weight: 500;
background: var(--color-background-alt);
}
swp-price-matrix td span {
font-family: var(--font-mono);
}
swp-price-matrix td span[contenteditable="true"] {
display: inline-block;
min-width: 60px;
padding: 4px 8px;
border-radius: 4px;
background: var(--color-surface);
border: 1px solid var(--color-border);
cursor: text;
}
swp-price-matrix td span[contenteditable="true"]:focus {
outline: none;
border-color: var(--color-teal);
}
/* Price mode toggle */
swp-price-mode {
display: flex;
gap: 8px;
margin-bottom: 16px;
}
swp-price-mode-btn {
padding: 8px 16px;
font-size: 13px;
font-weight: 500;
border-radius: 6px;
border: 1px solid var(--color-border);
background: var(--color-surface);
color: var(--color-text-secondary);
cursor: pointer;
transition: all 150ms ease;
}
swp-price-mode-btn.active {
background: var(--color-teal);
color: white;
border-color: var(--color-teal);
}
swp-price-mode-btn:hover:not(.active) {
background: var(--color-background);
}
/* Simple price view */
swp-price-simple {
display: block;
margin-top: 16px;
}
/* ==========================================
DURATION LIST
========================================== */
swp-duration-list {
display: flex;
flex-direction: column;
gap: 8px;
}
swp-duration-item {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 16px;
background: var(--color-background-alt);
border-radius: 6px;
border: 1px solid var(--color-border);
}
swp-duration-name {
flex: 1;
font-weight: 500;
}
swp-duration-value {
display: flex;
align-items: center;
gap: 6px;
}
swp-duration-value span {
font-family: var(--font-mono);
min-width: 40px;
padding: 4px 8px;
border-radius: 4px;
background: var(--color-surface);
border: 1px solid var(--color-border);
text-align: right;
}
swp-duration-value span[contenteditable="true"]:focus {
outline: none;
border-color: var(--color-teal);
}
swp-duration-unit {
font-size: 13px;
color: var(--color-text-secondary);
}
swp-duration-delete {
padding: 4px 8px;
color: var(--color-text-secondary);
cursor: pointer;
border-radius: 4px;
transition: all 150ms ease;
}
swp-duration-delete:hover {
color: var(--color-red);
background: color-mix(in srgb, var(--color-red) 10%, white);
}
/* ==========================================
EMPLOYEE LIST
========================================== */
swp-employee-list {
display: flex;
flex-direction: column;
gap: 8px;
}
swp-employee-item {
display: flex;
align-items: center;
gap: 16px;
padding: 16px;
background: var(--color-background-alt);
border-radius: 6px;
border: 1px solid var(--color-border);
}
swp-employee-item.disabled swp-toggle-slider {
opacity: 0.4;
pointer-events: none;
}
swp-employee-avatar {
width: 44px;
height: 44px;
border-radius: 50%;
background: linear-gradient(135deg, var(--color-teal) 0%, #00695c 100%);
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 14px;
flex-shrink: 0;
}
swp-employee-info {
flex: 1;
min-width: 0;
}
swp-employee-name {
font-weight: 500;
color: var(--color-text);
}
swp-employee-level {
font-size: 13px;
color: var(--color-text-secondary);
}
swp-employee-overrides {
display: flex;
gap: 16px;
font-size: 13px;
color: var(--color-text-secondary);
}
swp-employee-override-value {
color: var(--color-text);
font-weight: 500;
}
swp-employee-warning {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 10px;
font-weight: 500;
color: #b8860b;
background: color-mix(in srgb, var(--color-amber) 20%, white);
padding: 3px 8px;
border-radius: 10px;
margin-left: 8px;
}
/* ==========================================
ADDON LIST
========================================== */
swp-addon-list {
display: flex;
flex-direction: column;
gap: 8px;
}
swp-addon-item {
display: flex;
align-items: center;
gap: 12px;
padding: 16px;
background: var(--color-background-alt);
border-radius: 6px;
border: 1px solid var(--color-border);
cursor: pointer;
transition: all 150ms ease;
}
swp-addon-item:hover {
background: var(--color-background);
}
swp-addon-item.selected {
border-color: var(--color-teal);
background: color-mix(in srgb, var(--color-teal) 5%, white);
}
swp-addon-checkbox {
width: 20px;
height: 20px;
border: 2px solid var(--color-border);
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
transition: all 150ms ease;
}
swp-addon-item.selected swp-addon-checkbox {
background: var(--color-teal);
border-color: var(--color-teal);
color: white;
}
swp-addon-checkbox svg {
width: 14px;
height: 14px;
fill: currentColor;
opacity: 0;
}
swp-addon-item.selected swp-addon-checkbox svg {
opacity: 1;
}
swp-addon-info {
flex: 1;
}
swp-addon-name {
font-weight: 500;
color: var(--color-text);
}
swp-addon-meta {
display: flex;
gap: 12px;
font-size: 13px;
color: var(--color-text-secondary);
margin-top: 4px;
}
swp-addon-price {
color: var(--color-teal);
font-weight: 500;
font-family: var(--font-mono);
}
swp-addon-type {
display: inline-block;
padding: 2px 8px;
background: color-mix(in srgb, var(--color-blue) 12%, white);
color: var(--color-blue);
border-radius: 10px;
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
}
swp-addon-type.required {
background: color-mix(in srgb, var(--color-amber) 15%, white);
color: #b8860b;
}
/* ==========================================
AVAILABILITY LIST
========================================== */
swp-availability-list {
display: flex;
flex-direction: column;
}
swp-availability-row {
display: flex;
align-items: center;
gap: 16px;
padding: 10px 0;
border-bottom: 1px solid var(--color-border);
}
swp-availability-row:last-child {
border-bottom: none;
}
swp-availability-row[data-enabled="false"] {
opacity: 0.5;
}
swp-availability-day {
width: 80px;
font-size: 14px;
font-weight: 500;
color: var(--color-text);
}
swp-availability-time {
flex: 1;
2025-12-23 09:53:31 +01:00
display: flex;
flex-direction: column;
gap: 4px;
}
swp-time-range {
display: flex;
align-items: center;
gap: 12px;
2025-12-23 09:32:49 +01:00
}
2025-12-23 09:53:31 +01:00
swp-time-range-slider {
position: relative;
flex: 1;
height: 20px;
display: flex;
align-items: center;
}
swp-time-range-track {
position: absolute;
2025-12-23 09:32:49 +01:00
width: 100%;
2025-12-23 09:53:31 +01:00
height: 4px;
background: var(--color-border);
border-radius: 2px;
}
swp-time-range-fill {
position: absolute;
height: 4px;
background: var(--color-teal);
border-radius: 2px;
cursor: grab;
}
swp-time-range-fill:active {
cursor: grabbing;
}
swp-time-range-fill.disabled {
pointer-events: none;
cursor: default;
}
swp-time-range-slider input[type="range"] {
position: absolute;
width: 100%;
height: 4px;
-webkit-appearance: none;
appearance: none;
background: transparent;
pointer-events: none;
margin: 0;
}
swp-time-range-slider input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 14px;
height: 14px;
background: var(--color-teal);
border: 2px solid white;
border-radius: 50%;
2025-12-23 09:32:49 +01:00
cursor: pointer;
2025-12-23 09:53:31 +01:00
pointer-events: auto;
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
2025-12-23 09:32:49 +01:00
}
2025-12-23 09:53:31 +01:00
swp-time-range-slider input[type="range"]::-moz-range-thumb {
width: 14px;
height: 14px;
background: var(--color-teal);
border: 2px solid white;
border-radius: 50%;
cursor: pointer;
pointer-events: auto;
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
2025-12-23 09:32:49 +01:00
}
2025-12-23 09:53:31 +01:00
swp-time-range-label {
font-size: 12px;
font-family: var(--font-mono);
color: var(--color-text);
min-width: 90px;
text-align: center;
background: var(--color-background-alt);
padding: 3px 8px;
border-radius: 4px;
}
swp-availability-row[data-enabled="false"] swp-time-range-slider input[type="range"]::-webkit-slider-thumb {
background: var(--color-text-secondary);
}
swp-availability-row[data-enabled="false"] swp-time-range-fill {
background: var(--color-text-secondary);
2025-12-23 09:32:49 +01:00
}
2025-12-23 09:53:31 +01:00
swp-availability-row[data-enabled="false"] swp-time-range-label {
2025-12-23 09:32:49 +01:00
opacity: 0.5;
}
/* ==========================================
COLOR DROPDOWN (Popover)
========================================== */
swp-color-dropdown {
position: relative;
}
swp-color-dropdown button {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 12px;
font-size: 14px;
font-family: inherit;
border-radius: 4px;
background: var(--color-background-alt);
border: 1px solid transparent;
cursor: pointer;
transition: all 150ms ease;
min-width: 160px;
anchor-name: --color-trigger;
}
swp-color-dropdown button:hover {
background: var(--color-background);
}
swp-color-dropdown button .color-name {
flex: 1;
text-align: left;
}
swp-color-dropdown button .chevron {
opacity: 0.5;
}
swp-color-dropdown [popover] {
position: absolute;
position-anchor: --color-trigger;
top: anchor(bottom);
left: anchor(left);
margin: 4px 0 0 0;
padding: 6px;
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
box-shadow: 0 4px 16px rgba(0,0,0,0.12);
min-width: 180px;
max-height: 280px;
overflow-y: auto;
}
swp-color-dropdown [popover]:popover-open {
display: flex;
flex-direction: column;
gap: 2px;
}
swp-color-option {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
transition: background 150ms ease;
font-size: 13px;
}
swp-color-option:hover {
background: var(--color-background);
}
swp-color-option.selected {
background: color-mix(in srgb, var(--color-teal) 12%, white);
font-weight: 500;
}
swp-color-dot {
width: 18px;
height: 12px;
border-radius: 3px;
flex-shrink: 0;
}
/* ==========================================
CUSTOM DROPDOWN (Popover)
========================================== */
swp-custom-dropdown {
position: relative;
}
swp-custom-dropdown button {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 12px;
font-size: 14px;
font-family: inherit;
border-radius: 4px;
background: var(--color-background-alt);
border: 1px solid transparent;
cursor: pointer;
transition: all 150ms ease;
min-width: 180px;
text-align: left;
anchor-name: --dropdown-trigger;
}
swp-custom-dropdown button:hover {
background: var(--color-background);
}
swp-custom-dropdown button .dropdown-value {
flex: 1;
}
swp-custom-dropdown button .chevron {
opacity: 0.5;
}
swp-custom-dropdown [popover] {
position: absolute;
position-anchor: --dropdown-trigger;
top: anchor(bottom);
left: anchor(left);
margin: 4px 0 0 0;
padding: 6px;
background: var(--color-surface);
border: 1px solid var(--color-border);
border-radius: 8px;
box-shadow: 0 4px 16px rgba(0,0,0,0.12);
min-width: 180px;
max-height: 280px;
overflow-y: auto;
}
swp-custom-dropdown [popover]:popover-open {
display: flex;
flex-direction: column;
gap: 2px;
}
swp-dropdown-option {
display: flex;
align-items: center;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
transition: background 150ms ease;
font-size: 13px;
}
swp-dropdown-option:hover {
background: var(--color-background);
}
swp-dropdown-option.selected {
background: color-mix(in srgb, var(--color-teal) 12%, white);
font-weight: 500;
color: var(--color-teal);
}
/* Color classes */
swp-color-dot.is-red { background: var(--b-color-red); }
swp-color-dot.is-pink { background: var(--b-color-pink); }
swp-color-dot.is-magenta { background: var(--b-color-magenta); }
swp-color-dot.is-purple { background: var(--b-color-purple); }
swp-color-dot.is-violet { background: var(--b-color-violet); }
swp-color-dot.is-deep-purple { background: var(--b-color-deep-purple); }
swp-color-dot.is-indigo { background: var(--b-color-indigo); }
swp-color-dot.is-blue { background: var(--b-color-blue); }
swp-color-dot.is-light-blue { background: var(--b-color-light-blue); }
swp-color-dot.is-cyan { background: var(--b-color-cyan); }
swp-color-dot.is-teal { background: var(--b-color-teal); }
swp-color-dot.is-green { background: var(--b-color-green); }
swp-color-dot.is-light-green { background: var(--b-color-light-green); }
swp-color-dot.is-lime { background: var(--b-color-lime); }
swp-color-dot.is-yellow { background: var(--b-color-yellow); }
swp-color-dot.is-amber { background: var(--b-color-amber); }
swp-color-dot.is-orange { background: var(--b-color-orange); }
swp-color-dot.is-deep-orange { background: var(--b-color-deep-orange); }
/* ==========================================
ADD BUTTON
========================================== */
swp-add-button {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 12px;
border: 2px dashed var(--color-border);
border-radius: 6px;
color: var(--color-text-secondary);
font-size: 13px;
cursor: pointer;
transition: all 150ms ease;
margin-top: 12px;
}
swp-add-button:hover {
border-color: var(--color-teal);
color: var(--color-teal);
background: color-mix(in srgb, var(--color-teal) 5%, white);
}
/* ==========================================
SEE ALL LINK
========================================== */
swp-see-all {
display: block;
text-align: center;
padding: 12px;
font-size: 13px;
color: var(--color-teal);
cursor: pointer;
margin-top: 12px;
border-top: 1px solid var(--color-border);
}
swp-see-all:hover {
text-decoration: underline;
}
< / style >
< / head >
< body >
<!-- Topbar -->
< swp-topbar >
< swp-topbar-left >
< swp-back-link >
< svg viewBox = "0 0 24 24" > < path d = "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" / > < / svg >
Tilbage til services
< / swp-back-link >
< swp-topbar-title > Service detaljer< / swp-topbar-title >
< / swp-topbar-left >
< swp-topbar-actions >
< swp-btn class = "secondary" > Duplikér< / swp-btn >
< swp-btn class = "primary" > Gem ændringer< / swp-btn >
< / swp-topbar-actions >
< / swp-topbar >
<!-- Service Header -->
< swp-service-header >
< swp-service-info >
< swp-service-name-row >
< swp-service-name contenteditable = "true" > Klip & Farve< / swp-service-name >
< swp-tags-editor >
< swp-tag class = "popular" > Populær< / swp-tag >
< swp-tag class = "combo" > Kombi< / swp-tag >
< swp-tag class = "color" > Farve< / swp-tag >
< swp-tag-add > + Tilføj tag< / swp-tag-add >
< / swp-tags-editor >
< swp-service-status data-active = "true" id = "serviceStatus" >
< span class = "icon" > ●< / span >
< span class = "text" > Aktiv< / span >
< / swp-service-status >
< / swp-service-name-row >
< swp-fact-boxes-inline >
< swp-fact-inline >
< swp-fact-inline-value > 60-120< / swp-fact-inline-value >
< swp-fact-inline-label > min varighed< / swp-fact-inline-label >
< / swp-fact-inline >
< swp-fact-inline >
< swp-fact-inline-value > 795 kr< / swp-fact-inline-value >
< swp-fact-inline-label > fra pris< / swp-fact-inline-label >
< / swp-fact-inline >
< swp-fact-inline >
< swp-fact-inline-value > 4< / swp-fact-inline-value >
< swp-fact-inline-label > medarbejdere< / swp-fact-inline-label >
< / swp-fact-inline >
< swp-fact-inline >
< swp-fact-inline-value > 156< / swp-fact-inline-value >
< swp-fact-inline-label > bookinger i år< / swp-fact-inline-label >
< / swp-fact-inline >
< / swp-fact-boxes-inline >
< / swp-service-info >
< / swp-service-header >
<!-- Tab Bar -->
< swp-tab-bar >
< swp-tab class = "active" data-tab = "general" > Generelt< / swp-tab >
< swp-tab data-tab = "prices" > Priser< / swp-tab >
< swp-tab data-tab = "duration" > Varighed< / swp-tab >
< swp-tab data-tab = "employees" > Medarbejdere< / swp-tab >
< swp-tab data-tab = "addons" > Tilvalg< / swp-tab >
< swp-tab data-tab = "rules" > Regler< / swp-tab >
< / swp-tab-bar >
<!-- ==========================================
GENERELT TAB
========================================== -->
< swp-tab-content class = "active" data-tab = "general" >
< div class = "grid-2" >
< div >
< swp-card >
< swp-section-label > Grundlæggende< / swp-section-label >
< swp-edit-section >
< swp-edit-row >
< swp-edit-label > Servicenavn< / swp-edit-label >
< swp-edit-value contenteditable = "true" > Klip & Farve< / swp-edit-value >
< / swp-edit-row >
< swp-edit-row >
< swp-edit-label > Kategori< / swp-edit-label >
< swp-custom-dropdown >
< button type = "button" popovertarget = "categoryPopover" id = "categoryTrigger" >
< span class = "dropdown-value" > Kombi-behandlinger< / span >
< svg class = "chevron" viewBox = "0 0 24 24" width = "16" height = "16" > < path d = "M7 10l5 5 5-5z" fill = "currentColor" / > < / svg >
< / button >
< div popover id = "categoryPopover" >
< swp-dropdown-option class = "selected" data-value = "kombi" > Kombi-behandlinger< / swp-dropdown-option >
< swp-dropdown-option data-value = "klip" > Klip< / swp-dropdown-option >
< swp-dropdown-option data-value = "farve" > Farve< / swp-dropdown-option >
< swp-dropdown-option data-value = "behandlinger" > Behandlinger< / swp-dropdown-option >
< swp-dropdown-option data-value = "styling" > Styling< / swp-dropdown-option >
< / div >
< / swp-custom-dropdown >
< / swp-edit-row >
< swp-edit-row >
< swp-edit-label > Farve i kalenderen< / swp-edit-label >
< swp-color-dropdown >
< button type = "button" popovertarget = "colorPopover" id = "colorTrigger" >
< swp-color-dot class = "is-teal" > < / swp-color-dot >
< span class = "color-name" > Teal< / span >
< svg class = "chevron" viewBox = "0 0 24 24" width = "16" height = "16" > < path d = "M7 10l5 5 5-5z" fill = "currentColor" / > < / svg >
< / button >
< div popover id = "colorPopover" >
< swp-color-option data-value = "red" data-label = "Rød" > < swp-color-dot class = "is-red" > < / swp-color-dot > < span > Rød< / span > < / swp-color-option >
< swp-color-option data-value = "pink" data-label = "Pink" > < swp-color-dot class = "is-pink" > < / swp-color-dot > < span > Pink< / span > < / swp-color-option >
< swp-color-option data-value = "magenta" data-label = "Magenta" > < swp-color-dot class = "is-magenta" > < / swp-color-dot > < span > Magenta< / span > < / swp-color-option >
< swp-color-option data-value = "purple" data-label = "Lilla" > < swp-color-dot class = "is-purple" > < / swp-color-dot > < span > Lilla< / span > < / swp-color-option >
< swp-color-option data-value = "violet" data-label = "Violet" > < swp-color-dot class = "is-violet" > < / swp-color-dot > < span > Violet< / span > < / swp-color-option >
< swp-color-option data-value = "deep-purple" data-label = "Mørk lilla" > < swp-color-dot class = "is-deep-purple" > < / swp-color-dot > < span > Mørk lilla< / span > < / swp-color-option >
< swp-color-option data-value = "indigo" data-label = "Indigo" > < swp-color-dot class = "is-indigo" > < / swp-color-dot > < span > Indigo< / span > < / swp-color-option >
< swp-color-option data-value = "blue" data-label = "Blå" > < swp-color-dot class = "is-blue" > < / swp-color-dot > < span > Blå< / span > < / swp-color-option >
< swp-color-option data-value = "light-blue" data-label = "Lyseblå" > < swp-color-dot class = "is-light-blue" > < / swp-color-dot > < span > Lyseblå< / span > < / swp-color-option >
< swp-color-option data-value = "cyan" data-label = "Cyan" > < swp-color-dot class = "is-cyan" > < / swp-color-dot > < span > Cyan< / span > < / swp-color-option >
< swp-color-option data-value = "teal" data-label = "Teal" class = "selected" > < swp-color-dot class = "is-teal" > < / swp-color-dot > < span > Teal< / span > < / swp-color-option >
< swp-color-option data-value = "green" data-label = "Grøn" > < swp-color-dot class = "is-green" > < / swp-color-dot > < span > Grøn< / span > < / swp-color-option >
< swp-color-option data-value = "light-green" data-label = "Lysegrøn" > < swp-color-dot class = "is-light-green" > < / swp-color-dot > < span > Lysegrøn< / span > < / swp-color-option >
< swp-color-option data-value = "lime" data-label = "Lime" > < swp-color-dot class = "is-lime" > < / swp-color-dot > < span > Lime< / span > < / swp-color-option >
< swp-color-option data-value = "yellow" data-label = "Gul" > < swp-color-dot class = "is-yellow" > < / swp-color-dot > < span > Gul< / span > < / swp-color-option >
< swp-color-option data-value = "amber" data-label = "Amber" > < swp-color-dot class = "is-amber" > < / swp-color-dot > < span > Amber< / span > < / swp-color-option >
< swp-color-option data-value = "orange" data-label = "Orange" > < swp-color-dot class = "is-orange" > < / swp-color-dot > < span > Orange< / span > < / swp-color-option >
< swp-color-option data-value = "deep-orange" data-label = "Mørk orange" > < swp-color-dot class = "is-deep-orange" > < / swp-color-dot > < span > Mørk orange< / span > < / swp-color-option >
< / div >
< / swp-color-dropdown >
< / swp-edit-row >
< swp-edit-row >
< swp-edit-label > Service aktiv< / swp-edit-label >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-edit-row >
< / swp-edit-section >
< swp-section-label style = "margin-top: 20px;" > Interne noter< / swp-section-label >
< swp-edit-textarea contenteditable = "true" > Komplet farvebehandling med klip. Husk konsultation ved første besøg. Anbefal Olaplex til kemisk behandlet hår.< / swp-edit-textarea >
< / swp-card >
< swp-card >
< swp-section-label > Bookingtype< / swp-section-label >
< swp-toggle-row >
< div >
< swp-toggle-label > Kan bookes som hovedservice< / swp-toggle-label >
< swp-toggle-description > Vises i servicelisten og kan bookes selvstændigt< / swp-toggle-description >
< / div >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-toggle-row >
< swp-toggle-row >
< div >
< swp-toggle-label > Kan bookes som tilvalg< / swp-toggle-label >
< swp-toggle-description > Kan tilføjes som ekstra ydelse til andre services< / swp-toggle-description >
< / div >
< swp-toggle-slider data-value = "no" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-toggle-row >
< / swp-card >
< / div >
< div >
< swp-card >
< swp-section-label > Online booking< / swp-section-label >
< swp-toggle-row >
< div >
< swp-toggle-label > Vis i online booking< / swp-toggle-label >
< swp-toggle-description > Synlig for kunder i online booking< / swp-toggle-description >
< / div >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-toggle-row >
< swp-toggle-row >
< div >
< swp-toggle-label > Fremhævet service< / swp-toggle-label >
< swp-toggle-description > Vises øverst med fremhævet styling< / swp-toggle-description >
< / div >
< swp-toggle-slider data-value = "no" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-toggle-row >
< swp-section-label style = "margin-top: 20px;" > Beskrivelse< / swp-section-label >
< swp-edit-textarea contenteditable = "true" > Forkæl dig selv med en komplet forvandling! Vores Klip & Farve behandling inkluderer professionel farverådgivning, farvning tilpasset din hudtone, præcisionsklip og styling. Perfekt til dig der ønsker et helt nyt look.< / swp-edit-textarea >
< swp-section-label style = "margin-top: 20px;" > Billede< / swp-section-label >
< swp-add-button > + Upload billede< / swp-add-button >
< / swp-card >
< / div >
< / div >
< / swp-tab-content >
<!-- ==========================================
PRISER TAB
========================================== -->
< swp-tab-content data-tab = "prices" >
< swp-card >
< swp-section-label > Prisstruktur< / swp-section-label >
< swp-price-mode >
< swp-price-mode-btn data-mode = "simple" > Simpel pris< / swp-price-mode-btn >
< swp-price-mode-btn data-mode = "matrix" class = "active" > Matrix-pris< / swp-price-mode-btn >
< / swp-price-mode >
<!-- Simpel pris visning -->
< swp-price-simple style = "display: none;" >
< swp-edit-section >
< swp-edit-row >
< swp-edit-label > Pris< / swp-edit-label >
< swp-edit-value contenteditable = "true" > 995 kr< / swp-edit-value >
< / swp-edit-row >
< / swp-edit-section >
< / swp-price-simple >
<!-- Matrix pris visning -->
< swp-price-matrix >
< table >
< thead >
< tr >
< th > Niveau< / th >
< th > Kort hår< / th >
< th > Mellem hår< / th >
< th > Langt hår< / th >
< th > Ekstra langt< / th >
< / tr >
< / thead >
< tbody >
< tr >
< td > Junior< / td >
< td > < span contenteditable = "true" > 795< / span > kr< / td >
< td > < span contenteditable = "true" > 895< / span > kr< / td >
< td > < span contenteditable = "true" > 995< / span > kr< / td >
< td > < span contenteditable = "true" > 1.095< / span > kr< / td >
< / tr >
< tr >
< td > Senior< / td >
< td > < span contenteditable = "true" > 895< / span > kr< / td >
< td > < span contenteditable = "true" > 995< / span > kr< / td >
< td > < span contenteditable = "true" > 1.095< / span > kr< / td >
< td > < span contenteditable = "true" > 1.195< / span > kr< / td >
< / tr >
< tr >
< td > Master< / td >
< td > < span contenteditable = "true" > 995< / span > kr< / td >
< td > < span contenteditable = "true" > 1.095< / span > kr< / td >
< td > < span contenteditable = "true" > 1.195< / span > kr< / td >
< td > < span contenteditable = "true" > 1.295< / span > kr< / td >
< / tr >
< / tbody >
< / table >
< swp-add-button > + Tilføj niveau eller hårlængde< / swp-add-button >
< / swp-price-matrix >
< / swp-card >
< div class = "grid-2" >
< swp-card >
< swp-section-label > Økonomi< / swp-section-label >
< swp-edit-section >
< swp-edit-row >
< swp-edit-label > Momssats< / swp-edit-label >
< swp-edit-select >
< select >
< option selected > 25% (standard)< / option >
< option > 0% (momsfri)< / option >
< / select >
< / swp-edit-select >
< / swp-edit-row >
< swp-edit-row >
< swp-edit-label > Produktomkostning< / swp-edit-label >
< swp-edit-value contenteditable = "true" > 85 kr< / swp-edit-value >
< / swp-edit-row >
< swp-edit-row >
< swp-edit-label > Provision< / swp-edit-label >
< swp-edit-select >
< select >
< option selected > Standard (fra lønsats)< / option >
< option > Fast beløb< / option >
< option > Procent af pris< / option >
< / select >
< / swp-edit-select >
< / swp-edit-row >
< / swp-edit-section >
< / swp-card >
< swp-card >
< swp-section-label > Rabatter & Loyalitet< / swp-section-label >
< swp-toggle-row >
< swp-toggle-label > Medlemsrabat (10%)< / swp-toggle-label >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-toggle-row >
< swp-toggle-row >
< swp-toggle-label > Kan betales med gavekort< / swp-toggle-label >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-toggle-row >
< swp-toggle-row >
< swp-toggle-label > Optjen loyalitetspoint< / swp-toggle-label >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-toggle-row >
< / swp-card >
< / div >
< / swp-tab-content >
<!-- ==========================================
VARIGHED TAB
========================================== -->
< swp-tab-content data-tab = "duration" >
< div class = "grid-2" >
< swp-card >
< swp-section-label > Varighedsvarianter< / swp-section-label >
< swp-duration-list >
< swp-duration-item >
< swp-duration-name > Kort hår< / swp-duration-name >
< swp-duration-value >
< span contenteditable = "true" > 60< / span >
< swp-duration-unit > min< / swp-duration-unit >
< / swp-duration-value >
< swp-duration-delete > ✕< / swp-duration-delete >
< / swp-duration-item >
< swp-duration-item >
< swp-duration-name > Mellem hår< / swp-duration-name >
< swp-duration-value >
< span contenteditable = "true" > 90< / span >
< swp-duration-unit > min< / swp-duration-unit >
< / swp-duration-value >
< swp-duration-delete > ✕< / swp-duration-delete >
< / swp-duration-item >
< swp-duration-item >
< swp-duration-name > Langt hår< / swp-duration-name >
< swp-duration-value >
< span contenteditable = "true" > 120< / span >
< swp-duration-unit > min< / swp-duration-unit >
< / swp-duration-value >
< swp-duration-delete > ✕< / swp-duration-delete >
< / swp-duration-item >
< swp-duration-item >
< swp-duration-name > Ekstra langt hår< / swp-duration-name >
< swp-duration-value >
< span contenteditable = "true" > 150< / span >
< swp-duration-unit > min< / swp-duration-unit >
< / swp-duration-value >
< swp-duration-delete > ✕< / swp-duration-delete >
< / swp-duration-item >
< / swp-duration-list >
< swp-add-button > + Tilføj variant< / swp-add-button >
< / swp-card >
< swp-card >
< swp-section-label > Buffer-tider< / swp-section-label >
< swp-edit-section >
< swp-edit-row >
< swp-edit-label > Buffer før aftale< / swp-edit-label >
< swp-edit-select >
< select >
< option > Ingen< / option >
< option > 5 minutter< / option >
< option > 10 minutter< / option >
< option selected > 15 minutter< / option >
< option > 30 minutter< / option >
< / select >
< / swp-edit-select >
< / swp-edit-row >
< swp-edit-row >
< swp-edit-label > Buffer efter aftale< / swp-edit-label >
< swp-edit-select >
< select >
< option > Ingen< / option >
< option > 5 minutter< / option >
< option selected > 10 minutter< / option >
< option > 15 minutter< / option >
< option > 30 minutter< / option >
< / select >
< / swp-edit-select >
< / swp-edit-row >
< swp-edit-row >
< swp-edit-label > Oprydningstid< / swp-edit-label >
< swp-edit-select >
< select >
< option > Ingen< / option >
< option selected > 5 minutter< / option >
< option > 10 minutter< / option >
< option > 15 minutter< / option >
< / select >
< / swp-edit-select >
< / swp-edit-row >
< / swp-edit-section >
< / swp-card >
< / div >
< / swp-tab-content >
<!-- ==========================================
MEDARBEJDERE TAB
========================================== -->
< swp-tab-content data-tab = "employees" >
< swp-card >
< swp-section-label > Medarbejdere der udfører denne service< / swp-section-label >
< swp-employee-list >
< swp-employee-item >
< swp-employee-avatar > AS< / swp-employee-avatar >
< swp-employee-info >
< swp-employee-name > Anna Sørensen< / swp-employee-name >
< swp-employee-level > Master Stylist< / swp-employee-level >
< / swp-employee-info >
< swp-employee-overrides >
< span > Pris: < swp-employee-override-value > Standard< / swp-employee-override-value > < / span >
< span > Varighed: < swp-employee-override-value > Standard< / swp-employee-override-value > < / span >
< / swp-employee-overrides >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-employee-item >
< swp-employee-item >
< swp-employee-avatar > MJ< / swp-employee-avatar >
< swp-employee-info >
< swp-employee-name > Mette Jensen< / swp-employee-name >
< swp-employee-level > Senior Stylist< / swp-employee-level >
< / swp-employee-info >
< swp-employee-overrides >
< span > Pris: < swp-employee-override-value > Standard< / swp-employee-override-value > < / span >
< span > Varighed: < swp-employee-override-value > +15 min< / swp-employee-override-value > < / span >
< / swp-employee-overrides >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-employee-item >
< swp-employee-item >
< swp-employee-avatar > LN< / swp-employee-avatar >
< swp-employee-info >
< swp-employee-name > Louise Nielsen< / swp-employee-name >
< swp-employee-level > Senior Stylist< / swp-employee-level >
< / swp-employee-info >
< swp-employee-overrides >
< span > Pris: < swp-employee-override-value > Standard< / swp-employee-override-value > < / span >
< span > Varighed: < swp-employee-override-value > Standard< / swp-employee-override-value > < / span >
< / swp-employee-overrides >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-employee-item >
< swp-employee-item >
< swp-employee-avatar > KP< / swp-employee-avatar >
< swp-employee-info >
< swp-employee-name > Katrine Pedersen< / swp-employee-name >
< swp-employee-level > Stylist< / swp-employee-level >
< / swp-employee-info >
< swp-employee-overrides >
< span > Pris: < swp-employee-override-value > Standard< / swp-employee-override-value > < / span >
< span > Varighed: < swp-employee-override-value > +15 min< / swp-employee-override-value > < / span >
< / swp-employee-overrides >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-employee-item >
< swp-employee-item class = "disabled" >
< swp-employee-avatar > SA< / swp-employee-avatar >
< swp-employee-info >
< swp-employee-name > Sofie Andersen< swp-employee-warning > ⚠ Ikke certificeret< / swp-employee-warning > < / swp-employee-name >
< swp-employee-level > Junior Stylist< / swp-employee-level >
< / swp-employee-info >
< swp-employee-overrides >
< span > Pris: < swp-employee-override-value > —< / swp-employee-override-value > < / span >
< span > Varighed: < swp-employee-override-value > —< / swp-employee-override-value > < / span >
< / swp-employee-overrides >
< swp-toggle-slider data-value = "no" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-employee-item >
< / swp-employee-list >
< swp-see-all > Vælg alle / Fravælg alle< / swp-see-all >
< / swp-card >
< / swp-tab-content >
<!-- ==========================================
TILVALG TAB
========================================== -->
< swp-tab-content data-tab = "addons" >
< swp-card >
< swp-section-label > Tilvalg til denne service< / swp-section-label >
< swp-addon-list >
< swp-addon-item class = "selected" >
< swp-addon-checkbox >
< svg viewBox = "0 0 24 24" > < path d = "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" / > < / svg >
< / swp-addon-checkbox >
< swp-addon-info >
< swp-addon-name > Olaplex Behandling< / swp-addon-name >
< swp-addon-meta >
< swp-addon-price > +250 kr< / swp-addon-price >
< span > +15 min< / span >
< swp-addon-type > Valgfri< / swp-addon-type >
< / swp-addon-meta >
< / swp-addon-info >
< / swp-addon-item >
< swp-addon-item class = "selected" >
< swp-addon-checkbox >
< svg viewBox = "0 0 24 24" > < path d = "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" / > < / svg >
< / swp-addon-checkbox >
< swp-addon-info >
< swp-addon-name > Kerastase Hårkur< / swp-addon-name >
< swp-addon-meta >
< swp-addon-price > +195 kr< / swp-addon-price >
< span > +10 min< / span >
< swp-addon-type > Valgfri< / swp-addon-type >
< / swp-addon-meta >
< / swp-addon-info >
< / swp-addon-item >
< swp-addon-item class = "selected" >
< swp-addon-checkbox >
< svg viewBox = "0 0 24 24" > < path d = "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" / > < / svg >
< / swp-addon-checkbox >
< swp-addon-info >
< swp-addon-name > Styling / Curls< / swp-addon-name >
< swp-addon-meta >
< swp-addon-price > +150 kr< / swp-addon-price >
< span > +20 min< / span >
< swp-addon-type > Valgfri< / swp-addon-type >
< / swp-addon-meta >
< / swp-addon-info >
< / swp-addon-item >
< swp-addon-item class = "selected" >
< swp-addon-checkbox >
< svg viewBox = "0 0 24 24" > < path d = "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" / > < / svg >
< / swp-addon-checkbox >
< swp-addon-info >
< swp-addon-name > Hovedbundsmassage< / swp-addon-name >
< swp-addon-meta >
< swp-addon-price > +75 kr< / swp-addon-price >
< span > +5 min< / span >
< swp-addon-type > Valgfri< / swp-addon-type >
< / swp-addon-meta >
< / swp-addon-info >
< / swp-addon-item >
< swp-addon-item >
< swp-addon-checkbox >
< svg viewBox = "0 0 24 24" > < path d = "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" / > < / svg >
< / swp-addon-checkbox >
< swp-addon-info >
< swp-addon-name > Patch Test< / swp-addon-name >
< swp-addon-meta >
< swp-addon-price > Gratis< / swp-addon-price >
< span > 48t før< / span >
< swp-addon-type class = "required" > Påkrævet (nye)< / swp-addon-type >
< / swp-addon-meta >
< / swp-addon-info >
< / swp-addon-item >
< / swp-addon-list >
< swp-add-button > + Tilføj eksisterende tilvalg< / swp-add-button >
< / swp-card >
< / swp-tab-content >
<!-- ==========================================
REGLER TAB
========================================== -->
< swp-tab-content data-tab = "rules" >
< div class = "grid-2" >
< swp-card >
< swp-section-label > Booking-regler< / swp-section-label >
< swp-edit-section >
< swp-edit-row >
< swp-edit-label > Minimum varsel< / swp-edit-label >
< swp-edit-select >
< select >
< option > Ingen< / option >
< option > 2 timer< / option >
< option > 4 timer< / option >
< option selected > 24 timer< / option >
< option > 48 timer< / option >
< option > 1 uge< / option >
< / select >
< / swp-edit-select >
< / swp-edit-row >
< swp-edit-row >
< swp-edit-label > Maks. forudbooking< / swp-edit-label >
< swp-edit-select >
< select >
< option > 1 måned< / option >
< option > 2 måneder< / option >
< option selected > 3 måneder< / option >
< option > 6 måneder< / option >
< option > 1 år< / option >
< / select >
< / swp-edit-select >
< / swp-edit-row >
< swp-edit-row >
< swp-edit-label > Afbestillingsfrist< / swp-edit-label >
< swp-edit-select >
< select >
< option > Ingen< / option >
< option > 2 timer< / option >
< option > 4 timer< / option >
< option selected > 24 timer< / option >
< option > 48 timer< / option >
< / select >
< / swp-edit-select >
< / swp-edit-row >
< swp-edit-row >
< swp-edit-label > No-show gebyr< / swp-edit-label >
< swp-edit-select >
< select >
< option > Intet< / option >
< option > 25% af pris< / option >
< option selected > 50% af pris< / option >
< option > Fuld pris< / option >
< option > Fast beløb< / option >
< / select >
< / swp-edit-select >
< / swp-edit-row >
< / swp-edit-section >
< / swp-card >
< swp-card >
< swp-section-label > Tilgængelighed< / swp-section-label >
< swp-availability-list >
< swp-availability-row data-enabled = "true" >
< swp-availability-day > Mandag< / swp-availability-day >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
2025-12-23 09:53:31 +01:00
< swp-availability-time >
< swp-time-range >
< swp-time-range-slider >
< swp-time-range-track > < / swp-time-range-track >
< swp-time-range-fill > < / swp-time-range-fill >
< input type = "range" class = "range-start" min = "0" max = "60" value = "8" step = "1" >
< input type = "range" class = "range-end" min = "0" max = "60" value = "48" step = "1" >
< / swp-time-range-slider >
< swp-time-range-label > 08:00 – 18:00< / swp-time-range-label >
< / swp-time-range >
< / swp-availability-time >
2025-12-23 09:32:49 +01:00
< / swp-availability-row >
< swp-availability-row data-enabled = "true" >
< swp-availability-day > Tirsdag< / swp-availability-day >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
2025-12-23 09:53:31 +01:00
< swp-availability-time >
< swp-time-range >
< swp-time-range-slider >
< swp-time-range-track > < / swp-time-range-track >
< swp-time-range-fill > < / swp-time-range-fill >
< input type = "range" class = "range-start" min = "0" max = "60" value = "8" step = "1" >
< input type = "range" class = "range-end" min = "0" max = "60" value = "48" step = "1" >
< / swp-time-range-slider >
< swp-time-range-label > 08:00 – 18:00< / swp-time-range-label >
< / swp-time-range >
< / swp-availability-time >
2025-12-23 09:32:49 +01:00
< / swp-availability-row >
< swp-availability-row data-enabled = "true" >
< swp-availability-day > Onsdag< / swp-availability-day >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
2025-12-23 09:53:31 +01:00
< swp-availability-time >
< swp-time-range >
< swp-time-range-slider >
< swp-time-range-track > < / swp-time-range-track >
< swp-time-range-fill > < / swp-time-range-fill >
< input type = "range" class = "range-start" min = "0" max = "60" value = "8" step = "1" >
< input type = "range" class = "range-end" min = "0" max = "60" value = "48" step = "1" >
< / swp-time-range-slider >
< swp-time-range-label > 08:00 – 18:00< / swp-time-range-label >
< / swp-time-range >
< / swp-availability-time >
2025-12-23 09:32:49 +01:00
< / swp-availability-row >
< swp-availability-row data-enabled = "true" >
< swp-availability-day > Torsdag< / swp-availability-day >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
2025-12-23 09:53:31 +01:00
< swp-availability-time >
< swp-time-range >
< swp-time-range-slider >
< swp-time-range-track > < / swp-time-range-track >
< swp-time-range-fill > < / swp-time-range-fill >
< input type = "range" class = "range-start" min = "0" max = "60" value = "8" step = "1" >
< input type = "range" class = "range-end" min = "0" max = "60" value = "24" step = "1" >
< / swp-time-range-slider >
< swp-time-range-label > 08:00 – 12:00< / swp-time-range-label >
< / swp-time-range >
< / swp-availability-time >
2025-12-23 09:32:49 +01:00
< / swp-availability-row >
< swp-availability-row data-enabled = "true" >
< swp-availability-day > Fredag< / swp-availability-day >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
2025-12-23 09:53:31 +01:00
< swp-availability-time >
< swp-time-range >
< swp-time-range-slider >
< swp-time-range-track > < / swp-time-range-track >
< swp-time-range-fill > < / swp-time-range-fill >
< input type = "range" class = "range-start" min = "0" max = "60" value = "8" step = "1" >
< input type = "range" class = "range-end" min = "0" max = "60" value = "48" step = "1" >
< / swp-time-range-slider >
< swp-time-range-label > 08:00 – 18:00< / swp-time-range-label >
< / swp-time-range >
< / swp-availability-time >
2025-12-23 09:32:49 +01:00
< / swp-availability-row >
< swp-availability-row data-enabled = "false" >
< swp-availability-day > Lørdag< / swp-availability-day >
< swp-toggle-slider data-value = "no" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
2025-12-23 09:53:31 +01:00
< swp-availability-time >
< swp-time-range >
< swp-time-range-slider >
< swp-time-range-track > < / swp-time-range-track >
< swp-time-range-fill > < / swp-time-range-fill >
< input type = "range" class = "range-start" min = "0" max = "60" value = "8" step = "1" disabled >
< input type = "range" class = "range-end" min = "0" max = "60" value = "48" step = "1" disabled >
< / swp-time-range-slider >
< swp-time-range-label > 08:00 – 18:00< / swp-time-range-label >
< / swp-time-range >
< / swp-availability-time >
2025-12-23 09:32:49 +01:00
< / swp-availability-row >
< swp-availability-row data-enabled = "false" >
< swp-availability-day > Søndag< / swp-availability-day >
< swp-toggle-slider data-value = "no" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
2025-12-23 09:53:31 +01:00
< swp-availability-time >
< swp-time-range >
< swp-time-range-slider >
< swp-time-range-track > < / swp-time-range-track >
< swp-time-range-fill > < / swp-time-range-fill >
< input type = "range" class = "range-start" min = "0" max = "60" value = "8" step = "1" disabled >
< input type = "range" class = "range-end" min = "0" max = "60" value = "48" step = "1" disabled >
< / swp-time-range-slider >
< swp-time-range-label > 08:00 – 18:00< / swp-time-range-label >
< / swp-time-range >
< / swp-availability-time >
2025-12-23 09:32:49 +01:00
< / swp-availability-row >
< / swp-availability-list >
< / swp-card >
< swp-card >
< swp-section-label > Krav & Forberedelse< / swp-section-label >
< swp-toggle-row >
< div >
< swp-toggle-label > Konsultation påkrævet< / swp-toggle-label >
< swp-toggle-description > Kunde skal have konsultation før første booking< / swp-toggle-description >
< / div >
< swp-toggle-slider data-value = "no" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-toggle-row >
< swp-toggle-row >
< div >
< swp-toggle-label > Patch test påkrævet< / swp-toggle-label >
< swp-toggle-description > Allergitest 48 timer før farvebehandling (nye kunder)< / swp-toggle-description >
< / div >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-toggle-row >
< swp-toggle-row >
< div >
< swp-toggle-label > Aldersbegrænsning< / swp-toggle-label >
< swp-toggle-description > Minimum alder for booking af denne service< / swp-toggle-description >
< / div >
< swp-toggle-slider data-value = "no" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-toggle-row >
< swp-toggle-row >
< div >
< swp-toggle-label > Samtykke-formular< / swp-toggle-label >
< swp-toggle-description > Kunde skal underskrive samtykke før behandling< / swp-toggle-description >
< / div >
< swp-toggle-slider data-value = "no" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-toggle-row >
< / swp-card >
< / div >
< swp-card >
< swp-section-label > Online booking indstillinger< / swp-section-label >
< swp-toggle-row >
< swp-toggle-label > Vis i online booking< / swp-toggle-label >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-toggle-row >
< swp-toggle-row >
< swp-toggle-label > Tillad valg af medarbejder< / swp-toggle-label >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-toggle-row >
< swp-toggle-row >
< swp-toggle-label > Vis pris< / swp-toggle-label >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-toggle-row >
< swp-toggle-row >
< swp-toggle-label > Vis varighed< / swp-toggle-label >
< swp-toggle-slider data-value = "yes" >
< swp-toggle-option > Ja< / swp-toggle-option >
< swp-toggle-option > Nej< / swp-toggle-option >
< / swp-toggle-slider >
< / swp-toggle-row >
< / swp-card >
< / swp-tab-content >
< script >
// ==========================================
// TAB SWITCHING
// ==========================================
document.querySelectorAll('swp-tab').forEach(tab => {
tab.addEventListener('click', () => {
const tabName = tab.dataset.tab;
// Update tab active state
document.querySelectorAll('swp-tab').forEach(t => t.classList.remove('active'));
tab.classList.add('active');
// Update content visibility
document.querySelectorAll('swp-tab-content').forEach(content => {
content.classList.remove('active');
if (content.dataset.tab === tabName) {
content.classList.add('active');
}
});
});
});
2025-12-23 09:53:31 +01:00
// ==========================================
// TIME RANGE SLIDERS
// ==========================================
function valueToTime(value) {
// value 0-60 represents 06:00-21:00 in 15-min intervals
const totalMinutes = (value * 15) + (6 * 60); // Add 6 hour offset
const hours = Math.floor(totalMinutes / 60);
const minutes = totalMinutes % 60;
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
}
const TIME_RANGE_MAX = 60; // 15 hours (06:00-21:00) * 4 intervals
function updateTimeRange(slider) {
const startInput = slider.querySelector('.range-start');
const endInput = slider.querySelector('.range-end');
const fill = slider.querySelector('swp-time-range-fill');
const label = slider.closest('swp-time-range').querySelector('swp-time-range-label');
let startVal = parseInt(startInput.value);
let endVal = parseInt(endInput.value);
// Ensure start doesn't exceed end
if (startVal > endVal) {
if (startInput === document.activeElement) {
startInput.value = endVal;
startVal = endVal;
} else {
endInput.value = startVal;
endVal = startVal;
}
}
// Update fill bar position
const startPercent = (startVal / TIME_RANGE_MAX) * 100;
const endPercent = (endVal / TIME_RANGE_MAX) * 100;
fill.style.left = startPercent + '%';
fill.style.width = (endPercent - startPercent) + '%';
// Update label
label.textContent = valueToTime(startVal) + ' – ' + valueToTime(endVal);
}
document.querySelectorAll('swp-time-range-slider').forEach(slider => {
const startInput = slider.querySelector('.range-start');
const endInput = slider.querySelector('.range-end');
const fill = slider.querySelector('swp-time-range-fill');
const track = slider.querySelector('swp-time-range-track');
// Initialize
updateTimeRange(slider);
startInput.addEventListener('input', () => updateTimeRange(slider));
endInput.addEventListener('input', () => updateTimeRange(slider));
// Drag fill bar to move entire range
let isDragging = false;
let dragStartX = 0;
let dragStartValues = { start: 0, end: 0 };
fill.addEventListener('mousedown', (e) => {
if (startInput.disabled) return;
isDragging = true;
dragStartX = e.clientX;
dragStartValues.start = parseInt(startInput.value);
dragStartValues.end = parseInt(endInput.value);
e.preventDefault();
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
const sliderWidth = track.offsetWidth;
const deltaX = e.clientX - dragStartX;
const deltaValue = Math.round((deltaX / sliderWidth) * TIME_RANGE_MAX);
const duration = dragStartValues.end - dragStartValues.start;
let newStart = dragStartValues.start + deltaValue;
let newEnd = dragStartValues.end + deltaValue;
// Clamp to bounds
if (newStart < 0 ) {
newStart = 0;
newEnd = duration;
}
if (newEnd > TIME_RANGE_MAX) {
newEnd = TIME_RANGE_MAX;
newStart = TIME_RANGE_MAX - duration;
}
startInput.value = newStart;
endInput.value = newEnd;
updateTimeRange(slider);
});
document.addEventListener('mouseup', () => {
isDragging = false;
});
});
2025-12-23 09:32:49 +01:00
// ==========================================
// TOGGLE SLIDERS (Ja/Nej)
// ==========================================
document.querySelectorAll('swp-toggle-slider').forEach(slider => {
const options = slider.querySelectorAll('swp-toggle-option');
options.forEach((option, index) => {
option.addEventListener('click', () => {
const newValue = index === 0 ? 'yes' : 'no';
slider.dataset.value = newValue;
// Handle availability row toggle
const availabilityRow = slider.closest('swp-availability-row');
if (availabilityRow) {
const isEnabled = newValue === 'yes';
availabilityRow.dataset.enabled = isEnabled;
2025-12-23 09:53:31 +01:00
const rangeInputs = availabilityRow.querySelectorAll('input[type="range"]');
rangeInputs.forEach(input => {
input.disabled = !isEnabled;
});
const fill = availabilityRow.querySelector('swp-time-range-fill');
if (fill) {
fill.classList.toggle('disabled', !isEnabled);
2025-12-23 09:32:49 +01:00
}
}
});
});
});
// ==========================================
// ADDON ITEMS
// ==========================================
document.querySelectorAll('swp-addon-item').forEach(item => {
item.addEventListener('click', () => {
item.classList.toggle('selected');
});
});
// ==========================================
// COLOR DROPDOWN
// ==========================================
const colorPopover = document.getElementById('colorPopover');
const colorTrigger = document.getElementById('colorTrigger');
if (colorPopover) {
colorPopover.querySelectorAll('swp-color-option').forEach(option => {
option.addEventListener('click', () => {
const value = option.dataset.value;
const label = option.dataset.label;
// Update selected state
colorPopover.querySelectorAll('swp-color-option').forEach(o => o.classList.remove('selected'));
option.classList.add('selected');
// Update trigger button
const triggerDot = colorTrigger.querySelector('swp-color-dot');
const triggerName = colorTrigger.querySelector('.color-name');
triggerDot.className = `is-${value}`;
triggerName.textContent = label;
// Close popover
colorPopover.hidePopover();
});
});
}
// ==========================================
// CATEGORY DROPDOWN
// ==========================================
const categoryPopover = document.getElementById('categoryPopover');
const categoryTrigger = document.getElementById('categoryTrigger');
if (categoryPopover) {
categoryPopover.querySelectorAll('swp-dropdown-option').forEach(option => {
option.addEventListener('click', () => {
const label = option.textContent;
// Update selected state
categoryPopover.querySelectorAll('swp-dropdown-option').forEach(o => o.classList.remove('selected'));
option.classList.add('selected');
// Update trigger button
categoryTrigger.querySelector('.dropdown-value').textContent = label;
// Close popover
categoryPopover.hidePopover();
});
});
}
// ==========================================
// PRICE MODE TOGGLE
// ==========================================
document.querySelectorAll('swp-price-mode-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('swp-price-mode-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
const mode = btn.dataset.mode;
const simpleView = document.querySelector('swp-price-simple');
const matrixView = document.querySelector('swp-price-matrix');
if (mode === 'simple') {
simpleView.style.display = 'block';
matrixView.style.display = 'none';
} else {
simpleView.style.display = 'none';
matrixView.style.display = 'block';
}
});
});
// ==========================================
// DURATION DELETE
// ==========================================
document.querySelectorAll('swp-duration-delete').forEach(btn => {
btn.addEventListener('click', () => {
const item = btn.closest('swp-duration-item');
if (item) {
item.style.opacity = '0';
item.style.transform = 'translateX(20px)';
setTimeout(() => item.remove(), 200);
}
});
});
// ==========================================
// TAG REMOVE
// ==========================================
document.querySelectorAll('swp-tag .remove').forEach(btn => {
btn.addEventListener('click', (e) => {
e.stopPropagation();
const tag = btn.closest('swp-tag');
if (tag) tag.remove();
});
});
// ==========================================
// SERVICE STATUS TOGGLE
// ==========================================
const serviceStatus = document.getElementById('serviceStatus');
if (serviceStatus) {
serviceStatus.addEventListener('click', () => {
const isActive = serviceStatus.dataset.active === 'true';
serviceStatus.dataset.active = isActive ? 'false' : 'true';
serviceStatus.querySelector('.icon').textContent = isActive ? '○' : '●';
serviceStatus.querySelector('.text').textContent = isActive ? 'Inaktiv' : 'Aktiv';
});
}
< / script >
< / body >
< / html >