Files
SDS-CRM/public/js/pages/tickets.js

129 lines
4.3 KiB
JavaScript

import { apiGet, apiPost, isAuthRedirectError } from '../api.js';
import { guard } from '../core/auth-guard.js';
import {
ticketStatusLabel,
ticketPriorityLabel,
statusBadgeClass,
priorityBadgeClass,
} from '../core/constants.js';
import { esc, extrasName } from '../core/utils.js';
const loadingEl = document.getElementById('page-loading');
const mainEl = document.getElementById('page-main');
const errEl = document.getElementById('page-error');
function showError(msg) {
loadingEl.hidden = true;
mainEl.hidden = true;
errEl.hidden = false;
errEl.textContent = msg;
}
function ticketListQuery() {
const q = new URLSearchParams(location.search);
const p = new URLSearchParams();
if (q.get('status')) p.set('status', q.get('status'));
if (q.get('priority')) p.set('priority', q.get('priority'));
if (q.get('machineId')) p.set('machineId', q.get('machineId'));
const s = p.toString();
return s ? `?${s}` : '';
}
function fillMachineSelects(allMachines, selectedMid) {
const selNm = document.getElementById('sel-nm');
const selFm = document.getElementById('sel-fm');
const opts = allMachines
.map(
(m) =>
`<option value="${esc(m.id)}">${esc(m.seriennummer)}${extrasName(m) ? ` · ${esc(extrasName(m))}` : ''}</option>`,
)
.join('');
selNm.innerHTML = `<option value="">— wählen —</option>${opts}`;
selFm.innerHTML = `<option value="">Alle</option>${opts}`;
if (selectedMid) {
selNm.value = selectedMid;
selFm.value = selectedMid;
}
}
function renderTicketRows(tickets) {
const tbody = document.getElementById('tickets-table-body');
tbody.innerHTML = tickets
.map(
(t) => `
<tr${t.isOverdue ? ' class="ticket-row-overdue"' : ''}>
<td><a href="/ticket.html?id=${esc(t.id)}">${esc(t.title)}</a></td>
<td><span class="badge ${statusBadgeClass[t.status] || ''}">${esc(ticketStatusLabel[t.status])}</span></td>
<td><span class="badge ${priorityBadgeClass[t.priority] || ''}">${esc(ticketPriorityLabel[t.priority])}</span></td>
<td class="muted">${t.machine ? esc(t.machine.seriennummer) : ''}${t.machine ? (extrasName(t.machine) ? ` · ${esc(extrasName(t.machine))}` : '') : ''}</td>
</tr>`,
)
.join('');
}
async function run(canEdit) {
const qs = ticketListQuery();
const urlParams = new URLSearchParams(location.search);
const newCard = document.getElementById('tickets-new-card');
if (newCard) newCard.hidden = !canEdit;
const [tickets, allMachines] = await Promise.all([
apiGet(`/tickets${qs}`),
apiGet('/machines'),
]);
const mid = urlParams.get('machineId') || '';
fillMachineSelects(allMachines, mid);
const filterStatus = urlParams.get('status') || '';
const filterPriority = urlParams.get('priority') || '';
const formFilter = document.getElementById('form-filter');
formFilter.elements.status.value = filterStatus;
formFilter.elements.priority.value = filterPriority;
renderTicketRows(tickets);
if (canEdit) {
document.getElementById('form-new-ticket').onsubmit = async (e) => {
e.preventDefault();
const fd = new FormData(e.target);
await apiPost('/tickets', {
machineId: fd.get('machineId'),
title: fd.get('title'),
description: fd.get('description'),
});
e.target.reset();
fillMachineSelects(allMachines, mid);
location.reload();
};
}
document.getElementById('form-filter').onsubmit = (e) => {
e.preventDefault();
const fd = new FormData(e.target);
const p = new URLSearchParams();
if (fd.get('status')) p.set('status', fd.get('status'));
if (fd.get('priority')) p.set('priority', fd.get('priority'));
if (fd.get('machineId')) p.set('machineId', fd.get('machineId'));
const q = p.toString();
location.href = `/tickets.html${q ? `?${q}` : ''}`;
};
}
async function init() {
const st = await guard({ activeNav: 'tickets' });
if (!st) return;
const canEdit = st.user?.canEditCrm === true;
loadingEl.hidden = true;
mainEl.hidden = false;
try {
await run(canEdit);
} catch (e) {
if (isAuthRedirectError(e)) return;
showError(e.message || 'Fehler');
}
}
init();