163 lines
6.1 KiB
JavaScript
163 lines
6.1 KiB
JavaScript
document.addEventListener('DOMContentLoaded', () => {
|
|
const navToggle = document.querySelector('.nav-toggle');
|
|
const navMenu = document.querySelector('.nav-menu');
|
|
|
|
if (navToggle && navMenu) {
|
|
navToggle.addEventListener('click', () => {
|
|
navMenu.classList.toggle('open');
|
|
navToggle.classList.toggle('is-open');
|
|
});
|
|
}
|
|
|
|
const flashMessages = document.querySelectorAll('.flash-message');
|
|
flashMessages.forEach(message => {
|
|
const closeButton = message.querySelector('.flash-close');
|
|
const hideMessage = () => {
|
|
message.classList.add('is-hidden');
|
|
window.setTimeout(() => message.remove(), 250);
|
|
};
|
|
|
|
if (closeButton) {
|
|
closeButton.addEventListener('click', hideMessage);
|
|
}
|
|
|
|
window.setTimeout(hideMessage, 5000);
|
|
});
|
|
|
|
const filterForm = document.querySelector('.filter-card form');
|
|
if (filterForm) {
|
|
const inputs = filterForm.querySelectorAll('input, select');
|
|
inputs.forEach(input => {
|
|
input.addEventListener('change', () => {
|
|
input.classList.add('has-value');
|
|
});
|
|
|
|
if (input.value) {
|
|
input.classList.add('has-value');
|
|
}
|
|
});
|
|
}
|
|
|
|
const chartElements = document.querySelectorAll('[data-chart]');
|
|
if (chartElements.length > 0 && typeof window.Chart !== 'undefined') {
|
|
chartElements.forEach(canvas => {
|
|
const rawConfig = canvas.dataset.chart;
|
|
if (!rawConfig) {
|
|
return;
|
|
}
|
|
|
|
let config;
|
|
try {
|
|
config = JSON.parse(rawConfig);
|
|
} catch (error) {
|
|
console.error('Diagrammkonfiguration ist ungültig.', error);
|
|
return;
|
|
}
|
|
|
|
if (!config || !Array.isArray(config.labels) || !Array.isArray(config.values)) {
|
|
return;
|
|
}
|
|
|
|
const chartType = config.type ?? 'doughnut';
|
|
const isCircular = chartType === 'doughnut' || chartType === 'pie';
|
|
const parsedValues = config.values.map(value => (typeof value === 'number' ? value : Number(value)))
|
|
.map(value => (Number.isFinite(value) ? value : 0));
|
|
|
|
const providedColors = Array.isArray(config.colors)
|
|
? config.colors
|
|
: (typeof config.colors === 'string' ? [config.colors] : []);
|
|
|
|
const dataset = {
|
|
label: config.datasetLabel ?? '',
|
|
data: parsedValues,
|
|
borderWidth: config.borderWidth ?? (isCircular ? 1 : 2),
|
|
fill: config.fill ?? !isCircular,
|
|
tension: config.tension ?? (isCircular ? 0 : 0.35)
|
|
};
|
|
|
|
if (isCircular) {
|
|
dataset.backgroundColor = providedColors.length > 0
|
|
? providedColors
|
|
: ['#4460f7', '#3ac0a0', '#ff9f43', '#ef476f'];
|
|
dataset.borderColor = config.borderColor ?? '#ffffff';
|
|
dataset.hoverOffset = 8;
|
|
} else {
|
|
const borderColor = config.borderColor
|
|
?? (providedColors.length > 0 ? providedColors[0] : '#4460f7');
|
|
const backgroundColor = providedColors.length > 0
|
|
? providedColors[0]
|
|
: 'rgba(68, 96, 247, 0.18)';
|
|
|
|
dataset.borderColor = borderColor;
|
|
dataset.backgroundColor = config.fill === false ? 'transparent' : backgroundColor;
|
|
dataset.pointBackgroundColor = borderColor;
|
|
dataset.pointBorderColor = '#ffffff';
|
|
dataset.pointRadius = config.pointRadius ?? 4;
|
|
}
|
|
|
|
const options = {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
legend: {
|
|
display: config.legend ?? isCircular,
|
|
position: config.legendPosition ?? 'bottom'
|
|
},
|
|
tooltip: {
|
|
callbacks: {
|
|
label: context => {
|
|
const value = context.parsed;
|
|
if (isCircular) {
|
|
const datasetValues = context.dataset.data ?? [];
|
|
const total = datasetValues.reduce((sum, entry) =>
|
|
(typeof entry === 'number' ? sum + entry : sum), 0);
|
|
const percentage = total > 0 ? Math.round((value / total) * 100) : 0;
|
|
return `${context.label}: ${value} (${percentage}%)`;
|
|
}
|
|
|
|
const label = context.label ?? '';
|
|
return label ? `${label}: ${value}` : `${value}`;
|
|
}
|
|
}
|
|
},
|
|
title: config.title
|
|
? {
|
|
display: true,
|
|
text: config.title
|
|
}
|
|
: undefined
|
|
},
|
|
scales: isCircular
|
|
? undefined
|
|
: {
|
|
y: {
|
|
beginAtZero: true,
|
|
ticks: {
|
|
precision: 0,
|
|
stepSize: 1
|
|
},
|
|
grid: {
|
|
borderDash: [4, 4],
|
|
color: 'rgba(107, 114, 133, 0.2)'
|
|
}
|
|
},
|
|
x: {
|
|
grid: {
|
|
display: false
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
new Chart(canvas, {
|
|
type: chartType,
|
|
data: {
|
|
labels: config.labels,
|
|
datasets: [dataset]
|
|
},
|
|
options
|
|
});
|
|
});
|
|
}
|
|
});
|