This commit is contained in:
Janus C. H. Knudsen 2025-12-23 09:53:31 +01:00
parent 9f46ff8824
commit 35c30c058d

View file

@ -981,35 +981,106 @@
swp-availability-time { swp-availability-time {
flex: 1; flex: 1;
display: flex;
flex-direction: column;
gap: 4px;
} }
swp-availability-time select { 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%; width: 100%;
max-width: 200px; height: 4px;
padding: 6px 10px; background: var(--color-border);
font-size: 13px; border-radius: 2px;
font-family: inherit; }
border: 1px solid var(--color-border);
border-radius: 4px; swp-time-range-fill {
background: var(--color-background-alt); position: absolute;
color: var(--color-text); 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%;
cursor: pointer; cursor: pointer;
transition: all 150ms ease; pointer-events: auto;
box-shadow: 0 1px 3px rgba(0,0,0,0.2);
} }
swp-availability-time select:hover:not(:disabled) { swp-time-range-slider input[type="range"]::-moz-range-thumb {
background: var(--color-background); 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-availability-time select:focus { swp-time-range-label {
outline: none; font-size: 12px;
border-color: var(--color-teal); font-family: var(--font-mono);
background: var(--color-surface); color: var(--color-text);
min-width: 90px;
text-align: center;
background: var(--color-background-alt);
padding: 3px 8px;
border-radius: 4px;
} }
swp-availability-time select:disabled { 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);
}
swp-availability-row[data-enabled="false"] swp-time-range-label {
opacity: 0.5; opacity: 0.5;
cursor: not-allowed;
} }
/* ========================================== /* ==========================================
@ -1887,108 +1958,129 @@
<swp-availability-list> <swp-availability-list>
<swp-availability-row data-enabled="true"> <swp-availability-row data-enabled="true">
<swp-availability-day>Mandag</swp-availability-day> <swp-availability-day>Mandag</swp-availability-day>
<swp-availability-time>
<select>
<option selected>Hele dagen</option>
<option>Formiddag (før 12:00)</option>
<option>Eftermiddag (efter 12:00)</option>
<option>Brugerdefineret</option>
</select>
</swp-availability-time>
<swp-toggle-slider data-value="yes"> <swp-toggle-slider data-value="yes">
<swp-toggle-option>Ja</swp-toggle-option> <swp-toggle-option>Ja</swp-toggle-option>
<swp-toggle-option>Nej</swp-toggle-option> <swp-toggle-option>Nej</swp-toggle-option>
</swp-toggle-slider> </swp-toggle-slider>
<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>
</swp-availability-row> </swp-availability-row>
<swp-availability-row data-enabled="true"> <swp-availability-row data-enabled="true">
<swp-availability-day>Tirsdag</swp-availability-day> <swp-availability-day>Tirsdag</swp-availability-day>
<swp-availability-time>
<select>
<option selected>Hele dagen</option>
<option>Formiddag (før 12:00)</option>
<option>Eftermiddag (efter 12:00)</option>
<option>Brugerdefineret</option>
</select>
</swp-availability-time>
<swp-toggle-slider data-value="yes"> <swp-toggle-slider data-value="yes">
<swp-toggle-option>Ja</swp-toggle-option> <swp-toggle-option>Ja</swp-toggle-option>
<swp-toggle-option>Nej</swp-toggle-option> <swp-toggle-option>Nej</swp-toggle-option>
</swp-toggle-slider> </swp-toggle-slider>
<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>
</swp-availability-row> </swp-availability-row>
<swp-availability-row data-enabled="true"> <swp-availability-row data-enabled="true">
<swp-availability-day>Onsdag</swp-availability-day> <swp-availability-day>Onsdag</swp-availability-day>
<swp-availability-time>
<select>
<option selected>Hele dagen</option>
<option>Formiddag (før 12:00)</option>
<option>Eftermiddag (efter 12:00)</option>
<option>Brugerdefineret</option>
</select>
</swp-availability-time>
<swp-toggle-slider data-value="yes"> <swp-toggle-slider data-value="yes">
<swp-toggle-option>Ja</swp-toggle-option> <swp-toggle-option>Ja</swp-toggle-option>
<swp-toggle-option>Nej</swp-toggle-option> <swp-toggle-option>Nej</swp-toggle-option>
</swp-toggle-slider> </swp-toggle-slider>
<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>
</swp-availability-row> </swp-availability-row>
<swp-availability-row data-enabled="true"> <swp-availability-row data-enabled="true">
<swp-availability-day>Torsdag</swp-availability-day> <swp-availability-day>Torsdag</swp-availability-day>
<swp-availability-time>
<select>
<option>Hele dagen</option>
<option selected>Formiddag (før 12:00)</option>
<option>Eftermiddag (efter 12:00)</option>
<option>Brugerdefineret</option>
</select>
</swp-availability-time>
<swp-toggle-slider data-value="yes"> <swp-toggle-slider data-value="yes">
<swp-toggle-option>Ja</swp-toggle-option> <swp-toggle-option>Ja</swp-toggle-option>
<swp-toggle-option>Nej</swp-toggle-option> <swp-toggle-option>Nej</swp-toggle-option>
</swp-toggle-slider> </swp-toggle-slider>
<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>
</swp-availability-row> </swp-availability-row>
<swp-availability-row data-enabled="true"> <swp-availability-row data-enabled="true">
<swp-availability-day>Fredag</swp-availability-day> <swp-availability-day>Fredag</swp-availability-day>
<swp-availability-time>
<select>
<option selected>Hele dagen</option>
<option>Formiddag (før 12:00)</option>
<option>Eftermiddag (efter 12:00)</option>
<option>Brugerdefineret</option>
</select>
</swp-availability-time>
<swp-toggle-slider data-value="yes"> <swp-toggle-slider data-value="yes">
<swp-toggle-option>Ja</swp-toggle-option> <swp-toggle-option>Ja</swp-toggle-option>
<swp-toggle-option>Nej</swp-toggle-option> <swp-toggle-option>Nej</swp-toggle-option>
</swp-toggle-slider> </swp-toggle-slider>
<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>
</swp-availability-row> </swp-availability-row>
<swp-availability-row data-enabled="false"> <swp-availability-row data-enabled="false">
<swp-availability-day>Lørdag</swp-availability-day> <swp-availability-day>Lørdag</swp-availability-day>
<swp-availability-time>
<select disabled>
<option selected>Hele dagen</option>
<option>Formiddag (før 12:00)</option>
<option>Eftermiddag (efter 12:00)</option>
<option>Brugerdefineret</option>
</select>
</swp-availability-time>
<swp-toggle-slider data-value="no"> <swp-toggle-slider data-value="no">
<swp-toggle-option>Ja</swp-toggle-option> <swp-toggle-option>Ja</swp-toggle-option>
<swp-toggle-option>Nej</swp-toggle-option> <swp-toggle-option>Nej</swp-toggle-option>
</swp-toggle-slider> </swp-toggle-slider>
<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>
</swp-availability-row> </swp-availability-row>
<swp-availability-row data-enabled="false"> <swp-availability-row data-enabled="false">
<swp-availability-day>Søndag</swp-availability-day> <swp-availability-day>Søndag</swp-availability-day>
<swp-availability-time>
<select disabled>
<option selected>Hele dagen</option>
<option>Formiddag (før 12:00)</option>
<option>Eftermiddag (efter 12:00)</option>
<option>Brugerdefineret</option>
</select>
</swp-availability-time>
<swp-toggle-slider data-value="no"> <swp-toggle-slider data-value="no">
<swp-toggle-option>Ja</swp-toggle-option> <swp-toggle-option>Ja</swp-toggle-option>
<swp-toggle-option>Nej</swp-toggle-option> <swp-toggle-option>Nej</swp-toggle-option>
</swp-toggle-slider> </swp-toggle-slider>
<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>
</swp-availability-row> </swp-availability-row>
</swp-availability-list> </swp-availability-list>
</swp-card> </swp-card>
@ -2094,6 +2186,106 @@
}); });
}); });
// ==========================================
// 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;
});
});
// ========================================== // ==========================================
// TOGGLE SLIDERS (Ja/Nej) // TOGGLE SLIDERS (Ja/Nej)
// ========================================== // ==========================================
@ -2109,9 +2301,13 @@
if (availabilityRow) { if (availabilityRow) {
const isEnabled = newValue === 'yes'; const isEnabled = newValue === 'yes';
availabilityRow.dataset.enabled = isEnabled; availabilityRow.dataset.enabled = isEnabled;
const select = availabilityRow.querySelector('select'); const rangeInputs = availabilityRow.querySelectorAll('input[type="range"]');
if (select) { rangeInputs.forEach(input => {
select.disabled = !isEnabled; input.disabled = !isEnabled;
});
const fill = availabilityRow.querySelector('swp-time-range-fill');
if (fill) {
fill.classList.toggle('disabled', !isEnabled);
} }
} }
}); });