let reminderUserId = null; const remindersCaseId = {{ case.id }}; function getReminderUserId() { const token = localStorage.getItem('access_token') || sessionStorage.getItem('access_token'); if (token) { try { const payload = JSON.parse(atob(token.split('.')[1])); return payload.sub || payload.user_id; } catch (e) { console.warn('Could not decode token for reminder user_id'); } } const metaTag = document.querySelector('meta[name="user-id"]'); if (metaTag) return metaTag.getAttribute('content'); return null; } async function ensureReminderUserId() { const localId = getReminderUserId(); if (localId) return localId; try { const res = await fetch('/api/v1/auth/me', { credentials: 'include' }); if (!res.ok) return null; const me = await res.json(); return me?.id || me?.user_id || null; } catch (err) { return null; } } function formatReminderDate(value) { if (!value) return '-'; const date = new Date(value); if (Number.isNaN(date.getTime())) return '-'; return date.toLocaleString('da-DK', { hour12: false }); } function updateReminderTriggerFields() { const triggerType = document.getElementById('rem_trigger_type')?.value; const timeWrap = document.getElementById('rem_trigger_time_wrap'); const statusWrap = document.getElementById('rem_trigger_status_wrap'); if (timeWrap && statusWrap) { if (triggerType === 'status_change') { timeWrap.classList.add('d-none'); statusWrap.classList.remove('d-none'); } else { timeWrap.classList.remove('d-none'); statusWrap.classList.add('d-none'); } } } function updateReminderRecurrenceFields() { const recurrenceType = document.getElementById('rem_recurrence_type')?.value; const dowWrap = document.getElementById('rem_recurrence_dow_wrap'); const domWrap = document.getElementById('rem_recurrence_dom_wrap'); if (!dowWrap || !domWrap) return; dowWrap.classList.toggle('d-none', recurrenceType !== 'weekly'); domWrap.classList.toggle('d-none', recurrenceType !== 'monthly'); } function openCreateReminderModal(defaultEventType) { reminderUserId = getReminderUserId(); const warning = document.getElementById('rem_user_warning'); if (warning) warning.classList.toggle('d-none', !!reminderUserId); const form = document.getElementById('createReminderForm'); if (form) form.reset(); document.getElementById('rem_notify_frontend').checked = true; document.getElementById('rem_priority').value = 'normal'; document.getElementById('rem_event_type').value = defaultEventType || 'reminder'; document.getElementById('rem_trigger_type').value = 'time_based'; document.getElementById('rem_recurrence_type').value = 'once'; updateReminderTriggerFields(); updateReminderRecurrenceFields(); new bootstrap.Modal(document.getElementById('createReminderModal')).show(); } async function loadReminders() { const list = document.getElementById('remindersList'); if (!list) return; reminderUserId = await ensureReminderUserId(); if (!reminderUserId) { list.innerHTML = '
Kunne ikke finde bruger-id.
'; setModuleContentState('reminders', true); return; } list.innerHTML = '
Henter reminders...
'; try { const res = await fetch(`/api/v1/sag/${remindersCaseId}/reminders?user_id=${reminderUserId}`); if (!res.ok) throw new Error('Kunne ikke hente reminders'); const reminders = await res.json(); renderReminders(reminders); } catch (e) { console.error(e); list.innerHTML = '
Fejl ved hentning af reminders
'; setModuleContentState('reminders', true); } } function renderReminders(reminders) { const list = document.getElementById('remindersList'); if (!list) return; if (!reminders || reminders.length === 0) { list.innerHTML = '
Ingen reminders endnu.
'; setModuleContentState('reminders', false); return; } const triggerLabels = { time_based: 'Tidspunkt', status_change: 'Status ændring', deadline_approaching: 'Deadline' }; const eventTypeLabels = { reminder: 'Reminder', meeting: 'Moede', technician_visit: 'Teknikerbesoeg', obs: 'OBS', deadline: 'Deadline' }; const recurrenceLabels = { once: 'Én gang', daily: 'Dagligt', weekly: 'Ugentligt', monthly: 'Månedligt' }; list.innerHTML = reminders.map(reminder => { const nextCheck = formatReminderDate(reminder.next_check_at); const createdAt = formatReminderDate(reminder.created_at); const isActive = reminder.is_active; const statusBadge = isActive ? 'Aktiv' : 'Inaktiv'; return `
${reminder.title}
${reminder.message || '-'}
Type: ${eventTypeLabels[reminder.event_type] || reminder.event_type || 'Reminder'} · Trigger: ${triggerLabels[reminder.trigger_type] || reminder.trigger_type} · Gentagelse: ${recurrenceLabels[reminder.recurrence_type] || reminder.recurrence_type}
Næste: ${nextCheck} · Oprettet: ${createdAt}
${statusBadge}
`; }).join(''); setModuleContentState('reminders', true); } async function saveReminder() { reminderUserId = await ensureReminderUserId(); if (!reminderUserId) { alert('Mangler bruger-id. Log ind igen.'); return; } const title = document.getElementById('rem_title').value.trim(); const message = document.getElementById('rem_message').value.trim(); const priority = document.getElementById('rem_priority').value; const eventType = document.getElementById('rem_event_type').value; const triggerType = document.getElementById('rem_trigger_type').value; const scheduledAtValue = document.getElementById('rem_scheduled_at').value; const targetStatus = document.getElementById('rem_target_status').value; const recurrenceType = document.getElementById('rem_recurrence_type').value; const recurrenceDow = document.getElementById('rem_recurrence_dow').value; const recurrenceDom = document.getElementById('rem_recurrence_dom').value; const notifyFrontend = document.getElementById('rem_notify_frontend').checked; const notifyEmail = document.getElementById('rem_notify_email').checked; const notifyMattermost = document.getElementById('rem_notify_mattermost').checked; const overridePrefs = document.getElementById('rem_override_prefs').checked; if (!title) { alert('Titel er påkrævet'); return; } let triggerConfig = {}; let scheduledAt = null; if (triggerType === 'status_change') { if (!targetStatus) { alert('Vælg en status for statusændring'); return; } triggerConfig = { target_status: targetStatus }; } else { if (!scheduledAtValue) { alert('Vælg et tidspunkt'); return; } scheduledAt = new Date(scheduledAtValue).toISOString(); } const payload = { title, message: message || null, priority, event_type: eventType, trigger_type: triggerType, trigger_config: triggerConfig, recipient_user_ids: [Number(reminderUserId)], recipient_emails: [], notify_mattermost: notifyMattermost, notify_email: notifyEmail, notify_frontend: notifyFrontend, override_user_preferences: overridePrefs, recurrence_type: recurrenceType, recurrence_day_of_week: recurrenceType === 'weekly' ? Number(recurrenceDow) : null, recurrence_day_of_month: recurrenceType === 'monthly' ? Number(recurrenceDom) : null, scheduled_at: scheduledAt }; try { const res = await fetch(`/api/v1/sag/${remindersCaseId}/reminders?user_id=${reminderUserId}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!res.ok) { const err = await res.json(); throw new Error(err.detail || 'Kunne ikke oprette reminder'); } bootstrap.Modal.getInstance(document.getElementById('createReminderModal')).hide(); await loadReminders(); await loadCaseCalendar(); } catch (e) { alert('Fejl: ' + e.message); } } async function deleteReminder(reminderId) { if (!confirm('Vil du slette denne reminder?')) return; try { const res = await fetch(`/api/v1/sag/reminders/${reminderId}`, { method: 'DELETE' }); if (!res.ok) throw new Error('Kunne ikke slette reminder'); await loadReminders(); await loadCaseCalendar(); } catch (e) { alert('Fejl: ' + e.message); } } function formatCalendarEvent(event) { const dateLabel = formatReminderDate(event.start); const typeLabelMap = { reminder: 'Reminder', meeting: 'Moede', technician_visit: 'Teknikerbesoeg', obs: 'OBS', deadline: 'Deadline', deferred: 'Deferred' }; const typeLabel = typeLabelMap[event.event_kind] || event.event_kind || 'Reminder'; return `
${event.title || 'Aftale'}
${typeLabel} · ${dateLabel}
`; } async function loadCaseCalendar() { const currentList = document.getElementById('caseCalendarCurrent'); const childrenList = document.getElementById('caseCalendarChildren'); if (!currentList || !childrenList) return; currentList.innerHTML = '
Indlæser aftaler...
'; childrenList.innerHTML = '
Indlæser børnesager...
'; try { const res = await fetch(`/api/v1/sag/${remindersCaseId}/calendar-events?include_children=true`); if (!res.ok) throw new Error('Kunne ikke hente kalenderaftaler'); const data = await res.json(); const currentEvents = data.current || []; const childGroups = data.children || []; const childCount = childGroups.reduce((sum, child) => sum + (child.events || []).length, 0); const hasAnyEvents = currentEvents.length > 0 || childCount > 0; if (!currentEvents.length) { currentList.innerHTML = '
Ingen aftaler for denne sag.
'; } else { currentList.innerHTML = currentEvents .map(formatCalendarEvent) .join(''); } if (!childGroups.length) { childrenList.innerHTML = '
Ingen børnesager.
'; } else { childrenList.innerHTML = childGroups.map(child => { const eventsHtml = (child.events || []).length ? child.events.map(formatCalendarEvent).join('') : '
Ingen aftaler.
'; return `
${child.case_title}
${eventsHtml}
`; }).join(''); } setModuleContentState('calendar', hasAnyEvents); } catch (e) { console.error(e); currentList.innerHTML = '
Fejl ved hentning af aftaler.
'; childrenList.innerHTML = ''; setModuleContentState('calendar', true); } } document.addEventListener('DOMContentLoaded', function() { updateReminderTriggerFields(); updateReminderRecurrenceFields(); loadReminders(); loadCaseCalendar(); });