diff --git a/app/modules/sag/templates/detail_v3.html b/app/modules/sag/templates/detail_v3.html index 1c799b9..e090a4a 100644 --- a/app/modules/sag/templates/detail_v3.html +++ b/app/modules/sag/templates/detail_v3.html @@ -8601,6 +8601,16 @@ +
+
+
Timere på denne sag
+ 0 +
+
+
Henter timere på sagen...
+
+
+
@@ -11213,6 +11223,94 @@ return 'Afventer'; } + function caseTimerDuration(entry) { + let seconds = Number(entry.live_elapsed_seconds || 0); + if (!seconds && entry.faktisk_tid_min != null) seconds = Number(entry.faktisk_tid_min || 0) * 60; + if (!seconds && entry.start_tid && entry.slut_tid) { + const start = new Date(entry.start_tid).getTime(); + const end = new Date(entry.slut_tid).getTime(); + if (Number.isFinite(start) && Number.isFinite(end)) { + seconds = Math.max(0, Math.floor((end - start) / 1000) - Number(entry.pause_total_seconds || 0)); + } + } + const hh = String(Math.floor(seconds / 3600)).padStart(2, '0'); + const mm = String(Math.floor((seconds % 3600) / 60)).padStart(2, '0'); + const ss = String(Math.floor(seconds % 60)).padStart(2, '0'); + return `${hh}:${mm}:${ss}`; + } + + function renderCaseTimerWorkQueue(entries) { + const container = document.getElementById('caseTimerWorkQueue'); + const count = document.getElementById('caseTimerWorkQueueCount'); + if (!container) return; + + const rows = (entries || []).filter((entry) => { + const running = entry.aktiv_timer === true && !entry.slut_tid; + const paused = !entry.slut_tid && Boolean(entry.paused_at); + const pending = Boolean(entry.slut_tid) + && String(entry.entry_status || 'afventer').toLowerCase() !== 'godkendt' + && String(entry.status || 'pending').toLowerCase() === 'pending'; + return running || paused || pending; + }); + if (count) count.textContent = String(rows.length); + + if (!rows.length) { + container.innerHTML = '
Ingen åbne eller afventende timere på sagen.
'; + return; + } + + container.innerHTML = '
' + rows.map((entry) => { + const id = Number(entry.id || 0); + const own = entry.is_own_timer === true; + const running = entry.aktiv_timer === true && !entry.slut_tid; + const paused = !entry.slut_tid && Boolean(entry.paused_at); + const state = running ? 'Aktiv' : (paused ? 'Pauset' : 'Klar til registrering'); + const badge = running ? 'success' : (paused ? 'warning text-dark' : 'info text-dark'); + const employee = escapeHtml(entry.employee_display_name || entry.bruger_navn || entry.user_name || 'Ukendt medarbejder'); + const workType = escapeHtml(entry.work_type || 'support'); + let actions = ''; + if (own && running) { + actions = ` + `; + } else if (own && paused) { + actions = ``; + } else if (own) { + actions = ``; + } + return `
+ ${state} +
+
${escapeHtml(entry.description || entry.beskrivelse || 'Arbejde på sagen')}
+
${employee} · ${workType} · ${caseTimerDuration(entry)}
+
+
${actions}
+
`; + }).join('') + '
'; + } + + async function resumeCaseTimerByIdV1(timeId) { + try { + const res = await fetch('/api/v1/timetracking/time/resume', { + method: 'POST', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ time_id: Number(timeId) }) + }); + if (!res.ok) { + const error = await res.json().catch(() => ({})); + throw new Error(error.detail || 'Kunne ikke genoptage timeren'); + } + await loadTimeTrackingTab(); + } catch (error) { + alert(error.message || 'Kunne ikke genoptage timeren'); + } + } + + function openCaseTimerConversionV1(timeId) { + if (typeof window.openBottomBarTimeConversion === 'function') { + window.openBottomBarTimeConversion(Number(timeId)); + return; + } + alert('Konverteringsvinduet kunne ikke åbnes. Genindlæs siden og prøv igen.'); + } + function renderTimeV1Timeline(entries) { const timeline = document.getElementById('timeTimelineColumns'); if (!timeline) return; @@ -11818,6 +11916,7 @@ ownTimers = await ownTimerRes.json().catch(() => null); } updateCaseTimerControls(entries || [], ownTimers); + renderCaseTimerWorkQueue(entries || []); timeV1EntriesById = Object.fromEntries((entries || []).map((entry) => [Number(entry.id), entry])); window.initialCaseTabCounts = Object.assign({}, window.initialCaseTabCounts || {}, { timetracking: (entries || []).length }); renderTimeV1Timeline(entries || []); @@ -12092,6 +12191,7 @@ dateInput.valueAsDate = new Date(); } }); + window.addEventListener('bb:time-converted', () => loadTimeTrackingTab()); - +