diff --git a/wwwroot/data/kk-services.json b/wwwroot/data/kk-services.json new file mode 100644 index 0000000..5c84a0a --- /dev/null +++ b/wwwroot/data/kk-services.json @@ -0,0 +1,125 @@ +{ + "Klip dame, herre og børn": [ + { "name": "Dameklip", "duration": 60, "price": 725 }, + { "name": "Dameklip uden snak", "duration": 60, "price": 725 }, + { "name": "Dameklip spidser mellemlangt og langt hår", "duration": 40, "price": 575 }, + { "name": "Dameklip Luksus ekstra glans og pleje", "duration": 75, "price": 925 }, + { "name": "Herreklip", "duration": 60, "price": 645 }, + { "name": "Herreklip uden snak", "duration": 60, "price": 645 }, + { "name": "Skin fade", "duration": 60, "price": 645 }, + { "name": "Klip med maskine (herre klip)", "duration": 30, "price": 475 }, + { "name": "Børneklip 0-4 år", "duration": 45, "price": 475 }, + { "name": "Børneklip 4-8 år", "duration": 45, "price": 525 }, + { "name": "Touch up Dame", "duration": 10, "price": 0 }, + { "name": "Touch up Herre", "duration": 10, "price": 0 }, + { "name": "Pandehår helt nyt", "duration": 20, "price": 325 }, + { "name": "Konsultation uden behandling", "duration": 10, "price": 0 }, + { "name": "Herreklip", "duration": 60, "price": 550 }, + { "name": "Klip med maskine (herre klip)", "duration": 45, "price": 525 } + ], + + "Farvebehandlinger": [ + { "name": "Bundfarve almindelig udgroning maks 3 cm", "duration": 90, "price": 785 }, + { "name": "Helfarve kort hår", "duration": 105, "price": 950 }, + { "name": "Helfarve mellemlangt hår", "duration": 120, "price": 1450 }, + { "name": "Helfarve langt hår", "duration": 120, "price": 1550 }, + { "name": "Bundfarve/ Lysning", "duration": 105, "price": 975 }, + { "name": "Afblegning kort hår + gloss", "duration": 150, "price": 1895 } + ], + + "Striber/ Refleksbehandling": [ + { "name": "Striber kort hår", "duration": 120, "price": 1465 }, + { "name": "Striber mellemlangt hår", "duration": 150, "price": 1665 }, + { "name": "Striber langt hår", "duration": 180, "price": 1865 }, + { "name": "Striber på toppen/ overhår", "duration": 90, "price": 1065 }, + { "name": "Striber babylights tæt lysning mellemlangt hår", "duration": 180, "price": 2650 }, + { "name": "Striber babylights tæt lysning langt hår", "duration": 180, "price": 2850 }, + { "name": "Striber babylights tæt lysning på toppen", "duration": 120, "price": 1650 }, + { "name": "AirTouch skulderlangt hår", "duration": 210, "price": 3250 }, + { "name": "AirTouch langt hår", "duration": 240, "price": 3850 } + ], + + "Hårvask med styling eller uden styling": [ + { "name": "Hårvask uden styling", "duration": 30, "price": 265 }, + { "name": "Hårvask med styling (kun føn)", "duration": 40, "price": 450 }, + { "name": "Vask + Styling med varme glatning/krøller (mellemlangt/langt)", "duration": 60, "price": 650 } + ], + + "Henna naturlig hårfarver": [ + { "name": "Henna kort hår", "duration": 90, "price": 965 }, + { "name": "Henna mellemlangt/langt hår", "duration": 90, "price": 1265 }, + { "name": "Henna bundfarve", "duration": 90, "price": 750 } + ], + + "Kurbehandling": [ + { "name": "Olaplex Stand alone", "duration": 60, "price": 550 }, + { "name": "Kurbehandling fugt/protein", "duration": 40, "price": 365 } + ], + + "Bryn og vipper": [ + { "name": "Farvning vipper & bryn", "duration": 30, "price": 345 }, + { "name": "Farvning vipper", "duration": 20, "price": 185 }, + { "name": "Farvning og retning af bryn", "duration": 20, "price": 185 }, + { "name": "Retning af bryn", "duration": 10, "price": 100 } + ], + + "Balayage": [ + { "name": "Balayage maks til skulderen", "duration": 150, "price": 1850 }, + { "name": "Balayage maks skulder + gloss/toning", "duration": 180, "price": 2250 }, + { "name": "Balayage langt hår", "duration": 150, "price": 2150 }, + { "name": "Balayage langt hår + gloss/toning", "duration": 180, "price": 2550 } + ], + + "Skæg": [ + { "name": "Skægtrim", "duration": 20, "price": 300 } + ], + + "Gloss": [ + { "name": "Gloss ekstra langt/tykt hår", "duration": 75, "price": 900 }, + { "name": "Glossing kort hår", "duration": 60, "price": 685 }, + { "name": "Glossing mellemlangt/ langt hår", "duration": 60, "price": 745 }, + { "name": "Glossing mænd", "duration": 40, "price": 350 }, + { "name": "Gloss ifb. anden farvebehandling", "duration": 20, "price": 450 }, + { "name": "Gloss ifb. anden farvebehandling", "duration": 30, "price": 450 } + ], + + "Håropsætning": [ + { "name": "Håropsætning kort hår", "duration": 60, "price": 850 }, + { "name": "Håropsætning langt hår", "duration": 60, "price": 1450 }, + { "name": "Håropsætning Brud/brudepiger/Galla/Oscar", "duration": 90, "price": 1599 }, + { "name": "Make-up Special Brud/Galla mm", "duration": 90, "price": 3000 } + ], + + "Modeller": [ + { "name": "Dameklip Model", "duration": 60, "price": 0 }, + { "name": "Herreklip Model", "duration": 60, "price": 0 }, + { "name": "Balayage Model", "duration": 240, "price": 0 }, + { "name": "Striber Model", "duration": 180, "price": 0 }, + { "name": "Bryn & Vippe Model", "duration": 40, "price": 0 }, + { "name": "Bundfarve Model", "duration": 120, "price": 0 }, + { "name": "Gloss", "duration": 30, "price": 0 } + ], + + "Tristan farve modeller": [ + { "name": "Bundfarve med HP/HPF", "duration": 90, "price": 325 }, + { "name": "Striber Model", "duration": 240, "price": 400 } + ], + + "Uden kategori": [ + { "name": "P-afgift", "duration": 0, "price": -25 }, + { "name": "Børneklip 9-12 år", "duration": 60, "price": 450 } + ], + + "Tilvalg services": [ + { "name": "Touch up kur", "duration": 15, "price": 175 }, + { "name": "Root shading", "duration": 30, "price": 425 }, + { "name": "Styling med varme (efter behandling)", "duration": 60, "price": 475 }, + { "name": "Styling kort hår (efter farve)", "duration": 20, "price": 175 }, + { "name": "Olaplex efter afblegning", "duration": 10, "price": 325 }, + { "name": "Let afrensning af gloss/klor/kemi", "duration": 20, "price": 220 }, + { "name": "Forpigmentering", "duration": 20, "price": 300 }, + { "name": "Knække bund ifb. farvebehandling", "duration": 20, "price": 400 }, + { "name": "Olaplex i farve", "duration": 10, "price": 230 }, + { "name": "Metal DX intens kur redken gloss", "duration": 20, "price": 225 } + ] +} diff --git a/wwwroot/icons/drag.svg b/wwwroot/icons/drag.svg new file mode 100644 index 0000000..0ecb252 --- /dev/null +++ b/wwwroot/icons/drag.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/wwwroot/poc-employee.html b/wwwroot/poc-employee.html index 0e079c5..52454d3 100644 --- a/wwwroot/poc-employee.html +++ b/wwwroot/poc-employee.html @@ -611,6 +611,356 @@ display: block; } + swp-tab-info { + display: flex; + align-items: flex-start; + gap: 10px; + padding: 12px 16px; + background: color-mix(in srgb, var(--color-teal) 8%, white); + border: 1px solid color-mix(in srgb, var(--color-teal) 25%, white); + border-radius: 8px; + margin-bottom: 20px; + font-size: 13px; + color: var(--color-text-secondary); + line-height: 1.4; + } + + swp-tab-info svg { + flex-shrink: 0; + color: var(--color-teal); + margin-top: 1px; + } + + swp-tab-info strong { + color: var(--color-teal); + font-weight: 600; + } + + /* ========================================== + SERVICES DRAG-DROP + ========================================== */ + .services-grid { + align-items: start; + } + + /* Services layout with collapsible panel */ + .services-layout { + display: flex; + gap: 0; + align-items: stretch; + min-height: 500px; + } + + swp-services-panel { + display: flex; + transition: width 300ms ease; + overflow: hidden; + } + + swp-services-panel.collapsed { + width: 40px; + } + + swp-services-panel.expanded { + width: 420px; + } + + swp-panel-toggle { + display: flex; + align-items: center; + justify-content: center; + width: 40px; + min-width: 40px; + background: linear-gradient(135deg, var(--color-teal) 0%, color-mix(in srgb, var(--color-teal) 80%, #000) 100%); + color: white; + cursor: pointer; + border-radius: 8px 0 0 8px; + transition: all 200ms ease; + flex-shrink: 0; + } + + swp-panel-toggle:hover { + background: linear-gradient(135deg, color-mix(in srgb, var(--color-teal) 90%, #fff) 0%, var(--color-teal) 100%); + } + + swp-panel-toggle svg { + transition: transform 200ms ease; + } + + swp-services-panel.expanded swp-panel-toggle svg { + transform: rotate(180deg); + } + + swp-panel-content { + display: none; + flex: 1; + min-width: 0; + } + + swp-services-panel.expanded swp-panel-content { + display: block; + } + + swp-services-panel swp-card { + border-radius: 0 8px 8px 0; + border-left: none; + height: 100%; + } + + .selected-services-card { + flex: 1; + } + + /* Edit button in section label */ + .selected-services-card swp-section-label { + display: flex; + align-items: center; + justify-content: space-between; + } + + .edit-services-btn { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 6px 12px; + background: var(--color-teal); + color: white; + border: none; + border-radius: 4px; + font-size: 13px; + font-weight: 500; + cursor: pointer; + transition: all 150ms ease; + } + + .edit-services-btn:hover { + background: color-mix(in srgb, var(--color-teal) 85%, #000); + } + + .edit-services-btn.active { + background: var(--color-text-secondary); + } + + .services-card { + display: flex; + flex-direction: column; + } + + .services-card swp-search-field { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 12px; + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: 6px; + margin-bottom: 12px; + } + + .services-card swp-search-field img { + opacity: 0.5; + flex-shrink: 0; + } + + .services-card swp-search-field input { + flex: 1; + border: none; + background: none; + outline: none; + font-size: 14px; + color: var(--color-text); + } + + .services-card swp-search-field input::placeholder { + color: var(--color-text-muted); + } + + swp-services-selected, + swp-services-available { + display: flex; + flex-direction: column; + gap: 8px; + min-height: 300px; + max-height: 600px; + overflow-y: auto; + padding: 4px; + border-radius: 8px; + transition: all 150ms ease; + } + + swp-services-selected.drag-over, + swp-services-available.drag-over { + background: color-mix(in srgb, var(--color-teal) 8%, white); + outline: 2px dashed var(--color-teal); + outline-offset: -2px; + } + + swp-services-empty { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 8px; + padding: 40px 20px; + color: var(--color-text-muted); + border: 2px dashed var(--color-border); + border-radius: 8px; + text-align: center; + font-size: 14px; + } + + swp-services-empty svg { + opacity: 0.4; + } + + /* Service category in columns */ + swp-service-category-group { + display: flex; + flex-direction: column; + gap: 4px; + } + + swp-service-category-header { + font-size: 11px; + font-weight: 600; + color: var(--color-text-muted); + text-transform: uppercase; + letter-spacing: 0.5px; + padding: 8px 0 4px 0; + border-bottom: 1px solid var(--color-border); + margin-bottom: 4px; + } + + /* Service row - draggable */ + swp-service-row { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 12px; + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: 6px; + cursor: url('icons/drag.svg') 12 12, grab; + transition: all 150ms ease; + user-select: none; + } + + swp-service-row:hover { + border-color: var(--color-teal); + box-shadow: 0 2px 4px rgba(0,0,0,0.05); + } + + swp-service-row:active { + cursor: url('icons/drag.svg') 12 12, grabbing; + } + + swp-service-row.dragging { + opacity: 0.5; + transform: scale(0.98); + } + + swp-service-row.multi-selected { + background: color-mix(in srgb, var(--color-teal) 12%, white); + border-color: var(--color-teal); + box-shadow: 0 0 0 1px var(--color-teal); + } + + swp-drag-handle { + color: var(--color-text-muted); + font-size: 14px; + cursor: url('icons/drag.svg') 12 12, grab; + padding: 0 2px; + } + + swp-service-row:hover swp-drag-handle { + color: var(--color-text-secondary); + } + + + swp-service-color { + width: 4px; + height: 28px; + border-radius: 2px; + flex-shrink: 0; + } + + swp-service-info { + flex: 1; + min-width: 0; + } + + swp-service-name { + font-size: 12px; + font-weight: 500; + color: var(--color-text); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + swp-service-meta { + font-size: 12px; + color: var(--color-text-secondary); + margin-top: 2px; + } + + /* Price and duration columns */ + swp-service-price-col { + width: 75px; + text-align: right; + font-size: 13px; + font-family: var(--font-mono); + color: var(--color-text-secondary); + flex-shrink: 0; + } + + swp-service-duration-col { + width: 50px; + text-align: right; + font-size: 13px; + font-family: var(--font-mono); + color: var(--color-text-secondary); + flex-shrink: 0; + } + + /* Editable inputs in selected column */ + swp-services-selected swp-service-price-col, + swp-services-selected swp-service-duration-col { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 4px; + } + + swp-services-selected swp-service-price-col input, + swp-services-selected swp-service-duration-col input { + width: 55px; + padding: 4px 6px; + border: 1px solid var(--color-border); + border-radius: 4px; + font-size: 12px; + font-family: var(--font-mono); + text-align: right; + background: var(--color-surface); + } + + swp-services-selected swp-service-price-col input:focus, + swp-services-selected swp-service-duration-col input:focus { + border-color: var(--color-teal); + outline: none; + } + + swp-services-selected swp-service-price-col input::-webkit-inner-spin-button, + swp-services-selected swp-service-price-col input::-webkit-outer-spin-button { + opacity: 1; + } + + /* Override indicator */ + swp-service-row.has-override swp-service-price-col, + swp-service-row.has-override swp-service-duration-col { + color: var(--color-teal); + } + /* ========================================== LAYOUT GRID ========================================== */ @@ -1085,51 +1435,6 @@ font-weight: 500; } - /* ========================================== - SPECIALTY TAGS - ========================================== */ - swp-specialty-tags { - display: flex; - flex-wrap: wrap; - gap: 8px; - } - - swp-specialty-tag { - display: inline-flex; - align-items: center; - gap: 6px; - padding: 8px 14px; - font-size: 13px; - border-radius: 20px; - border: 1px solid var(--color-border); - cursor: pointer; - transition: all 150ms ease; - } - - swp-specialty-tag:hover { - background: var(--color-background-hover); - } - - swp-specialty-tag.selected { - background: color-mix(in srgb, var(--color-teal) 12%, white); - border-color: var(--color-teal); - color: var(--color-teal); - } - - swp-specialty-tag::before { - content: ''; - width: 8px; - height: 8px; - border-radius: 50%; - border: 1px solid var(--color-border); - transition: all 150ms ease; - } - - swp-specialty-tag.selected::before { - background: var(--color-teal); - border-color: var(--color-teal); - } - /* ========================================== CERTIFICATION LIST ========================================== */ @@ -1364,6 +1669,168 @@ color: var(--color-teal); background: color-mix(in srgb, var(--color-teal) 5%, white); } + + /* Duration slider (same style as time-range-slider) */ + swp-duration-slider { + position: relative; + width: 80px; + height: 20px; + display: flex; + align-items: center; + } + + swp-duration-slider swp-slider-track { + position: absolute; + width: 100%; + height: 4px; + background: var(--color-border); + border-radius: 2px; + } + + swp-duration-slider input[type="range"] { + position: absolute; + width: 100%; + height: 4px; + -webkit-appearance: none; + appearance: none; + background: transparent; + margin: 0; + } + + swp-duration-slider input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 14px; + height: 14px; + background: var(--color-teal); + border: 2px solid white; + border-radius: 50%; + cursor: pointer; + box-shadow: 0 1px 3px rgba(0,0,0,0.2); + } + + swp-duration-slider input[type="range"]::-moz-range-thumb { + width: 14px; + height: 14px; + background: var(--color-teal); + border: 2px solid white; + border-radius: 50%; + cursor: pointer; + box-shadow: 0 1px 3px rgba(0,0,0,0.2); + } + + /* Compact service list (main view) */ + swp-service-compact-list { + display: flex; + flex-direction: column; + gap: 6px; + } + + swp-service-compact-category { + font-size: 11px; + font-weight: 600; + color: var(--color-text-secondary); + text-transform: uppercase; + letter-spacing: 0.5px; + margin-top: 12px; + padding-bottom: 4px; + } + + swp-service-compact-category:first-child { + margin-top: 0; + } + + swp-service-compact-item { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 12px; + background: var(--color-background-alt); + border-radius: 6px; + } + + swp-service-compact-color { + width: 4px; + height: 24px; + border-radius: 2px; + flex-shrink: 0; + } + + swp-service-compact-name { + flex: 1; + font-size: 14px; + color: var(--color-text); + } + + swp-service-compact-override { + display: flex; + gap: 8px; + font-size: 12px; + font-family: var(--font-mono); + } + + swp-service-compact-override .duration-override { + color: var(--color-teal); + padding: 2px 8px; + background: color-mix(in srgb, var(--color-teal) 10%, white); + border-radius: 4px; + } + + swp-service-compact-override .price-override { + color: var(--color-teal); + padding: 2px 8px; + background: color-mix(in srgb, var(--color-teal) 10%, white); + border-radius: 4px; + } + + swp-service-compact-override .price-override s { + color: var(--color-text-muted); + margin-right: 4px; + } + + swp-service-compact-override.standard { + display: none; + } + + swp-service-compact-empty { + display: block; + padding: 24px 16px; + text-align: center; + color: var(--color-text-muted); + font-size: 14px; + } + + /* Edit link for services card */ + swp-card-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 16px; + } + + swp-card-header swp-section-label { + margin-bottom: 0; + } + + swp-edit-link { + font-size: 13px; + color: var(--color-teal); + cursor: pointer; + display: flex; + align-items: center; + gap: 4px; + transition: color 150ms ease; + } + + swp-edit-link:hover { + color: #00695c; + } + + swp-edit-link svg { + width: 14px; + height: 14px; + fill: currentColor; + }
@@ -1735,96 +2202,45 @@ SERVICES TAB ========================================== -->