This commit is contained in:
younes elhaddoury
2025-09-17 10:28:02 +02:00
parent 9c8fb9b205
commit bb13759af4
288 changed files with 102393 additions and 0 deletions

View File

@@ -0,0 +1,162 @@
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
});
});
}
});