Calendar/wwwroot/poc-arbejdstidsplan.html
Janus C. H. Knudsen 83723c170f Enhances service detail and employee selection UI
Improves employee selection with checkbox interaction
Adds visual refinements to employee and availability sections
Updates styling for employee levels and selection states
Removes unnecessary consent form toggle
2025-12-25 15:58:42 +01:00

1684 lines
56 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

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

<!DOCTYPE html>
<html lang="da">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Arbejdstidsplan</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&display=swap');
:root {
--color-background: #ffffff;
--color-background-alt: #f8f9fa;
--color-border: #e5e7eb;
--color-text: #1f2937;
--color-text-secondary: #6b7280;
--color-text-muted: #9ca3af;
--color-teal: #00897b;
--color-teal-light: #ccfbf1;
--font-mono: 'JetBrains Mono', monospace;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: var(--color-background-alt);
color: var(--color-text);
line-height: 1.5;
}
/* ==========================================
PAGE LAYOUT
========================================== */
swp-page {
display: block;
max-width: 1200px;
margin: 0 auto;
padding: 24px;
}
swp-page-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 24px;
}
swp-page-title {
font-size: 24px;
font-weight: 600;
color: var(--color-text);
}
swp-page-actions {
display: flex;
gap: 12px;
}
/* ==========================================
WEEK NAVIGATION
========================================== */
swp-week-nav {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 24px;
}
swp-week-date-nav {
display: flex;
align-items: center;
gap: 12px;
}
swp-week-nav button {
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border: 1px solid var(--color-border);
border-radius: 6px;
background: var(--color-background);
cursor: pointer;
color: var(--color-text);
font-size: 16px;
}
swp-week-nav button:hover {
background: var(--color-background-alt);
}
swp-week-label {
font-size: 15px;
font-weight: 500;
color: var(--color-text-secondary);
min-width: 200px;
text-align: center;
}
/* ==========================================
BUTTONS
========================================== */
swp-button {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 16px;
border-radius: 6px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
border: none;
transition: all 0.15s ease;
}
swp-button.primary {
background: var(--color-teal);
color: white;
}
swp-button.primary:hover {
background: #0f766e;
}
swp-button.secondary {
background: var(--color-background);
color: var(--color-text);
border: 1px solid var(--color-border);
}
swp-button.secondary:hover {
background: var(--color-background-alt);
}
/* ==========================================
SCHEDULE TABLE (flat grid with cell borders)
========================================== */
swp-schedule-table {
display: grid;
grid-template-columns: 180px repeat(7, minmax(100px, 1fr));
border-radius: 8px;
overflow: hidden;
border: 1px solid var(--color-border);
}
swp-schedule-cell {
display: flex;
flex-direction: column;
justify-content: center;
padding: 12px 16px;
min-height: 60px;
background: var(--color-background);
border-right: 1px solid var(--color-border);
border-bottom: 1px solid var(--color-border);
user-select: none;
}
/* Sidste kolonne: ingen højre border */
swp-schedule-cell:nth-child(8n) {
border-right: none;
}
/* Sidste række: ingen bund border */
swp-schedule-cell:nth-last-child(-n+8) {
border-bottom: none;
}
swp-schedule-cell.header {
background: var(--color-background-alt);
font-weight: 500;
font-size: 13px;
color: var(--color-text-secondary);
min-height: 48px;
text-align: center;
align-items: center;
}
swp-schedule-cell.header.week-number {
font-size: 15px;
font-weight: 600;
color: var(--color-text);
}
swp-schedule-cell.employee {
align-items: flex-start;
gap: 2px;
}
swp-schedule-cell.day {
align-items: center;
text-align: center;
position: relative;
}
/* ==========================================
EMPLOYEE INFO
========================================== */
swp-employee-name {
font-size: 14px;
font-weight: 500;
color: var(--color-text);
}
swp-employee-hours {
font-family: var(--font-mono);
font-size: 12px;
color: var(--color-text-muted);
}
/* ==========================================
TIME DISPLAY
========================================== */
swp-time-display {
font-family: var(--font-mono);
font-size: 12px;
font-weight: 500;
padding: 4px 8px;
border-radius: 4px;
background: color-mix(in srgb, var(--color-teal) 10%, white);
color: var(--color-text);
white-space: nowrap;
min-width: 90px;
text-align: center;
display: inline-block;
}
swp-time-display.off {
background: transparent;
color: var(--color-text-muted);
}
swp-time-display.off.off-override {
background: color-mix(in srgb, #7c3aed 12%, white);
color: #6d28d9;
}
swp-time-display.vacation {
background: color-mix(in srgb, #f59e0b 15%, white);
color: #b45309;
}
swp-time-display.sick {
background: color-mix(in srgb, #ef4444 15%, white);
color: #dc2626;
}
/* ==========================================
DAY HEADER
========================================== */
swp-day-name {
font-weight: 500;
color: var(--color-text);
}
swp-day-date {
font-size: 12px;
color: var(--color-text-muted);
font-weight: 400;
}
/* ==========================================
EDIT MODE
========================================== */
body.edit-mode swp-schedule-cell.day {
cursor: pointer;
position: relative;
}
body.edit-mode swp-schedule-cell.day:hover {
background: var(--color-background-alt);
}
body.edit-mode swp-schedule-cell.day.selected {
background: color-mix(in srgb, var(--color-teal) 12%, white);
border-color: var(--color-teal);
border-width: 2px;
border-left: 2px solid var(--color-teal);
border-top: 2px solid var(--color-teal);
/* Kompenser for ekstra border-bredde */
margin-left: -1px;
margin-top: -1px;
padding: 11px 15px;
}
/* Én border mellem tilstødende valgte celler */
/* Venstre celle beholder sin højre border, højre celle fjerner sin venstre */
body.edit-mode swp-schedule-cell.day.selected.adj-left {
border-left: none;
margin-left: 0;
padding-left: 12px;
}
/* Øverste celle beholder sin bund border, nederste celle fjerner sin top */
body.edit-mode swp-schedule-cell.day.selected.adj-top {
border-top: none;
margin-top: 0;
padding-top: 12px;
}
/* ==========================================
DRAWER
========================================== */
swp-drawer {
display: block;
position: fixed;
top: 0;
right: -400px;
width: 400px;
height: 100vh;
background: var(--color-background);
box-shadow: -4px 0 20px rgba(0, 0, 0, 0.1);
z-index: 101;
transition: right 0.3s ease;
overflow-y: auto;
}
swp-drawer.open {
right: 0;
}
swp-drawer-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-drawer-title {
font-size: 18px;
font-weight: 600;
color: var(--color-text);
}
swp-drawer-subtitle {
font-size: 13px;
color: var(--color-text-secondary);
margin-top: 2px;
}
swp-drawer-close {
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border: none;
background: transparent;
cursor: pointer;
border-radius: 6px;
color: var(--color-text-secondary);
font-size: 20px;
}
swp-drawer-close:hover {
background: var(--color-border);
}
swp-drawer-content {
display: block;
padding: 24px;
}
swp-drawer-section {
display: block;
margin-bottom: 24px;
}
swp-drawer-section-title {
display: block;
font-size: 12px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--color-text-secondary);
margin-bottom: 12px;
}
/* ==========================================
DRAWER FORM ELEMENTS
========================================== */
swp-form-row {
display: flex;
flex-direction: column;
gap: 6px;
margin-bottom: 16px;
}
swp-form-label {
font-size: 11px;
font-weight: 400;
color: var(--color-text-secondary);
text-transform: uppercase;
letter-spacing: 0.5px;
}
swp-form-label .optional,
swp-form-label .auto {
font-weight: 400;
text-transform: none;
color: var(--color-text-muted);
}
swp-form-value {
font-size: 15px;
font-weight: 500;
color: var(--color-text);
}
swp-form-divider {
display: block;
height: 1px;
background: var(--color-border);
margin: 20px 0;
}
swp-form-group {
display: block;
padding: 16px;
background: var(--color-background-alt);
border-radius: 8px;
margin-top: 16px;
}
swp-form-group swp-form-row:last-child {
margin-bottom: 0;
}
swp-form-hint {
display: block;
font-size: 12px;
color: var(--color-text-muted);
margin: -8px 0 16px 0;
line-height: 1.4;
}
swp-form-select {
display: block;
}
swp-form-select select {
width: 100%;
padding: 10px 12px;
border: 1px solid var(--color-border);
border-radius: 6px;
font-size: 14px;
color: var(--color-text);
background: var(--color-background);
cursor: pointer;
}
swp-form-select select:focus {
outline: none;
border-color: var(--color-teal);
}
swp-drawer-content input[type="time"],
swp-drawer-content input[type="text"],
swp-drawer-content input[type="date"] {
width: 100%;
padding: 10px 12px;
border: 1px solid var(--color-border);
border-radius: 6px;
font-size: 14px;
color: var(--color-text);
background: var(--color-background);
}
swp-drawer-content input[type="time"] {
font-family: var(--font-mono);
}
swp-drawer-content input:focus {
outline: none;
border-color: var(--color-teal);
}
swp-drawer-content input::placeholder {
color: var(--color-text-muted);
}
/* ==========================================
TOGGLE OPTIONS (Enkelt/Gentagelse)
========================================== */
swp-toggle-options {
display: flex;
gap: 0;
border: 1px solid var(--color-border);
border-radius: 6px;
overflow: hidden;
}
swp-toggle-option {
flex: 1;
padding: 10px 16px;
text-align: center;
font-size: 14px;
cursor: pointer;
background: var(--color-background);
border-right: 1px solid var(--color-border);
transition: all 0.15s ease;
}
swp-toggle-option:last-child {
border-right: none;
}
swp-toggle-option:hover {
background: var(--color-background-alt);
}
swp-toggle-option.selected {
background: var(--color-teal);
color: white;
}
/* ==========================================
STATUS OPTIONS (badge style like poc-detail-drawer)
========================================== */
swp-status-options {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
swp-status-option {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 10px;
border: none;
border-radius: 4px;
cursor: pointer;
transition: all 0.15s ease;
font-size: 13px;
font-weight: 500;
background: var(--color-background-alt);
color: var(--color-text-secondary);
}
swp-status-option::before {
content: '';
width: 6px;
height: 6px;
border-radius: 50%;
flex-shrink: 0;
}
swp-status-option[data-status="work"] {
--status-color: var(--color-teal);
}
swp-status-option[data-status="off"] {
--status-color: #7c3aed;
}
swp-status-option[data-status="vacation"] {
--status-color: #f59e0b;
}
swp-status-option[data-status="sick"] {
--status-color: #e53935;
}
swp-status-option::before {
background: var(--status-color);
}
swp-status-option:hover {
background: var(--color-border);
}
swp-status-option.selected {
background: color-mix(in srgb, var(--status-color) 15%, white);
color: var(--status-color);
}
/* ==========================================
DRAWER FOOTER
========================================== */
swp-drawer-footer {
display: flex;
gap: 12px;
padding: 20px 24px;
border-top: 1px solid var(--color-border);
background: var(--color-background-alt);
}
swp-drawer-footer swp-button {
flex: 1;
}
/* ==========================================
OVERRIDE DISPLAY
========================================== */
swp-time-override {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
}
swp-time-original {
font-family: var(--font-mono);
font-size: 10px;
color: var(--color-text-muted);
text-decoration: line-through;
}
swp-override-badge {
position: absolute;
top: 4px;
right: 4px;
width: 8px;
height: 8px;
border-radius: 50%;
background: #f59e0b;
}
/* ==========================================
TIME RANGE SLIDER
========================================== */
swp-time-range {
display: flex;
align-items: center;
gap: 12px;
}
swp-time-range-slider {
position: relative;
flex: 1;
height: 20px;
display: flex;
align-items: center;
}
swp-time-range-track {
position: absolute;
width: 100%;
height: 4px;
background: var(--color-border);
border-radius: 2px;
}
swp-time-range-fill {
position: absolute;
height: 4px;
background: var(--color-teal);
border-radius: 2px;
cursor: grab;
}
swp-time-range-fill:active {
cursor: grabbing;
}
swp-time-range-slider input[type="range"] {
position: absolute;
width: 100%;
height: 4px;
-webkit-appearance: none;
appearance: none;
background: transparent;
pointer-events: none;
margin: 0;
}
swp-time-range-slider input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 14px;
height: 14px;
background: var(--color-teal);
border: 2px solid white;
border-radius: 50%;
cursor: pointer;
pointer-events: auto;
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}
swp-time-range-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);
}
swp-time-range-label {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
min-width: 100px;
text-align: center;
background: var(--color-background-alt);
padding: 6px 12px;
border-radius: 4px;
}
swp-time-range-times {
font-size: 13px;
font-family: var(--font-mono);
font-weight: 500;
color: var(--color-text);
white-space: nowrap;
}
swp-time-range-duration {
font-size: 11px;
font-family: var(--font-mono);
color: var(--color-text-secondary);
white-space: nowrap;
}
/* ==========================================
DRAWER EMPLOYEE DISPLAY
========================================== */
swp-employee-display {
display: flex;
align-items: center;
gap: 10px;
}
swp-employee-display swp-employee-avatar {
width: 32px;
height: 32px;
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: 12px;
flex-shrink: 0;
}
swp-employee-display.empty swp-employee-avatar {
background: var(--color-border);
color: var(--color-text-muted);
}
swp-employee-display.multi swp-employee-avatar {
background: var(--color-text-muted);
}
/* Note icon i celle */
swp-note-icon {
position: absolute;
bottom: 7px;
right: 4px;
width: 14px;
height: 14px;
opacity: 0.5;
}
swp-note-icon img {
width: 100%;
height: 100%;
filter: brightness(0) saturate(100%) invert(20%) sepia(30%) saturate(700%) hue-rotate(190deg) brightness(90%) contrast(95%);
}
/* Override indikator - viser original tid overstreget */
swp-override-original {
position: absolute;
bottom: 1px;
left: 8px;
font-family: var(--font-mono);
font-size: 10px;
color: var(--color-text-muted);
text-decoration: line-through;
opacity: 0.7;
}
</style>
</head>
<body>
<swp-page>
<swp-page-header>
<swp-page-title>Arbejdstidsplan</swp-page-title>
<swp-page-actions>
<swp-button class="primary" id="editModeBtn">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
</svg>
Rediger
</swp-button>
</swp-page-actions>
</swp-page-header>
<swp-week-nav>
<swp-week-date-nav>
<button id="prevWeek">&#8249;</button>
<swp-week-label>23. - 29. december 2025</swp-week-label>
<button id="nextWeek">&#8250;</button>
</swp-week-date-nav>
</swp-week-nav>
<swp-schedule-table>
<!-- Header row -->
<swp-schedule-cell class="header week-number">Uge 52</swp-schedule-cell>
<swp-schedule-cell class="header">
<swp-day-name>Man</swp-day-name>
<swp-day-date>23/12</swp-day-date>
</swp-schedule-cell>
<swp-schedule-cell class="header">
<swp-day-name>Tir</swp-day-name>
<swp-day-date>24/12</swp-day-date>
</swp-schedule-cell>
<swp-schedule-cell class="header">
<swp-day-name>Ons</swp-day-name>
<swp-day-date>25/12</swp-day-date>
</swp-schedule-cell>
<swp-schedule-cell class="header">
<swp-day-name>Tor</swp-day-name>
<swp-day-date>26/12</swp-day-date>
</swp-schedule-cell>
<swp-schedule-cell class="header">
<swp-day-name>Fre</swp-day-name>
<swp-day-date>27/12</swp-day-date>
</swp-schedule-cell>
<swp-schedule-cell class="header">
<swp-day-name>Lør</swp-day-name>
<swp-day-date>28/12</swp-day-date>
</swp-schedule-cell>
<swp-schedule-cell class="header">
<swp-day-name>Søn</swp-day-name>
<swp-day-date>29/12</swp-day-date>
</swp-schedule-cell>
<!-- Anna Sørensen -->
<swp-schedule-cell class="employee">
<swp-employee-name>Anna Sørensen</swp-employee-name>
<swp-employee-hours>32 timer</swp-employee-hours>
</swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Anna Sørensen" data-day="Man" data-date="23/12"><swp-time-display>09:00 - 17:00</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Anna Sørensen" data-day="Tir" data-date="24/12"><swp-time-display>09:00 - 13:00</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Anna Sørensen" data-day="Ons" data-date="25/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Anna Sørensen" data-day="Tor" data-date="26/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Anna Sørensen" data-day="Fre" data-date="27/12"><swp-time-display>09:00 - 17:00</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Anna Sørensen" data-day="Lør" data-date="28/12"><swp-time-display>10:00 - 14:00</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Anna Sørensen" data-day="Søn" data-date="29/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
<!-- Mette Jensen -->
<swp-schedule-cell class="employee">
<swp-employee-name>Mette Jensen</swp-employee-name>
<swp-employee-hours>40 timer</swp-employee-hours>
</swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Mette Jensen" data-day="Man" data-date="23/12"><swp-time-display>10:00 - 18:00</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Mette Jensen" data-day="Tir" data-date="24/12"><swp-time-display>10:00 - 18:00</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Mette Jensen" data-day="Ons" data-date="25/12"><swp-time-display class="vacation">Ferie</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Mette Jensen" data-day="Tor" data-date="26/12"><swp-time-display class="vacation">Ferie</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Mette Jensen" data-day="Fre" data-date="27/12"><swp-time-display class="vacation">Ferie</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Mette Jensen" data-day="Lør" data-date="28/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Mette Jensen" data-day="Søn" data-date="29/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
<!-- Louise Nielsen -->
<swp-schedule-cell class="employee">
<swp-employee-name>Louise Nielsen</swp-employee-name>
<swp-employee-hours>37 timer</swp-employee-hours>
</swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Louise Nielsen" data-day="Man" data-date="23/12"><swp-time-display>09:00 - 17:00</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Louise Nielsen" data-day="Tir" data-date="24/12"><swp-time-display>09:00 - 17:00</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Louise Nielsen" data-day="Ons" data-date="25/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Louise Nielsen" data-day="Tor" data-date="26/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Louise Nielsen" data-day="Fre" data-date="27/12"><swp-time-display>09:00 - 17:00</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Louise Nielsen" data-day="Lør" data-date="28/12"><swp-time-display>09:00 - 14:00</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Louise Nielsen" data-day="Søn" data-date="29/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
<!-- Katrine Pedersen -->
<swp-schedule-cell class="employee">
<swp-employee-name>Katrine Pedersen</swp-employee-name>
<swp-employee-hours>24 timer</swp-employee-hours>
</swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Katrine Pedersen" data-day="Man" data-date="23/12"><swp-time-display>12:00 - 20:00</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Katrine Pedersen" data-day="Tir" data-date="24/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Katrine Pedersen" data-day="Ons" data-date="25/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Katrine Pedersen" data-day="Tor" data-date="26/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Katrine Pedersen" data-day="Fre" data-date="27/12"><swp-time-display>12:00 - 20:00</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Katrine Pedersen" data-day="Lør" data-date="28/12"><swp-time-display>10:00 - 18:00</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Katrine Pedersen" data-day="Søn" data-date="29/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
<!-- Sofie Andersen -->
<swp-schedule-cell class="employee">
<swp-employee-name>Sofie Andersen</swp-employee-name>
<swp-employee-hours>20 timer</swp-employee-hours>
</swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Sofie Andersen" data-day="Man" data-date="23/12"><swp-time-display class="sick">Syg</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Sofie Andersen" data-day="Tir" data-date="24/12"><swp-time-display>09:00 - 15:00</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Sofie Andersen" data-day="Ons" data-date="25/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Sofie Andersen" data-day="Tor" data-date="26/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Sofie Andersen" data-day="Fre" data-date="27/12"><swp-time-display>09:00 - 15:00</swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Sofie Andersen" data-day="Lør" data-date="28/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
<swp-schedule-cell class="day" data-employee="Sofie Andersen" data-day="Søn" data-date="29/12"><swp-time-display class="off"></swp-time-display></swp-schedule-cell>
</swp-schedule-table>
</swp-page>
<!-- DRAWER -->
<swp-drawer id="scheduleDrawer">
<swp-drawer-header>
<swp-drawer-title id="drawerTitle">Redigér vagt</swp-drawer-title>
<swp-drawer-close id="drawerClose">×</swp-drawer-close>
</swp-drawer-header>
<swp-drawer-content>
<swp-form-row>
<swp-form-label>Medarbejder</swp-form-label>
<swp-employee-display id="fieldEmployeeDisplay">
<swp-employee-avatar id="fieldAvatar"></swp-employee-avatar>
<swp-form-value id="fieldEmployee">Vælg celle...</swp-form-value>
</swp-employee-display>
</swp-form-row>
<swp-form-row>
<swp-form-label>Dato</swp-form-label>
<swp-form-value id="fieldDate"></swp-form-value>
</swp-form-row>
<swp-form-divider></swp-form-divider>
<swp-form-row>
<swp-form-label>Status</swp-form-label>
<swp-status-options id="statusOptions">
<swp-status-option data-status="work" class="selected">Arbejde</swp-status-option>
<swp-status-option data-status="off">Fri</swp-status-option>
<swp-status-option data-status="vacation">Ferie</swp-status-option>
<swp-status-option data-status="sick">Syg</swp-status-option>
</swp-status-options>
</swp-form-row>
<swp-form-row id="timeRow">
<swp-form-label>Tidsrum</swp-form-label>
<swp-time-range id="drawerTimeRange">
<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="12" step="1">
<input type="range" class="range-end" min="0" max="60" value="44" step="1">
</swp-time-range-slider>
<swp-time-range-label>
<swp-time-range-times>09:00 17:00</swp-time-range-times>
<swp-time-range-duration>8 timer</swp-time-range-duration>
</swp-time-range-label>
</swp-time-range>
</swp-form-row>
<swp-form-row>
<swp-form-label>Note <span class="optional">(valgfrit)</span></swp-form-label>
<input type="text" id="fieldNote" placeholder="F.eks. Aftenvagt">
</swp-form-row>
<swp-form-divider></swp-form-divider>
<swp-form-row>
<swp-form-label>Type</swp-form-label>
<swp-toggle-options id="typeOptions">
<swp-toggle-option data-value="single">Enkelt</swp-toggle-option>
<swp-toggle-option data-value="template" class="selected">Gentagelse</swp-toggle-option>
</swp-toggle-options>
</swp-form-row>
<swp-form-group id="repeatGroup">
<swp-form-row>
<swp-form-label>Gentag</swp-form-label>
<swp-form-select>
<select id="repeatInterval">
<option value="1">Hver uge</option>
<option value="2">Hver 2. uge</option>
<option value="3">Hver 3. uge</option>
<option value="4">Hver 4. uge</option>
</select>
</swp-form-select>
</swp-form-row>
<swp-form-hint>
Gentagelser bruger valgt dato som startuge.
</swp-form-hint>
<swp-form-row>
<swp-form-label>Slutdato <span class="optional">(valgfrit)</span></swp-form-label>
<input type="date" id="repeatEndDate">
</swp-form-row>
<swp-form-row>
<swp-form-label>Ugedag <span class="auto">(auto)</span></swp-form-label>
<swp-form-value id="fieldWeekday"></swp-form-value>
</swp-form-row>
</swp-form-group>
</swp-drawer-content>
<swp-drawer-footer>
<swp-button class="secondary" id="drawerCancel">Annuller</swp-button>
<swp-button class="primary" id="drawerSave">Gem</swp-button>
</swp-drawer-footer>
</swp-drawer>
<script>
// ==========================================
// EDIT MODE
// ==========================================
const editModeBtn = document.getElementById('editModeBtn');
let isEditMode = false;
editModeBtn.addEventListener('click', () => {
isEditMode = !isEditMode;
document.body.classList.toggle('edit-mode', isEditMode);
if (isEditMode) {
editModeBtn.innerHTML = `
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/>
<polyline points="17 21 17 13 7 13 7 21"/>
<polyline points="7 3 7 8 15 8"/>
</svg>
Færdig`;
openDrawer();
showEmptyState();
} else {
editModeBtn.innerHTML = `
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
</svg>
Rediger`;
closeDrawer();
clearSelection();
}
});
// ==========================================
// DRAWER
// ==========================================
const drawer = document.getElementById('scheduleDrawer');
const drawerClose = document.getElementById('drawerClose');
const drawerCancel = document.getElementById('drawerCancel');
const drawerSave = document.getElementById('drawerSave');
const drawerContent = document.querySelector('swp-drawer-content');
const drawerFooter = document.querySelector('swp-drawer-footer');
// Form fields
const fieldEmployee = document.getElementById('fieldEmployee');
const fieldEmployeeDisplay = document.getElementById('fieldEmployeeDisplay');
const fieldAvatar = document.getElementById('fieldAvatar');
const fieldDate = document.getElementById('fieldDate');
const fieldWeekday = document.getElementById('fieldWeekday');
const timeRow = document.getElementById('timeRow');
const repeatGroup = document.getElementById('repeatGroup');
const drawerTimeRange = document.getElementById('drawerTimeRange');
function getInitials(name) {
return name.split(' ').map(n => n[0]).join('').toUpperCase().slice(0, 2);
}
const weekdays = ['Søndag', 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag'];
// ==========================================
// TIME RANGE SLIDER
// ==========================================
const TIME_RANGE_MAX = 60; // 15 hours (06:00-21:00) * 4 intervals
function valueToTime(value) {
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')}`;
}
function timeToValue(timeStr) {
const [hours, minutes] = timeStr.split(':').map(Number);
const totalMinutes = hours * 60 + minutes;
return Math.round((totalMinutes - 6 * 60) / 15);
}
function updateTimeRange(slider) {
const startInput = slider.querySelector('.range-start');
const endInput = slider.querySelector('.range-end');
const fill = slider.querySelector('swp-time-range-fill');
const labelContainer = slider.closest('swp-time-range').querySelector('swp-time-range-label');
const timesEl = labelContainer.querySelector('swp-time-range-times');
const durationEl = labelContainer.querySelector('swp-time-range-duration');
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) + '%';
// Calculate duration in hours
const durationIntervals = endVal - startVal;
const durationMinutes = durationIntervals * 15;
const durationHours = durationMinutes / 60;
const durationText = durationHours % 1 === 0
? `${durationHours} timer`
: `${durationHours.toFixed(1).replace('.', ',')} timer`;
// Update time range and duration separately
timesEl.textContent = `${valueToTime(startVal)} ${valueToTime(endVal)}`;
durationEl.textContent = durationText;
}
function initTimeRangeSlider(sliderContainer) {
const slider = sliderContainer.querySelector('swp-time-range-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);
updateSelectedCellsTime();
});
endInput.addEventListener('input', () => {
updateTimeRange(slider);
updateSelectedCellsTime();
});
// Drag fill bar to move entire range
let isDragging = false;
let dragStartX = 0;
let dragStartValues = { start: 0, end: 0 };
fill.addEventListener('mousedown', (e) => {
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);
updateSelectedCellsTime();
});
document.addEventListener('mouseup', () => {
isDragging = false;
});
}
// Initialize the drawer time range slider
initTimeRangeSlider(drawerTimeRange);
// Opdater valgte celler i realtid når tiden ændres
function updateSelectedCellsTime() {
const selectedStatus = document.querySelector('#statusOptions swp-status-option.selected');
const status = selectedStatus ? selectedStatus.dataset.status : 'work';
// Kun opdater hvis status er "work"
if (status !== 'work') return;
const slider = drawerTimeRange.querySelector('swp-time-range-slider');
const startVal = parseInt(slider.querySelector('.range-start').value);
const endVal = parseInt(slider.querySelector('.range-end').value);
const startTime = valueToTime(startVal);
const endTime = valueToTime(endVal);
const formattedTime = `${startTime} - ${endTime}`;
selectedCells.forEach(cell => {
const timeDisplay = cell.querySelector('swp-time-display');
if (timeDisplay && !timeDisplay.classList.contains('off') &&
!timeDisplay.classList.contains('vacation') &&
!timeDisplay.classList.contains('sick')) {
timeDisplay.textContent = formattedTime;
}
});
}
let selectedCells = [];
const GRID_COLUMNS = 8; // 1 employee + 7 days
const allCells = Array.from(document.querySelectorAll('swp-schedule-table > swp-schedule-cell'));
function updateAdjacentClasses() {
// Fjern adjacency klasser først
selectedCells.forEach(c => c.classList.remove('adj-left', 'adj-right', 'adj-top', 'adj-bottom'));
// Find indices af alle valgte celler
const selectedIndices = selectedCells.map(cell => allCells.indexOf(cell));
selectedCells.forEach(cell => {
const idx = allCells.indexOf(cell);
const col = idx % GRID_COLUMNS;
// Venstre nabo
if (col > 1 && selectedIndices.includes(idx - 1)) {
cell.classList.add('adj-left');
}
// Højre nabo
if (col < GRID_COLUMNS - 1 && selectedIndices.includes(idx + 1)) {
cell.classList.add('adj-right');
}
// Nabo ovenover
if (selectedIndices.includes(idx - GRID_COLUMNS)) {
cell.classList.add('adj-top');
}
// Nabo nedenunder
if (selectedIndices.includes(idx + GRID_COLUMNS)) {
cell.classList.add('adj-bottom');
}
});
}
function showEmptyState() {
fieldEmployee.textContent = 'Vælg celle...';
fieldAvatar.textContent = '?';
fieldEmployeeDisplay.classList.add('empty');
fieldEmployeeDisplay.classList.remove('multi');
fieldDate.textContent = '—';
fieldWeekday.textContent = '—';
drawerContent.style.opacity = '0.5';
drawerContent.style.pointerEvents = 'none';
drawerFooter.style.display = 'none';
}
function showEditState() {
drawerContent.style.opacity = '1';
drawerContent.style.pointerEvents = 'auto';
drawerFooter.style.display = 'flex';
}
function updateDrawerFields() {
if (selectedCells.length === 0) {
showEmptyState();
return;
}
showEditState();
fieldEmployeeDisplay.classList.remove('empty', 'multi');
if (selectedCells.length === 1) {
const cell = selectedCells[0];
const employeeName = cell.dataset.employee;
fieldEmployee.textContent = employeeName;
fieldAvatar.textContent = getInitials(employeeName);
fieldDate.textContent = cell.dataset.date + '/2025';
// Calculate weekday from day name
const dayMap = { 'Man': 1, 'Tir': 2, 'Ons': 3, 'Tor': 4, 'Fre': 5, 'Lør': 6, 'Søn': 0 };
fieldWeekday.textContent = weekdays[dayMap[cell.dataset.day]];
// Pre-fill form with current cell values
prefillFormFromCell(cell);
} else {
const employees = [...new Set(selectedCells.map(c => c.dataset.employee))];
const days = [...new Set(selectedCells.map(c => c.dataset.day))];
if (employees.length === 1) {
fieldEmployee.textContent = employees[0];
fieldAvatar.textContent = getInitials(employees[0]);
fieldDate.textContent = `${selectedCells.length} dage valgt`;
} else if (days.length === 1) {
fieldEmployee.textContent = `${selectedCells.length} medarbejdere`;
fieldAvatar.textContent = employees.length;
fieldEmployeeDisplay.classList.add('multi');
fieldDate.textContent = selectedCells[0].dataset.date + '/2025';
} else {
fieldEmployee.textContent = `${selectedCells.length} valgt`;
fieldAvatar.textContent = selectedCells.length;
fieldEmployeeDisplay.classList.add('multi');
fieldDate.textContent = `${employees.length} medarbejdere, ${days.length} dage`;
}
fieldWeekday.textContent = days.length === 1 ? weekdays[{ 'Man': 1, 'Tir': 2, 'Ons': 3, 'Tor': 4, 'Fre': 5, 'Lør': 6, 'Søn': 0 }[days[0]]] : 'Flere dage';
// Reset form to default for multi-select
resetFormToDefault();
}
}
function prefillFormFromCell(cell) {
const timeDisplay = cell.querySelector('swp-time-display');
if (!timeDisplay) return;
// Determine current status
let status = 'work';
if (timeDisplay.classList.contains('off')) status = 'off';
else if (timeDisplay.classList.contains('vacation')) status = 'vacation';
else if (timeDisplay.classList.contains('sick')) status = 'sick';
// Update status options
document.querySelectorAll('#statusOptions swp-status-option').forEach(opt => {
opt.classList.toggle('selected', opt.dataset.status === status);
});
// Show/hide time slider based on status
const showTime = status === 'work';
timeRow.style.display = showTime ? 'flex' : 'none';
// Parse and fill time if work status
if (status === 'work') {
const timeText = timeDisplay.textContent.trim();
const timeMatch = timeText.match(/(\d{2}:\d{2})\s*-\s*(\d{2}:\d{2})/);
if (timeMatch) {
const slider = drawerTimeRange.querySelector('swp-time-range-slider');
slider.querySelector('.range-start').value = timeToValue(timeMatch[1]);
slider.querySelector('.range-end').value = timeToValue(timeMatch[2]);
updateTimeRange(slider);
}
}
// Reset type to template (gentagelse)
document.querySelectorAll('#typeOptions swp-toggle-option').forEach(opt => {
opt.classList.toggle('selected', opt.dataset.value === 'template');
});
repeatGroup.style.display = 'block';
// Udfyld note hvis den findes
document.getElementById('fieldNote').value = cell.dataset.note || '';
}
function resetFormToDefault() {
// Reset to work status
document.querySelectorAll('#statusOptions swp-status-option').forEach(opt => {
opt.classList.toggle('selected', opt.dataset.status === 'work');
});
timeRow.style.display = 'flex';
// Reset time slider to 09:00-17:00
const slider = drawerTimeRange.querySelector('swp-time-range-slider');
slider.querySelector('.range-start').value = 12; // 09:00
slider.querySelector('.range-end').value = 44; // 17:00
updateTimeRange(slider);
// Reset type to template (gentagelse)
document.querySelectorAll('#typeOptions swp-toggle-option').forEach(opt => {
opt.classList.toggle('selected', opt.dataset.value === 'template');
});
repeatGroup.style.display = 'block';
// Nulstil note
document.getElementById('fieldNote').value = '';
}
function openDrawer() {
drawer.classList.add('open');
}
function closeDrawer() {
drawer.classList.remove('open');
}
function clearSelection() {
selectedCells.forEach(c => {
c.classList.remove('selected', 'adj-left', 'adj-right', 'adj-top', 'adj-bottom');
});
selectedCells = [];
}
drawerClose.addEventListener('click', () => {
// Exit edit mode
isEditMode = false;
document.body.classList.remove('edit-mode');
editModeBtn.innerHTML = `
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
</svg>
Rediger`;
closeDrawer();
clearSelection();
});
drawerCancel.addEventListener('click', () => {
clearSelection();
showEmptyState();
});
drawerSave.addEventListener('click', () => {
if (selectedCells.length === 0) return;
const selectedStatus = document.querySelector('#statusOptions swp-status-option.selected');
const status = selectedStatus ? selectedStatus.dataset.status : 'work';
// Get time from slider
const slider = drawerTimeRange.querySelector('swp-time-range-slider');
const startVal = parseInt(slider.querySelector('.range-start').value);
const endVal = parseInt(slider.querySelector('.range-end').value);
const startTime = valueToTime(startVal);
const endTime = valueToTime(endVal);
const noteValue = document.getElementById('fieldNote').value.trim();
selectedCells.forEach(cell => {
const timeDisplay = cell.querySelector('swp-time-display');
if (!timeDisplay) return;
// Store original if not already stored (kun hvis cellen har en reel tid)
const hasRealTime = !timeDisplay.classList.contains('off') &&
!timeDisplay.classList.contains('vacation') &&
!timeDisplay.classList.contains('sick');
if (!cell.dataset.originalTime && hasRealTime) {
cell.dataset.originalTime = timeDisplay.textContent;
}
// Remove all status classes
timeDisplay.classList.remove('off', 'off-override', 'vacation', 'sick');
switch (status) {
case 'work':
const formattedTime = `${startTime} - ${endTime}`;
timeDisplay.textContent = formattedTime;
break;
case 'off':
timeDisplay.classList.add('off');
if (cell.dataset.originalTime) {
timeDisplay.classList.add('off-override');
timeDisplay.textContent = 'Fri';
} else {
timeDisplay.textContent = '—';
}
break;
case 'vacation':
timeDisplay.classList.add('vacation');
timeDisplay.textContent = 'Ferie';
break;
case 'sick':
timeDisplay.classList.add('sick');
timeDisplay.textContent = 'Syg';
break;
}
// Håndter note-ikon
let noteIcon = cell.querySelector('swp-note-icon');
if (noteValue) {
if (!noteIcon) {
noteIcon = document.createElement('swp-note-icon');
noteIcon.innerHTML = '<img src="icons/note-sticky.svg" alt="Note">';
cell.appendChild(noteIcon);
}
cell.dataset.note = noteValue;
} else {
if (noteIcon) {
noteIcon.remove();
}
delete cell.dataset.note;
}
// Håndter override-indikator (vis original tid når ændret)
let overrideEl = cell.querySelector('swp-override-original');
if (cell.dataset.originalTime) {
// Der er en original værdi - vis override
if (!overrideEl) {
overrideEl = document.createElement('swp-override-original');
cell.appendChild(overrideEl);
}
overrideEl.textContent = cell.dataset.originalTime;
}
// Mark as modified
cell.dataset.modified = 'true';
});
clearSelection();
showEmptyState();
});
// ==========================================
// CELL CLICK (in edit mode)
// ==========================================
const dayCells = Array.from(document.querySelectorAll('swp-schedule-cell.day'));
let anchorCell = null; // Første valgte celle til shift-selection
document.querySelectorAll('swp-schedule-cell.day').forEach(cell => {
// Dobbeltklik aktiverer edit-mode
cell.addEventListener('dblclick', (e) => {
if (!isEditMode) {
isEditMode = true;
document.body.classList.add('edit-mode');
editModeBtn.innerHTML = `
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/>
<polyline points="17 21 17 13 7 13 7 21"/>
<polyline points="7 3 7 8 15 8"/>
</svg>
Færdig`;
openDrawer();
// Vælg den dobbeltklikkede celle
clearSelection();
cell.classList.add('selected');
selectedCells = [cell];
anchorCell = cell;
updateAdjacentClasses();
updateDrawerFields();
}
});
cell.addEventListener('click', (e) => {
if (!isEditMode) return;
if (e.shiftKey && anchorCell) {
// Shift-click: vælg alle celler fra anchor til denne
const anchorIdx = dayCells.indexOf(anchorCell);
const targetIdx = dayCells.indexOf(cell);
const startIdx = Math.min(anchorIdx, targetIdx);
const endIdx = Math.max(anchorIdx, targetIdx);
// Beregn rækkevidde baseret på grid position
const anchorRow = Math.floor(anchorIdx / 7);
const anchorCol = anchorIdx % 7;
const targetRow = Math.floor(targetIdx / 7);
const targetCol = targetIdx % 7;
const minRow = Math.min(anchorRow, targetRow);
const maxRow = Math.max(anchorRow, targetRow);
const minCol = Math.min(anchorCol, targetCol);
const maxCol = Math.max(anchorCol, targetCol);
clearSelection();
// Vælg alle celler i rektanglet
dayCells.forEach((c, idx) => {
const row = Math.floor(idx / 7);
const col = idx % 7;
if (row >= minRow && row <= maxRow && col >= minCol && col <= maxCol) {
c.classList.add('selected');
selectedCells.push(c);
}
});
} else if (e.ctrlKey || e.metaKey) {
// Multi-select with Ctrl/Cmd
if (cell.classList.contains('selected')) {
cell.classList.remove('selected');
selectedCells = selectedCells.filter(c => c !== cell);
} else {
cell.classList.add('selected');
selectedCells.push(cell);
anchorCell = cell;
}
} else {
// Single click - clear previous and select this one
clearSelection();
cell.classList.add('selected');
selectedCells = [cell];
anchorCell = cell;
}
updateAdjacentClasses();
updateDrawerFields();
});
});
// ==========================================
// STATUS OPTIONS
// ==========================================
function updateSelectedCellsStatus() {
const selectedStatus = document.querySelector('#statusOptions swp-status-option.selected');
const status = selectedStatus ? selectedStatus.dataset.status : 'work';
const slider = drawerTimeRange.querySelector('swp-time-range-slider');
const startVal = parseInt(slider.querySelector('.range-start').value);
const endVal = parseInt(slider.querySelector('.range-end').value);
const startTime = valueToTime(startVal);
const endTime = valueToTime(endVal);
selectedCells.forEach(cell => {
const timeDisplay = cell.querySelector('swp-time-display');
if (!timeDisplay) return;
// Gem original tid hvis ikke allerede gemt
const hasRealTime = !timeDisplay.classList.contains('off') &&
!timeDisplay.classList.contains('vacation') &&
!timeDisplay.classList.contains('sick');
const currentText = timeDisplay.textContent;
const isRealTimeText = currentText.includes(':'); // Tjek om det er en tid
if (!cell.dataset.originalTime && (hasRealTime || isRealTimeText)) {
cell.dataset.originalTime = currentText;
}
// Fjern alle status klasser
timeDisplay.classList.remove('off', 'off-override', 'vacation', 'sick');
switch (status) {
case 'work':
timeDisplay.textContent = `${startTime} - ${endTime}`;
break;
case 'off':
timeDisplay.classList.add('off');
if (cell.dataset.originalTime) {
timeDisplay.classList.add('off-override');
timeDisplay.textContent = 'Fri';
} else {
timeDisplay.textContent = '—';
}
break;
case 'vacation':
timeDisplay.classList.add('vacation');
timeDisplay.textContent = 'Ferie';
break;
case 'sick':
timeDisplay.classList.add('sick');
timeDisplay.textContent = 'Syg';
break;
}
});
}
document.querySelectorAll('#statusOptions swp-status-option').forEach(option => {
option.addEventListener('click', () => {
document.querySelectorAll('#statusOptions swp-status-option').forEach(o => o.classList.remove('selected'));
option.classList.add('selected');
const status = option.dataset.status;
const showTime = status === 'work';
timeRow.style.display = showTime ? 'flex' : 'none';
// Opdater celler i realtid
updateSelectedCellsStatus();
});
});
// ==========================================
// TYPE TOGGLE (Enkelt/Gentagelse)
// ==========================================
document.querySelectorAll('#typeOptions swp-toggle-option').forEach(option => {
option.addEventListener('click', () => {
document.querySelectorAll('#typeOptions swp-toggle-option').forEach(o => o.classList.remove('selected'));
option.classList.add('selected');
const isTemplate = option.dataset.value === 'template';
repeatGroup.style.display = isTemplate ? 'block' : 'none';
});
});
// ==========================================
// WEEK NAVIGATION
// ==========================================
document.getElementById('prevWeek').addEventListener('click', () => {
console.log('Previous week');
});
document.getElementById('nextWeek').addEventListener('click', () => {
console.log('Next week');
});
</script>
</body>
</html>