chore: initialize public repository
CI / checks (push) Has been cancelled

This commit is contained in:
maddin
2026-03-22 12:55:55 +00:00
commit 9794362f39
143 changed files with 19832 additions and 0 deletions
+153
View File
@@ -0,0 +1,153 @@
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();
}