/** * ملف رسم وتهيئة المخططات البيانية */ // دالة التهيئة عند تحميل الصفحة document.addEventListener('DOMContentLoaded', function() { // تهيئة المخططات initializeCharts(); }); /** * تهيئة جميع المخططات في الصفحة */ function initializeCharts() { // التحقق من توفر مكتبة Chart.js if (typeof Chart === 'undefined') { console.warn('مكتبة Chart.js غير متوفرة. لا يمكن تهيئة المخططات.'); return; } // تعيين الخيارات العامة للمخططات Chart.defaults.font.family = "'Tajawal', sans-serif"; Chart.defaults.font.size = 14; Chart.defaults.color = '#333'; Chart.defaults.plugins.tooltip.rtl = true; Chart.defaults.plugins.tooltip.titleAlign = 'right'; Chart.defaults.plugins.tooltip.bodyAlign = 'right'; Chart.defaults.plugins.legend.rtl = true; Chart.defaults.plugins.legend.labels.textAlign = 'right'; // إنشاء مخططات مختلفة بناءً على نوع المخطط initializeBarCharts(); initializeLineCharts(); initializePieCharts(); initializeRadarCharts(); initializeGaugeCharts(); initializeDashboardCharts(); } /** * تهيئة المخططات الشريطية */ function initializeBarCharts() { const barChartElements = document.querySelectorAll('.bar-chart'); barChartElements.forEach(element => { const ctx = element.getContext('2d'); const dataUrl = element.getAttribute('data-url'); // استدعاء البيانات من الخادم إذا كان متوفرًا if (dataUrl) { fetch(dataUrl) .then(response => response.json()) .then(data => { createBarChart(ctx, element, data); }) .catch(error => { console.error('خطأ في تحميل بيانات المخطط:', error); // استخدام بيانات افتراضية في حال حدوث خطأ createBarChart(ctx, element, getDefaultBarChartData()); }); } else { // استخدام البيانات المضمنة من سمة data-config let chartData; try { chartData = JSON.parse(element.getAttribute('data-config') || '{}'); } catch (e) { console.error('تنسيق بيانات المخطط غير صالح:', e); chartData = getDefaultBarChartData(); } createBarChart(ctx, element, chartData); } }); } /** * إنشاء مخطط شريطي */ function createBarChart(ctx, element, data) { const isVertical = element.getAttribute('data-orientation') !== 'horizontal'; const isStacked = element.getAttribute('data-stacked') === 'true'; // تكوين الخيارات const options = { indexAxis: isVertical ? 'x' : 'y', scales: { x: { beginAtZero: true, grid: { display: false } }, y: { beginAtZero: true, grid: { display: true, color: '#f0f0f0' } } }, plugins: { title: { display: data.title ? true : false, text: data.title || '', align: 'right', font: { size: 16, weight: 'bold' } }, legend: { display: (data.datasets && data.datasets.length > 1) ? true : false, position: 'top', align: 'end' } }, responsive: true, maintainAspectRatio: false }; // إضافة خيارات للمخطط المكدس إذا لزم الأمر if (isStacked) { options.scales.x.stacked = true; options.scales.y.stacked = true; } // إنشاء المخطط new Chart(ctx, { type: 'bar', data: { labels: data.labels || [], datasets: data.datasets || [] }, options: options }); } /** * تهيئة المخططات الخطية */ function initializeLineCharts() { const lineChartElements = document.querySelectorAll('.line-chart'); lineChartElements.forEach(element => { const ctx = element.getContext('2d'); const dataUrl = element.getAttribute('data-url'); // استدعاء البيانات من الخادم إذا كان متوفرًا if (dataUrl) { fetch(dataUrl) .then(response => response.json()) .then(data => { createLineChart(ctx, element, data); }) .catch(error => { console.error('خطأ في تحميل بيانات المخطط:', error); createLineChart(ctx, element, getDefaultLineChartData()); }); } else { // استخدام البيانات المضمنة let chartData; try { chartData = JSON.parse(element.getAttribute('data-config') || '{}'); } catch (e) { console.error('تنسيق بيانات المخطط غير صالح:', e); chartData = getDefaultLineChartData(); } createLineChart(ctx, element, chartData); } }); } /** * إنشاء مخطط خطي */ function createLineChart(ctx, element, data) { const isCurved = element.getAttribute('data-curved') === 'true'; const showPoints = element.getAttribute('data-points') !== 'false'; // تكوين الخيارات const options = { scales: { x: { grid: { display: false } }, y: { beginAtZero: element.getAttribute('data-start-at-zero') === 'true', grid: { color: '#f0f0f0' } } }, elements: { line: { tension: isCurved ? 0.4 : 0, borderWidth: 2 }, point: { radius: showPoints ? 4 : 0, hoverRadius: showPoints ? 6 : 0 } }, plugins: { title: { display: data.title ? true : false, text: data.title || '', align: 'right', font: { size: 16, weight: 'bold' } }, legend: { position: 'top', align: 'end' } }, responsive: true, maintainAspectRatio: false, interaction: { mode: 'index', intersect: false } }; // إنشاء المخطط new Chart(ctx, { type: 'line', data: { labels: data.labels || [], datasets: data.datasets || [] }, options: options }); } /** * تهيئة المخططات الدائرية */ function initializePieCharts() { const pieChartElements = document.querySelectorAll('.pie-chart, .doughnut-chart'); pieChartElements.forEach(element => { const ctx = element.getContext('2d'); const dataUrl = element.getAttribute('data-url'); const isDoughnut = element.classList.contains('doughnut-chart'); // استدعاء البيانات من الخادم إذا كان متوفرًا if (dataUrl) { fetch(dataUrl) .then(response => response.json()) .then(data => { createPieChart(ctx, element, data, isDoughnut); }) .catch(error => { console.error('خطأ في تحميل بيانات المخطط:', error); createPieChart(ctx, element, getDefaultPieChartData(), isDoughnut); }); } else { // استخدام البيانات المضمنة let chartData; try { chartData = JSON.parse(element.getAttribute('data-config') || '{}'); } catch (e) { console.error('تنسيق بيانات المخطط غير صالح:', e); chartData = getDefaultPieChartData(); } createPieChart(ctx, element, chartData, isDoughnut); } }); } /** * إنشاء مخطط دائري */ function createPieChart(ctx, element, data, isDoughnut) { // تكوين الخيارات const options = { plugins: { title: { display: data.title ? true : false, text: data.title || '', align: 'right', font: { size: 16, weight: 'bold' } }, legend: { position: 'bottom', align: 'start', rtl: true, labels: { boxWidth: 12, padding: 15 } } }, responsive: true, maintainAspectRatio: false }; // إضافة خيارات لمخطط الدونات إذا لزم الأمر if (isDoughnut) { options.cutout = '60%'; options.plugins.tooltip = { callbacks: { title: function(tooltipItems) { return tooltipItems[0].label; }, label: function(context) { const value = context.raw; const total = context.chart.getDatasetMeta(0).total; const percentage = Math.round((value / total) * 100); return percentage + '% (' + value + ')'; } } }; } // إنشاء المخطط new Chart(ctx, { type: isDoughnut ? 'doughnut' : 'pie', data: { labels: data.labels || [], datasets: [{ data: data.values || [], backgroundColor: data.colors || getDefaultColors(), borderWidth: 1, borderColor: '#fff' }] }, options: options }); } /** * تهيئة مخططات الرادار */ function initializeRadarCharts() { const radarChartElements = document.querySelectorAll('.radar-chart'); radarChartElements.forEach(element => {