154 lines
4.2 KiB
JavaScript
154 lines
4.2 KiB
JavaScript
function isInteractiveTouchTarget(target) {
|
|
if (!target || typeof target.closest !== 'function') {
|
|
return false;
|
|
}
|
|
return Boolean(target.closest('a, button, input, select, textarea, summary, details, label, form'));
|
|
}
|
|
|
|
function attachSwipeNavigation(target, prevUrl, nextUrl) {
|
|
if (!target || !prevUrl || !nextUrl) {
|
|
return;
|
|
}
|
|
|
|
const minSwipeDistance = 60;
|
|
const maxVerticalRatio = 1.25;
|
|
const maxSwipeDuration = 900;
|
|
let startX = 0;
|
|
let startY = 0;
|
|
let startAt = 0;
|
|
let tracking = false;
|
|
let navigating = false;
|
|
|
|
target.addEventListener('touchstart', (event) => {
|
|
if (event.touches.length !== 1 || isInteractiveTouchTarget(event.target)) {
|
|
tracking = false;
|
|
return;
|
|
}
|
|
|
|
const touch = event.touches[0];
|
|
startX = touch.clientX;
|
|
startY = touch.clientY;
|
|
startAt = Date.now();
|
|
tracking = true;
|
|
}, { passive: true });
|
|
|
|
target.addEventListener('touchend', (event) => {
|
|
if (!tracking || navigating || event.changedTouches.length !== 1) {
|
|
tracking = false;
|
|
return;
|
|
}
|
|
|
|
tracking = false;
|
|
const touch = event.changedTouches[0];
|
|
const deltaX = touch.clientX - startX;
|
|
const deltaY = touch.clientY - startY;
|
|
const absX = Math.abs(deltaX);
|
|
const absY = Math.abs(deltaY);
|
|
const duration = Date.now() - startAt;
|
|
|
|
if (duration > maxSwipeDuration || absX < minSwipeDistance || absX <= absY * maxVerticalRatio) {
|
|
return;
|
|
}
|
|
|
|
navigating = true;
|
|
if (deltaX < 0) {
|
|
window.location.assign(nextUrl);
|
|
} else {
|
|
window.location.assign(prevUrl);
|
|
}
|
|
}, { passive: true });
|
|
}
|
|
|
|
function initSwipeNavigation() {
|
|
if (!window.matchMedia('(pointer: coarse)').matches && !('ontouchstart' in window)) {
|
|
return;
|
|
}
|
|
|
|
document.querySelectorAll('[data-component="swipe-nav"]').forEach((node) => {
|
|
attachSwipeNavigation(node, node.dataset.prevUrl, node.dataset.nextUrl);
|
|
});
|
|
}
|
|
|
|
function initWarningBanner() {
|
|
const warningBanner = document.querySelector('[data-component="workhours-warning"]');
|
|
if (!warningBanner) {
|
|
return;
|
|
}
|
|
|
|
const warningKey = warningBanner.getAttribute('data-workhours-warning') || '';
|
|
const storageKey = warningKey ? `workhours-warning-dismissed:${warningKey}` : '';
|
|
|
|
if (storageKey && window.localStorage.getItem(storageKey) === '1') {
|
|
warningBanner.remove();
|
|
return;
|
|
}
|
|
|
|
const closeButton = warningBanner.querySelector('[data-action="warning-close"]');
|
|
if (closeButton) {
|
|
closeButton.addEventListener('click', () => {
|
|
warningBanner.remove();
|
|
if (storageKey) {
|
|
window.localStorage.setItem(storageKey, '1');
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function initWeeklyTargetEditor() {
|
|
const form = document.querySelector('.weekly-target-form');
|
|
const editor = document.querySelector('[data-component="weekly-target-editor"]');
|
|
const toggleButtons = document.querySelectorAll('.js-toggle-weekly-target-editor');
|
|
|
|
if (form && toggleButtons.length && editor) {
|
|
toggleButtons.forEach((toggleButton) => {
|
|
toggleButton.addEventListener('click', () => {
|
|
editor.classList.toggle('is-hidden');
|
|
});
|
|
});
|
|
}
|
|
|
|
if (!form) {
|
|
return;
|
|
}
|
|
|
|
form.addEventListener('submit', (event) => {
|
|
const scopeSelect = form.querySelector("select[name='scope']");
|
|
const hoursInput = form.querySelector("input[name='weekly_target_hours']");
|
|
if (!scopeSelect || !hoursInput) {
|
|
return;
|
|
}
|
|
|
|
const scope = scopeSelect.value;
|
|
const hours = hoursInput.value;
|
|
let scopeText = '';
|
|
|
|
if (scope === 'current_week') {
|
|
scopeText = 'Nur die aktuell ausgewählte Woche';
|
|
} else if (scope === 'all_weeks') {
|
|
scopeText = 'Alle Wochen (Vergangenheit und Zukunft)';
|
|
} else if (scope === 'from_current_week') {
|
|
scopeText = 'Aktuelle Woche und alle zukünftigen Wochen';
|
|
}
|
|
|
|
if (!scopeText) {
|
|
return;
|
|
}
|
|
|
|
const confirmed = window.confirm(`Wochen-Soll wirklich ändern?\nNeuer Wert: ${hours} h\nGültigkeit: ${scopeText}`);
|
|
if (!confirmed) {
|
|
event.preventDefault();
|
|
return;
|
|
}
|
|
|
|
if (editor) {
|
|
editor.classList.add('is-hidden');
|
|
}
|
|
});
|
|
}
|
|
|
|
export function initDashboard() {
|
|
initSwipeNavigation();
|
|
initWarningBanner();
|
|
initWeeklyTargetEditor();
|
|
}
|