function toggleSidebar(){document.body.classList.add('sidebar-open');} function closeSidebar(){document.body.classList.remove('sidebar-open');} function openModal(id){ document.getElementById(id).classList.add('open'); document.body.classList.add('modal-open'); } function closeModal(id){ document.getElementById(id).classList.remove('open'); if(!document.querySelector('.modal-backdrop.open'))document.body.classList.remove('modal-open'); } function closeOnBackdrop(e,id){ if(e.target===e.currentTarget)closeModal(id); } document.addEventListener('keydown',e=>{ if(e.key==='Escape'){ document.querySelectorAll('.modal-backdrop.open').forEach(m=>m.classList.remove('open')); document.body.classList.remove('modal-open'); } }); function switchTab(btn,panelId){ const tabList=btn.closest('.tab-list'); tabList.querySelectorAll('button').forEach(b=>b.classList.remove('active')); btn.classList.add('active'); const tabs=btn.closest('.tabs'); tabs.querySelectorAll('.tab-panel').forEach(p=>p.classList.remove('active')); document.getElementById(panelId).classList.add('active'); } function toggleNavDd(btn){ const li=btn.closest('li'); const isOpen=li.classList.contains('open'); document.querySelectorAll('.topnav-links li.open').forEach(l=>l.classList.remove('open')); if(!isOpen)li.classList.add('open'); } function toggleDropdown(id){ const dd=document.getElementById(id); const isOpen=dd.classList.contains('open'); document.querySelectorAll('.dropdown.open').forEach(d=>d.classList.remove('open')); if(!isOpen)dd.classList.add('open'); } function dismissAlert(btn){ const alert=btn.closest('.alert'); alert.classList.add('is-dismissing'); alert.addEventListener('transitionend',()=>alert.remove(),{once:true}); } function sortTable(th){ const table=th.closest('table'); const col=[...th.parentElement.children].indexOf(th); const dir=th.dataset.sort==='asc'?'desc':'asc'; table.querySelectorAll('th[data-sort]').forEach(t=>{ if(t!==th)t.dataset.sort=''; }); th.dataset.sort=dir; const tbody=table.querySelector('tbody'); [...tbody.querySelectorAll('tr')] .sort((a,b)=>{ const aVal=a.cells[col].textContent.trim(); const bVal=b.cells[col].textContent.trim(); const aNum=parseFloat(aVal.replace(/[^0-9.-]/g,'')); const bNum=parseFloat(bVal.replace(/[^0-9.-]/g,'')); if(!isNaN(aNum)&&!isNaN(bNum)) return dir==='asc'?aNum-bNum:bNum-aNum; return dir==='asc' ?aVal.localeCompare(bVal,'de') :bVal.localeCompare(aVal,'de'); }) .forEach(r=>tbody.appendChild(r)); } function showToast(message,type='info'){ const icons={success:'✓',warning:'⚠',danger:'✕',info:'ℹ'}; if(!(type in icons))type='info'; const id='toast-'+Date.now()+'-'+Math.random().toString(36).slice(2,7); const toast=document.createElement('div'); toast.className='toast'; toast.id=id; toast.setAttribute('role','status'); const icon=document.createElement('span'); icon.className='toast-icon toast-icon-'+type; icon.textContent=icons[type]; const content=document.createElement('div'); content.className='toast-content'; const title=document.createElement('p'); title.className='toast-title'; title.textContent=message; content.appendChild(title); const close=document.createElement('button'); close.className='toast-close'; close.type='button'; close.setAttribute('aria-label','Schließen'); close.dataset.action='toast-close'; close.textContent='×'; toast.append(icon,content,close); document.getElementById('toast-container').appendChild(toast); setTimeout(()=>removeToast(id),4000); } function removeToast(id){ const el=document.getElementById(id); if(el){ el.classList.add('is-leaving'); setTimeout(()=>el.remove(),200); } } function applyProgress(root){ (root||document).querySelectorAll('[data-progress]').forEach(el=>{ const wert=Math.max(0,Math.min(100,parseFloat(el.dataset.progress)||0)); el.style.width=wert+'%'; }); } document.addEventListener('DOMContentLoaded',()=>applyProgress()); document.addEventListener('htmx:load',e=>applyProgress(e.target)); const frameworkActions={ 'sidebar-open':()=>toggleSidebar(), 'sidebar-close':()=>closeSidebar(), 'modal-open':el=>openModal(el.dataset.target), 'modal-close':el=>closeModal(el.dataset.target||el.closest('.modal-backdrop').id), 'modal-backdrop':(el,e)=>{if(e.target===el)closeModal(el.id);}, 'tab':el=>switchTab(el,el.dataset.target), 'nav-dropdown':el=>toggleNavDd(el), 'dropdown':el=>toggleDropdown(el.dataset.target||el.closest('.dropdown').id), 'alert-dismiss':el=>dismissAlert(el), 'sort':el=>sortTable(el), 'toggle-class':el=>el.classList.toggle(el.dataset.class), 'toast':el=>showToast(el.dataset.message,el.dataset.type), 'toast-close':el=>removeToast(el.closest('.toast').id), }; document.addEventListener('click',e=>{ const el=e.target.closest('[data-action]'); const action=el&&frameworkActions[el.dataset.action]; if(action)action(el,e); if(!e.target.closest('.topnav-links li')) document.querySelectorAll('.topnav-links li.open').forEach(l=>l.classList.remove('open')); if(!e.target.closest('.dropdown')) document.querySelectorAll('.dropdown.open').forEach(d=>d.classList.remove('open')); });