bmc_hub/static/js/customer-workflow.js

92 lines
4.8 KiB
JavaScript
Raw Normal View History

/* Isolated CRM preference panel; global runtime settings are read-only here. */
(() => {
'use strict';
function initialise() {
const card = document.getElementById('customerWorkflowCard');
if (!card) return;
const customerId = Number(card.dataset.customerId);
if (!Number.isInteger(customerId) || customerId <= 0) return;
const field = name => document.getElementById('customerWorkflow' + name);
const endpoint = '/api/v1/workflows/customers/' + customerId + '/activation';
let saved = null, busy = false;
function message(text, error = false) {
field('Message').textContent = text;
field('Message').className = 'small mt-2 ' + (error ? 'text-danger' : 'text-success');
}
function render(data) {
saved = data;
const canManage = !!data.can_manage && data.schema_ready !== false;
card.hidden = false;
field('Enabled').checked = data.enabled === true;
field('Enabled').disabled = !canManage || busy;
field('Write').hidden = !canManage;
field('Write').classList.toggle('d-flex', !!canManage);
field('Reason').disabled = !canManage || busy;
field('Save').disabled = !canManage || busy;
field('Effective').textContent = data.effective_enabled ? 'Aktiv for kunden' : 'Ikke aktiv';
field('Effective').className = 'badge ' + (data.effective_enabled ? 'text-bg-success' : 'text-bg-secondary');
field('Global').textContent = !data.global_enabled
? 'Workflowmotoren er slukket. Kundens valg er gemt og bruges, når motoren aktiveres.'
: data.mode === 'shadow'
? 'Motoren kører i skyggetilstand. Kundens valg er gemt; afregningen ændres ikke.'
: data.effective_enabled
? 'Automatisk afregning er slået til. Bogholderiet godkender tiden.'
: 'Motoren er aktiv, men workflows er slået fra for denne kunde.';
field('Preference').textContent = 'Kundens gemte valg: ' + (data.enabled ? 'Til' : 'Fra')
+ (data.inherited ? ' · tidligere opsætning' : '');
if (data.schema_ready === false) message('Workflowindstillingen kan først ændres, når databasens workflowopdatering er installeret.', true);
}
async function request(body) {
const response = await fetch(endpoint, {
method: body ? 'PUT' : 'GET', credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' },
body: body ? JSON.stringify(body) : undefined
});
const data = await response.json().catch(() => ({}));
if (!response.ok) {
const error = new Error(typeof data.detail === 'string' ? data.detail : 'Workflowindstillingen kunne ikke hentes.');
error.status = response.status;
throw error;
}
return data;
}
field('Save').addEventListener('click', async () => {
if (!saved?.can_manage || saved.schema_ready === false || busy) return;
const reason = field('Reason').value.trim();
if (reason.length < 3 || reason.length > 1000) {
message('Angiv en kort begrundelse, før du gemmer.', true);
field('Reason').focus();
return;
}
const enabled = field('Enabled').checked;
busy = true;
field('Save').disabled = field('Enabled').disabled = field('Reason').disabled = true;
field('Save').textContent = 'Gemmer…';
try {
const updated = await request({ enabled, reason });
busy = false;
render(updated);
field('Reason').value = '';
message('Kundens workflowvalg er gemt. Eksisterende tidsregistreringer genbehandles ikke.');
} catch (error) {
busy = false;
render(saved);
message(error.message, true);
} finally {
field('Save').textContent = 'Gem';
}
});
request().then(render).catch(error => {
// Lack of workflow access does not interrupt the existing customer page.
if (error.status === 401 || error.status === 403) return;
card.hidden = false;
field('Effective').textContent = 'Status ukendt';
field('Global').textContent = 'Kundens workflowindstilling kunne ikke hentes.';
message(error.message, true);
});
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', initialise, { once: true });
else initialise();
})();