(()=>{'use strict'; function init(){ const main=document.getElementById('createForm');if(!main)return; const trigger=document.createElement('button');trigger.type='button';trigger.className='btn btn-outline-primary px-4 fw-bold';trigger.textContent='Kun tid';trigger.title='Kun tid · minus (-)';const caseCard=main.closest('.card');const modes=document.createElement('div');modes.className='d-flex gap-2 mb-3';modes.setAttribute('aria-label','Vælg oprettelse');const caseMode=document.createElement('button');caseMode.type='button';caseMode.className='btn btn-primary px-4 fw-bold';caseMode.textContent='Opret sag';caseMode.setAttribute('aria-pressed','true');trigger.setAttribute('aria-pressed','false');modes.append(caseMode,trigger);caseCard.before(modes); const panel=document.createElement('section');panel.id='quickTimeOnly';panel.className='card mt-4';panel.hidden=true; panel.innerHTML=`

Kun tid

Små opgaver uden en sag. Firma og kontakt er valgfrie.

Medarbejdere
Hver valgt medarbejder får det angivne antal minutter. Registreringer gemmes til chefkontrol. Tab skifter felt, piletaster skifter knap, Enter vælger. Cmd/Ctrl+Enter gemmer.
`; modes.after(panel);const q=s=>panel.querySelector(s),form=q('[data-form]');let options=null,customer=null,contact=null,request=crypto.randomUUID(),pending=null; const state=q('[data-status]'); async function api(url,opts){const r=await fetch(url,{credentials:'include',...opts});const d=await r.json();if(!r.ok){const e=new Error(typeof d.detail==='string'?d.detail:d.detail?.message||'Kunne ikke gemme');e.status=r.status;e.detail=d.detail;throw e;}return d;} function local(date){return new Date(date.getTime()-date.getTimezoneOffset()*60000).toISOString().slice(0,16);} function paint(button,selected){button.setAttribute('aria-pressed',String(selected));button.classList.toggle('btn-primary',selected);button.classList.toggle('btn-outline-primary',!selected);} function syncChoices(){panel.querySelectorAll('[data-choice]').forEach(group=>group.querySelectorAll('button').forEach(button=>paint(button,button.dataset.value===form.elements[group.dataset.choice].value)));} panel.addEventListener('click',e=>{const button=e.target.closest('[data-choice] button');if(!button||button.disabled)return;const group=button.closest('[data-choice]'),field=form.elements[group.dataset.choice];field.value=button.dataset.value;field.dispatchEvent(new Event('change'));syncChoices();if(!pending)request=crypto.randomUUID();}); panel.addEventListener('keydown',e=>{if(!['ArrowLeft','ArrowRight','ArrowUp','ArrowDown','Home','End'].includes(e.key))return;const button=e.target.closest('button'),group=button?.closest('[role="group"],.list-group');if(!group)return;const buttons=[...group.querySelectorAll('button:not(:disabled)')];if(!buttons.length)return;e.preventDefault();const index=buttons.indexOf(button),step=['ArrowLeft','ArrowUp'].includes(e.key)?-1:1;buttons[e.key==='Home'?0:e.key==='End'?buttons.length-1:(index+step+buttons.length)%buttons.length].focus();}); q('[data-conflict]').addEventListener('click',()=>{const selected=form.elements.confirm.value!=='true';form.elements.confirm.value=String(selected);q('[data-conflict]').setAttribute('aria-pressed',String(selected));q('[data-conflict]').classList.toggle('btn-warning',selected);if(!pending)request=crypto.randomUUID();}); async function load(){options=await api('/api/v1/timetracking/quick-time/options');const host=q('[data-plans]');host.replaceChildren();for(const p of options.plans){const button=document.createElement('button');button.type='button';button.className='btn btn-sm btn-outline-primary text-start';button.dataset.value=String(p.id);button.textContent=`${p.description} · ${p.user_name} · ${new Date(p.starts_at).toLocaleString('da-DK')}`;host.append(button);}if(!options.plans.length)host.textContent='Ingen planlagte opgaver at konvertere.';users();syncChoices();} function users(){const converting=form.elements.mode.value==='convert',planning=form.elements.mode.value==='planned';const host=q('[data-users]');host.replaceChildren();for(const u of options?.users||[]){if(planning?!u.can_plan:!u.can_register)continue;const button=document.createElement('button');button.type='button';button.className='btn btn-sm btn-outline-primary';button.dataset.userId=u.id;button.textContent=u.name;paint(button,u.id===options.current_user_id);button.disabled=converting;button.addEventListener('click',()=>{paint(button,button.getAttribute('aria-pressed')!=='true');if(!pending)request=crypto.randomUUID();});host.append(button);}} async function open(){caseCard.classList.add('d-none');panel.hidden=false;caseMode.className='btn btn-outline-primary px-4 fw-bold';trigger.className='btn btn-primary px-4 fw-bold';caseMode.setAttribute('aria-pressed','false');trigger.setAttribute('aria-pressed','true');if(pending){panel.scrollIntoView({behavior:'smooth',block:'start'});return;}panel.scrollIntoView({behavior:'smooth',block:'start'});form.elements.start.value=local(new Date(Date.now()-Number(form.elements.minutes.value||30)*60000));q('#qtDescription').focus();state.textContent='Indlæser…';try{await load();state.textContent='';}catch(e){state.textContent=e.message;}} document.addEventListener('keydown',e=>{if((e.metaKey||e.ctrlKey)&&e.key==='Enter'&&!panel.hidden){e.preventDefault();e.stopImmediatePropagation();if(!q('[data-save]').disabled)form.requestSubmit();}},true); trigger.addEventListener('click',open);function close(){panel.hidden=true;caseCard.classList.remove('d-none');caseMode.className='btn btn-primary px-4 fw-bold';trigger.className='btn btn-outline-primary px-4 fw-bold';caseMode.setAttribute('aria-pressed','true');trigger.setAttribute('aria-pressed','false');caseMode.focus();}caseMode.addEventListener('click',close);q('[data-close]').textContent='Tilbage til sag';q('[data-close]').addEventListener('click',close); window.openQuickTimeOnly=open; form.elements.mode.addEventListener('change',()=>{form.elements.start.value=local(new Date(Date.now()-(form.elements.mode.value==='registered'?Number(form.elements.minutes.value||30)*60000:0)));q('[data-plan-wrap]').hidden=form.elements.mode.value!=='convert';q('[data-save]').textContent=form.elements.mode.value==='planned'?'Gem planlægning':form.elements.mode.value==='convert'?'Konvertér til registreret tid':'Gem tid';q('[data-conflict]').hidden=true;form.elements.confirm.value='false';q('[data-conflict]').setAttribute('aria-pressed','false');q('[data-conflict]').classList.remove('btn-warning');users();customer=null;contact=null;q('#qtCustomer').disabled=q('#qtContact').disabled=form.elements.mode.value==='convert';q('#qtCustomer').value=q('#qtContact').value='';}); form.elements.plan.addEventListener('change',()=>{const p=options.plans.find(x=>x.id===Number(form.elements.plan.value));if(!p)return;form.elements.description.value=p.description;form.elements.minutes.value=Math.round((new Date(p.ends_at)-new Date(p.starts_at))/60000);form.elements.start.value=local(new Date(p.starts_at));form.elements.priority.value=p.priority;customer=p.customer_id;contact=p.contact_id;q('#qtCustomer').value=p.customer_name||'';q('#qtContact').value=p.contact_id?`Kontakt #${p.contact_id}`:'';q('[data-users]').querySelectorAll('button').forEach(x=>paint(x,Number(x.dataset.userId)===p.user_id));syncChoices();}); function search(input,list,type){let timer=0,generation=0;input.addEventListener('keydown',e=>{if(e.key==='ArrowDown'&&list.firstElementChild){e.preventDefault();list.firstElementChild.focus();}});input.addEventListener('input',()=>{const current=++generation;if(type==='customers')customer=null;else contact=null;clearTimeout(timer);list.replaceChildren();const term=input.value.trim();if(term.length<2)return;timer=setTimeout(async()=>{try{const data=await api(`/api/v1/search/${type}?q=${encodeURIComponent(term)}`);if(current!==generation)return;const rows=Array.isArray(data)?data:data.results||data.items||[];for(const r of rows.slice(0,10)){const b=document.createElement('button');b.type='button';b.className='list-group-item list-group-item-action small';const name=r.name||r.contact_name||[r.first_name,r.last_name].filter(Boolean).join(' ')||r.label;b.textContent=name;b.addEventListener('click',()=>{if(type==='customers')customer=r.id;else contact=r.id;input.value=name;list.replaceChildren();input.focus();});list.append(b);}}catch(e){state.textContent=e.message;}},250);});} search(q('#qtCustomer'),q('[data-customers]'),'customers');search(q('#qtContact'),q('[data-contacts]'),'contacts'); form.addEventListener('input',()=>{if(!pending)request=crypto.randomUUID();}); form.addEventListener('submit',async e=>{e.preventDefault();if(!options){state.textContent='Muligheder er ikke indlæst.';return;}const ids=[...q('[data-users]').querySelectorAll('button[aria-pressed="true"]')].map(x=>Number(x.dataset.userId));if(!ids.length){state.textContent='Vælg mindst én medarbejder.';return;}const mode=form.elements.mode.value;if(mode!=='convert'&&((q('#qtCustomer').value.trim()&&!customer)||(q('#qtContact').value.trim()&&!contact))){state.textContent='Vælg firma/kontakt fra søgeresultaterne, eller ryd felterne.';return;}if(mode==='convert'&&!form.elements.plan.value){state.textContent='Vælg en planlagt opgave.';return;}pending=pending||{request_id:request,mode,description:form.elements.description.value,minutes:Number(form.elements.minutes.value),starts_at:new Date(form.elements.start.value).toISOString(),priority:form.elements.priority.value,user_ids:ids,customer_id:customer,contact_id:contact,plan_ids:mode==='convert'?[Number(form.elements.plan.value)]:[],confirm_conflicts:form.elements.confirm.value==='true'};const controls=[...form.querySelectorAll('input,select,button')],disabled=controls.map(x=>x.disabled);controls.forEach(x=>x.disabled=true);state.textContent='Gemmer…';try{await api('/api/v1/timetracking/quick-time',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(pending)});pending=null;request=crypto.randomUUID();try{await load();}catch{options=null;}state.textContent=mode==='planned'?'Planlægning gemt uden sag.':'Tid registreret uden sag og sendt til chefkontrol.';form.elements.description.value='';q('[data-conflict]').hidden=true;form.elements.confirm.value='false';q('[data-conflict]').setAttribute('aria-pressed','false');q('[data-conflict]').classList.remove('btn-warning');}catch(error){state.textContent=error.message;if(error.status&&error.status<500){pending=null;request=crypto.randomUUID();if(error.detail?.confirm_conflicts)q('[data-conflict]').hidden=false;}else state.textContent+=' Tryk Gem igen for at genprøve samme registrering.';}finally{controls.forEach((x,i)=>x.disabled=disabled[i]);if(pending){controls.forEach(x=>x.disabled=true);q('[data-save]').disabled=false;}}}); const params=new URLSearchParams(location.search);if(params.get('quick_time')==='1')open();const planParam=params.get('quick_plan');if(planParam){open().then(()=>{form.elements.mode.value='convert';form.elements.mode.dispatchEvent(new Event('change'));syncChoices();form.elements.plan.value=planParam;form.elements.plan.dispatchEvent(new Event('change'));});} } if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init);else init();})();